请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化平台 帖子:3364730 新帖:17

【机器学习】线性模型与岭回归

我们棒棒哒发表于:5 月 10 日 06:59回复(1)

上一节中,学习了k-NN模型,用一句话来总结它的特点就是:近朱者赤,近墨者黑。

本节将开始涉及线性模型相关的概念与模型。

线性模型是在实践中广泛使用的一类模型,它利用输入特征的线性函数进行预测。所以,线性模型非常的耿直

备注:mgleran中的数据是用来展示的,不与机器学习的sklern模块相重叠。

*mgleran请使用pip install mglearn命令。

# 在学习之前,先导入这些常用的模块import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport mglearn

认识线性模型

对于回归问题,线性模型预测的一般公式如下:

y = w[0]*x[0] w1*x[0] ... w[p]*x[p]

这里 x[0] 到 x[p] 表示单个数据点的特征, w 和 b 是学习模型的参数, y 是模型的预测结果。对于单一特征的数据集,公式如下:

y = w[0]*x[0] b

类似于初中学到的:

y = ax b

也就是说,w[0]就是斜率,b是截距。对于有更多特征的数据集,w 包含沿每个特征坐标轴的斜率。或者,你也可以将预测的响应值看作输入特征的加权求和,权重由 w 的元素给出(可以取负值)。

下列代码可以在一维w*e数据集上学习参数w[0]和b,也就是ax b的线性结果。

mglearn.plots.plot_linear_regression_w*e()
w[0]: 0.393906  b: -0.031804

从该模型可以看出,w[0] 在0.4左右,而b比0稍微小一点。

总结:用于回归的线性模型可以表示这样的回归模型:对单一特征的预测结果是一条直线,两个特征时是一个平面,或者在更高维度(即更多特征)时是一个超平面。

从上图中可发现,线性模型与k-NN的回归模型比较起来,似乎准确率没有那么高。但如果数据是多维度的,数量也非常庞大,线性模型将会给出比较完美的拟合。

不同的线性模型之间的区别仅在于如何从训练数据中学习参数w和b,以及如何控制模型复杂度。

认识线性回归模型

线性回归,又称普通最小二乘法,是回归问题最简单也最经典的线性方法。

线性回归寻找参数 w 和 b,使得对训练集的预测值与真实的回归目标值 y 之间的均方误差最小。均方误差是预测值与真实值之差的平方和除以样本数。线性回归没有参数,这是一个优点,但也因此无法控制模型的复杂度。

# 从 skleran 中导入线性模型模型 LinearRegressionfrom sklearn.linear_model import LinearRegression# 导入数据分割模块 train_test_splitfrom sklearn.model_selection import train_test_split# 导入线性回归数据X, y = mglearn.datasets.make_w*e(n_samples=60)# 将数据打乱,将分成训练集与测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)# 对训练集数据进行训练lr = LinearRegression().fit(X_train, y_train)

线性模型的“斜率”参数(w,也叫作权重或系数)被保存在coef_属性中,而偏移或截距(b)被保存在intercept_属性中:

print('查看模型的斜率:', lr.coef_)print('查看模型的截距:', lr.intercept_)
查看模型的斜率: [0.39390555]查看模型的截距: -0.031804343026759746

敲黑板:intercept是一个浮点数;而coef是一个NumPy数组,每个元素对应一个输入特征。这里因为只有一个输入特征,因此coef_中只有一个元素。

接下来,查看一下训练集与测集的性能:

print('训练集精度:', lr.score(X_train, y_train))print('测试集精度:', lr.score(X_test, y_test))
训练集精度: 0.6700890315075756测试集精度: 0.65933685968637

这个评估结果不是很好,说明模型在训练集和测试集上都存在欠拟合的情况。这是因此,此处提供的是二维的简单数据。如果是在高维度的数据上,线性模型将变得更加的强大,此时则可能有过拟合的可能。

接下来,看一下LinearRegression在更复杂的数据集上的表现——波士顿房价数据集,该数据集拥有506个样本和105个导出特征。

# 导入波士顿房价数据X, y = mglearn.datasets.load_extended_boston()# 将数据分为训练集与测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)# 对训练集数据进行训练lr = LinearRegression().fit(X_train, y_train)

然后再查看一下模型在训练集与测试集上的分数:

print('训练集评估分数:', lr.score(X_train, y_train))print('测试集评估分数:', lr.score(X_test, y_test))
训练集评估分数: 0.9523526436864238测试集评估分数: 0.6057754892935623

结果显示,在训练集的精度很高,而在测试集的精度则比较低,造成这种情况的原因是因为在训练集得出的模型存在近拟合的情况,因此无法更好的适应新的数据。

因此我们应该试图找一个可以控制复杂复杂度的模型,标准线性回归最常用的替代方法之一就是岭回归

认识岭回归

岭回归为何会成为标准线性回归的替代之一呢?

岭回归也是一种用于回归的线性模型,因此它的预测公式与普通最小二乘法相同。但在岭回归中,对系数 w 的选择不仅要在训练数据上得出好的预测结果,而且还要拟合附加线束——即希望系数尽量小。

直观上来看,这意味着每个特征对输出的影响应尽可能的小(即斜率很小),同时仍给出很好的预测结果。这种线束是所谓的正则化的一个例子。正则化是指对模型做显示约束,以避免过拟合。岭回归的这种正则化被称为L2正则化

岭回归在 liner_model.Ridge 中实现。来看一下它在波士顿房价的上效果如何。

# 导入岭回归模块from sklearn.linear_model import Ridge

ridge = Ridge().fit(X_train, y_train)print('训练集评估分数:', ridge.score(X_train, y_train))print('测试集评估分数:', ridge.score(X_test, y_test))
训练集评估分数: 0.8860578560395836测试集评估分数: 0.7527139600306947

结果显示,Ridge 在训练集上的分数要低于 LinearRegression, 在测试数据集上的表现比较优秀。

Ridge 是一种约束更强的模型,所以更不容易过拟合。

复杂度更小的模型意味着在训练集上的性能更差,但泛化性能更好。

由于Ridge的泛化能力更好,所以在这里应该选择Ridge模型。

通过设置alpha参数来控制模型的简单性和训练性能

在前面的例子中,我们用的是默认的参数 alpha=1.0。它的最取值取决于具体的数据集。

增大 alpha 会使得系数更加趋向于0,从而降低训练集性能,但可能会提高泛化性能。

例如:

ridge10 = Ridge(alpha=10).fit(X_train, y_train)print('训练集评估分数:', ridge10.score(X_train, y_train))print('测试集评估分数:', ridge10.score(X_test, y_test))
训练集评估分数: 0.7883461511233251测试集评估分数: 0.6358967327447731

减小 alpha 的值,可以让系数受到的限制更小。对于非常小的 alpha 值,系数几乎没有受到限制,将得到一个与 LinearRegression 类似的模型:

ridge01 = Ridge(alpha=0.1).fit(X_train, y_train)print('训练集评估分数:', ridge01.score(X_train, y_train))print('测试集评估分数:', ridge01.score(X_test, y_test))
训练集评估分数: 0.9285782082010736测试集评估分数: 0.7717933688844973

不同取值的alpha所对应的斜率变化是怎样的?

# 画出默认alpha参数的ridge模型的斜率分布点plt.plot(ridge.coef_, 's', label='Ridge alpha=1')# 画出alpha=10参数的ridge模型的斜率分布点plt.plot(ridge10.coef_, '^', label='Ridge alpha=10')# 画出alpha=0.1参数的ridge模型的斜率分布点plt.plot(ridge01.coef_, 'v', label='Ridge alpha=0.1')# 画出LinearRegression模型的斜率分布点plt.plot(lr.coef_, 'o', label='LinearRegression')# 设置横坐标标签plt.xlabel('Coefficient index')# 设置y坐标标签plt.ylabel('coefficient magnitude')# 按照lr斜率集的宽度在0轴画一条水平线plt.hlines(0, 0, len(lr.coef_))# 设置y轴的范围plt.ylim(-25,25)# 显示图例plt.legend()
plt.show()

以上的图例可以方便对不同的alpha系数与斜率的关系做出一个总结:

alpha=10对应的斜率集分布点大部分都集中在0轴附近。说明alpha越大,对于系数的约束更强。

alpha值固定,改变训练数据量,模型的性能将如何表现?

这里有个现成的图示,y轴为模型的评估分数,x轴为训练集数据的数量,分别列出了Ridge的训练集表现与测试集的表现,LinearRegression模型的训练集的表现和测试集的表现。

mglearn.plots.plot_ridge_n_samples()

通过上图,发现,训练集的分数普遍要高于测试集,而约束后的岭回归的训练集分数比标准回归的训练集分数要低,但岭回归在测试集的分数要比标准回归在测试集的分数高。并且,从上图还看出,岭回归随着数据的增加,学到的东西赵来赵多,而标准回归模型在最后才追赶上岭回归,这完全是数据量的功劳。

所以还能得出结论:如果数据量足够大,模型的线束将变得不那么重要。

另一个现象是,从测试集的分数来看,线性回归的性能随着数据的增加,性能一直在下降。

上一节中,学习了k-NN模型,用一句话来总结它的特点就是:近朱者赤,近墨者黑。

本节将开始涉及线性模型相关的概念与模型。

线性模型是在实践中广泛使用的一类模型,它利用输入特征的线性函数进行预测。所以,线性模型非常的耿直

备注:mgleran中的数据是用来展示的,不与机器学习的sklern模块相重叠。

*mgleran请使用pip install mglearn命令。

# 在学习之前,先导入这些常用的模块import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport mglearn

认识线性模型¶

对于回归问题,线性模型预测的一般公式如下:

y = w[0]*x[0]+w[1]*x[0]+...+w[p]*x[p]

这里 x[0] 到 x[p] 表示单个数据点的特征, w 和 b 是学习模型的参数, y 是模型的预测结果。对于单一特征的数据集,公式如下:

y = w[0]*x[0]+b

类似于实践学到的:

y = ax+b

也就是说,w[0]就是斜率,b是截距。对于有更多特征的数据集,w 包含沿每个特征坐标轴的斜率。或者,你也可以将预测的响应值看作输入特征的加权求和,权重由 w 的元素给出(可以取负值)。

下列代码可以在一维w*e数据集上学习参数w[0]和b,也就是ax+b的线性结果。

mglearn.plots.plot_linear_regression_w*e()
w[0]: 0.393906  b: -0.031804

从该模型可以看出,w[0] 在0.4左右,而b比0稍微小一点。

总结:用于回归的线性模型可以表示这样的回归模型:对单一特征的预测结果是一条直线,两个特征时是一个平面,或者在更高维度(即更多特征)时是一个超平面。

从上图中可发现,线性模型与k-NN的回归模型比较起来,似乎准确率没有那么高。但如果数据是多维度的,数量也非常庞大,线性模型将会给出比较完美的拟合。

不同的线性模型之间的区别仅在于如何从训练数据中学习参数w和b,以及如何控制模型复杂度。

认识线性回归模型¶

线性回归,又称普通最小二乘法,是回归问题最简单也最经典的线性方法。

线性回归寻找参数 w 和 b,使得对训练集的预测值与真实的回归目标值 y 之间的均方误差最小。均方误差是预测值与真实值之差的平方和除以样本数。线性回归没有参数,这是一个优点,但也因此无法控制模型的复杂度。

# 从 skleran 中导入线性模型模型 LinearRegressionfrom sklearn.linear_model import LinearRegression# 导入数据分割模块 train_test_splitfrom sklearn.model_selection import train_test_split# 导入线性回归数据X, y = mglearn.datasets.make_w*e(n_samples=60)# 将数据打乱,将分成训练集与测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)# 对训练集数据进行训练lr = LinearRegression().fit(X_train, y_train)

线性模型的“斜率”参数(w,也叫作权重或系数)被保存在coef_属性中,而偏移或截距(b)被保存在intercept_属性中:

print('查看模型的斜率:', lr.coef_)print('查看模型的截距:', lr.intercept_)
查看模型的斜率: [0.39390555]
查看模型的截距: -0.031804343026759746

敲黑板:intercept是一个浮点数;而coef是一个NumPy数组,每个元素对应一个输入特征。这里因为只有一个输入特征,因此coef_中只有一个元素。

接下来,查看一下训练集与测集的性能:

print('训练集精度:', lr.score(X_train, y_train))print('测试集精度:', lr.score(X_test, y_test))
训练集精度: 0.6700890315075756
测试集精度: 0.65933685968637

这个评估结果不是很好,说明模型在训练集和测试集上都存在欠拟合的情况。这是因此,此处提供的是二维的简单数据。如果是在高维度的数据上,线性模型将变得更加的强大,此时则可能有过拟合的可能。

接下来,看一下LinearRegression在更复杂的数据集上的表现——波士顿房价数据集,该数据集拥有506个样本和105个导出特征。

# 导入波士顿房价数据X, y = mglearn.datasets.load_extended_boston()# 将数据分为训练集与测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)# 对训练集数据进行训练lr = LinearRegression().fit(X_train, y_train)

然后再查看一下模型在训练集与测试集上的分数:

print('训练集评估分数:', lr.score(X_train, y_train))print('测试庥评估分数:', lr.score(X_test, y_test))
训练集评估分数: 0.9523526436864238
测试庥评估分数: 0.6057754892935623

结果显示,在训练集的精度很高,而在测试集的精度则比较低,造成这种情况的原因是因为在训练集得出的模型存在近拟合的情况,因此无法更好的适应新的数据。

因此我们应该试图找一个可以控制复杂复杂度的模型,标准线性回归最常用的替代方法之一就是岭回归

认识岭回归¶

岭回归为何会成为标准线性回归的替代之一呢?

岭回归也是一种用于回归的线性模型,因此它的预测公式与普通最小二乘法相同。但在岭回归中,对系数 w 的选择不仅要在训练数据上得出好的预测结果,而且还要拟合附加线束——即希望系数尽量小。

直观上来看,这意味着每个特征对输出的影响应尽可能的小(即斜率很小),同时仍给出很好的预测结果。这种线束是所谓的正则化的一个例子。正则化是指对模型做显示约束,以避免过拟合。岭回归的这种正则化被称为L2正则化

岭回归在 liner_model.Ridge 中实现。来看一下它在波士顿房价的上效果如何。

# 导入岭回归模块from sklearn.linear_model import Ridgeridge = Ridge().fit(X_train, y_train)print('训练集评估分数:', ridge.score(X_train, y_train))print('测试庥评估分数:', ridge.score(X_test, y_test))
训练集评估分数: 0.8860578560395836
测试庥评估分数: 0.7527139600306947

结果显示,Ridge 在训练庥上的分数要低于 LinearRegression, 在测试数据集上的表现比较优秀。

Ridge 是一种约束更强的模型,所以更不容易过拟合。

复杂度更小的模型意味着在训练集上的性能更差,但泛化性能更好。

由于Ridge的泛化能力更好,所以在这里应该选择Ridge模型。

通过设置alpha参数来控制模型的简单性和训练性能¶

在前面的例子中,我们用的是默认的参数 alpha=1.0。它的最取值取决于具体的数据集。

增大 alpha 会使得系数更加趋向于0,从而降低训练集性能,但可能会提高泛化性能。

例如:

ridge10 = Ridge(alpha=10).fit(X_train, y_train)print('训练集评估分数:', ridge10.score(X_train, y_train))print('测试庥评估分数:', ridge10.score(X_test, y_test))
训练集评估分数: 0.7883461511233251
测试庥评估分数: 0.6358967327447731

减小 alpha 的值,可以让系数受到的限制更小。对于非常小的 alpha 值,系数几乎没有受到限制,将得到一个与 LinearRegression 类似的模型:

ridge01 = Ridge(alpha=0.1).fit(X_train, y_train)print('训练集评估分数:', ridge01.score(X_train, y_train))print('测试庥评估分数:', ridge01.score(X_test, y_test))
训练集评估分数: 0.9285782082010736
测试庥评估分数: 0.7717933688844973

不同取值的alpha所对应的斜率变化是怎样的?¶

# 画出默认alpha参数的ridge模型的斜率分布点plt.plot(ridge.coef_, 's', label='Ridge alpha=1')# 画出alpha=10参数的ridge模型的斜率分布点plt.plot(ridge10.coef_, '^', label='Ridge alpha=10')# 画出alpha=0.1参数的ridge模型的斜率分布点plt.plot(ridge01.coef_, 'v', label='Ridge alpha=0.1')# 画出LinearRegression模型的斜率分布点plt.plot(lr.coef_, 'o', label='LinearRegression')# 设置横坐标标签plt.xlabel('Coefficient index')# 设置y坐标标签plt.ylabel('coefficient magnitude')# 按照lr斜率集的宽度在0轴画一条水平线plt.hlines(0, 0, len(lr.coef_))# 设置y轴的范围plt.ylim(-25,25)# 显示图例plt.legend()plt.show()

以上的图例可以方便对不同的alpha系数与斜率的关系做出一个总结:

alpha=10对应的斜率集分布点大部分都集中在0轴附近。说明alpha越大,对于系数的约束更强。

alpha值固定,改变训练数据量,模型的性能将如何表现?¶

这里有个现成的图示,y轴为模型的评估分数,x轴为训练集数据的数量,分别列出了Ridge的训练集表现与测试集的表现,LinearRegression模型的训练集的表现和测试集的表现。

mglearn.plots.plot_ridge_n_samples()

通过上图,发现,训练集的分数普遍要高于测试集,而约束后的岭回归的训练集分数比标准回归的训练集分数要低,但岭回归在测试集的分数要比标准回归在测试集的分数高。并且,从上图还看出,岭回归随着数据的增加,学到的东西赵来赵多,而标准回归模型在最后才追赶上岭回归,这完全是数据量的功劳。

所以还能得出结论:如果数据量足够大,模型的线束将变得不那么重要。

另一个现象是,从测试集的分数来看,线性回归的性能随着数据的增加,性能一直在下降。

全部回复

0/140

量化课程

    移动端课程