利用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()