声明:
虽然本文从一开始就限定了机器学习的方法——线性回归,但是在大多数情况下,解决问题的主要难点在于寻找合适的机器学习方法上。而这方面需要长期的积累,所以显然不是本文要讲的内容了。
下面,本文将用面向过程的方式分解解决线性回归问题的步骤(每一个章节标题都是一个步骤),以此来帮助大家对机器学习有一个初步的了解。
没有数据,当然没法研究机器学习啦。:) 这里我们用UCI大学公开的机器学习数据来跑线性回归。
数据的介绍戳戳戳
数据的下载地址戳戳戳
里面是一个循环发电场的数据,共有9568个样本数据,每个数据有5列,分别是:AT(温度), V(压力), AP(湿度), RH(压强),
PE(输出电力)。我们不用纠结于每项具体的意思。我们的问题是得到一个线性的关系,对应PE是样本输出,而AT/V/AP/RH这4个是样本特征, 机器学习的目的就是得到一个线性回归模型,即:
PE=θ0+θ1∗AT+θ2∗V+θ3∗AP+θ4∗RH 而需要学习的,就是 θ0 、 θ1 、 θ2 、 θ3 、 θ4 这5个参数。
下载后的数据可以发现是一个压缩文件,解压后可以看到里面有一个xlsx文件,我们先用excel把它打开,接着“另存为”csv格式(只需要保存一个sheet就可以了),保存下来,后面我们就用这个csv来运行线性回归。
ps: 本文另存为了“ccpp.csv”。转成csv格式是为了读取更方便。打开这个csv可以发现数据已经整理好,没有非法数据,因此不需要做预处理。但是这些数据并没有归一化,也就是转化为均值0,方差1的格式。也不用我们搞,后面scikit-learn在线性回归时会先帮我们把归一化搞定。
好了,有了这个csv格式的数据,我们就可以大干一场了。
所谓非法数据,主要是指空值,一般在机器学习或者深度学习中都不接受空值,需要删除或者插值处理。
推荐使用的一个交互式编程工具:jupyter notebook
读取数据到变量data中
import pandas as pd
import numpy as np
data = pd.read_csv(r'./ccpp.csv', header=0)
查看data的信息
data.head() # 前五行的信息
data.shape # data的长和宽
'''输出'''
# (9568, 5)
可以看到,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']]
为什么要划分训练集和测试集?
上一个章节中,我们已经得到输入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)
这个函数涉及到两个问题:
test_size=0.25
,即默认训练集:测试集=3:1。可以改变这个参数以获得不同的分割比例。这一步就是线性回归算法部分了,看起来最神秘,但是由于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]]
经过训练的线性回归模型可以给我们返回一组系数,将这组系数带入前面的公式就可得线性回归预测的回归函数:
PE=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
确实,这样看模型的好坏程度很不直观,得到一个浮点数不能让我们确定模型训练的效果。但是这个数值的意义在于,当我们使用了多种机器学习模型时,如何进行横向比较选择效果最好的模型,具有重大的参考意义。
本文后面还会用可视化的方式直观的表示模型学习效果的好坏。
所谓调优,就是调整机器学习模型(本文中为线性回归)中的参数。很多人认为机器学习很简单,就是选个模型然和调参,实际并非如此。
言归正传,进行调优最常用的方法是交叉验证。进行交叉验证,我们不仅需要训练集和测试集,还应该再把训练集分成子训练集和验证集。然后,通过子训练集和验证集获得最优的参数。最后用测试集进行评估作为当前模型(本位为简单线性回归)的最终评分。
这里画图真实值和预测值的变化关系,离中间的直线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()
这是本文进行线性回归的流程图: