利用UCI大学公开的机器学习数据来跑线性回归,数据集是一个循环发电场的数据,共有9568个样本数据,每个数据有5列,分别是:AT(温度), V(压力), AP(湿度), RH(压强), PE(输出电力)。我们的目标是得到一个线性关系,其中AT/V/AP/RH这4个是样本特征,PE是样本输出, 也就是说机器学习的结果是得到一个线性回归模型:

\[PE=\theta _{0}+\theta _{1}*AT+\theta _{2}*V+\theta _{3}*AP+\theta _{4}*RH\]

1 pandas读取数据

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn import datasets, linear_model

data = pd.read_csv('D:/Python/Mechine_learning/data/CCPP/ccpp.csv')
print(data.head())

#输出
      AT      V       AP     RH      PE
0  23.25  71.29  1008.05  71.36  442.21
1  13.87  42.99  1007.45  81.52  471.12
2  16.91  43.96  1013.32  79.87  465.86
3  10.09  37.14  1012.99  72.59  473.66
4  12.72  40.60  1013.45  86.16  471.23

2 准备运行算法的数据

数据维度
print(data.shape) #(9568, 5) 表明是9568*5的数据集
准备样本特征X,用AT, V,AP和RH这4个列作为样本特征

X = data[['AT','V','AP','RH']]
print(X.head())
#输出
      AT      V       AP     RH
0  23.25  71.29  1008.05  71.36
1  13.87  42.99  1007.45  81.52
2  16.91  43.96  1013.32  79.87
3  10.09  37.14  1012.99  72.59
4  12.72  40.60  1013.45  86.16

准备样本输出y, 用PE作为样本输出

y = data[['PE']]
print(y.head())

#输出
       PE
0  442.21
1  471.12
2  465.86
3  473.66
4  471.23

3 划分训练集和测试集

from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)
print(X_train.shape)  #(7176, 4)
print(y_train.shape)  #(7176, 1)
print(X_test.shape)   #(2392, 4)
print(y_test.shape)   #(2392, 1)

75%的样本数据被作为训练集,25%的样本被作为测试集

4 运行scikit-learn的线性模型

scikit-learn的线性回归算法是使用最小二乘法来实现的

from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
linreg.fit(X_train,y_train)

拟合完成后,查看模型系数拟合结果

print(linreg.intercept_)  #[ 452.50329853]
print(linreg.coef_)       #[[-1.98558313 -0.23170236  0.06410905 -0.15673512]]

5 模型评估

评估模型好坏,对于线性回归,一般用均方差(Mean Squared Error, MSE)或者均方根差(Root Mean Squared Error, RMSE)在测试集上的表现来评价模型的好坏

#模型拟合测试集
y_pred = linreg.predict(X_test)
from sklearn import metrics
#scikit-learn计算MSE RMSE
print("MSE:",metrics.mean_squared_error(y_test, y_pred))    #MSE: 19.4303412392
print("RMSE:",np.sqrt(metrics.mean_squared_error(y_test, y_pred)))  #RMSE: 4.4079860752

得到MSE或者RMSE,如果用其他方法得到不同的系数,需要选择模型时,就用MSE较小的模型对应的参数。
比如用AT, V,AP这3个列作为样本特征。不要RH, 输出仍然是PE

X = data[['AT','V','AP']]
y = data[['PE']]
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)
from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
linreg.fit(X_train,y_train)
y_pred = linreg.predict(X_test)
from sklearn import metrics
print("MSE:",metrics.mean_squared_error(y_test, y_pred))    #MSE: 22.8503207832
print("RMSE:",np.sqrt(metrics.mean_squared_error(y_test, y_pred)))    #RMSE: 4.78020091452

去掉RH后,模型拟合效果变差,MSE变大了

6 交叉验证

通过交叉验证来持续优化模型,用10折交叉验证,即cross_val_predict中的cv参数为10

X = data[['AT','V','AP','RH']]
y = data[['PE']]

from sklearn.model_selection import cross_val_predict
predicted = cross_val_predict(linreg, X, y, cv=10)

print("MSE:",metrics.mean_squared_error(y, predicted))  #MSE: 20.7892840922
print("RMSE:",np.sqrt(metrics.mean_squared_error(y, predicted)))    #RMSE: 4.55952673994

采用交叉验证模型的MSE比第5节的大,主要原因是这里是对所有折的样本做测试集对应的预测值的MSE,而第5节仅仅对25%的测试集做了MSE。两者的先决条件并不同

7 画图观察结果

画图真实值和预测值的变化关系,离中间的直线y=x直接越近的点代表预测损失越低

fig, ax = plt.subplots()
ax.scatter(y, predicted)
ax.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=4)
ax.set_xlabel('Measured')
ax.set_ylabel('Predicted')
plt.show()

参考:用scikit-learn和pandas学习线性回归

01-26 05:08