机器学习几个重要概念
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习几个重要概念相关的知识,希望对你有一定的参考价值。
机器学习几个重要概念统计学习的算法可以分为以下几个类别:监督学习、非监督学习、半监督学习以及强化学习。监督学习的输入数据都有对应的
参考技术A 机器学习几个重要概念统计学习的算法可以分为以下几个类别:监督学习、非监督学习、半监督学习以及强化学习。
监督学习的输入数据都有对应的类标签或是一个输出值,其任务是学习一个模型,使模型能够对任意给定的输入,对其相应的输出做出一个好的预测。
非监督学习就是没有对应的类标签或是输出值。学习中并没有任何标准来告诉你,某个概念是否正确,需要学习器自身形成和评价概念。就是自动地从数据中挖掘出结构信息或是抽取出一些规则。近年来,非监督学习被认为是解决一些重要问题的突破口所在。因为科学的产生就是人类中无监督学习的最佳案例。
半监督学习就是介于监督学习和非监督学习之间。这在最近的研究领域也是被大家所热烈探讨的,因为对于现实数据来说,有标签的数据总是少量的,往往都需要人工来进行标注。而无标签数据是能够大量获得的。
增强学习强调如何基于环境而行动,以取得最大化的预期利益。其灵感来源于心理学中的行为主义理论,即有机体如何在环境给予的奖励或惩罚的刺激下,逐步形成对刺激的预期,产生能获得最大利益的习惯性行为。强化学习和标准的监督式学习之间的区别在于,它并不需要出现正确的输入/输出对,也不需要精确校正次优化的行为。(以上内容摘自维基百科)这在机器人、无人机领域中应用的还是非常广泛的。
在线学习与离线学习
对于机器学习算法的分类,站在不同的角度就能有不同的分类方法。在具体的应用中还有一种常用的分类方法是:在线学习与离线学习。
在线学习,是在获取到新的数据后就能够输入到模型中进行学习。这需要学习算法能够在处于任何状态时都能进行参数的更新。而且需要算法对噪声数据有很好的鲁棒性。
离线学习就正好与在线学习相反,当数据有更新时,需要将其与原来的数据一起对模型的参数进行重新地训练。这时,整个训练的过程能够被很好的控制,因为所有的数据都是已知的,能够对数据进行细致的预处理过程。
生成模型与判别模型
这种分类方式是针对于监督学习来进行分类的。这个在我腾讯面试的时候还被问到过这个问题。
生成模型
生成方法由数据学习联合概率分布P(X,Y)
,然后求出条件概率分布P(Y|X)
作为预测的模型,即生成模型:
模型表示了给定输入X产生输出Y的生成关系。典型的生成模型有:朴素贝叶斯方法和隐马尔可夫模型。
生成模型能够还原出联合概率分布P(X,Y)
;生成模型的收敛速度快,当样本容量增加的时候,学到的模型可以更快地收敛于真实模型;当存在隐变量时,仍可以使用生成学习方法,此时判别方法就不能用。
判别模型
判别方法由数据直接学习决策函数f(x)
或者条件概率分布P(Y|X)
作为预测的模型,即判别模型。典型的判别模型包括:k近邻法、感知机、决策树、logistic回归模型、最大熵模型、支持向量机、提升方法和条件随机场。
判别模型直接面对预测,往往学习的准确率越高。可以对数据进行各种程度上的抽象、定义特征并使用特征,因此可以简化学习问题。
算法的归纳偏好
机器学习算法在学习过程中对某种类型假设的偏好称为『归纳偏好』。这个『假设』包含了一个算法方方面面的内容。
任何一个有效的机器学习算法必有其归纳的偏好,否则它将被假设空间中看似在训练集上『等效』的假设所迷惑,而无法产生确定的学习结果。例如在分类问题中,如果随机抽选训练集上等效的假设(可以认为所有的正反例并没有区别),那么它的分类结果其实是不确定的,这要根据它所选取的样本来决定,这样的学习显然是没有意义的。
归纳偏好对应了学习算法本身所做出的关于『什么样的模型更好』的假设。在具体的问题中,这个假设是否成立,即算法的归纳偏好是否与问题本身匹配,大多数时候直接决定了算法能否取得好的性能。
『奥卡姆剃刀』就是一个常用的原则,『若有多个假设与观察一致,则选择最简单的那个』。对于一些以简洁为美的人来说是再正确不过了。在一些工程技术中有一些问题也确实是这样,一个较为简单的方法所取得的效果虽然不是最好,但是它的代价与其效果之比已然是最优。
对于一个线性回归问题,如下图所示:
根据『奥卡姆剃刀』原则,你肯定会选择中间那条经过回归处理之后的直线作为之后预测的标准。在一些场景下,这样选择自然是正确的。如果再给你更多的数据点,你发现这些点正好是在穿过所有红色点的曲线之上,你还会选择那条回归的直线吗?这就牵扯出一个非常有意思的定理,『没有免费的午餐』。
这个定理所描述的是,对于任意两个学习算法A和B,它们在任意分布数据上的误差其实是相等的。仔细想想的话确实是那么回事。这个定理有一个重要的前提:所有问题出现的机会相同或是所有问题都是同等重要的。
这时候你肯定会有疑问,既然所有的学习算法的期望性能都和随机猜测差不多,那学习的过程岂不是并没有什么用。注意到一点,上面所说的相等是在所有数据的分布之下,但是我们所处理的问题的数据往往是某一特定分布的。
欠拟合与过拟合
当目标函数给定时,基于目标函数的模型训练误差和模型测试误差就自然成为学习方法的评估标准。注意,学习方法具体采用的目标函数未必是评估时所使用的标准。关于评估标准这一问题会在之后的博客中提到。
假设学习到的模型是Y=f^(x)
,训练误差是模型关于训练数据数据集的平均损失:
其中N是训练样本容量。
测试误差是模型关于测试数据集的平均损失:
其中N’是测试样本容量。
通常将学习方法对未知数据的预测能力称为泛化能力。显然,我们希望得到泛化误差小的学习器。然而,事先我们并不知道新样本是什么样的,实际能做的是努力使在训练集上的误差最小化。
如果一味追求提高对训练数据的预测能力,所选模型的复杂度往往会比真模型要高。这种现象称为过拟合。过拟合是指学习时选择的模型包含参数过多,以致于出现这一模型对已知数据预测的很好,但对未知数据预测得很差的现象。与过拟合相对的是欠拟合,这是指对训练样本的一般性质尚未学好。
欠拟合比较容易克服,一般只需要增加训练的次数。而过拟合是机器学习面临的关键障碍,各类学习算法都必然带有一些针对过拟合的措施;然而必须认识到,过拟合是无法彻底避免的,我们所能做的只是缓解。这是因为,机器学习面临的问题一般是NP难甚至是更难的,而有效的学习算法必然是在多项式时间内完成的。若可以彻底避免过拟合,这就意味着我们构造性地证明了『NP = P』,那么你就可以获得图灵奖了。只要相信『P != NP』,过拟合就无法避免。
关于过拟合与欠拟合图形化的解释,下面那张图中有具体说明。
方差与偏差
偏差方差-分解试图对学习算法的期望泛化误差进行分解。推导的过程这里就不写了,直接给出公式。
这个式子表示的是泛化误差可以分解为偏差、方差与噪声之和。偏差度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力。为什么一个算法会有偏差呢,下面这句话给出了答案:
Biases are introduced by the generalizations made in the model including the configuration of the model and the selection of the algorithm to generate the model.
我个人的理解是,因为对于算法的选择乃至于调整参数方法的选择导致了算法是有偏差的。因为算法的选择中就蕴含着偏好。
方差度量了同样大小的训练集的变动所导致的学习性能的变化,即刻画了数据扰动所造成的影响;噪声则表达了在当前任务上任何学习算法所能到达的期望泛化误差的下界,即刻画了问题本身的难度。
泛化能力是由学习算法的能力、数据的充分性以及学习任务本身的难度所共同决定的。给定学习任务,为了取得好的泛化性能,则需使偏差较小,即能充分拟合数据,并且使方差较小,即使得数据扰动产生的影响小。
但偏差与方差是不能同时达到最优的,这称为偏差方差窘境。
这个图所表达的含义相信不用过多地解释了吧。
ML_6机器学习重要概念补充
学习目标
-
sklearn中的Pipeline
-
偏差与方差
-
模型正则化之L1正则、L2正则
一、sklearn中的Pipeline
研究一个因变量与一个或多个自变量间多项式的回归分析方法,称为多项式回归(Polynomial Regression)。多项式回归是线性回归模型的一种,其回归函数关于回归系数是线性的。其中自变量x和因变量y之间的关系被建模为n次多项式。
如果自变量只有一个时,称为一元多项式回归;如果自变量有多个时,称为多元多项式回归。在一元回归分析中,如果变量y与自变量x的关系为非线性的,但是又找不到适当的函数曲线来拟合,则可以采用一元多项式回归。
由于任一函数都可以用多项式逼近,因此多项式回归有着广泛应用。
多项式回归的思路是:添加一个特征,即对于X中的每个数据进行平方。
import numpy as np import matplotlib.pyplot as plt x = np.random.uniform(-3, 3, size=100) X = x.reshape(-1, 1) y = 0.5 + x**2 + x + 2 + np.random.normal(0, 1, size=100) plt.scatter(x, y) plt.show() from sklearn.linear_model import LinearRegression lin_reg = LinearRegression() lin_reg.fit(X, y) y_predict = lin_reg.predict(X) plt.scatter(x, y) plt.plot(x, y_predict, color=‘r‘) plt.show() #添加一个特征值 (X**2).shape # 凭借一个新的数据数据集 X2 = np.hstack([X, X**2]) # 用新的数据集进行线性回归训练 lin_reg2 = LinearRegression() lin_reg2.fit(X2, y) y_predict2 = lin_reg2.predict(X2) plt.scatter(x, y) plt.plot(np.sort(x), y_predict2[np.argsort(x)], color=‘r‘) plt.show() #%%一元多项式回归 #sklearn中的多项式回归 #多项式回归可以看作是对数据进行预处理,给数据添加新的特征,所以调用的库在preprocessing中 from sklearn.preprocessing import PolynomialFeatures poly=PolynomialFeatures(degree=2)# 这个degree表示我们使用多少次幂的多项式 poly.fit(X) X2 = poly.transform(X) X2.shape X2[:5,:] #X2的结果第一列常数项,可以看作是加入了一列x的0次方;第二列一次项系数(原来的样本X特征),第三列二次项系数(X平方前的特征)。 from sklearn.linear_model import LinearRegression reg=LinearRegression() reg.fit(X2,y) y_pre=reg.predict(X2) plt.scatter(x,y) plt.plot(np.sort(x),y_pre[np.argsort(x)],color=‘r‘) plt.show() #argsort函数返回的是数组值从小到大的索引值 reg.coef_ reg.intercept_ #%%多元 import numpy as np X = np.arange(1, 11).reshape(5, 2) # 5行2列 10个元素的矩阵 X.shape from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures() poly.fit(X) # 将X转换成最多包含X二次幂的数据集 X2 = poly.transform(X) # 5行6列 X2.shape X2 poly = PolynomialFeatures(degree=3) poly.fit(X) x3 = poly.transform(X) x3.shape #PolynomiaFeatures,将所有的可能组合,升维的方式呈指数型增长。这也会带来一定的问题。 # ============================================================================= # #在具体编程实践时,可以使用sklearn中的pipeline对操作进行整合。 # 首先我们回顾多项式回归的过程: # 将原始数据通过PolynomialFeatures生成相应的多项式特征 # 多项式数据可能还要进行特征归一化处理 # 将数据送给线性回归 # Pipeline就是将这些步骤都放在一起。参数传入一个列表,列表中的每个元素是管道中的一个步骤。每个元素是一个元组,元组的第一个元素是名字(字符串),第二个元素是实例化。 # # ============================================================================= x = np.random.uniform(-3, 3, size=100) X = x.reshape(-1, 1) y = 0.5 + x**2 + x + 2 + np.random.normal(0, 1, size=100) from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression from sklearn.preprocessing import StandardScaler poly_reg=Pipeline([ (‘poly‘,PolynomialFeatures(degree=2)), (‘std_scale‘,StandardScaler()), (‘lin_reg‘,LinearRegression()) ]) poly_reg.fit(x, y) y_predict = poly_reg.predict(x) plt.scatter(x, y) plt.plot(np.sort(x), y_predict[np.argsort(x)], color=‘r‘) plt.show() y =np.random.normal(0, 1, size=5) # ============================================================================= # 其实多项式回归在算法并没有什么新的地方,完全是使用线性回归的思路, #关键在于为数据添加新的特征,而这些新的特征是原有的特征的多项式组合,采用这样的方式就能解决非线性问题。 # 这样的思路跟PCA这种降维思想刚好相反,而多项式回归则是升维,添加了新的特征之后,使得更好地拟合高维数据。 # =============================================================================
二、偏差与方差
过拟合过拟合和欠拟合都会使训练好的机器学习模型在真实的数据中出现错误。我们可以将错误分为偏差(Bias)和方差(Variance)两类和欠拟合都会使训练好的机器学习模型在真实的数据中出现错误。我们可以将错误分为偏差(Bias)和方差(Variance)两类
-
偏差(bias):偏差衡量了模型的预测值与实际值之间的偏离关系。例如某模型的准确度为96%,则说明是低偏差;反之,如果准确度只有70%,则说明是高偏差。
-
方差(variance):方差描述的是训练数据在不同迭代阶段的训练模型中,预测值的变化波动情况(或称之为离散情况)。从数学角度看,可以理解为每个预测值与预测均值差的平方和的再求平均数。通常在模型训练中,初始阶段模型复杂度不高,为低方差;随着训练量加大,模型逐步拟合训练数据,复杂度开始变高,此时方差会逐渐变高。
四种情况
- 低偏差,低方差:这是训练的理想模型,此时蓝色点集基本落在靶心范围内,且数据离散程度小,基本在靶心范围内;
- 低偏差,高方差:这是深度学习面临的最大问题,过拟合了。也就是模型太贴合训练数据了,导致其泛化(或通用)能力差,若遇到测试集,则准确度下降的厉害;
- 高偏差,低方差:这往往是训练的初始阶段;
- 高偏差,高方差:这是训练最糟糕的情况,准确度差,数据的离散程度也差。
模型误差 = 偏差 + 方差 + 不可避免的误差(噪音)。一般来说,随着模型复杂度的增加,方差会逐渐增大,偏差会逐渐减小,见下图:
产生原因
一个模型有偏差,主要的原因可能是对问题本身的假设是不正确的,或者欠拟合。如:针对非线性的问题使用线性回归;或者采用的特征和问题完全没有关系,如用学生姓名预测考试成绩,就会导致高偏差。
方差表现为数据的一点点扰动就会较大地影响模型。即模型没有完全学习到问题的本质,而学习到很多噪音。通常原因可能是使用的模型太复杂,如:使用高阶多项式回归,也就是过拟合。
有一些算法天生就是高方差的算法,如kNN算法。非参数学习算法通常都是高方差,因为不对数据进行任何假设。
有一些算法天生就是高偏差算法,如线性回归。参数学习算法通常都是高偏差算法,因为对数据有迹象。
权衡
偏差和方差通常是矛盾的。降低偏差,会提高方差;降低方差,会提高偏差。
这就需要在偏差和方差之间保持一个平衡。
以多项式回归模型为例,我们可以选择不同的多项式的次数,来观察多项式次数对模型偏差&方差的影响
我们要知道偏差和方差是无法完全避免的,只能尽量减少其影响。
- 在避免偏差时,需尽量选择正确的模型,一个非线性问题而我们一直用线性模型去解决,那无论如何,高偏差是无法避免的。
- 有了正确的模型,我们还要慎重选择数据集的大小,通常数据集越大越好,但大到数据集已经对整体所有数据有了一定的代表性后,再多的数据已经不能提升模型了,反而会带来计算量的增加。而训练数据太小一定是不好的,这会带来过拟合,模型复杂度太高,方差很大,不同数据集训练出来的模型变化非常大。
- 最后,要选择合适的模型复杂度,复杂度高的模型通常对训练数据有很好的拟合能力。
其实在机器学习领域,主要的挑战来自方差。处理高方差的手段有:
- 降低模型复杂度
- 减少数据维度;降噪
- 增加样本数
- 使用验证集
参数或者线性的算法一般是高偏差低方差;非参数或者非线性的算法一般是低偏差高方差。所以我们需要调整参数来去衡量方差和偏差的关系
三、模型正则化之L1正则、L2正则
什么是模型正则化
模型正则化(Regularization),对学习算法的修改,限制参数的大小,减少泛化误差而不是训练误差。我们在构造机器学习模型时,最终目的是让模型在面对新数据的时候,可以有很好的表现。当你用比较复杂的模型比如神经网络,去拟合数据时,很容易出现过拟合现象(训练集表现很好,测试集表现较差),这会导致模型的泛化能力下降,这时候,我们就需要使用正则化,降低模型的复杂度。
正则化的策略包括:约束和惩罚被设计为编码特定类型的先验知识 偏好简单模型 其他形式的正则化,如:集成的方法,即结合多个假说解释训练数据
在实践中,过于复杂的模型不一定包含数据的真实的生成过程,甚至也不包括近似过程,这意味着控制模型的复杂程度不是一个很好的方法,或者说不能很好的找到合适的模型的方法。实践中发现的最好的拟合模型通常是一个适当正则化的大型模型。
LASSO回归思路
所谓的L1正则化,就是在目标函数中加了L1范数这一项。使用L1正则化的模型叫做LASSO回归。
在这里有几个细节需要注意:
-
,取值范围是1~n,即不包含。这是因为,不是任何一个参数的系数,是截距。反映到图形上就是反映了曲线的高低,而不决定曲线每一部分的陡峭与缓和。所以模型正则化时不需要。
-
对于超参数
alpha
系数,在模型正则化的新的损失函数中,要让每个都尽可能小的程度占整个优化损失函数程度的多少。即alpha
的大小表示优化的侧重
正则化与稀疏性
我们说,LASSO回归的全称是:Least Absolute Shrinkage and Selection OperatorRegression.
这里面有一个特征选择的部分,或者说L1正则化可以使得参数稀疏化,即得到的参数是一个稀疏矩阵。
稀疏模型,很多参数是0,表示只有少数特征对这个模型有贡献,绝大部分特征是没有贡献的,即使去掉对模型也没有什么影响,此时我们就可以只关注系数是非零值的特征。
这相当于对模型进行了一次特征选择,只留下一些比较重要的特征,提高模型的泛化能力,降低过拟合的可能。
由此可见:加入L1正则项相当于倾向将参数向离原点近的方向去压缩。直观上来说,就是加上正则项,参数空间会被缩小,意味着模型的复杂度会变小。
L1正则使用
我们利用第一节得到的数据来对比使用LASSO回归进行正则化的方式。
在sklearn中,包含了一个方法:Lasso
。下面我们以Pipeline的方式去封装一个LASSO回归的过程:
#%%lasso import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import PolynomialFeatures from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split x = np.random.uniform(-3, 3, size=100) X = x.reshape(-1, 1) y = 0.5 + x**2 + x + 2 + np.random.normal(0, 1, size=100) plt.scatter(x, y) np.random.seed(666) #过拟合 lin_reg = LinearRegression() def PolynomialRegression(degree): return Pipeline([ (‘poly‘,PolynomialFeatures(degree)), (‘std_scaler‘,StandardScaler()), (‘lin_reg‘,lin_reg) ]) np.random.seed(666) X_train, X_test, y_train, y_test = train_test_split(X,y) poly30_reg = PolynomialRegression(degree=30) poly30_reg.fit(X_train,y_train) y30_predict = poly30_reg.predict(X_test) mean_squared_error(y_test,y30_predict) X_plot = np.linspace(-3,3,100).reshape(100,1) y_plot = poly30_reg.predict(X_plot) plt.scatter(X,y) plt.plot(X_plot[:,0],y_plot,color=‘r‘) plt.axis([-3,3,0,10]) plt.show() #lasso from sklearn.linear_model import Lasso def LassoRegression(degree,alpha): return Pipeline([ (‘poly‘,PolynomialFeatures(degree=degree)), (‘std_scaler‘,StandardScaler()), (‘lasso_reg‘,Lasso(alpha=alpha)) ]) #调参 lasso_reg1 = LassoRegression(30,0.0001) lasso_reg1.fit(X_train,y_train) y1_predict=lasso_reg1.predict(X_test) mean_squared_error(y_test,y1_predict) lasso_reg3 = LassoRegression(30,10) #放大alpha后的模型线更加平了,则alpha的选取也很重要 lasso_reg3.fit(X_train,y_train) y3_predict=lasso_reg3.predict(X_test) mean_squared_error(y_test,y3_predict) #%%岭回归
岭回归思路
from sklearn.linear_model import Ridge from sklearn.pipeline import Pipeline # 需要传入一个多项式项数的参数degree以及一个alpha值 def ridgeregression(degree,alpha): return Pipeline([ ("poly", PolynomialFeatures(degree=degree)), ("standard", StandardScaler()), ("ridge_reg", Ridge(alpha=alpha)) #alpha值就是正则化那一项的系数 ]) ridge1_reg = ridgeregression(degree=30,alpha=0.0001) ridge1_reg.fit(X_train,y_train) y1_predict = ridge1_reg.predict(X_test) mean_squared_error(y_test,y1_predict) #如果我们调整系数,将其变大,意味着对参数的约束又变强了,曲线会更加光滑 ridge2_reg = ridgeregression(degree=30,alpha=1) ridge2_reg.fit(X_train,y_train) y2_predict = ridge2_reg.predict(X_test) mean_squared_error(y_test,y2_predict)
可见LASSO回归和岭回归类似,alpha取值过大反而会导致误差增加,拟合曲线为直线。但是LASSO更趋向于使得一部分theta的值为0,拟合曲线更趋向于直线,所以可以作为特征选择来使用,去除一些模型认为不需要的特征。LASSO可能会去除掉正确的特征,从而降低准确度,但如果特征特别大,使用LASSO可以使模型变小。
总结
L1正则化就是在损失函数后边所加正则项为L1范数,加上L1范数容易得到稀疏解(0比较多),一般来说L1正则化较常使用。
L2正则化就是损失后边所加正则项为L2范数,加上L2正则相比于L1正则来说,得到的解比较平滑(不是稀疏),但是同样能够保证解中接近于0(但不是等于0,所以相对平滑)的维度比较多,降低模型的复杂度。
以上是关于机器学习几个重要概念的主要内容,如果未能解决你的问题,请参考以下文章