参考资料:有监督学习、泛化能力、《机器学习》(周志华)、过拟合欠拟合、线性回归、目标函数、牛顿法、sklearn
Table of Contents
1. 机器学习的一些概念
1.1 有监督学习
1.2 无监督学习
1.3 泛化能力
1.4 过拟合欠拟合
1.5 交叉验证(cross-validation)
2. 线性回归
2.1 线性回归定义(linear regression)
2.2 原理
3. 线性回归损失函数、代价函数、目标函数
3.1 损失函数
3.2 代价函数
3.3 目标函数
4. 优化方法
4.1 梯度下降
4.2 牛顿法(Newton's method)
5、线性回归的评估指标
6、sklearn参数详解
6.1 Sklearn简介
6.2 Sklearn通用学习模式
6.3 Sklearn datasets
6.4 Sklearn Model的属性和功能
6.5 Sklearn数据预处理
有监督学习是从标签化训练数据集中推断出函数的机器学习任务(数据有标签)
根据类别未知(没有被标记)的训练样本解决模式识别中的各种问题,称之为无监督学习。(数据没有标签)
通常期望经训练样本训练的网络具有较强的泛化能力,也就是对新输入给出合理响应的能力。应当指出并非训练的次数越多越能得到正确的输入输出映射关系。网络的性能主要用它的泛化能力来衡量。
Bias(偏差):反映的是模型在样本上的输出与真实值之间的误差,即模型本身的精准度
Error(误差):反映的是整个模型的准确度
Variance(方差):反映的是模型每一次输出结果与模型输出期望之间的误差,即模型的稳定性
三者关系:模型的Error = Bias + Variance
定义:通俗一点地来说过拟合就是模型把数据学习的太彻底,以至于把噪声数据的特征也学习到了,这样就会导致在后期测试的时候不能够很好地识别数据,即不能正确的分类,模型泛化能力太差。例如下面的例子。
上面左图表示size和prize的关系,我们学习到的模型曲线如右图所示,虽然在训练的时候模型可以很好地匹配数据,但是很显然过度扭曲了曲线,不是真实的size与prize曲线。
解决方法:
1)重新清洗数据,导致过拟合的一个原因也有可能是数据不纯导致的,如果出现了过拟合就需要我们重新清洗数据。
2)增大数据的训练量,还有一个原因就是我们用于训练的数据量太小导致的,训练数据占总数据的比例过小。
3)采用正则化方法。正则化方法包括L0正则、L1正则和L2正则,而正则一般是在目标函数之后加上对于的范数。但是在机器学习中一般使用L2正则,下面看具体的原因。
L0范数是指向量中非0的元素的个数。L1范数是指向量中各个元素绝对值之和,也叫“稀疏规则算子”(Lasso regularization)。两者都可以实现稀疏性,既然L0可以实现稀疏,为什么不用L0,而要用L1呢?个人理解一是因为L0范数很难优化求解(NP难问题),二是L1范数是L0范数的最优凸近似,而且它比L0范数要容易优化求解。所以大家才把目光和万千宠爱转于L1范数。
L2范数是指向量各元素的平方和然后求平方根。可以使得W的每个元素都很小,都接近于0,但与L1范数不同,它不会让它等于0,而是接近于0。L2正则项起到使得参数w变小加剧的效果,但是为什么可以防止过拟合呢?一个通俗的理解便是:更小的参数值w意味着模型的复杂度更低,对训练数据的拟合刚刚好(奥卡姆剃刀),不会过分拟合训练数据,从而使得不会过拟合,以提高模型的泛化能力。还有就是看到有人说L2范数有助于处理 condition number不好的情况下矩阵求逆很困难的问题(具体这儿我也不是太理解)。
4)采用dropout方法。这个方法在神经网络里面很常用。dropout方法是ImageNet中提出的一种方法,通俗一点讲就是dropout方法在训练的时候让神经元以一定的概率不工作。具体看下图:
如上图所示,左边a图是没用用dropout方法的标准神经网络,右边b图是在训练过程中使用了dropout方法的神经网络,即在训练时候以一定的概率p来跳过一定的神经元。
欠拟合就是模型没有很好地捕捉到数据特征,不能够很好地拟合数据,例如下面的例子:
左图表示size与prize关系的数据,中间的图就是出现欠拟合的模型,不能够很好地拟合数据,如果在中间的图的模型后面再加一个二次项,就可以很好地拟合图中的数据了,如右面的图所示。
解决方法:
1)添加其他特征项,有时候我们模型出现欠拟合的时候是因为特征项不够导致的,可以添加其他特征项来很好地解决。例如,“组合”、“泛化”、“相关性”三类特征是特征添加的重要手段,无论在什么场景,都可以照葫芦画瓢,总会得到意想不到的效果。除上面的特征之外,“上下文特征”、“平台特征”等等,都可以作为特征添加的首选项。
2)添加多项式特征,这个在机器学习算法里面用的很普遍,例如将线性模型通过添加二次项或者三次项使模型泛化能力更强。例如上面的图片的例子。
3)减少正则化参数,正则化的目的是用来防止过拟合的,但是现在模型出现了欠拟合,则需要减少正则化参数。
交叉验证的基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set or test set)。首先用训练集对分类器进行训练,再利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标。
线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。其表达形式为,为误差服从均值为0的正态分布。
回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。
在线性回归中,数据使用线性预测函数来建模,并且未知的模型参数也是通过数据来估计。这些模型被叫做线性模型。最常用的线性回归建模是给定X值的y的条件均值是X的仿射函数。不太一般的情况,线性回归模型可以是一个中位数或一些其他的给定X的条件下y的条件分布的分位数作为X的线性函数表示。像所有形式的回归分析一样,线性回归也把焦点放在给定X值的y的条件概率分布,而不是X和y的联合概率分布(多元分析领域)。
线性回归模型经常用最小二乘逼近来拟合,但他们也可能用别的方法来拟合,比如用最小化“拟合缺陷”在一些其他规范里(比如最小绝对误差回归),或者在桥回归中最小化最小二乘损失函数的惩罚.相反,最小二乘逼近可以用来拟合那些非线性的模型.因此,尽管“最小二乘法”和“线性模型”是紧密相连的,但他们是不能划等号的。
假设线性关系满足:,
m:训练样本的个数
y:原训练样本中的y值,也就是标准答案
上角标(i):第i个样本
公式中θ和x是向量,n是样本数。
定义在单个样本上的,计算的是一个样本的误差。
我们要做的是依据我们的训练集,选取最优的θ,在我们的训练集中让h(x)尽可能接近真实的值。h(x)和真实的值之间的差距,我们定义了一个函数来描述这个差距,这个函数称为损失函数,表达式如下:
这里的这个损失函数就是著名的最小二乘损失函数
我们要选择最优的θ,使得h(x)最近进真实值。这个问题就转化为求解最优的θ,使损失函数J(θ)取最小值。
定义在整个训练集上的,是所有样本误差的平均,也就是损失函数的平均
任何能够衡量模型预测出来的值h(θ)与真实值y之间的差异的函数都可以叫做代价函数C(θ),如果有多个样本,则可以将所有代价函数的取值求均值,记做J(θ)。
在线性回归中,最常用的是均方误差(Mean squared error),具体形式为:
最终需要优化的函数。等于经验风险+结构风险(也就是Cost Function + 正则化项)
关于目标函数和代价函数的区别还有一种通俗的区别:目标函数是最大化或者最小化,而代价函数是最小化
线性回归的目标函数,一般使用均方误差:
我们需要最小化目标函数,关心 theta 取什么值的时候,目标函数取得最小值,而目标函数连续,那么 theta 一定为 目标函数的驻点,所以我们求导寻找驻点。
最终我们得到参数 theta 的解析式:
梯度下降是迭代法的一种,可以用于求解最小二乘问题(线性和非线性都可以)。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一,另一种常用的方法是最小二乘法。
在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随机梯度下降法和批量梯度下降法。
其中α表示学习率
一个优化技巧:不同的特征采用不同的学习率 Adagrad
每次迭代找到一个更好的,最后得到一个局部最优解,不一定是全局最优,但是是堪用的。
牛顿法是一种在实数域和复数域上近似求解方程的方法。方法使用函数f (x)的泰勒级数的前面几项来寻找方程f (x) = 0的根。牛顿法最大的特点就在于它的收敛速度很快。
具体步骤:
首先,选择一个接近函数 f (x)零点的 x0,计算相应的 f (x0) 和切线斜率f ' (x0)(这里f ' 表示函数 f 的导数)。然后我们计算穿过点(x0, f (x0)) 并且斜率为f '(x0)的直线和 x 轴的交点的x坐标,也就是求如下方程的解:
我们将新求得的点的 x 坐标命名为x1,通常x1会比x0更接近方程f (x) = 0的解。因此我们现在可以利用x1开始下一轮迭代。迭代公式可化简为如下所示:
已经证明,如果f ' 是连续的,并且待求的零点x是孤立的,那么在零点x周围存在一个区域,只要初始值x0位于这个邻近区域内,那么牛顿法必定收敛。 并且,如果f ' (x)不为0, 那么牛顿法将具有平方收敛的性能. 粗略的说,这意味着每迭代一次,牛顿法结果的有效数字将增加一倍。下图为一个牛顿法执行过程的例子。
由于牛顿法是基于当前位置的切线来确定下一次的位置,所以牛顿法又被很形象地称为是"切线法"。牛顿法的搜索路径(二维情况)如下图所示:
牛顿法搜索动态示例图:
从本质上去看,牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法就更快。如果更通俗地说的话,比如你想找一条最短的路径走到一个盆地的最底部,梯度下降法每次只从你当前所处位置选一个坡度最大的方向走一步,牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑你走了一步之后,坡度是否会变得更大。所以,可以说牛顿法比梯度下降法看得更远一点,能更快地走到最底部。(牛顿法目光更加长远,所以少走弯路;相对而言,梯度下降法只考虑了局部的最优,没有全局思想。)
根据wiki上的解释,从几何上说,牛顿法就是用一个二次曲面去拟合你当前所处位置的局部曲面,而梯度下降法是用一个平面去拟合当前的局部曲面,通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的下降路径会更符合真实的最优下降路径。
牛顿法的优缺点总结:
4.3 拟牛顿法
拟牛顿法是求解非线性优化问题最有效的方法之一,于20世纪50年代由美国Argonne国家实验室的物理学家W.C.Davidon所提出来。Davidon设计的这种算法在当时看来是非线性优化领域最具创造性的发明之一。不久R. Fletcher和M. J. D. Powell证实了这种新的算法远比其他方法快速和可靠,使得非线性优化这门学科在一夜之间突飞猛进。
拟牛顿法的本质思想是改善牛顿法每次需要求解复杂的Hessian矩阵的逆矩阵的缺陷,它使用正定矩阵来近似Hessian矩阵的逆,从而简化了运算的复杂度。拟牛顿法和最速下降法一样只要求每一步迭代时知道目标函数的梯度。通过测量梯度的变化,构造一个目标函数的模型使之足以产生超线性收敛性。这类方法大大优于最速下降法,尤其对于困难的问题。另外,因为拟牛顿法不需要二阶导数的信息,所以有时比牛顿法更为有效。如今,优化软件中包含了大量的拟牛顿算法用来解决无约束,约束,和大规模的优化问题。
具体步骤:
拟牛顿法的基本思想如下。首先构造目标函数在当前迭代的二次模型:
这里是一个对称正定矩阵,于是我们取这个二次模型的最优解作为搜索方向,并且得到新的迭代点:
其中我们要求步长 满足Wolfe条件。这样的迭代与牛顿法类似,区别就在于用近似的Hesse矩阵 代替真实的Hesse矩阵。所以拟牛顿法最关键的地方就是每一步迭代中矩阵Bk 的更新。现在假设得到一个新的迭代,并得到一个新的二次模型:
我们尽可能地利用上一步的信息来选取。具体地,我们要求
从而得到
这个公式被称为割线方程。常用的拟牛顿法有DFP算法和BFGS算法。
该统计参数计算的是拟合数据和原始数据对应点的误差的平方和,计算公式如下
SSE越接近于0,说明模型选择和拟合更好,数据预测也越成功。接下来的MSE和RMSE因为和SSE是同出一宗,所以效果一样
该统计参数是预测数据和原始数据对应点误差的平方和的均值,也就是SSE/n,和SSE没有太大的区别,计算公式如下
该统计参数,也叫回归系统的拟合标准差,是MSE的平方根,就算公式如下
在这之前,我们所有的误差参数都是基于预测值(y_hat)和原始值(y)之间的误差(即点对点)。从下面开始是所有的误差都是相对原始数据平均值(y_ba)而展开的(即点对全)!!!
平均绝对误差:MAE(Mean Absolute Error)
在讲确定系数之前,我们需要介绍另外两个参数SSR和SST,因为确定系数就是由它们两个决定的
(1)SSR:Sumof squares of the regression,即预测数据与原始数据均值之差的平方和,公式如下
(2)SST:Totalsum of squares,即原始数据和均值之差的平方和,公式如下
由此可见,,而确定系数定义的是SSR和SST的比值:
确定系数是通过数据的变化来表征一个拟合的好坏。
由上面的表达式可以知道“确定系数”的正常取值范围为[0 1]
越接近1,表明方程的变量对y的解释能力越强,这个模型对数据拟合的也较好,越大,说明预测出来的数据可以通过模型的解释性就越强。
平均绝对误差:MAE(Mean Absolute Error)
其中,n是样本数量,p是特征数量
Adjusted R-Square 抵消样本数量对 R-Square的影响,做到了真正的 0~1,越大越好。
Scikit-learn(sklearn)是机器学习中常用的第三方模块,对常用的机器学习方法进行了封装,包括回归(Regression)、降维(Dimensionality Reduction)、分类(Classfication)、聚类(Clustering)等方法。当我们面临机器学习问题时,便可根据下图来选择相应的方法。Sklearn具有以下特点:
Sklearn中包含众多机器学习方法,但各种学习方法大致相同,我们在这里介绍Sklearn通用学习模式。首先引入需要训练的数据,Sklearn自带部分数据集,也可以通过相应方法进行构造
然后选择相应机器学习方法进行训练,训练过程中可以通过一些技巧调整参数,使得学习准确率更高。模型训练完成之后便可预测新数据,然后我们还可以通过MatPlotLib
等方法来直观的展示数据。另外还可以将我们已训练好的Model进行保存,方便移动到其他平台,不必重新训练。
from sklearn import datasets#引入数据集,sklearn包含众多数据集
from sklearn.model_selection import train_test_split#将数据分为测试集和训练集
from sklearn.neighbors import KNeighborsClassifier#利用邻近点方式训练数据
###引入数据###
iris=datasets.load_iris()#引入iris鸢尾花数据,iris数据包含4个特征变量
iris_X=iris.data#特征变量
iris_y=iris.target#目标值
#利用train_test_split进行将训练集和测试集进行分开,test_size占30%
X_train,X_test,y_train,y_test=train_test_split(iris_X,iris_y,test_size=0.3)
print(y_train)#我们看到训练数据的特征值分为3类
'''
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
'''
###训练数据###
knn=KNeighborsClassifier()#引入训练方法
knn.fit(X_train,y_train)#进行填充测试数据进行训练
###预测数据###
print(knn.predict(X_test))#预测特征值
'''
[1 1 1 0 2 2 1 1 1 0 0 0 2 2 0 1 2 2 0 1 0 0 0 0 0 0 2 1 0 0 0 1 0 2 0 2 0
1 2 1 0 0 1 0 2]
'''
print(y_test)#真实特征值
'''
[1 1 1 0 1 2 1 1 1 0 0 0 2 2 0 1 2 2 0 1 0 0 0 0 0 0 2 1 0 0 0 1 0 2 0 2 0
1 2 1 0 0 1 0 2]
'''
Sklearn提供一些标准数据,我们不必再从其他网站寻找数据进行训练。例如我们上面用来训练的load_iris
数据,可以很方便的返回数据特征变量和目标值。除了引入数据之外,我们还可以通过load_sample_images()
来引入图片。
除了sklearn提供的一些数据之外,还可以自己来构造一些数据帮助我们学习。
from sklearn import datasets#引入数据集
#构造的各种参数可以根据自己需要调整
X,y=datasets.make_regression(n_samples=100,n_features=1,n_targets=1,noise=1)
###绘制构造的数据###
import matplotlib.pyplot as plt
plt.figure()
plt.scatter(X,y)
plt.show()
数据训练完成之后得到模型,我们可以根据不同模型得到相应的属性和功能,并将其输出得到直观结果。假如通过线性回归训练之后得到线性函数y=0.3x+1
,我们可通过_coef
得到模型的系数为0.3,通过_intercept
得到模型的截距为1。
from sklearn import datasets
from sklearn.linear_model import LinearRegression#引入线性回归模型
###引入数据###
load_data=datasets.load_boston()
data_X=load_data.data
data_y=load_data.target
print(data_X.shape)
#(506, 13)data_X共13个特征变量
###训练数据###
model=LinearRegression()
model.fit(data_X,data_y)
model.predict(data_X[:4,:])#预测前4个数据
###属性和功能###
print(model.coef_)
'''
[ -1.07170557e-01 4.63952195e-02 2.08602395e-02 2.68856140e+00
-1.77957587e+01 3.80475246e+00 7.51061703e-04 -1.47575880e+00
3.05655038e-01 -1.23293463e-02 -9.53463555e-01 9.39251272e-03
-5.25466633e-01]
'''
print(model.intercept_)
#36.4911032804
print(model.get_params())#得到模型的参数
#{'copy_X': True, 'normalize': False, 'n_jobs': 1, 'fit_intercept': True}
print(model.score(data_X,data_y))#对训练情况进行打分
#0.740607742865
数据集的标准化对于大部分机器学习算法来说都是一种常规要求,如果单个特征没有或多或少地接近于标准正态分布,那么它可能并不能在项目中表现出很好的性能。在实际情况中,我们经常忽略特征的分布形状,直接去均值来对某个特征进行中心化,再通过除以非常量特征(non-constant features)的标准差进行缩放。
例如, 许多学习算法中目标函数的基础都是假设所有的特征都是零均值并且具有同一阶数上的方差(比如径向基函数、支持向量机以及L1L2正则化项等)。如果某个特征的方差比其他特征大几个数量级,那么它就会在学习算法中占据主导位置,导致学习器并不能像我们说期望的那样,从其他特征中学习。例如我们可以通过Scale将数据缩放,达到标准化的目的。
from sklearn import preprocessing
import numpy as np
a=np.array([[10,2.7,3.6],
[-100,5,-2],
[120,20,40]],dtype=np.float64)
print(a)
print(preprocessing.scale(a))#将值的相差度减小
'''
[[ 10. 2.7 3.6]
[-100. 5. -2. ]
[ 120. 20. 40
[[ 0. -0.85170713 -0.55138018]
[-1.22474487 -0.55187146 -0.852133 ]
[ 1.22474487 1.40357859 1.40351318]]
'''