声明:
- 参考用Sckit-Learn和Pandas学习线性回归
- 入门机器学习仅仅靠这一篇文章还是有些不够,建议大家戳一戳文中的链接,看一下相关的知识。
从简单的线性回归入门机器学习
虽然本文从一开始就限定了机器学习的方法——线性回归,但是在大多数情况下,解决问题的主要难点在于寻找合适的机器学习方法上。而这方面需要长期的积累,所以显然不是本文要讲的内容了。
下面,本文将用面向过程的方式分解解决线性回归问题的步骤(每一个章节标题都是一个步骤),以此来帮助大家对机器学习有一个初步的了解。
获取数据,定义问题
没有数据,当然没法研究机器学习啦。:) 这里我们用UCI大学公开的机器学习数据来跑线性回归。
数据的介绍戳戳戳
数据的下载地址戳戳戳
里面是一个循环发电场的数据,共有9568个样本数据,每个数据有5列,分别是:AT(温度), V(压力), AP(湿度), RH(压强),
PE(输出电力)。我们不用纠结于每项具体的意思。我们的问题是得到一个线性的关系,对应PE是样本输出,而AT/V/AP/RH这4个是样本特征, 机器学习的目的就是得到一个线性回归模型,即:
PE=θ0+θ1∗AT+θ2∗V+θ3∗AP+θ4∗RH” role=”presentation” style=”position: relative;”>PE=θ0+θ1∗AT+θ2∗V+θ3∗AP+θ4∗RHPE=θ0+θ1∗AT+θ2∗V+θ3∗AP+θ4∗RH这5个参数。
整理数据
下载后的数据可以发现是一个压缩文件,解压后可以看到里面有一个xlsx文件,我们先用excel把它打开,接着“另存为”csv格式(只需要保存一个sheet就可以了),保存下来,后面我们就用这个csv来运行线性回归。
ps: 本文另存为了“ccpp.csv”。转成csv格式是为了读取更方便。打开这个csv可以发现数据已经整理好,没有非法数据,因此不需要做预处理。但是这些数据并没有归一化,也就是转化为均值0,方差1的格式。也不用我们搞,后面scikit-learn在线性回归时会先帮我们把归一化搞定。
好了,有了这个csv格式的数据,我们就可以大干一场了。
所谓非法数据,主要是指空值,一般在机器学习或者深度学习中都不接受空值,需要删除或者插值处理。
用pandas来读取数据
推荐使用的一个交互式编程工具:jupyter notebook
读取数据到变量data中
import pandas as pd
import numpy as np
data = pd.read_csv(r'./ccpp.csv', header=0)
- 1
- 2
- 3
查看data的信息
data.head() # 前五行的信息
- 1
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/399e3d0078b69da35d07ca31fb846ec5.png)
data.shape # data的长和宽
'''输出'''
# (9568, 5)
- 1
- 2
- 3
可以看到,data是一个pandas中的DataFrame类型,其列名是5个变量,索引是0, 1, 2…9567
准备运行算法的数据
我们的目的是通过对前四个变量AT, V, AP, RH建立一个线性关系来预测RE,即对于函数y=f(x)
,机器通过输入x和输出y,找到它们之间的线性映射。
机器学习的含义也可以在这里得到解释:通过对大量数据的学习,找出一定的规律,当再次碰到相似的数据时,可以通过之前获得的规律来作出判断。
所以我们的输出数据X是表格data的前4列,输出真实值y是表格data的最后一列。
X = data[['AT', 'V', 'AP', 'RH']]
y = data[['PE']]
- 1
- 2
划分训练集和测试集
为什么要划分训练集和测试集?
上一个章节中,我们已经得到输入X和输出y,这足以让我们完成对机器的训练。但是,为了评估机器学习效果的好坏,还需要一些数据进行测试。
训练集和测试集分开是机器学习界的公式,这样可以防止过拟合,增强机器学习算法的泛化能力。
如何划分训练集和测试集?
在sklearn库中提供了一个划分函数:
# 首先从sklearn库中导入划分函数
from sklearn.model_selection import train_test_split
# 然后执行函数获得结果
x_train, x_test, y_train, y_test = train_test_split(X, y, random_state=0)
print('x_train.shape: ', x_train.shape)
print('y_train.shape: ', y_train.shape)
print('x_test.shape: ', x_test.shape)
print('y_test.shape: ', y_test.shape)
'''输出'''
# x_train.shape: (7176, 4)
# y_train.shape: (7176, 1)
# x_test.shape: (2392, 4)
# y_test.shape: (2392, 1)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
这个函数涉及到两个问题:
- random_state是什么? 它是一个随机种子,用来生成随机数。当random_state一样时,划分的数据就服从同一种随机分布。
- 如何确定训练集和测试集分割的比例? 默认参数
test_size=0.25
,即默认训练集:测试集=3:1。可以改变这个参数以获得不同的分割比例。
运行scikit-learn的线性模型
这一步就是线性回归算法部分了,看起来最神秘,但是由于sklearn库已经将算法封装好了,所以用起来相当简单。
# 首先从sklearn库中导入线性回归函数
from sklearn.linear_model import LinearRegression
# 执行函数获得一个线性回归模型
linreg = LinearRegression() # 这是一个未经训练的机器学习模型
# 对模型传入输入数据x_train和输出数据y_train
linreg.fit(x_train, y_train) # 这是一个经过训练的机器学习模型
'''输出线性回归的截距和各个系数'''
print('linreg.intercept_: ', linreg.intercept_)
print('linreg.coef_: ', linreg.coef_)
'''输出'''
# linreg.intercept_: [ 451.19095935]
# linreg.coef_: [[-1.98357941 -0.23219575 0.06559288 -0.15932893]]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
经过训练的线性回归模型可以给我们返回一组系数,将这组系数带入前面的公式就可得线性回归预测的回归函数:
PE=447.06297099−1.97376045∗AT−0.23229086∗V+0.0693515∗AP−0.15806957∗RH” role=”presentation” style=”position: relative;”>PE=447.06297099−1.97376045∗AT−0.23229086∗V+0.0693515∗AP−0.15806957∗RHPE=447.06297099−1.97376045∗AT−0.23229086∗V+0.0693515∗AP−0.15806957∗RH
评价模型
现在,机器学习模型已经根据数据学习到了一个线性回归的规律。这一章节,我们需要评估我们的模型的好坏程度,对于线性回归来说,我们一般用均方差(Mean Squared Error, MSE)或者均方根差(Root Mean Squared Error, RMSE)在测试集上的表现来评价模型的好坏。
同时,sklearn提供了一套用于评估模型好坏的工具库——metrics,不用我们自己敲代码了。
前面划分的测试集在这里将排上用场:
y_pred = linreg.predict(x_test)
# 引入sklearn模型评价工具库
from sklearn import metrics
print("MSE: ", metrics.mean_squared_error(y_test, y_pred))
print("RMSE: ", np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
'''输出'''
# MSE: 20.5442988776
# RMSE: 4.53258192178
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
确实,这样看模型的好坏程度很不直观,得到一个浮点数不能让我们确定模型训练的效果。但是这个数值的意义在于,当我们使用了多种机器学习模型时,如何进行横向比较选择效果最好的模型,具有重大的参考意义。
本文后面还会用可视化的方式直观的表示模型学习效果的好坏。
调优
所谓调优,就是调整机器学习模型(本文中为线性回归)中的参数。很多人认为机器学习很简单,就是选个模型然和调参,实际并非如此。
言归正传,进行调优最常用的方法是交叉验证。进行交叉验证,我们不仅需要训练集和测试集,还应该再把训练集分成子训练集和验证集。然后,通过子训练集和验证集获得最优的参数。最后用测试集进行评估作为当前模型(本位为简单线性回归)的最终评分。
画图观察结果
这里画图真实值和预测值的变化关系,离中间的直线y=x直接越近的点代表预测损失越低。代码如下:
%matplotlib inline # 这是为了能在交互式界面中显示图像
import matplotlib.pyplot as plt
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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/3a8309d8fdf27355c18f54c59a2f2bfa.png)
为什么要这样画图?
对于输出y来说,真实值和预测值都是一维的,同时,真实值和预测值一一对应,它们之间的差值越小,预测越准确。显然,如果预测值=真实值,那么它们的差值最小,即上图中的黑色虚线。横坐标是真实值,纵坐标是预测值,那么对于所有的真实值,预测值离着黑线越近,预测越准确。
总结
这是本文进行线性回归的流程图:
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/b0d53faea6f5a561c269d0c77ddbbb57.png)