机器学习实战
机器学习实战
ccb机器学习实战
参考书目:
《机器学习实战:基于Scikit-Learn和TensorFlow》
《机器学习实战》
先导知识:
监督学习中,一般使用两种类型的目标变量,标称型和数值型。
标称型目标变量的结果只在有限目标集中取值,如真与假、动物分类集合{ 爬行类、鱼类、哺乳类、两栖类、植物、真菌};数值型目标变量则可以从无限的数值集合中取值,如0.100、42.001、1000.743 等。标称型目标变量主要用来分类,数值型目标变量主要用于回归分析。
机器学习的主要任务:分类和回归。
分类是将实例数据划分到合适的分类中,回归主要用于预测数值型数据。分类和回归均属于监督学习,即这类算法必须知道样本的类别,即目标变量的分类信息。另外,无监督学习则指训练数据没有类别信息,也不会给定目标值。无监督学习可以进行聚类、密度估计(寻找描述数据统计值),也可以减少数据特征的维度,以便使用二维或三维图形来更直观地展示数据信息。
如何选择算法:
(1)首先考虑使用算法的目的。
如果是想要知道数据的目标变量的值,可以选择监督学习算法。如果目标变量是离散的,就选择分类器算法;如果目标变量是连续的,就选择回归算法。
如果不想预测目标变量的值,可以选择无监督学习算法。如果是要将数据划分为离散的组,就选择聚类算法;如果需要估计数据与每个分组的相似程度,则需要使用密度估计算法。
(2)其次需要考虑数据问题。
特征值是离散型变量还是连续型,特征值中是否存在缺失的值,何种原因造成的缺失,数据中是否存在异常值,某个特征发生的频率如何等等。
开发机器学习应用程序的步骤:
(1)收集数据;
(2)准备输入数据;
(3)分析输入数据:查看数据中是否存在空值、异常值等,确保没有垃圾数据。
(4)训练算法;
(5)测试算法;
(6)使用算法。
第一章 线性模型
1. 线性回归(回归)
线性模型就是对输入特征加权求和,再加上一个我们称为偏置项(也称为截距项)的常数,以此进行预测。
由于线性回归模型的梯度下降对特征缩放敏感,所以需要保证所有特征值的大小比例都差不多(比如使用Scikit-Learn的StandardScaler类),否则收敛的时间会长很多。
1 | from sklearn.linear_model import LinearRegression |
其实大多数情况下不会使用纯线性回归,容易过拟合。通常会加上正则化(后面会讲到)。
计算复杂度:
特征数量比较大(例如100000)时,线性回归的计算将极其缓慢。但是另一方面,对于训练集中的实例数量来说,需要计算的方程是线性的,所以能够有效地处理大量的训练集,只要内存足够。在预测方面,线性回归模型一经训练(不论是标准方程还是梯度下降等其他算法),预测就非常快速:因为计算复杂度相对于想要预测的实例数量和特征数量来说,都是线性的。
2. 梯度下降
标准方程:
求线性模型的最优参数可以通过标准方程直接计算得到,但是涉及计算样本特征矩阵的内积,计算复杂度较高。但是优点是不需要特征缩放,不需要选择学习率以及进行迭代。
梯度下降:
梯度下降是一种非常通用的优化算法,能够为大范围的问题找到最优解。梯度下降的中心思想就是迭代地调整参数从而使成本函数最小化。
线性回归模型的成本函数恰好是个凸函数,所以在梯度下降时不会陷入局部最优。
应用梯度下降时,需要保证所有特征值的大小比例都差不多(比如使用Scikit-Learn的StandardScaler类),否则收敛的时间会长很多。
批量梯度下降(BGD):
基于整个训练数据集对所有需要优化的参数进行同步优化。因此,面对非常庞大的训练集时,算法会变得极慢(不过我们即将看到快得多的梯度下降算法)。但是,梯度下降算法随特征数量扩展的表现比较好:如果要训练的线性模型拥有几十万个特征,使用梯度下降比标准方程要快得多。
学习率控制了梯度下降的快慢,学习率太低,算法消耗时间太久,学习率太高,难以稳定到最优参数。要找到合适的学习率,可以使用网格搜索。
另外,参数优化的迭代次数也要适中,太低可能还未达到最优,太高浪费时间。一个简单的办法是,在开始时设置一个非常大的迭代次数,但是当梯度向量的值变得很微小时中断算法——也就是当它的范数变得低于(称为容差)时,因为这时梯度下降已经(几乎)到达了最小值。
随机梯度下降(SGD):
批量梯度下降的主要问题是它要用整个训练集来计算每一步的梯度,所以训练集很大时,算法会特别慢。与之相反的极端是随机梯度下降,每一步在训练集中随机选择一个实例,并且仅基于该单个实例来计算梯度。这让算法变得快多了,也可以被用来训练海量的数据集。
另一方面,由于算法的随机性质,它比批量梯度下降要不规则得多。成本函数将不再是缓缓降低直到抵达最小值,而是不断上上下下,但是从整体来看,还是在慢慢下降。但是即使它到达了最小值,依旧还会持续反弹,永远不会停止。所以算法停下来的参数值肯定是足够好的,但不是最优的。
随机梯度下降其实可以帮助算法跳出局部最小值,所以相比批量梯度下降,它对找到全局最小值更有优势。因此,随机性的好处在于可以逃离局部最优,但缺点是永远定位不出最小值。要解决这个困境,有一个办法是逐步降低学习率(模拟退火)。
1 | # 随机梯度下降,n_iter为迭代次数,penalty为惩罚项(正则化),eta0为迭代次数 |
小批量梯度下降:
每一步的梯度计算,基于一小部分随机的实例集也就是小批量。相比随机梯度下降,小批量梯度下降的主要优势在于可以从矩阵运算的硬件优化中获得显著的性能提升,特别是需要用到图形处理器时。
这个算法在参数空间层面的前进过程也不像SGD那样不稳定,特别是批量较大时。所以小批量梯度下降最终会比SGD更接近最小值一些。但是另一方面,它可能更难从局部最小值中逃脱
3. 多项式回归
当数据集并非线性时,可以将每个特征的幂次方添加为一个新特征,在拓展过的特征集上训练线性模型。这种方法被称为多项式回归。
PolynomialFeatures会在给定的多项式阶数下,添加所有特征组合。例如,有两个特征a和b,阶数degree=3,PolynomialFeatures不只会添加特征a2、a3、b2和b3,还会添加组合ab、a2b以及ab2。
所以要小心特征组合的数量爆炸。
1 | # 多项式回归,增加原特征的平方作为新特征 |
或者使用管道技术一次完成:、
1 | polynomial_regression = Pipeline([("poly_features", PolynomialFeatures(degree=2, include_bias=False)), ("sgd_reg", LinearRegression())]) |
4. 学习曲线
模型训练时会出现欠拟合和过拟合的问题。
如果无论怎么增大数据集,训练集和测试集的误差接近且较高,那么模型可能欠拟合。这时增大数据集是无效的,需要使用更复杂的模型和寻找更好的特征。
如果训练集和测试集的误差有一定差距,且在训练集上模型的表现好很多,那么说明模型过拟合了。这时需要增加训练数据,直到测试误差接近训练误差。或者对模型进行正则化。
5. 正则线性模型
减少过度拟合的一个好办法就是对模型正则化(即约束它):它拥有的自由度越低,就越不容易过度拟合数据。
比如对于多项式模型来说,正则化可以是降低多项式的阶数。对于线性模型,正则化通常通过约束模型的权重来实现。
岭回归(Ridge Regression):
在成本函数中添加一个正则项,使得学习中的算法不仅需要拟合数据,同时还要让模型权重保持最小。
在执行岭回归之前,必须对数据进行缩放(例如使用StandardScaler),因为它对输入特征的大小非常敏感。大多数正则化模型都是如此。
超参数α控制的是对模型进行正则化的程度。如果α=0,则岭回归就是线性模型。如果α非常大,那么所有的权重都将非常接近于零,结果是一条穿过数据平均值的水平线。
注意,正则项只能在训练的时候添加到成本函数中,一旦训练完成,你需要使用未经正则化的性能指标来评估模型性能。
1 | # 使用标准方程求解的岭回归 |
1 | # 使用梯度下降的岭回归,正则项为l2表示岭回归 |
超参数penalty设置的是使用正则项的类型。设为”l2”表示希望SGD在成本函数中添加一个正则项,等于权重向量的l2范数的平方的一半,即岭回归。
套索回归(Lasso Regression):
与岭回归一样,它也是向成本函数增加一个正则项,但是它增加的是权重向量的l1范数,而不是l2范数的平方的一半。
Lasso回归的一个重要特点是它倾向于完全消除掉最不重要特征的权重(也就是将它们设置为零)。也就是说,Lasso回归会自动执行特征选择并输出一个稀疏模型(即只有很少的特征有非零权重)。
1 | # 使用Lasso回归 |
弹性网络(Elastic Net):
弹性网络是岭回归与Lasso回归之间的中间地带。其正则项就是岭回归和Lasso回归的正则项的混合,混合比例通过r来控制。当r=0时,弹性网络即等同于岭回归,而当r=1时,即相当于Lasso回归。
1 | # 使用弹性网络 |
如何选择正则化模型:
模型正则化比不正则化可取。大多数情况下,应该避免使用纯线性回归。
岭回归是个不错的默认选择,但是如果你觉得实际用到的特征只有少数几个,那就应该更倾向于Lasso回归或是弹性网络,因为它们会将无用特征的权重降为零。
一般而言,弹性网络优于Lasso回归,因为当特征数量超过训练实例数量,又或者是几个特征强相关时,Lasso回归的表现可能非常不稳定。
6. 逻辑回归(分类)
将数据正则化之后,比如使用StandardScaler类,使用LogisticRegression类进行模型建立。逻辑回归被广泛用于估算一个实例属于某个特定类别的概率。
1 | from sklearn.linear_model import LogisticRegression |
如果你要求它预测出类别(使用predict()方法而不是predict_proba()方法),它将返回一个可能性最大的类别。
与其他线性模型一样,逻辑回归模型可以用l1或l2惩罚函数来正则化。Scikit-Learn默认添加的是l2函数。
控制Scikit-Learn的LogisticRegression模型正则化程度的超参数不是alpha(其他线性模型使用alpha),而是它的逆反:C,C的值越高,模型正则化程度越高。
Softmax回归:
逻辑回归模型经过推广,可以直接支持多个类别,而不需要训练并组合多个二元分类器(如第3章所述)。这就是Softmax回归。
原理很简单:对于一个给定的实例x,Softmax回归模型首先计算出每个类别k的分数sk(x),然后对这些分数应用softmax函数(也叫归一化指数),估算出每个类别的概率。跟逻辑回归分类器一样,Softmax回归分类器将估算概率值最高的类别作为预测类别(也就是分数最高的类别)。
Softmax回归分类器一次只会预测一个类别(也就是说,它是多类别,但是不是多输出),所以它应该仅适用于互斥的类别之上。
Softmax回归的训练目标是得到一个能对目标类别做出高概率估算的模型(也就是其他类别的概率相应要很低),其成本函数(交叉熵)如下:
当只有两个类别(K=2)时,该成本函数等价于逻辑回归的成本函数(log损失函数)。
1 | softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10) |
第二章 KNN算法
优点:精度高,对异常值不敏感,无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
适用范围:数值型和标称型。
对未知类别属性的数据集中的每个点依次执行以下操作:
(1) 计算已知类别数据集中的点与当前点之间的距离(欧氏距离);
(2) 按照距离递增次序排序;
(3) 选取与当前点距离最小的k个点;
(4) 确定前k个点所在类别的出现频率;
(5) 返回前k个点出现频率最高的类别作为当前点的预测分类。
1 | from sklearn.neighbors import KNeighborsClassifier |
当然,KNN也可以用来处理回归任务。返回邻近的K个样本点的标签值的平均数作为预测值。
1 | # 处理回归任务 |
第三章 SVM算法
能够执行线性或非线性分类、回归,甚至是异常值检测任务。它是机器学习领域最受欢迎的模型之一,特别适用于中小型复杂数据集的分类。
优点:
- 用于二元和多元分类器、回归和新奇性检测
- 良好的预测生成器,提供了鲁棒的过拟合、噪声数据和异常点处理
- 当变量比样本还多是依旧有效
- 快速,即使样本量大于1万
- 自动检测数据的非线性,不用做变量变换
缺点:
- 应用在二元分类表现最好,其他预测问题表现不是太好
- 变量比样例多很多的时候,有效性降低,需要使用其他方案,例如SGD方案
- 只提供预测结果,如果想要获取预测概率,需要额外方法去获取
- 如果想要最优结果,需要调参。
使用SVM预测模型的通用步骤:
- 选择使用的SVM类
- 用数据训练模型
- 检查验证误差并作为基准线
- 为SVM参数尝试不同的值
- 检查验证误差是否改进
- 再次使用最优参数的数据来训练模型
1. 线性SVM分类
生成决策边界(实线所示),不仅分离类别,并且尽可能远离最近的训练实例(大间隔分类)。决策边界由最接近边界的训练实例确定(支持),这些实例被称为支持向量(下图中已圈出)。
可以将SVM分类器视为在类别之间拟合可能的最宽的”街道“(平行的虚线所示)。
SVM对特征缩放非常敏感,在垂直刻度和水平刻度上生成的决策边界可能存在很大的差异。在左图中,垂直刻度(090)比水平刻度(06)大得多,因此可能的决策边界接近于水平。在特征缩放(例如使用Scikit-Learn的StandardScaler)后,决策边界看起来好很多(见右图)。
软间隔分类:
如果严格地让所有实例都不在”街道“上,并且位于正确的一边,这就是硬间隔分类。硬间隔分类有2个问题:一个是它只在数据线性可分离时才有效;一个是对异常值特别敏感(会影响泛化能力)。
为了避免以上问题,灵活地使用模型,我们尽可能在保持街道宽阔和限制间隔违例(即位于街道之上,甚至在错误的一边的实例)之间找到良好的平衡,这就是软间隔分类。在Scikit-Learn的SVM类中,可以通过超参数C来控制这个平衡:C值越小,则街道越宽,但是间隔违例也会越多。
如果你的SVM模型过度拟合,可以试试通过降低C来进行正则化。
SMO算法:
在求解SVM的决策边界(求解参数)时,会遇到规模正比于训练样本数量的问题,为了避开这个障碍,使用SMO算法来求解其中的参数。
SMO的思想:
每次选择2个变量,然后固定其他变量(参数),然后优化选择的这2个变量,因为每次只优化2个变量,所以非常高效。
使用:
LinearSVC类适用于样本数量较多的二元和多元分类(大于10000),它会对偏置项进行正则化,所以你需要先减去平均值,使训练集集中(归一化)。如果使用StandardScaler会自动进行这一步。此外,请确保超参数loss设置为”hinge”,因为它不是默认值。最后,为了获得更好的性能,还应该将超参数dual设置为False,除非特征数量比训练实例还多。可以使用管道技术将归一化和实例化算法统一起来。
1 | from sklearn.svm import LinearSVC |
SVC类可以使用核函数(后面会讲到),适用于样本数量较少的二元和多元分类(少于10000)。
1 | from sklearn.svm import SVC |
SGDClassifier类它不会像LinearSVC类那样快速收敛,但是对于内存处理不了的大型数据集(核外训练)或是在线分类任务,它非常有效。
1 | from sklearn.linear_model import SGDClassifier |
2. 非线性SVM分类
有些情况下,数据集无法直接做到线性可分,解决方法之一就是添加更多的特征,将原始数据映射到更高维的空间,使其变得线性可分。
核函数:
添加特征会使得在高维空间计算样本特征内积变得困难,为了避开这个障碍,可以设想一个函数,使样本在高维特征空间的内积等于它们在原始样本空间中通过该函数计算的结果。使用该函数的就可以替代在高维甚至无穷维特征空间中的内积。这个函数就叫做”核函数“。
线性核:
1 | svm_clf = SVC(kernel="linear", C=1) # SVC模型,使用线性核函数 |
多项式核:
为了将数据集映射到高维特征空间,可以使用PolynomialFeatures转换器直接添加多项式特征。但问题是,如果多项式太低阶,处理不了非常复杂的数据集,而高阶则会创造出大量的特征,导致模型变得太慢。
1 | polynomial_svm_clf = Pipeline([("poly_features", PolynomialFeatures(degree=3)), ("scaler", StandardScaler()), ("svm_clf", LinearSVC(C=10, loss="hinge", random_state=42))]) |
为了解决这个问题,出现了多项式核函数。下面这段代码使用了一个3阶多项式内核训练SVM分类器。超参数coef0控制的是模型受高阶多项式还是低阶多项式影响的程度。
1 | poly_kernel_svm_clf = Pipeline([("scaler", StandardScaler()), ("svm_clf", SVC(kernel="poly", degree=3, coef0=1, C=5))]) |
高斯核:
1 | # 使用RBF高斯核函数 |
另外,还有拉普拉斯核、Sigmoid核。
如何选择核函数:
有一个经验法则是,永远先从线性核函数开始尝试(要记住,LinearSVC比SVC(kernel=”linear”)快得多),特别是训练集非常大或特征非常多的时候。如果训练集不太大,你可以试试高斯RBF核,大多数情况下它都非常好用。如果你还有多余的时间和计算能力,你可以使用交叉验证和网格搜索来尝试一些其他的核函数,特别是那些专门针对你的数据集数据结构的核函数。
3. SVM回归(SVR)
SVM算法非常全面:它不仅支持线性和非线性分类,而且还支持线性和非线性回归。SVM回归要做的是让尽可能多的实例位于街道上,同时限制间隔违例(也就是不在街道上的实例)。
街道的宽度由超参数ε控制。在间隔内添加更多的实例不会影响模型的预测,所以这个模型被
称为ε不敏感。
1 | # SVM回归 |
要解决非线性回归任务,可以使用核化的SVM模型。
1 | # 使用核化的SVM模型进行回归 |
第四章 决策树DT
决策树是一种由结点和有向边构成的树形结构,结点类型分为内部结点和叶结点,每个内部结点代表对象的一个特征,叶结点则代表对象的类别。决策树中,每一个深度就是一次根据某一特征做出的判断。决策树的特质之一就是它们需要的数据准备工作非常少。特别是,完全不需要进行特征缩放或集中。
鸢尾花决策树:
节点的samples属性统计它应用的训练实例数量(满足该节点属性的实例数量),value属性说明了该节点上每个类别的训练实例数量,gini属性衡量其不纯度(impurity,基尼不纯度):如果应用的所有训练实例都属于同一个类别,那么节点就是“纯”的(gini=0)。
$P_{i,k}$是第$i$个节点上,类别为$k$的训练实例占比。
Scikit-Learn使用的是CART算法(Classification And Regression Tree),该算法仅生成二叉树,可用于分类和回归,使用:基尼不纯度来划分属性。但是,其他算法,比如ID3生成的决策树,其节点可以拥有两个以上的子节点,使用信息增益来划分属性。
一、CART算法
1. CART算法(分类)
过程如下:
(1)使用单个特征k和阈值tk(例如,花瓣长度≤2.45厘米)将训练集分成两个子集。k和tk就是使得成本函数$J$最小化(或者信息增益最大化)的$(k,t_k)$,成本函数衡量划分后的子集的不纯度。
(2)一旦成功将训练集一分为二,它将使用相同的逻辑,继续分裂子集,然后是子集的子集,依次循环递进。
(3)抵达最大深度(由超参数max_depth控制),或是再也找不到能够降低不纯度的分裂时,停止。
明显,决策树的思想是一种贪心选择,它并不会检视一次分裂的不纯度是否为可能的最低值,这样通常可以产生一个相当不错的解,但是不能保证是最优解。而寻找最优树是一个NP完全问题,即使训练集很小时间复杂度也很高,很难解决,所以我们必须接受这个”相当不错“的解。
计算复杂度:
决策树总体预测复杂度是O(log2(m)),m为实例数量,可以看出复杂度与特征数量无关,所以即便是处理大型数据集,预测也很快。
但是,训练时在每一个节点,算法都需要在所有样本上比较所有特征(如果设置了划分时考虑的最大特征数max_features会少一些)。这导致训练的复杂度为O(n×m log(m)),。对于小型训练集(几千个实例以内),Scikit-Learn可以通过对数据预处理(设置presort=True表示对样本进行预排序)来加快训练,但是对于较大训练集而言,可能会减慢训练的速度。
过拟合与正则化超参数:
决策树在训练时不会确定参数的数量(树的深度不确定),也叫非参数模型,这会导致模型结构自由而紧密地贴近数据,很可能过拟合。而比如线性回归有预先设定好一部分参数,所以其自由度受限,降低过拟合的风险(但是相应的也增加了拟合不足的风险)。
为了避免过拟合,需要在训练中降低决策树的自由度,即正则化。正则化超参数的选择取决于使用的模型,但是通常至少可以限制决策树的深度。在Scikit-Learn中,这由超参数max_depth控制(默认值为None,意味着无限制)。减小max_depth可使模型正则化,从而降低过度拟合的风险。另外,DecisionTreeClassifier类还有一些其他的参数也可以限制决策树的形状,比如min_samples_split(分裂前节点必须有的最小样本
数),min_samples_leaf(叶节点必须有的最小样本数量)等。
还可以先不加约束地训练模型,然后再对不必要的节点进行剪枝(删除),比如一个节点的子节点全部为叶节点,则该节点可被认为不必要,删除;比如χ2测试,是用来估算“提升纯粹是出于偶然”(被称为虚假设)的概率。如果这个概率(称之为p值)高于一个给定阈值(通常是5%,由超参数控制),那么这个节点可被认为不必要,其子节点可被删除。
2. CART算法(回归)
决策树也可以用来完成回归任务,用Scikit_Learn的DecisionTreeRegressor来构建一个回归树。
与分类决策树的主要差别在于,每个节点上不再是预测一个类别而是预测一个值。预测结果就是与最后到达的叶节点关联的110个实例的平均目标值。MSE表示在这个叶节点上得到的预测结果的均方误差。
回归任务中,CART算法的工作原理跟前面介绍的大致相同,唯一不同在于,它分裂训练集的方式不是最小化不纯度,而是最小化MSE。
同样,用于回归的决策树也会有过拟合的可能,所以需要设置min_samples_leaf。
3. 优缺点
决策树使用简单,不受特征数量的限制,但是青睐正交的决策边界(所有的分裂都与轴线垂直),这导致它们对训练集的旋转非常敏感,可能导致泛化不佳,限制这种问题的方法之一是使用PCA,让训练数据定位在一个更好的方向上。更概括地说,决策树的主要问题是它们对训练数据中的小变化非常敏感。
二、ID3算法
三、C4.5算法(J48)
使用信息增益选择特征
第五章 集成学习与随机森林
一、模型融合
1. 投票分类器
不同的算法在相同训练集上进行训练,得到多个预测模型,然后基于多个模型的预测结果投票选出最终结果。
硬投票法:
直接让各个预测模型给出预测结果(投票),然后选择大多数模型投票的类别作为最终预测结果。
软投票法:
模型估算出类别的概率(predict_proba()),将概率在所有单个分类器上(加权)平均,选出平均概率最高的类别进行预测。软投票法比硬投票的表现更优,因为它基于哪些高度自信的投票更高的权重。
2. bagging 和 pasting
对训练集随机采样,使用相同的算法在不同的训练子集上进行训练。采样时如果将样本放回,这种方法叫bagging,不放回叫pasting。(bootstrap=True表示bagging,否则表示pasting)
一旦预测器训练完成,集成就可以通过简单地聚合所有预测器的预测,来对新实例做出预测。聚合函数通常是统计法(即最多数的预测好比硬投票分类器一样)用于分类,或是平均法用于回归。最终结果是,与直接在原始训练集上训练的单个预测器相比,集成方法的单个预测器的偏差更大,但是最终结果的偏差相近,方差更低。
包外评估:
使用bagging时,有些样本可能会被多次采样,有些样本可能不会被采样。不划分单独的测试集,而直接将那些未被采样的样本作为测试集,就是包外评估。
3. stacking
第一层:将数据分为训练集和测试集,训练集再分为2个子集。首先在子集1上训练不同的模型:
第二层:分别使用前面训练好的几个模型对子集2进行预测,得到多个预测值。接着,使用这些预测值作为输入特征,创建一个新的训练集,并保留真实标签。在这个新的训练集上训练混合器,让它学习根据第一层的预测来在测试集上预测目标值。
当然,这个模型还可以增加层数,增加的层都是使用上一层的预测值作为输入特征来训练模型。
比如下面是一个三层的stacking模型:
将训练集分为3个子集。第一层使用子集1进行模型的训练,得到3个模型。第二层中,使用第一层的模型在子集2上的预测作为输入特征来训练三个新的模型。第三层中,使用第二层的模型在子集3上的预测作为输入特征来训练最终模型。最后使用最终模型在测试集上进行预测。
不幸的是,Scikit-Learn不直接支持堆叠,但是自己堆出stacking的实现并不太难。或者也可以使用开源的实现方案,例如brew(可从https://github.com/viisar/brew获得)。
二、随机森林RF
随机森林就是决策树的集成,通常采用bagging集成方法(有时也可以是pasting)。
训练子集的大小通过max_samples来设置。在sklearn中,除了先构建一个BaggingClassifier然后将结果传输到DecisionTreeClassifier,还有一种方法就是直接使用RandomForestClassifier或者RandomForestRegressor类。
随机森林在树的生长上引入了更多的随机性:分裂节点时不再是搜索最好的特征,而是在一个随机生成的特征子集里搜索最好的特征。这导致决策树具有更大的多样性,用更高的偏差换取更低的方差,总之,还是产生了一个整体性能更优的模型。
三、提升法boosting
提升法(Boosting,最初被称为假设提升)是指可以将几个弱学习器结合成一个强学习器的任意集成方法。大多数提升法的总体思路是循环训练预测器,每一次都对其前序做出一些改正。
1. AdaBoost
新预测器对其前序进行纠正的办法之一,就是更多地关注前序拟合不足的训练实例。从而使新的预测器不断地越来越专注于难缠的问题,这就是AdaBoost使用的技术。
过程如下:
(1)训练一个基础分类器(比如决策树),用它对训练集进行预测。
(2)然后对错误分类的训练实例增加其相对权重
(3)使用这个最新的权重对第二个分类器进行训练,然后再次对训练集进行预测
(4)继续对错误分类的训练实例增加其权重,如此循环
(5)当到达所需数量的预测器,或得到完美的预测器时,算法停止
(6)这样就得到若干个预测器,再使用bagging或pasting等集成方法得到最终预测结果
优缺点:
AdaBoost不再是调整单个预测器的参数使损失函数最小化,而是不断在集成中加入预测器,使模型越来越好。而且每次训练是基于加权的训练集。
这种依序学习技术有一个重要的缺陷就是无法并行(哪怕只是一部分),因为每个预测器只能在前一个预测器训练完成并评估之后才能开始训练,在这一点上AdaBoost的表现不及bagging和pasting方法。
权重:
AdaBoost中,每个预测器有一个权重,通过其加权误差率、学习率计算而来,预测器的准确率越高,其权重就越高。同时,每个样本实例也有权重。最开始每个实例的权重都一样,一个预测器预测完成后,会对实例的权重进行更新,也就是提升被错误分类的实例的权重。
使用:
Scikit-Learn使用的其实是AdaBoost的一个多分类版本,叫作SAMME(http://goo.gl/Eji2vR)[4](基于多类指数损失函数的逐步添加模型)。当只有两个类别时,SAMME即等同于AdaBoost。此外,如果预测器可以估算类别概率(即具有predict_proba()方法),Scikit-Learn会使用一种SAMME的变体,称为SAMME.R(R代表 “Real”,它依赖的是类别概率而不是类别预测,通常表现更好。
2. 梯度提升
GBDT
四、XGBoost
第六章 贝叶斯分类器
贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。
一、贝叶斯公式:
原理:
X:特征向量;Y:类别
先验概率P(X):指根据以往经验和分析得到的概率。
后验概率P(Y|X):事情已经发生,要求这件事情发生的原因是由某个因素引起的可能性的大小。
类条件概率P(X|Y):在已知某类别的特征空间中,出现特征值X的概率密度。
如果需要选出某样本属于哪类,则需要根据该条样本求出它属于每个类的概率,选择最大概率的那个类作为分类结果。
由于结果的产生是比较属于各个类别的概率,所以计算的概率的分母都是P(X),可以忽略掉P(X)。同时P(Y)容易求出,那么我们关注P(X|Y)。朴素贝叶斯之所以朴素是因为它假设X的每个特征都是独立的,回归原始。故而P(X|Y)的概率就可以计算为:
故,朴素贝叶斯公式:
二、朴素贝叶斯模型:
1. 多项式模型:
多项式模型在计算先验概率P(Yk)和条件概率P(xi|Yk)时,会做一些平滑处理,具体公式为:
$$
P(Y_k) = \frac{N_{Y_k}+\alpha}{N+K\alpha}
$$
$N_{Y_k}$:类别为$Y_k$的样本数
N:总样本数
K:总的类别个数
$\alpha$:平滑值
$N_{Y_k,x_i}$:类别为$Y_k$,且特征为$x_i$的样本数
n:特征$x_i$可以选择的数量
1 | # 多项式朴素贝叶斯,alpha为平滑参数,默认为1 |
2. 高斯模型:
当特征是连续变量的时候,假设特征分布为正太分布,根据样本算出均值和方差,再求得概率。
1 | # 高斯朴素贝叶斯 |
3. 伯努利模型:
伯努利模型适用于离散特征的情况,每个特征的取值只能是1和0。
1 | # 伯努利朴素贝叶斯(每个特征的取值只能是1和0) |
算法流程:
处理数据,得到m个具有n个特征的样本,这些样本分别属于${Y_1,Y_2,Y_3}$类别。
通过数据分析可以得到每个特征的类条件概率$P(x_i|Y)$,再通过全概率公式求得$P(X)$。
$P(X)=P(X|Y_1)P(Y_1)+P(X|Y_2)P(Y_2)+P(X|Y_3)P(Y_3)$
其中$P(X|Y_i)$可根据特征独立性展开。
将求得的先验概率和类条件概率带入朴素贝叶斯公式,求得每个类别的后验概率。我们可以选择概率最大的类别为最后确定的类别.
第七章 神经网络
第八章 聚类
K-means
附录:
《机器学习实战》目录:
1~7为分类算法,8~9为回归算法,10~12为无监督算法
- ML基础
- KNN
- DT
- NB(概率分布)
- LR(算法优化,处理数据集合中的缺失值)
- SVM
- AdaBoost
- 回归、去噪、局部线性回归
- CART(回归部分)
- k-means
- Apriori
- FP-Growth
- 主成分分析、奇异值分解、MapReduce