![Python机器学习算法: 原理、实现与案例](https://wfqqreader-1252317822.image.myqcloud.com/cover/317/27563317/b_27563317.jpg)
1.5 项目实战
最后,我们来做一个线性回归的实战项目:分别使用OLSLinearRegression和GDLinearRegression预测红酒口感,如表1-1所示。
表1-1 红酒口感数据集(https://archive.ics.uci.edu/ml/datasets/wine+quality)
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-T21_33020.jpg?sign=1739020886-XH6gO5r4BxGevxzmhNAcLleezSGqD6Gj-0-d272bcc927bc912af6e053b355f5c7be)
数据集中包含1599条数据,其中每一行包含红酒的11个化学特征以及专家评定的口感值。虽然口感值只是3~8的整数,但我们依然把该问题当作回归问题处理,而不是当作包含6种类别(3~8)的分类问题处理。如果当作分类问题,则预测出的类别间无法比较好坏,例如我们不清楚第1类口感是否比第5类口感好,但我们明确知道5.3比4.8口感好。
读者可使用任意方式将数据集文件winequality-red.csv下载到本地,此文件所在的URL为:https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequalityred.csv。
1.5.1 准备数据
调用Numpy的genfromtxt函数加载数据集:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P22_33022.jpg?sign=1739020886-FkHcemVS9JpHslWA5DXfVtfsEtAMbjYM-0-e3cad8afc0611cd49ed72a587f6d70ab)
1.5.2 模型训练与测试
我们要训练并测试两种不同方法实现的线性回归模型:OLSLinearRegression和GDLinearRegression。
1. OLSLinearRegression
先从更为简单的OLSLinearRegression开始。
首先创建模型:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P22_33023.jpg?sign=1739020886-SBLUbUgGEgT8DJqQZadlCqJTbgPI7MEq-0-0a3f1cc54fb7049c2db8f64d1c6e6367)
创建OLSLinearRegression时无须传入任何参数。
然后,调用sklearn中的train_test_split函数将数据集切分为训练集和测试集(比例 为7:3):
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P22_33024.jpg?sign=1739020886-APQYhCIPiqMMxlmWwsSKRODrq1SgxK5K-0-5c69e3a3d17ac7d390021cf09a3a8f5c)
接下来,训练模型:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P22_33025.jpg?sign=1739020886-caBCiXb76B89o2UqYgkla0kYQNrycZS4-0-d33cc5bead531d89a0ac3e2a056aec16)
因为训练集容量及实例特征数量都不大,所以很短时间内便可完成训练。
使用已训练好的模型对测试集中的实例进行预测:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P23_33049.jpg?sign=1739020886-nGfyOXb1Pk7FC7hj5ZUP3ErpVrUqX7cK-0-f14c9deae1e22d30e87edbaeeefa60de)
仍以均方误差(MSE)衡量回归模型的性能,调用sklearn中的mean_squared_error函数计算MSE:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P23_33050.jpg?sign=1739020886-o07NmKe6tQFbWVwhK01jDSMNyKRG5JjS-0-5a3312932a6bb0647b362ef0bb551807)
模型在测试集上的MSE为0.421,其平方根约为0.649。还可以测试模型在训练集上的MSE:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P23_33051.jpg?sign=1739020886-EYyZhBsgrbydi85MeKgKJKcF1KG32qmc-0-1c8e14b8d9306ffaadcf2ab1cccdda39)
模型在训练集与测试集的性能相差不大,表明未发生过度拟合现象。
注意
过度拟合也称为过拟合,不过在中文上下文中使用“过拟合”容易产生歧义,故本书统一使用“过度拟合”。
另一个常用的衡量回归模型的指标是平均绝对误差(MAE),其定义如下:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P23_10597.jpg?sign=1739020886-8Zm5dJckIrZBMcjzAiy4V7MRZx2OMriP-0-47f2fa4b9604a57f9441479955a76a78)
MAE的含义更加直观一些:所有实例预测值与实际值之误差绝对值的平均值。
调用sklearn中的mean_absolute_error函数计算模型在测试集上的MAE:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P23_33053.jpg?sign=1739020886-ERhmtX1FtbxHzYtZg8z4uneCXt0DpDSo-0-a589f3f84183118d58e522e16552db3f)
MAE为0.492,即预测口感值比实际口感值平均差了0.492。
2. GDLinearRegression
再来训练并测试GDLinearRegression,该过程比之前的OLSLinearRegression麻烦一些,因为它有3个超参数需要我们设置,而最优的超参数组合通常需要通过大量实验得到。
GDLinearRegression的超参数有:
(1)梯度下降最大迭代次数n_iter
(2)学习率eta
(3)损失降低阈值tol(tol不为None时,开启早期停止法)
先以超参数(n_iter=3000,eta=0.001,tol=0.00001)创建模型:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P24_33055.jpg?sign=1739020886-t98NoXoEylh2uGYUKBj6Rbff1YmAeEGE-0-2d1f997203f4b2be4203d20a8f916b37)
为了与之前的OLSLinearRegression进行对比,我们使用与之前相同的训练集和测试集(不重新切分X,y)训练模型:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P24_33056.jpg?sign=1739020886-nrPgB58aap2mwIaghQSjWiWsGAd5Jx0K-0-ecce90d6c7d4da5b506e0f7a5e6205a8)
以上输出表明,经过一步梯度下降以后,损失Loss不降反升,然后算法便停止了,这说明步长太大,已经迈到对面山坡上了,需调小学习率。将学习率调整为eta=0.0001再次尝试:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P25_33058.jpg?sign=1739020886-tB1EdKWfyDn6mR20BJz4jFfE292SJOZV-0-732fec2faee5dd08f085a844fa48f878)
这次虽然损失随着迭代逐渐下降了,但是迭代到了最大次数3000,算法依然没有收敛,最终损失(在训练集上的MSE)为0.539,距离之前用最小二乘法计算出的最小值0.417还差很远,并且发现后面每次迭代损失下降得非常小。这种状况主要是由于中各特征尺寸相差较大造成的,观察
中各特征的均值:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P25_33059.jpg?sign=1739020886-S50zODzYjnkl9bZoHXjtCnzIBV4lwoXA-0-21f14c045f4c745913093ae5c5d519a7)
可看出各特征尺寸差距确实很大,有的特征间相差了好几个数量级。以两个特征为例,如果特征尺寸比
的小很多(如图1-5所示),通常
的变化对损失函数值影响更大,梯度下降时就会先沿着接近
轴的方向下山,再沿着
轴进入一段长长的几乎平坦的山谷,用下山时谨慎的小步走平地,速度慢得像蜗牛爬,虽然最终也可以抵达最小值点,但需要更多的迭代次数,花费更长时间。
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P25_10817.jpg?sign=1739020886-aOmjmdgAegw6mTQMTQ75pNlIYeZC4CSW-0-76ef22ba2f264369681d6eeaa48ced70)
图1-5
相反,如果和
特征尺寸相同(见图1-6),梯度下降时将更直接地走向最小值点,算法收敛更快。
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P26_10831.jpg?sign=1739020886-hk4kYIKirsYJW1Wr9f0oDqaSNpiRLAGB-0-c9b8d80ef1c2464fd9224e3bdc11ba2c)
图1-6
接下来我们把各特征缩放到相同尺寸,然后重新训练模型。将特征缩放到相同尺寸有两种常用方法:归一化(Normalization)和标准化(Standardization)。
归一化是指使用min-max缩放将各特征的值缩放至[0, 1]区间。对于第i个实例的第j个特征,归一化转换公式为:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P26_10841.jpg?sign=1739020886-55lsukjTx62Dmjz3cZobkzRnzVwnkpYK-0-8cb56a3a106d2d7cd9517c2869c590d5)
其中,和
分别为所有实例第j个特征的最大值和最小值。调用sklearn中的MinMaxScaler函数可以完成归一化转换。
标准化是指将各特征的均值设置为0,方差设置为1。对于第i个实例的第j个特征,标准化转换公式为:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P26_10853.jpg?sign=1739020886-ykYME4KOMJ8PV6zaOg30sYLb5GEAaRBD-0-87b496769dc57771a18b93cb9b67a34c)
其中,和
分别为所有实例第j个特征的均值和标准差。调用sklearn中的StandardScaler函数可以完成标准化转换。
对于大多数机器学习算法而言,标准化更加实用,因为标准化保持了异常值所蕴含的有用信息。这里我们调用sklearn中的StandardScaler函数对各特征进行缩放:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P27_33061.jpg?sign=1739020886-CZhOJcaogrHN0mtrXVkH1afrGhcx8EnN-0-6d5fe06a86e3b8b506ba699528996f13)
这里需要注意,在以上的代码中,StandardScaler只对训练集进行拟合(计算均值和标准差
),然后使用相同的拟合参数对训练集和测试集进行转换,因为在预测时测试集对于我们是未知的。
现在各特征值被缩放到了相同的尺寸。接下来重新创建模型,并使用已缩放的数据进行训练:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P27_33062.jpg?sign=1739020886-iRlbXFLegxBGhhUPNDrGVf52PTBpsf3Q-0-217873e7c786650c1429cc1d06d752d0)
这次我们将eta大幅提高到了0.05,经过136次迭代后算法收敛,目前损失(在训练集上的MSE)为0.428,已接近用最小二乘法计算出的最小值0.417。
最后使用已训练好的模型对测试集中的实例进行预测,并评估性能:
![](https://epubservercos.yuewen.com/889FA0/15825992205221106/epubprivate/OEBPS/Images/Figure-P28_33064.jpg?sign=1739020886-KyLzXTqwv6qXUPI2xfIJsxdtJVBLHgbT-0-1265d2638d14c3c89e4af340710dba45)
此时MSE为0.393,MAE为0.492,与之前使用OLSLinearRegression的性能差不多。读者可以继续调整超参数进行优化,但性能不会有太明显的提升,毕竟线性回归是非常简单的模型。
至此,线性回归的项目就完成了。