# machine_learning_in_action_py3 **Repository Path**: zhaoyanjoin/machine_learning_in_action_py3 ## Basic Information - **Project Name**: machine_learning_in_action_py3 - **Description**: No description available - **Primary Language**: Unknown - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2020-09-20 - **Last Updated**: 2024-12-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

# 机器学习实战笔记(附:[源代码][src] 基于 **[GNU3.0][license]** 协议 附: [版本号][version] [作者][author] ## 第一部分 分类 ### 第一章 机器学习基础([代码][ch01]) - **熟悉[Python][Python]即可。** - **开发机器学习应用程序步骤** - 收集数据 - 制作网络爬虫从网站上抽取数据、从 RSS 反馈或者 API 中得到数据、设备发送过来的实测数据等. - 准备输入数据 - 必须确保数据格式符合要求. - 分析输入数据 - 最简单的方法是用文本编辑器打开数据文件,查看得到的数据是否为空值. - 还可以进一步浏览数据,分析是否可以识别出模式. - 数据中是否存在明显的异常值. - 通过一维、二维、三维展示数据也是不错方法. - 训练算法 - 测试算法 - 对于监督学习,必须已知用于评估算法的目标变量值. - 对于无监督学习,也必须用其他的评测手段来检验算法的成功率. - 如果不满意算法的输出结果,可以回到第 4 步,改正并加以测试. - 问题常常会跟数据的收集和准备有关,这是必须调回到第 1 步重新开始. - 使用算法 - 将机器学习算法转换成应用程序,执行实际任务,以检验以上步骤是否可以实际环境中正常工作。此时如果碰到新的数据问题,同样需要重复执行上述的步骤. - **掌握[numpy][numpy]函数库基础** `>> from numpy import *` ### 第二章 K-近邻算法([代码][ch02]) - **K-近邻算法优缺点** -. 优点:精度高,对异常值步敏感,无数据输入假定。 - 缺点:计算复杂度高,空间复杂度高。 - 范围:数值型和标称型。 - **测试分类器** **`错误率是常用的评估方法,完美评估器为0,最差的评估器为1.0`** - **k-近邻算法的一般流程** - 收集数据:可以使用任何方法; - 准备数据:距离计算所需要的数值,最好是结构化的数据格式; - 分析数据:可以使用任何方法; - 训练算法:此步骤不适用于 k-近邻算法; - 测试算法:计算错误率; - 使用算法:首先需要输入样本数据和结构化的输出结果,然后运行 k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。 - **例子:使用k-近邻算法改进约会网站的配对效果** - 准备数据:从文本数据中解析出数据,用`numpy`转化文本为矩阵,同时进行归一化数值操作(将对数据有影响的数值归纳为`0~1`之间)。 - 分析数据:使用`matplotlib`实现数据可视化。 - 测试数据:错误评估 **`训练数据/测试数据 = 90%/10%`**。 - 使用算法:基于用户的输入,自动匹配。 - **例子:手写识别系统** - 准备数据:将图像分为`32*32`的二进制图像转化为`1*1024`的数组,每次读取`32`行,存入数组,并且返回数组。 - 分析数据:确保数据准确无误。 - 测试数据:随机选取数据测试。 - 使用数据:将评估错误率,选择`最低评估错误率`来作为首选算法。 - **小节** **K-近邻算法是最简单的分类算法,如果数据量太大,会变得非常耗时。** ### 第三章 决策树([代码][ch03]) - **决策树算法优缺点** - 优点:计算复杂度不高,输出结果易于理解,对中间值不明干,可以处理不相关特征数据。 - 缺点:可能会产生过度匹配。 - 范围:数值型和标称型。 - **决策树的一般流程** - 收集数据 - 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化 - 分析数据:可以使用任何方法,构造树完成之后,应该检查图形是否符合预期 - 训练算法:使用经验树计算错误率 - 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义 - **信息增益** - 原则: 将无序的数据变得更加有序。 - 在划分数据集之前之后信息发生的变化 - 熵: 信息的期望值,或者集合信息的度量方式。 - **熵** - 若数据都为一类,那么`H=-1*log2(1)=0,`不用任何信息就能区分这个数据。 - 如有一枚正反两面硬币,分为正面或者反面的概率都为`0.5, H= -0.5log2(0.5) - 0.5log2(0.5) = 1,` 需要一个单位比特信息区分是否是正面或者反面,也即0或者1。 - 熵,代表信息的混乱度信息。其基本作用就是消除人们对事物的不确定性。一个系统越是有序,信息熵就越低;反之,一个系统越是混乱,信息熵就越高。所以,信息熵也可以说是系统有序化程度的一个度量。 - 具体地可参考《信息论》。 - **划分数据集** **将每个特征划分数据集的结果计算一次信息熵,然后判断按照哪个特征划分数据集是最好的划分方式。** - **递归构建决策树** - 工作原理:得到原始数据集,基于最好的属性值划分数据集,第一次划分后,再次划分数据。因此可以递归处理数据集。 - 递归结束的条件:划分数据集所有属性,或者每个分支下的所有实例都具有相同的分类。 - 如果数据集已经处理了所有属性,但是类标签依然不是唯一的,此时我们通常采用多数表决的方法决定该叶子节点的分类。 - **测试算法:使用决策树执行分类** - 执行分类时,需要使用决策树以及用于决策树的标签向量。 - 测试数据与决策树上的数值,递归执行该过程直到进入叶子节点。 - 最后将测试数据定义为叶子节点所属的属性。 - **使用算法:决策树的存储** **为了节约时间和节省内存消耗,使用了pickle模块序列化对象。** - **例子:使用决策树预测隐形眼睛类型** **目标:通过决策树预测患者需要佩戴的隐形眼睛类型。** ```python import trees fr = open('lensens.txt') lenses = [inst.strip().split('\t') for inst in fr.readlines()] lenseslabels = ['age', 'prescipt', 'astigmatic', 'tearRate'] lensestree = trees.create_tree(lenses, lenseslabels) lensestree treePlotter.create_plot(lensestree) ``` - **小节** **这里主要是采用`ID3算法划`分数据集,用递归的方法将数据集转化为决策树,并可用`pickle模块存`储决策树的结构。ID3算法无法处理直接数值型数据,需要将其化为标量型数值。决策树最大的缺点在于`过拟合问题`。在构建树的时候,其能够完全匹配实验数据,但是这并不是我们想要的,为此,可以删掉一些只增加了很少信息的节点,将其并入到其他叶子节点中,或者裁剪一些分支。具体决策树的很多问题也待整理。** ### 第四章 基于概率论的分类方法:朴素贝叶斯([代码][ch04]) - **基于贝叶斯决策理论算法优缺点** - 优点:在数据较少的情况下仍然有效。可以处理多类别问题。 - 缺点:对于输入数据的准备方式较为敏感。 - 范围:标称型数据。 - **Tip:贝叶斯决策理论的核心思想是选择高概率对应的类别,即选择具有最高概率的决策** - **贝叶斯法则** **后验概率 = 标准似然度 * 先验概率。** - **贝叶斯定理** - 对于变量有二个以上的情况,贝叶斯定理亦成立。例如: - P(A|B,C)=P(B|A)*P(A)*P(C|A,B)/(P(B)*P(C|B)) - 这个式子可以由套用多次二个变量的贝叶斯定理及条件机率的定义导出。 - **使用Python进行文本分类** - 背景 **以在线社区的留言板为例。为了不影响社区的发展,我们要屏蔽侮厚性的言论,所以要构建一个快速过滤器,如果某条留言使用了负面或者侮辱性的语言,那么就将该留言标识为内容不当。过滤这类内容是-一个很常见的需求。对此问题建立两个类别:侮厚类和非侮辱类,使用1和0分别表示。** - 准备数据:从文本中构建词向量 - 训练算法:从词向量计算概率 - 测试算法:根据现实情况修改分类器 - 贝叶斯概率需要计算多个概率的乘积以获得文档属于某个类别的概率,即计算p(w0|1)p(w1|1)p(w2|1)。如果其中一个概率值为0,那么最后的乘积也为0 - 第二个问题就是下溢出,这是由于太多过小的数相乘造成的。由于大部分因子都非常小,所以程序会下溢出或者得不到正确的答案。解决办法是对乘积取自然对数这样可以避免下溢出或者浮点数舍入导致的错误。 - 每个单词的出现与否作为一个特征,被称为词集模型;在词袋模型中,每个单词可以出现多次。 - 准备数据:文档词袋模型 - **例子:使用朴素贝叶斯过滤垃圾邮件** - 准备数据:切分文本 - 测试算法:使用朴素贝叶进行交叉验证 - **例子:使用朴素贝叶斯从个人广告中获取区域倾向** - 收集数据:导入RSS源 - 分析数据:显示低于相关的用词 **Tip:这里训练测试的方法是从总的数据集中随机选择数字,将其添加到测试集中,同时将其从训练集中剔除。这种随机选择数据的一部分作为训练集,而剩余部分作为测试集的过程为留存交叉验证(hold-out cross validation)。有时为了更精确地估计分类器的错误率,就应该进行多次迭代后求出平均错误率。** - **小节** **贝叶斯可以通过特征之间的独立性假设,降低对数据量的需求。尽管条件独立性的假设并不正确,但是朴素贝叶斯仍然是一种有效的分类器** ### 第五章 Logistic回归([代码][ch05]) - **Logistic算法优缺点** - 优点:计算代价不高,易于理解和实现。 - 缺点:容易欠似合,分类的精度不高。 - 范围:数值型和标量型数据。 - **基于Logistic回归和Sigmoid函数** - Sigmoid函数是单位阶越函数。 - 在数学上比较容易处理。 - 在数据量比较大的时候,跨度大;数据量小的时候,跨度平稳。 - **基于最优化方法的最佳回归系数确定** - 梯度上升法和梯度下降法 - 伪代码 - 每个回归系数初始化为1 - 重复 R 次: - 计算整个数据集的梯度 - 使用 alpha * gradient 更新回归系数的向量 - 返回回归系数 - 找到函数的最大值和函数的最小值。 - 一直执行某个迭代的公式,达到某个可以允许误差的范围内。 - 训练算法:找到最佳参数 - 分析数据:画出决策边界 - 训练算法:随机梯度提升 **一次仅用一个样本点来更新回归系数。由于可以在新样本到来时对分类器进行增量式更新,因此也是一个在线学习算法.** - 伪代码 - 所有回归系数初始化为1 - 对数据集中每个样本 - 计算该样本的梯度 - 使用 alpha*gradient 更新回归系数值 - 返回回归系数值 - **例子:预测病马的死亡率** - 收集数据:给定数据文件。 - 准备数据:用 python 解析文本文件并填充缺失值。 - 分析数据:可视化并观察数据。 - 训练算法:使用优化算法,找到最佳的系数。 - 测试算法:为了量化回归的效果,需要观察错误率。根据错误率决定是否回退到训练阶段,通过改变迭代的次数和步长等参数得到更好的回归系数。 - 使用算法:实现一个简单的命令行程序来收集马的症状并输出预测结果。 **注意:除了部分指标主观和难以测量外,该数据还存在一个问题,数据集中有 30% 的值是缺失的。** - 处理数据中的缺失值: - 使用可用特征的均值来填补缺失值。 - 使用特殊值来填补缺失值,如 -1。 - 忽略缺失值的样本。 - 使用相似样本的均值填补缺失值。 - 使用另外的机器学习算法预测缺失值。 - 测试算法:用Logistic回归进行分类。 - **小节** **在最优化算法中,最常用的就是随机梯度上升算法,二梯度上升算法可以简化为随机梯度上身算法。** **随机梯度上身算法与梯度上升算法相当,但占用更少的资源。** **随机梯度上升算法是一个在线算法,他可以在新数据刚加入的时候就完成参数更新** ### 第六章 支持向量机([代码][ch06]) - **SVM算法优缺点** - 优点:泛化错误率低,计算开销不大,结果易解释。 - 缺点:对参数调节和和核函数的选择敏感,原始分类器不加修改仅适用于处理二分类问题。 - 范围:数值型和标称型数据。 - **SVM分类(Tip:不讲非线性支持向量机)** - 线性支持向量机 - 求解线性支持向量机的过程是凸二次规划问题,所谓凸二次规划问题,就是目标函数是凸的二次可微函数,约束函数为仿射函数`(满足f(x)=a*x+b,a,x均为n为向量)`。而我们说求解凸二次规划问题可以利用对偶算法--即引入拉格朗日算子,利用拉格朗日对偶性将原始问题的最优解问题转化为拉格朗日对偶问题,这样就将求w*,b的原始问题的极小问题转化为求alpha*(alpha>=0)的对偶问题的极大问题,即求出alpha*,在通过KKT条件求出对应的参数w*,b,从而找到这样的间隔最大化超平面,进而利用该平面完成样本分类 - 近似线性支持向量机    - 当数据集并不是严格线性可分时,即满足绝不部分样本点是线性可分,存在极少部分异常点;这里也就是说存在部分样本不能满足约束条件,此时我们可以引入松弛因子,这样这些样本点到超平面的函数距离加上松弛因子,就能保证被超平面分隔开来;当然,添加了松弛因子sigma,我们也会添加对应的代价项,使得alpha满足0=啤酒这样的关联规则。而我们是要通过关联分析大规模数据从而发现数据之间存在的有趣关系,那么问题来了,什么样的关系是有趣的呢?而这个有趣又是怎么定义的呢?我们可以通过支持度(support)和可信度(置信度confidence)来定义。一个项集的支持度指的是数据集中包含该项集记录所占的比例,上例中{豆奶}的支持度是2/5,{啤酒,尿布}的支持度是3/5;可信度是针对于像{尿布}->{啤酒}这样的关联规则来定义的,定义为:支持度({尿布,葡萄酒})/支持度(尿布). - **Apriori 原理** - **Apriori算法优缺点** - 优点:易编码实现 - 缺点:在大数据集上可能较慢 - 适用数据类型:数值型 或者 标称型数据。 - **Apriori 算法流程步骤** - 收集数据:使用任意方法 - 准备数据:任何数据类型都可以,因为我们只保存集合 - 分析数据:使用任意方法 - 训练数据:使用Apiori算法来找到频繁项集 - 测试算法:不需要测试过程 - 使用算法:用于发现频繁项集以及物品之间的关联规则 - **使用Apriori算法来发现频繁集** - Apriori 算法的两个输入参数分别是最小支持度和数据集 - 该算法首先会生成所有单个物品的项集列表 - 接着扫描交易记录来查看哪些项集满足最小支持度要求,那些不满足最小支持度要求的集合会被去掉 - 燃尽后对生下来的集合进行组合以声场包含两个元素的项集 - 接下来再重新扫描交易记录,去掉不满足最小支持度的项集 - 该过程重复进行直到所有项集被去掉 - **生成候选项集** - **数据集扫描伪代码** - 对数据集中的每条交易记录 tran - 对每个候选项集 can - 检查一下 can 是否是 tran 的子集: 如果是则增加 can 的计数值 - 对每个候选项集 - 如果其支持度不低于最小值,则保留该项集 - 返回所有频繁项集列表 - **从频繁项集中挖掘关联规则** **频繁项集可以使用Apriori算法寻找,当然下来就是要找出关联规则了。我们知道,假设有一个频繁项集,它们之间就有可能有一条关联规则,即可以表示为:"...—>...",但反过来并不一定成立(其中箭头左边对应的集合为前件,箭头右边对应的集合为后件)。在上一节,我们使用最小支持度来量化频繁项集,对应的,采用可信度来量化关联规则。其中一条规则p—>H的可信度定义为:support(P|H)/support(P),为找到其中的关联规则,我们可以先生成一个可能的规则列表,然后测试每条规则的可信度,结合可信度的最小要求,得到关联规则。同寻找频繁项集类似,我们可以为每个频繁项集产生许多关联规则,这样就会有很多的关联规则产生。结合Apriori原理,如果某条规则不满足最小可信度要求,那么该规则的所有子集也就不满足最小可信度要求,据此我们可以减少需要测试的规则数目,简化问题。** - **寻找关联规则的思想** - 从一个频繁项集开始,创建一个规则列表,首先将规则的右边限定为一个元素,对这些规则进行测试 - 合并剩下的规则来创建一个新的规则列表,规则的右边限定为两个元素 - **小节** - **关联分析适用于发现发数据之间有趣关系的一个工作集,可以采用两种方式,一种是使用频繁项集,另外一种是使用关联规则** - **使用Apriori原理可以有效的减少数据库上进行检查的集合的数目** ### 第12章 使用FP-growth算法来高效发现频繁项集([代码][ch12]) - **FP** - **优点** - 因为 FP-growth 算法只需要对数据集遍历两次,所以速度更快。 - FP树将集合按照支持度降序排序,不同路径如果有相同前缀路径共用存储空间,使得数据得到了压缩。 - 不需要生成候选集。 - 比Apriori更快。 - **缺点** - FP-Tree第二次遍历会存储很多中间过程的值,会占用很多内存。 - 构建FP-Tree是比较昂贵的。 - **适用数据类型** - 标称型数据(离散型数据)。 **FP-Tree算法全称是FrequentPattern Tree算法,就是频繁模式树算法,他与Apriori算法一样也是用来挖掘频繁项集的,不过不同的是,FP-Tree算法是Apriori算法的优化处理,他解决了Apriori算法在过程中会产生大量的候选集的问题,而FP-Tree算法则是发现频繁模式而不产生候选集。但是频繁模式挖掘出来后,产生关联规则的步骤还是和Apriori是一样的。** - **创建FP树步骤** - 创建根节点,用NULL标记。 - 统计所有的事务数据,统计事务中各个类型项的总支持度(在下面的例子中就是各个商品ID的总个数) - 依次读取每条事务,比如T1, 1, 2, 5,因为按照总支持度计数数量降序排列,输入的数据顺序就是2, 1, 5,然后挂到根节点上。 -依次读取后面的事务,并以同样的方式加入的FP树中,顺着根节点路径添加,并更新节点上的支持度计数。 - **Fp树的数据挖掘** - 由长度为1 的频繁模式开始,构造他的条件模式基(一个“子数据库”,由FP树中与后缀模式一起出现的前缀路径集组成)。 - 构造该初始后缀模式的条件FP树,并递归的在该树上实现挖掘。模式增长通过后缀模式与条件FP树产生的频繁模式连接实现。 - **Fp树性质** - (结点链性质)对于任何频繁项ia,从FP-tree的头表对应ia项的头指针(headof node_link)开始,通过遍历ia的结点链(node_link)可以挖掘出所有包含ia的频繁模式。 - (前缀路径性质)为了计算以ia为后缀的频繁模式,仅仅需要在FP-tree中计算ia结点的前缀路径,并且前缀路径中每个结点的频繁计数等于ia结点的频繁计数。 - (分段增长)设α为事务数据库D中的一个项集,B是α的条件模式基,而β是B中的一个项集,那么在D中α∪β的支持度等于B中β的支持度。 - (模式增长)设项α为事务数据D中的一个项集,B是α的条件模式基,13而β是B中的一个项集,那么α∪β为频繁项集的充分必要条件是β也为频繁项集。 - (单路径频繁项集产生)如果FP-treeT包含一条单路径P,那么T包含的所有频繁项集的集合可以通过枚举路径P中结点的所有可能组合得到,其支持度计数为组合中结点的支持度计数的最小值。 - 给定一个事务数据库D,最小支持度阈值minσ和频繁项头表=<……>nLi,i,,i12。挖掘频繁闭项集的问题可以分解为n个子问题:第j(1≤j≤n)个子问题是找到所有包含ijn+1?但不包含i(n1jkn)k+?<≤的频繁闭项集。 可以看出,后挖掘到的频繁闭项集不可能包含先前找到的频繁闭项集,但是它可能被已有的一个频繁闭项集所包含,因此在挖掘过程中要对新挖掘的候选频繁闭项集进行检验。如果刚得到的候选频繁闭项集X不是已有的一个频繁闭项集的子集或者两者的支持度不同,那么就说X通过了FCI超集检测,是一个频繁闭项集。 - 如果X是一个频繁闭项集,那么在X的条件模式基中不存在任何一个项i出现在每一个事务中。 - 如果Y是一个最大项集合(Y满足:出现在X的条件模式基的每一个事务中,但Y的直接超集不满足这一性质),并且X∪Y通过了FCI超集检测,那么X∪Y是一个频繁闭项集。 - 单路径候选频繁闭项集:设i是X的条件模式基中的一个频繁项目,如果X的条件模式树中只有一个结点N标记为i,并且N的所有祖先结点只有一个子女,N若满足下列三个条件之一: - N没有子女。 - N有两个以上的子女。 - N有一个子女,它的支持度计数小于N的。 **那么单路径候选频繁闭项集就是X∪Z,Z包含N和N的祖先(除根结点)。如果条件模式X的条件FP-tree存在单路径,在单路径中提取候选频繁闭项集的个数为单路径中具有不等的频度个数。** - 对单路径候选频繁闭项集Y,如果Y通过了FCI超集检测,则Y是一个频繁闭项集。 - X和Y是两个频繁项集且具有相同的支持度。如果X?Y且Y是闭项集,那么不存在只包含X不包含Y?X的频繁闭项集。 - **小节** **FP算法是一种用于发现数据集中频繁模式有效的办法** **FP树构建完成之后,可以通过查找元素项的条件基于及构建条件FP树来发现频繁项集** **该过程不断以更多元素作为条件重复执行,直到FP树中只包含了一个元素为止** ## 第四部分 其他工具 ### 第13章 利用PCA来简化数据([代码][ch13]) - **降维技术** **降维的意思是能够用一组个数为d的向量zi来代表个数为D的向量xi所包含的有用信息,其中d