公众号:尤而小屋
作者:Peter
编辑:Peter
大家好,我是Peter~
今天带来的是机器学习的一篇实战文章:利用机器学习库scikit-learn实战线性回归模型。
机器学习实战—线性回归
在理想的状态下,任何非线性的东西都是可以通过线性的东西来拟合的(参考泰勒公式)。而且线性模型本质上是均值预测,而大部分事物的变化都只是围绕着均值来波动(参考大数定理),所以线性模型能够模拟绝大部分的现象。
文章目录
基本形式
基本表达
假设x是由d个属性来描述:;其中表示第i个属性上的取值。线性模型是通过各个属性之间的组合来得到一个进行预测的函数,可表示为:
如果用向量表示为:
其中称之为权重,b称之为偏置
不同形式
不同尺度下的线性函数f(x):
- f(x)取离散的值:线性多分类模型
- f(x)取实数域上实值函数:线性回归模型
- f(x)为对数:对数线性模式
- f(x)进行sigmoid非线性变换:对数几率回归
本文中重点讲解的是线性回归问题,参考资料:《周志华-机器学习》和李航《统计学习方法》,还有datawhale的《南瓜书》公式部分。
线性回归
给定数据集。
线性回归linear regression试图学得一个线性模型,尽可能使得预测值和实际值之间的差别最小
衡量方法
使用均方误差来衡量:找到合适的w和b,满足
均方误差对应的就是常用的欧几里得距离(欧式距离)。基于均方误差最小化来进行模型求解的方法称之为:最小二乘法。
在线性回归模型中,最小二乘法就是试图找到一条直线,使得所有样本到直线上的欧氏距离之和最小
参数求解
求解w和b使达到最小,这个过程称之为最小二乘法的参数估计
E(w,b)对w和b单独求导的过程,具体推导过程参考:https://datawhalechina.github.io/pumpkin-book/#/chapter3/chapter3
令上面的两个求导出来的结果等于0,我们可以得到w和b的两个结果:
sklearn实战线性回归
我们通过网上的一个公开的数据集,来实现如何利用机器学习库sklearn进行线性回归学习线性回归问题。
数据来源
数据探索
数据处理
运行sklearn的线性模型
模型评估
模型优化
可视化展示结果
数据来源
1、数据的介绍看这里: http://archive.ics.uci.edu/ml/datasets/Combined+Cycle+Power+Plant
2、数据的下载地址请移步 http://archive.ics.uci.edu/ml/machine-learning-databases/00294/
数据中有4个字段属性用来描述发电厂的输出电力,最后一个是真实的输出电力值。
我们现在需要做的是利用线性回归模型找到4个因素对输出电力的影响,来预测后期的发电力。
数据探索
import pandas as pd
import numpy as np
from sklearn import datasets, linear_model
from sklearn.linear_model import LinearRegression # 导入线性回归模型
import matplotlib.pyplot as plt
%matplotlib inline
1、读取数据
2、数据信息查看
3、数据统计信息查看
数据处理
1、选择需要的样本数据X,也就是前4个字段的信息
2、选择我们的样本输出标签数据y,也就是最后一个属性字段的数据
数据集划分
数据集的划分:一部分变成训练集,另一部分划分成测试集
from sklearn.model_selection import train_test_split # 从模型选择模块中导入训练、测试集模块
X_train,X_test,y_train,y_test = train_test_split(X, y, random_state=1)
X_train # 7176条数据训练数据
测试集的数据是2392条:
样本的输出值的行记录是和对应的X相同的;同时我们也发现:本次案例有75%的数据作为了训练集,25%作为了测试集
拟合实例化对象
line.fit(X_train,y_train)
LinearRegression()
查看我们模拟出来的系数:
print(line.intercept_) # 相当于是d;类似于截距
print(line.coef_) # 相当于是每个w的取值
[460.05727267]
[[-1.96865472 -0.2392946 0.0568509 -0.15861467]]
到这里,我们就已经模拟出来了线性回归的表达式:也就是PE和前面4个变量之间的关系式子:
模型评价
通过训练集的数据我们得到了线性回归的表达式,现在我们通过该表达式来模拟我们之前产生的测试集数据。
一个模型的评估,对于线性回归通常就是用上面我们介绍的均方差(Mean Squared Error, MSE)或者均方根差(Root Mean Squared Error, RMSE)在测试集上的表现来评价模型的好坏。下面通过代码来进行测试:
y_pred = line.predict(X_test) # 对测试集数据进行预测
y_pred
array([[457.26722361],
[466.70748375],
[440.33763981],
...,
[457.39596168],
[429.37990249],
[438.16837983]])
len(y_pred)
2392
预测到结果之后,我们将预测值和实际值进行比较:
from sklearn import metrics # 对比模块
# 输出MSE
print("MSE:",metrics.mean_squared_error(y_test,y_pred))
MSE: 20.837191547220346
# 输出RMSE:MSE开根号的结果
print("RMSE: ",np.sqrt(metrics.mean_squared_error(y_test,y_pred)))
RMSE: 4.564777272465804
使用交叉验证优化模型
交叉验证法:将全部的数据样本D划分成k个大小相似的互斥子集。每个子集尽量保持数据分布的一致性。然后用用k-1个子集作为训练集,剩下的那个作为测试集。
这样就可以获取k组训练集/测试集,从而进行k次的训练和测试,最终返回k次训练的均值。
我们可以使用sklearn中自带的交叉验证方法来优化我们得到的模型,下面的例子中,采用的10折交叉验证:
line
LinearRegression()
from sklearn.model_selection import cross_val_predict # 导入交叉验证模块
y_predicted = cross_val_predict(line,X,y,cv=10)
y_predicted # 通过交叉验证得到的预测值
array([[467.24487977],
[444.06421837],
[483.53893768],
...,
[432.47556666],
[443.07355843],
[449.74395838]])
len(y_predicted)
9568
通过交叉验证得到的预测值predicted和真实值求MSE和RMSE:
# 输出MSE
print("MSE:",metrics.mean_squared_error(y,y_predicted))
MSE: 20.79367250985753
print("RMSE: ",np.sqrt(metrics.mean_squared_error(y,y_predicted)))
RMSE: 4.560007950635342
我们发现:通过使用交叉验证后的均方误差优于未使用情况下的误差
绘图
最后,我们画出真实的样本值和预测值之间的图形,当点距离中间y=x的值越近,说明预测损失越低。
下面是使用matplotlib绘图的代码和效果:
fig, ax = plt.subplots()
ax.scatter(y, y_predicted)
ax.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=3)
ax.set_xlabel('Measured') # 真实值
ax.set_ylabel('Predicted') # 预测值
plt.show()
我把数据用Plotly_express重新绘制了一遍,看看效果:
data = pd.concat([pd.DataFrame(y),pd.DataFrame(y_predicted)],axis=1)
data.columns = ["Measured", "Predicted"]
data
import plotly_express as px
fig = px.scatter(data,
x="Measured", # 真实值
y="Predicted", # 预测值
trendline="ols", # 趋势线
trendline_color_override="red" # 颜色
)
fig.show()