机器学习入门之Python3入门机器学习(八)- 多项式回归
小标 2018-12-12 来源 : 阅读 1358 评论 0

摘要:本文主要向大家介绍机器学习入门之Python3入门机器学习(八)- 多项式回归了,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。

本文主要向大家介绍机器学习入门之Python3入门机器学习(八)- 多项式回归了,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。


1.多项式回归简介

考虑下面的数据,虽然我们可以使用线性回归来拟合这些数据,但是这些数据更像是一条二次曲线,相应的方程是y=ax2+bx+c,这是式子虽然可以理解为二次方程,但是我们呢可以从另外一个角度来理解这个式子:

如果将x2理解为一个特征,将x理解为另外一个特征,换句话说,本来我们的样本只有一个特征x,现在我们把他看成有两个特征的一个数据集。多了一个特征x2,那么从这个角度来看,这个式子依旧是一个线性回归的式子,但是从x的角度来看,他就是一个二次的方程


1-1

以上这样的方式,就是所谓的多项式回归

相当于我们为样本多添加了一些特征,这些特征是原来样本的多项式项,增加了这些特征之后,我们们可以使用线性回归的思路更好的我们的数据

2.编程实验多项式回归

1.模拟多项式回归的数据集

import numpy as npimport 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)

<matplotlib.collections.PathCollection at 0x114f17160>

[图片上传失败...(image-46be02-1527345377921)]

2.使用线性回归拟合

很明显,我们用一跟直线来拟合一根有弧度的曲线,效果是不好的

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')

[<matplotlib.lines.Line2D at 0x1a1c90ecf8>]

[图片上传失败...(image-e9e717-1527345377922)]

3.解决方案,添加一个特征

原来所有的数据都在X中,现在对X中每一个数据都进行平方,
再将得到的数据集与原数据集进行拼接,
在用新的数据集进行线性回归

(X**2).shape

(100, 1)

X2 = np.hstack([X,X**2])
lin_reg2 = LinearRegression()
lin_reg2.fit(X2,y)
y_predict2 = lin_reg2.predict(X2)

plt.scatter(x,y)# 由于x是乱的,所以应该进行排序plt.plot(np.sort(x),y_predict2[np.argsort(x)],color='r')

[<matplotlib.lines.Line2D at 0x1a1c691198>]

[图片上传失败...(image-414310-1527345377922)]

从上图可以看出,当我们添加了一个特征(原来特征的平方)之后,再从x的维度来看,就形成了一条曲线,显然这个曲线对原来数据集的拟合程度是更好的

# 第一个系数是x前面的系数,第二个系数是x平方前面的系数lin_reg2.coef_

array([1.08043759, 0.52423752])

lin_reg2.intercept_

1.9427736300237914

3.总结

多线性回归在机器学习算法上并没有新的地方,完全是使用线性回归的思路
他的关键在于为原来的样本,添加新的特征。而我们得到新的特征的方式是原有特征的多项式的组合。
采用这样的方式,我们就可以解决一些非线性的问题

与此同时需要主要,我们在上一章所讲的PCA是对我们的数据进行降维处理,而我们这一章所讲的多项式回归显然在做一件相反的事情,他让我们的数据升维,在升维之后使得我们的算法可以更好的拟合高纬度的数据

2.scikit-learn中的多项式回归于pipeline

1.使用scikit-learn中的多项式对数据进行预处理

# sklearn中对数据进行预处理的函数都封装在preprocessing模块下,包括之前学的归一化StandardScalerfrom sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures()
poly.fit(X)
X2 = poly.transform(X)# 第一列是sklearn为我们添加的X的零次方的特征# 第二列和原来的特征一样是X的一次方的特征# 第三列是添加的X的二次方的特征X2[:5]

array([[ 1. , 2.5980174 , 6.74969443],
[ 1. , 2.07484052, 4.30496317],
[ 1. , -1.74999096, 3.06246837],
[ 1. , -2.74141103, 7.51533441],
[ 1. , -1.3420996 , 1.80123135]])

2.调用LinearRegression对X2进行预测

lin_reg2 = LinearRegression()
lin_reg2.fit(X2,y)
y_predict2 = lin_reg2.predict(X2)

plt.scatter(x,y)# 由于x是乱的,所以应该进行排序plt.plot(np.sort(x),y_predict2[np.argsort(x)],color='r')

[<matplotlib.lines.Line2D at 0x1a1c4e8860>]

[图片上传失败...(image-80f622-1527345377922)]

lin_reg2.coef_

array([0. , 1.08043759, 0.52423752])

3.关于PolynomialFeatures

# 测试多维的数据集X = np.arange(1,11).reshape(5,2)
X.shape

(5, 2)

X

array([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10]])

poly = PolynomialFeatures(degree=2)
poly.fit(X)
X2 = poly.transform(X)
X2

array([[ 1., 1., 2., 1., 2., 4.],
[ 1., 3., 4., 9., 12., 16.],
[ 1., 5., 6., 25., 30., 36.],
[ 1., 7., 8., 49., 56., 64.],
[ 1., 9., 10., 81., 90., 100.]])

将52的矩阵进行多项式转换后变成了56

第一列是1 对应的是0次幂

第二列和第三列对应的是原来的x矩阵,此时他有两列一次幂的项

第四列是原来数据的第一列平方的结果

第六列是原来数据的第二列平方的结果

第五列是原来数据的两列相乘的结果

可以想象如果将degree设置为3,那么将产生一下10个元素

1,X1,X2

X21,X22,X1*X2

X13,X23,X12X2,X22X1

也就是说PolynomialFeatures会穷举出所有的多项式组合

3.Pipline

pipline的英文名字是管道,那么 我们如何使用管道呢,先考虑我们多项式回归的过程

1.使用PolynomialFeatures生成多项式特征的数据集
2.如果生成数据幂特别的大,那么特征直接的差距就会很大,导致我们的搜索非常慢,这时候可以进行数据归一化
3.进行线性回归
pipline 的作用就是把上面的三个步骤合并,使得我们不用一直重复这三步

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.preprocessing import PolynomialFeaturesfrom sklearn.preprocessing import StandardScalerfrom sklearn.pipeline import Pipeline# 传入每一步的对象名和类的实例化poly_reg = Pipeline([
('poly',PolynomialFeatures(degree=2)),
('std_scaler',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')

[<matplotlib.lines.Line2D at 0x1a1ccc15c0>]

[图片上传失败...(image-4c2d99-1527345377922)]

3.过拟合与前拟合

1.什么是过拟合和欠拟合

import numpy as npimport matplotlib.pyplot as pltfrom sklearn.linear_model import LinearRegression

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)

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')

0.5406237455773699

[图片上传失败...(image-f3daf8-1527345377922)]

# 直接使用线性回归,显然分数太低lin_reg.score(X,y)

0.5406237455773699

使用均方误差来看拟合的结果,这是因为我们同样都是对一组数据进行拟合,所以使用不同的方法对数据进行拟合
得到的均方误差的指标是具有可比性的,(但是对于多项式回归来说,使用r2score进行衡量是没有问题是)

from sklearn.metrics import mean_squared_error

y_predict = lin_reg.predict(X)
mean_squared_error(y,y_predict)

2.6112077267395803

使用多项式回归

from sklearn.preprocessing import PolynomialFeaturesfrom sklearn.preprocessing import StandardScalerfrom sklearn.pipeline import Pipeline# 使用Pipeline构建多项式回归def PolynomialRegression(degree):poly_reg = Pipeline([
('poly',PolynomialFeatures(degree=degree)),
('std_scaler',StandardScaler()),
('lin_reg',LinearRegression())
])return poly_reg
poly_reg2 = PolynomialRegression(2)
poly_reg2.fit(X,y)
y2_predict = poly_reg2.predict(X)# 显然使用多项式回归得到的结果是更好的mean_squared_error(y,y2_predict)

1.000151338154146

plt.scatter(x,y)
plt.plot(np.sort(x),y2_predict[np.argsort(x)],color='r')

[<matplotlib.lines.Line2D at 0x1a1d536908>]

[图片上传失败...(image-6e5e74-1527345377922)]

使用更多的维度进行多项式回归

# 使用10个维度poly_reg10 = PolynomialRegression(10)
poly_reg10.fit(X,y)
y10_predict = poly_reg10.predict(X)
mean_squared_error(y,y10_predict)

0.9394112675409493

plt.scatter(x,y)
plt.plot(np.sort(x),y10_predict[np.argsort(x)],color='r')

[<matplotlib.lines.Line2D at 0x1a1d78c198>]

[图片上传失败...(image-97cb38-1527345377922)]

poly_reg100 = PolynomialRegression(100)
poly_reg100.fit(X,y)
y100_predict = poly_reg100.predict(X)# 显然使用多项式回归得到的结果是更好的mean_squared_error(y,y100_predict)

0.5431979125088253

plt.scatter(x,y)
plt.plot(np.sort(x),y100_predict[np.argsort(x)],color='r')

[<matplotlib.lines.Line2D at 0x1a1da201d0>]

[图片上传失败...(image-463c7c-1527345377922)]

这条曲线只是原来的点对应的y的预测值连接起来的曲线,不过有很多地方可能没有那个数据点,所以连接的结果和原来的曲线不一样
下面尝试真正还原原来的曲线(构造均匀分布的原数据集)

X_plot = np.linspace(-3,3,100).reshape(100,1)
y_plot = poly_reg100.predict(X_plot)

plt.scatter(x,y)
plt.plot(X_plot,y_plot,color='r')
plt.axis([-3 , 3 , -1,10 ])

[-3, 3, -1, 10]

[图片上传失败...(image-44edb2-1527345377922)]

说明总有一条曲线,他能拟合所有的样本点,使得均方误差的值为0
degree从2到10到100的过程中,虽然均方误差是越来越小的,从均方误差的角度来看是更加小的
但是他真的能更好的预测我们数据的走势吗,例如我们选择2.5到3的一个x,使用上图预测出来的y的大小(0或者-1之间)显然不符合我们的数据

换句话说,我们使用了一个非常高维的数据,虽然使得我们的样本点获得了更小的误差,但是这根曲线完全不是我们想要的样子
他为了拟合我们所有的样本点,变的太过复杂了,这种情况就是过拟合【over-fitting】

相反,在最开始,我们直接使用一根直线来拟合我们的数据,也没有很好的拟合我们的样本特征,当然他犯的错误不是太过复杂了,而是太过简单了
这种情况,我们成为欠拟合-【under-fitting】

对于现在的数据(基于二次方程构造),我们使用低于2项的拟合结果,就是欠拟合;高于2项的拟合结果,就是过拟合

2.为什么要使用训练数据集和测试数据集

模型的泛化能力

使用上小节的过拟合结果,我们可以得知,虽然我们训练出的曲线将原来的样本点拟合的非常好,总体的误差非常的小,
但是一旦来了新的样本点,他就不能很好的预测了,在这种情况下,我们就称我们得到的这条弯弯曲曲的曲线,他的泛化能力(由此及彼的能力)非常弱


image.png


训练数据集和测试数据集的意义

我们训练的模型目的是为了使得预测的数据能够尽肯能的准确,在这种情况下,我们观察训练数据集的拟合程度是没有意义的
我们真正需要的是,我们得到的模型的泛化能力更高,解决这个问题的方法也就是使用训练数据集,测试数据集的分离


image.png

测试数据对于我们的模型是全新的数据,如果使用训练数据获得的模型面对测试数据也能获得很好的结果,那么我们就说我们的模型泛化能力是很强的。
如果我们的模型面对测试数据结果很差的话,那么他的泛化能力就很弱。事实上,这是训练数据集更大的意义

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y)

lin_reg = LinearRegression()
lin_reg.fit(X_train,y_train)
y_predict = lin_reg.predict(X_test)# 训练模型使用的X_train,是预测的模型使用X_test,以计算模型的泛化能力mean_squared_error(y_test,y_predict)

2.7714817137686794

poly_reg2 = PolynomialRegression(2)
poly_reg2.fit(X_train,y_train)
y2_predict = poly_reg2.predict(X_test)
mean_squared_error(y_test,y2_predict)

0.7922037464116539

poly_reg10 = PolynomialRegression(10)
poly_reg10.fit(X_train,y_train),
y10_predict = poly_reg10.predict(X_test)
mean_squared_error(y_test,y10_predict)

1.336192585265726

使用degree=10的时候得到的均方误差要大于degree=2的时候,说明当degree等于10的时候,他的模型泛化能力变弱了

poly_reg100 = PolynomialRegression(100)
poly_reg100.fit(X_train,y_train)
y100_predict = poly_reg100.predict(X_test)
mean_squared_error(y_test,y100_predict)

4.192433747323001e+21

刚刚我们进行的实验实际上在实验模型的复杂度,对于多项式模型来说,我们回归的阶数越高,我们的模型会越复杂,在这种情况下对于我们的机器学习算法来说,通常是有下面一张图的。横轴是模型复杂度(对于不同的算法来说,代表的是不同的意思,比如对于多项式回归来说,是阶数越高,越复杂;对于KNN来说,是K越小,模型越复杂,k越大,模型最简单,当k=n的时候,模型就简化成了看整个样本里,哪种样本最多,当k=1来说,对于每一个点,都要找到离他最近的那个点),另一个维度是模型准确率(也就是他能够多好的预测我们的曲线)


image.png

通常对于这样一个图,会有两根曲线:

一个是对于训练数据集来说的,模型越复杂,模型准确率越高,因为模型越复杂,对训练数据集的拟合就越好,相应的模型准确率就越高

对于测试数据集来说,在模型很简单的时候,模型的准确率也比较低,随着模型逐渐变复杂,对测试数据集的准确率在逐渐的提升,提升到一定程度后,如果模型继续变复杂,那么我们的模型准确率将会进行下降(欠拟合->正合适->过拟合)

欠拟合和过拟合的标准定义

欠拟合:算法所训练的模型不能完整表述数据关系
过拟合:算法所训练的模型过多的表达了数据间的噪音关系

4.学习曲线

1. 什么是学习曲线

随着训练样本的主键增多,算法训练出的模型的表现能力

import numpy as npimport matplotlib.pyplot as plt

np.random.seed(666)
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)

<matplotlib.collections.PathCollection at 0x107369240>

[图片上传失败...(image-de5417-1527345377922)]

2.实际编程实现学习曲线

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=10)
X_train.shape

(75, 1)

2.1观察线性回归的学习曲线:观察线性回归模型,随着训练数据集增加,性能的变化

from sklearn.linear_model import LinearRegressionfrom sklearn.metrics import mean_squared_errordef plot_learning_curve(algo,X_train,X_test,y_train,y_test):train_score = []
test_score = []# 计算学习曲线数据for i in range(1,len(X_train)+1):
algo.fit(X_train[:i],y_train[:i])

y_train_predict = algo.predict(X_train[:i])
train_score.append(mean_squared_error(y_train[:i],y_train_predict))

y_test_predict = algo.predict(X_test)
test_score.append(mean_squared_error(y_test,y_test_predict))# 绘制学习曲线plt.plot([i for i in range(1,len(X_train)+1)],np.sqrt(train_score),label = 'train')
plt.plot([i for i in range(1,len(X_train)+1)],np.sqrt(test_score),label = 'test')
plt.axis([0,len(X_train)+1,0,4])
plt.legend()

plot_learning_curve(LinearRegression(),X_train,X_test,y_train,y_test)

[图片上传失败...(image-7c3927-1527345377922)]

从趋势上看:

在训练数据集上,误差是逐渐升高的。这是因为我们的训练数据越来越多,我们的数据点越难得到全部的累积,不过整体而言,在刚开始的时候误差变化的比较快,后来就几乎不变了

在测试数据集上,在使用非常少的样本进行训练的时候,刚开始我们的测试误差非常的大,当训练样本大到一定程度以后,我们的测试误差就会逐渐减小,减小到一定程度后,也不会小太多,达到一种相对稳定的情况

在最终,测试误差和训练误差趋于相等,不过测试误差还是高于训练误差一些,这是因为,训练数据在数据非常多的情况下,可以将数据拟合的比较好,误差小一些,但是泛化到测试数据集的时候,还是有可能多一些误差

2.2 观察多项式回归的学习曲线

from sklearn.preprocessing import StandardScalerfrom sklearn.preprocessing import PolynomialFeaturesfrom sklearn.pipeline import Pipeline# 使用Pipline构建多项式回归模型def PolynomialRegression(degree):return Pipeline([
("poly",PolynomialFeatures(degree=degree)),
("std_scaler",StandardScaler()),
("lin_reg",LinearRegression())
])# 使用二阶多项式回归poly2_reg = PolynomialRegression(2)
plot_learning_curve(poly2_reg,X_train,X_test,y_train,y_test)

[图片上传失败...(image-ec1d61-1527345377922)]

首先整体从趋势上,和线性回归的学习曲线是类似的
仔细观察,和线性回归曲线的不同在于,线性回归的学习曲线1.5,1.8左右;2阶多项式回归稳定在了1.0,0.9左右,2阶多项式稳定的误差比较低,说明
使用二阶线性回归的性能是比较好的

# 使用20阶多项式回归poly20_reg = PolynomialRegression(20)
plot_learning_curve(poly20_reg,X_train,X_test,y_train,y_test)

[图片上传失败...(image-db9bf9-1527345377922)]

在使用20阶多项式回归训练模型的时候可以发现,在数据量偏多的时候,我们的训练数据集拟合的是比较好的,但是测试数据集的误差相对来说增大了很多,离训练数据集比较远,通常这就是过拟合的结果,他的泛化能力是不够的

3.总结


image.png


对于欠拟合比最佳的情况趋于稳定的那个位置要高一些,说明无论对于训练数据集还是测试数据集来说,误差都比较大。这是因为我们本身模型选的就不对,所以即使在训练数据集上,他的误差也是大的,所以才会呈现出这样的一种形态


image.png


对于过拟合的情况,在训练数据集上,他的误差不大,和最佳的情况是差不多的,甚至在极端情况,如果degree取更高的话,那么训练数据集的误差会更低,但是问题在于,测试数据集的误差相对是比较大的,并且训练数据集的误差和测试数据集的误差相差比较大(表现在图上相差比较远),这就说明了此时我们的模型的泛化能力不够好,他的泛化能力是不够的

5.验证数据集与交叉验证

使用分割训练数据集和测试数据集来判断我们的机器学习性能的好坏,虽然是一个非常好的方案,但是会产生一个问题:针对特定测试数据集过拟合

我们每次使用测试数据来分析性能的好坏。一旦发现结果不好,我们就换一个参数(可能是degree也可能是其他超参数)重新进行训练。这种情况下,我们的模型在一定程度上围绕着测试数据集打转。也就是说我们在寻找一组参数,使得这组参数训练出来的模型在测试结果集上表现的最好。但是由于这组测试数据集是已知的,我们相当于在针对这组测试数据集进行调参,那么他也有可能产生过拟合的情况,也就是我们得到的模型针对测试数据集过拟合了


image.png


那么怎么解决这个问题呢?
解决的方式其实就是:我们需要将我们的问题分为三部分,这三部分分别是训练数据集,验证数据集,测试数据集。
我们使用训练数据集训练好模型之后,将验证数据集送给这个模型,看看这个训练数据集训练的效果是怎么样的,如果效果不好的话,我们重新换参数,重新训练模型。直到我们的模型针对验证数据来说已经达到最优了。
这样我们的模型达到最优以后,再讲测试数据集送给模型,这样才能作为衡量模型最终的性能。换句话说,我们的测试数据集是不参与模型的创建的,而其他两个数据集都参与了训练。但是我们的测试数据集对于模型是完全不可知的,相当于我们在模型这个模型完全不知道的数据


image.png

这种方法还会有一个问题。由于我们的模型可能会针对验证数据集过拟合,而我们只有一份验证数据集,一旦我们的数据集里有比较极端的情况,那么模型的性能就会下降很多,那么为了解决这个问题,就有了交叉验证。

1.交叉验证 Cross Validation

交叉验证相对来说是比较正规的、比较标准的在我们调整我们的模型参数的时候看我们的性能的方式

交叉验证:在训练模型的时候,通常把数据分成k份,例如分成3份(ABC)(分成k分,k属于超参数),这三份分别作为验证数据集和训练数据集。这样组合后可以分别产生三个模型,这三个模型,每个模型在测试数据集上都会产生一个性能的指标,这三个指标的平均值作为当前这个算法训练处的模型衡量的标准是怎样的。
由于我们有一个求平均的过程,所以不会由于一份验证数据集中有比较极端的数据而导致模型有过大的偏差,这比我们只分成训练、验证、测试数据集要更加准确

2.编程实现

import numpy as npfrom sklearn import datasets
digits = datasets.load_digits()
X = digits.data
y = digits.target

训练train_test_spilt

from sklearn.model_selection import train_test_split

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.4,random_state =666)from sklearn.neighbors import KNeighborsClassifier

best_score,best_k,best_p = 0,0,0# k为k近邻中的寻找k个最近元素for k in range(2,10):# p为明科夫斯基距离的pfor p in range(1,5):
knn_clf = KNeighborsClassifier(weights='distance',n_neighbors=k,p=p)
knn_clf.fit(X_train,y_train)
score = knn_clf.score(X_test,y_test)if score > best_score:
best_score,best_k,best_p = score,k,p
print("Best_score = ",best_score)
print("Best_k = ",best_k)
print("Best_p = ",best_p)

Best_score = 0.9860917941585535
Best_k = 3
Best_p = 4

使用交叉验证

# 使用sklearn提供的交叉验证from sklearn.model_selection import cross_val_score

knn_clf = KNeighborsClassifier()# 返回的是一个数组,有三个元素,说明cross_val_score方法默认将我们的数据集分成了三份# 这三份数据集进行交叉验证后产生了这三个结果# cv默认为3,可以修改改参数,修改修改不同分数的数据集cross_val_score(knn_clf,X_train,y_train,cv=3)

array([0.98895028, 0.97777778, 0.96629213])

# 使用交叉验证的方式来进行调参的过程best_score,best_k,best_p = 0,0,0# k为k近邻中的寻找k个最近元素for k in range(2,10):# p为明科夫斯基距离的pfor p in range(1,5):
knn_clf = KNeighborsClassifier(weights='distance',n_neighbors=k,p=p)
scores = cross_val_score(knn_clf,X_train,y_train)
score = np.mean(scores)if score > best_score:
best_score,best_k,best_p = score,k,p
print("Best_score = ",best_score)
print("Best_k = ",best_k)
print("Best_p = ",best_p)

Best_score = 0.9823599874006478
Best_k = 2
Best_p = 2

通过观察两组调参过程的结果可以发现
1.两组调参得出的参数结果是不同的,通常这时候我们更愿意详细使用交叉验证的方式得出的结果。
因为使用train_test_split很有可能只是过拟合了测试数据集得出的结果
2.使用交叉验证得出的最好分数0.982是小于使用分割训练测试数据集得出的0.986,因为在交叉验证的
过程中,通常不会过拟合某一组的测试数据,所以平均来讲这个分数会稍微低一些

但是使用交叉验证得到的最好参数Best_score并不是真正的最好的结果,我们使用这种方式只是为了拿到
一组超参数而已,拿到这组超参数后我们就可以训练处我们的最佳模型

knn_clf = KNeighborsClassifier(weights='distance',n_neighbors=2,p=2)# 用我们找到的k和p。来对X_train,y_train整体fit一下,来看他对X_test,y_test的测试结果knn_clf.fit(X_train,y_train)# 注意这个X_test,y_test在交叉验证过程中是完全没有用过的,也就是说我们这样得出的结果是可信的knn_clf.score(X_test,y_test)

0.980528511821975

回顾网格搜素

我们上面的操作,实际上在网格搜索的过程中已经进行了,只不过这个过程是sklean的网格搜索自带的一个过程

# GridSearchCV里的cv实际上就是交叉验证的方式from sklearn.model_selection import GridSearchCV

param_grid = [
{"weights":['distance'],"n_neighbors":[i for i in range(2,10)],"p":[i for i in range(1,6)]
}
]
knn_clf = KNeighborsClassifier()# cv默认为3,可以修改改参数,修改修改不同分数的数据集grid_search = GridSearchCV(knn_clf,param_grid,verbose=1,cv=3)
grid_search.fit(X_train,y_train)

Fitting 3 folds for each of 40 candidates, totalling 120 fits

[Parallel(n_jobs=1)]: Done 120 out of 120 | elapsed: 1.0min finished

GridSearchCV(cv=None, error_score='raise',
estimator=KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=1, n_neighbors=5, p=2,
weights='uniform'),
fit_params=None, iid=True, n_jobs=1,
param_grid=[{'weights': ['distance'], 'n_neighbors': [2, 3, 4, 5, 6, 7, 8, 9], 'p': [1, 2, 3, 4, 5]}],
pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
scoring=None, verbose=1)

Fitting 3 folds for each of 40 candidates, totalling 120 fits
的意思就是交叉验证中分割了三组数据集,而我们的参数组合为8*5=40中组合
3组数据集,30种组合,一共要进行120次的训练

grid_search.best_score_# 0.9823747680890538 和我们上面得到的best_score 是吻合的

0.9823747680890538

grid_search.best_params_

{'n_neighbors': 2, 'p': 2, 'weights': 'distance'}

best_knn_clf = grid_search.best_estimator_
best_knn_clf.fit(X_train,y_train)
best_knn_clf.score(X_test,y_test)

0.980528511821975

3.总结


image.png


虽然整体速度慢了,但是这个结果却是可信赖的
极端情况下,K-folds cross validation可以叫做留一法



image.png

6.偏差方差均衡

模型误差=偏差(Bias)均差(Variance)+不可避免的误差

偏差


image.png

方差

模型没有完全的学到数据的中心,而学习到了很多噪音



image.png

有一些算法天生是高方差算法。如KNN(过于依赖数据,一点选取的数据点有多数是不正确的,那么预测的结果就是错误的。导致有的很准确,有的非常不准确,方差非常大)

非参数学习通常都是高方差的算法。因为不对数据做任何假设

有一些算法天生是高偏差算法。如线性回归(用一条直线去拟合一条曲线,导致整体预测结果都距离真实数据查很大,偏差非常大)

参数学习通常都是高偏差的算法。因为对数据具有极强的假设

大多数算法具有相应的参数,可以调整偏差和方差

如KNN中的k,线性回归中使用多项式回归

偏差和方差是互相矛盾的。降低方差会提高偏差,降低偏差会提高方差

机器学习的主要调整来源于方差(这是站在算法的角度上,而不是问题的角度上,比如对金融市场的理解,很多人尝试用历史的数据预测未来的金融走势,这样的尝试通常都不太理想。很有可能因为历史的金融趋势不能很好的反应未来的走向,这种预测方法本身带来的非常大的偏差)换句话说,我们很容易让模型变的很复杂,从而降低模型的偏差,但是由于这样的模型的方差非常的大,最终也没有很好的性能。

解决高方差的通常手段:

1.降低模型复杂度
2.减少数据维度;降噪
3.增加样本数(模型太过复杂,模型中的参数非常多,而样本数不足以支撑计算出这么复杂的参数)
4.使用验证集
5.模型正则化


image.png

7.模型正则化-Regularization

1.什么是模型正则化

下图是我们之前使用多项式回归过拟合一个样本的例子,可以看到这条模型曲线非常的弯曲,而且非常的陡峭,可以想象这条曲线的一些θ系数会非常的大。
模型正则化需要做的事情就是限制这些系数的大小



image.png

模型正则化基本原理


image.png

一些需要注意的细节:

对于θ的求和i是从1到n,没有将θ0加进去,因为他不是任意一项的系数,他只是一个截距,决定了整个曲线的高低,但是不决定曲线每一部分的陡峭和缓和

θ求和的系数二分之一是一个惯例,加不加都可以,加上的原因是因为,将来对θ2>求导的时候可以抵消系数2,方便计算。不要也是可以的

α实际上是一个超参数,代表在我们模型正则化下新的损失函数中,我们要让每一个θ尽可能的小,小的程度占我们整个损失函数的多少,如果α等于0,相当于没有正则化;如果α是正无穷的话,那么我们主要的优化任务就是让每一个θ尽可能的小

岭回归 Ridge Regression

<img class="lazyload" data-original="https://upload-images.jianshu.io/upload_images/7220971-b3aca68e141af312.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700" style="border-color: rgb(51, 51, 51); border-style: none; border-width: 0px; border-image: none; box-sizing: border-box; cursor: pointer; vertical-align: middle;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original-src="//upload-images.jianshu.io/upload_images/7220971-b3aca68e141af312.png" data-original-wi    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标人工智能机器学习频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved