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

 

 

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

from http://www.javashuo.com/article/p-kabizhvn-bd.htmljavascript

就算是简单的算法,也须要跑通整个流程,经过一个简单的回归的例子,能够看到: 数据的准备 ,数据的维度? 用哪一个模型,如何训练,如何评价,可视化? 有一系列的东西须要去落地,推导理解十一方面,同时也要会用。 就这个回归的例子,和以前的 GMM 的例子很像,整个一套流程的东西很像,可是这里咱们是用 sklearn 这个框架来完成的。css


这里咱们用 UCI 大学公开的机器学习数据来跑线性回归。html

数据的介绍在这: http://archive.ics.uci.edu/ml/datasets/Combined+Cycle+Power+Planthtml5

数据的下载地址在这: http://archive.ics.uci.edu/ml/machine-learning-databases/00294/java

里面是一个循环发电场的数据,共有 9568 个样本数据,每一个数据有 5 列,分别是: AT(温度), V(压力), AP(湿度), RH(压强), PE(输出电力)。咱们不用纠结于每项具体的意思。python

咱们的问题是获得一个线性的关系,对应 PE 是样本输出,而 AT/V/AP/RH 这 4 个是样本特征, 机器学习的目的就是获得一个线性回归模型,即:jquery

PE=θ0+θ1∗AT+θ2∗V+θ3∗AP+θ4∗RHPE=θ0+θ1∗AT+θ2∗V+θ3∗AP+θ4∗RHlinux

而须要学习的,就是θ0,θ1,θ2,θ3,θ4θ0,θ1,θ2,θ3,θ4 这 5 个参数。android

下载后的数据能够发现是一个压缩文件,解压后能够看到里面有一个 xlsx 文件,咱们先用 excel 把它打开,接着 “另存为 “”csv 格式,保存下来,后面咱们就用这个 csv 来运行线性回归。css3

打开这个 csv 能够发现数据已经整理好,没有非法数据,所以不须要作预处理。可是这些数据并无归一化,也就是转化为均值 0,方差 1 的格式。也不用咱们搞,后面 scikit-learn 在线性回归时会先帮咱们把归一化搞定。

好了,有了这个 csv 格式的数据,咱们就能够大干一场了。

In [1]:
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import pandas as pd
from sklearn import datasets, linear_model
 

用 pandas 来读取数据

In [2]:
data = pd.read_csv('Folds5x2_pp.csv')
data.head()
Out[2]:
 
  AT V AP RH PE
0 8.34 40.77 1010.84 90.01 480.48
1 23.64 58.49 1011.40 74.20 445.75
2 29.74 56.90 1007.15 41.91 438.76
3 19.07 49.69 1007.22 76.79 453.09
4 11.80 40.66 1017.13 97.20 464.43
 

准备运行算法的数据

In [3]:
data.shape
Out[3]:
(9568, 5)
In [4]:
X = data[['AT', 'V', 'AP', 'RH']]
X.head()
Out[4]:
 
  AT V AP RH
0 8.34 40.77 1010.84 90.01
1 23.64 58.49 1011.40 74.20
2 29.74 56.90 1007.15 41.91
3 19.07 49.69 1007.22 76.79
4 11.80 40.66 1017.13 97.20
In [16]:
y = data[['PE']]
print(type(y))
y.head()
 
<class 'pandas.core.frame.DataFrame'>
Out[16]:
 
  PE
0 480.48
1 445.75
2 438.76
3 453.09
4 464.43
 

划分训练集和测试集

咱们把 X 和 y 的样本组合划分红两部分,一部分是训练集,一部分是测试集,代码以下:

能够看到75%的样本数据被做为训练集,25%的样本被做为测试集。

In [30]:
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,y_train.shape,X_test.shape,y_test.shape,type(X_train))
 
(7176, 4) (7176, 1) (2392, 4) (2392, 1) <class 'pandas.core.frame.DataFrame'>
 

运行 scikit-learn 的线性模型

终于到了临门一脚了,咱们能够用scikit-learn的线性模型来拟合咱们的问题了。scikit-learn的线性回归算法使用的是最小二乘法来实现的。代码以下:

In [31]:
from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
linreg.fit(X_train, y_train)
print(linreg.intercept_)     #在线性模型的属性里。
print(linreg.coef_)
 
[447.06297099]
[[-1.97376045 -0.23229086  0.0693515  -0.15806957]]
 

也就是说 PE 和其余 4 个变量的关系以下:

PE=447.06297099−1.97376045∗AT−0.23229086∗V+0.0693515∗AP−0.15806957∗RH

 

模型评价

    咱们须要评估咱们的模型的好坏程度,对于线性回归来讲,咱们通常用均方差(Mean Squared Error, MSE)或者均方根差 (Root Mean Squared Error, RMSE) 在测试集上的表现来评价模型的好坏。

    咱们看看咱们的模型的 MSE 和 RMSE,代码以下:

In [11]:
#模型拟合测试集
y_pred = linreg.predict(X_test)
from sklearn import metrics
# 用scikit-learn计算MSE
print("MSE:",metrics.mean_squared_error(y_test, y_pred))
# 用scikit-learn计算RMSE
print("RMSE:",np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
 
MSE: 20.080401202073904
RMSE: 4.481116066570236
 

获得了 MSE 或者 RMSE,若是咱们用其余方法获得了不一样的系数,须要选择模型时,就用 MSE 小的时候对应的参数。

    好比此次咱们用 AT, V,AP 这 3 个列做为样本特征。不要 RH, 输出仍然是 PE。代码以下:

In [12]:
X = data[['AT', 'V', 'AP']]
y = data[['PE']]
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
# 用scikit-learn计算MSE
print("MSE:",metrics.mean_squared_error(y_test, y_pred))
# 用scikit-learn计算RMSE
print("RMSE:",np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
 
MSE: 23.208907470136236
RMSE: 4.817562399194871
 

能够看出,去掉RH后,模型拟合的没有加上RH的好,MSE变大了。

 

交叉验证

咱们能够经过交叉验证来持续优化模型,代码以下,咱们采用10折交叉验证,即cross_val_predict中的cv参数为10:

In [18]:
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)
# 用scikit-learn计算MSE
print("MSE:",metrics.mean_squared_error(y, predicted))
# 用scikit-learn计算RMSE
print("RMSE:",np.sqrt(metrics.mean_squared_error(y, predicted)))
 
MSE: 20.7955974619431
RMSE: 4.560219014690314
 

能够看出,采用交叉验证模型的 MSE 比第 6 节的大,主要缘由是咱们这里是对全部折的样本作测试集对应的预测值的 MSE,而第 6 节仅仅对 25% 的测试集作了 MSE。二者的先决条件并不一样。

 

疑惑解答:

2018-01-04 14:10 小北潜行
你好~ 真的很是感谢你的文章。理论和实际使用相结合,好理解不少~~ 有个问题,就是不太明白 8. 交叉验证这一部分的做用 上文中 8 使用的数据集和前面计算均方差的数据集不同,因此获得的数值不同 可是若是使用相同的数据集,那和前面计算出来的数值没有差别 那这部分的做用体如今哪里呢?

[楼主] 2018-01-05 10:52 刘建平 Pinard
@ 小北潜行 你好,这是一个简单的例子,主要是说均方差能够用来衡量模型的好坏,能够怎么用,通常在交叉验证的时候不用看 MSE。

何时用 MSE 呢?在作模型测试的时候。

针对训练集和测试集,第一次选择合适参数 (好比优化方法,正则化参数等),训练集交叉验证出来的模型 A,来预测测试集,能够计算 MSE-A,第二次选择合适参数,训练集交叉验证出来的模型 B,来预测测试集,能够计算 MSE-B,经过 MSE-A 和 MSE-B 的大小,能够衡量模型 A 和 B 的好坏。


2018-03-18 18:50 TinyLaughing
博主,您好! 对于第 8 节的 10 折交叉验证有点不明白。 个人理解是 10 折交叉验证,获得了 10 个不一样的模型,每个模型有各自的系数、截距以及 MSE。(这样理解不知道对不对?) 那么,博主文中计算的 MSE 是 10 个模型的 MSE 的平均值,仍是 10 个模型中最优模型的 MSE(即 10 个 MSE 的最小值)? [楼主] 2018-03-25 18:51 刘建平 Pinard
@ TinyLaughing 你好,就是 10 个模型中最优模型的 MSE(即 10 个 MSE 的最小值)。 由于交叉验证的目的是找到最好的模型参数,而如何评判呢?对于这个例子就看这 10 折交叉验证中哪一次的 MSE 最好,那么对应的模型参数咱们认为是最优的。

至于你们都很关心的,如何求出交叉验证的 参数和截距:

对于你说的需求,直接使用 skearn 单个 API 是没法获得的。 可行的作法是: 1)用 sklearn.model_selection.KFold 将数据分红 K 折。 2) 本身作一个循环(共 K 次),每次合并其中的 K-1 折的数据作训练集,另 1 折作测试集,按第 6 节的方法训练,打印模型参数和 MSE。 3)选择最小 MSE 对应的模型参数。

 

画图观察结果

这里画图真实值和预测值的变化关系,离中间的直线 y=x 直接越近的点表明预测损失越低。代码以下:

In [27]:
fig, ax = plt.subplots()
ax.scatter(y, predicted)
ax.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=4) #lw表示线宽
ax.set_xlabel('Measured')
ax.set_ylabel('Predicted')
plt.show()
 
相关文章
相关标签/搜索