本文适合入门级同学,老司机绕行。
吴恩达老师的机器学习课程,介绍的第一个模型就是线性回归模型。机器学习(尤其是监督学习),主要围绕分类和回归两类问题展开,而线性回归模型作为最简单的回归模型,与大多数监督学习算法具有相同的建模思路,包括建立损失函数、优化参数、模型评估。可谓麻雀虽小五脏俱全,了解线性回归的建模思想能够有助于理解复杂的深度学习模型。
import numpy as np
from numpy import random
import matplotlib.pyplot as plt
X = random.uniform(0, 30, 100) # 随机生成在[0,30]区间内服从均匀分布的100个数
y = 1.85 * X + random.normal(2, 5, 100) # 对X乘以固定系数后加上随机扰动
plt.scatter(X, y)
plt.xlabel('X')
plt.ylabel('y')
plt.show()
以上代码随机生成一组样本X和y,现在给定一组X值,需要预测其对应的y值。
解决这个问题的思路如下:
以上问题中 X X 称为自变量, y y 称为因变量,找到最优直线方程 y=w∗X+b∗ y = w ∗ X + b ∗ ,使得因变量的估计值与实际值之间的误差最小的过程,称为线性回归。
- 导入相关模块
# coding: utf8
import numpy as np
from numpy import random
import matplotlib.pyplot as plt
from keras.layers import Input, Dense
from keras.optimizers import SGD
from keras.models import Model
from keras.utils import plot_model
- 随机生成数据集(与本文最开始重复,但为保证连贯性,此处重写)
X = random.uniform(0, 30, 100) # 随机生成在[0,30]区间内服从均匀分布的100个数
y = 1.85 * X + random.normal(0, 2, 100) # 对X乘以固定系数后加上随机扰动
plt.scatter(X, y)
plt.xlabel('X')
plt.ylabel('y')
plt.show() # 查看数据散点图
input_shape = (1,) # 声明输入tensor的shape
input_tensor = Input(shape=input_shape) # 由于输入必须是tensor,所以通过Input函数根据指定的输入tensor的shape,生成输入tensor
predict = Dense(1, activation='linear', name='output')(input_tensor) # 通过Dense函数添加回归函数,指定为'linear'即为线性函数,函数输入为输入tensor
model = Model(inputs=input_tensor, outputs=predict) # 生成model,并指定输入和输出
print(model.summary()) # 查看生成的模型结构
从model.summary()输出的结果可以看到:输入层仅仅是将输入数据转变成tensor,而shape不变,所以输入的shape为(None, 1),None表示输入的样本数据数量,此处由于没有指定具体的输入,所以对应值为None,shape里面的1表示输入样本的维度;output层的输出shape与输入层一样,表示输出值得维度也为1,与本文线性回归的样本数据维度一致;输出层的参数数为2,表示有2个参数需要训练,对应前文的 w w 和 b b 。
# 编译模型:loss参数指定损失函数为均方误差,optimizer指定优化算法为随机梯度下降法,学习率为0.01,作为入门,不必过于关心优化算法的参数
model.compile(loss='mse', optimizer=SGD(lr=0.01))
# 训练模型:指定样本输入和输出,将训练样本中的20%作为验证集评估模型效果
train_history = model.fit(X, y, validation_split=0.2,
epochs=100, batch_size=100, verbose=2)
从上面过程可以看出,在Keras里面搭建模型,就跟搭积木一样,非常方便!
可以看到,在迭代到40次左右,目标函数就收敛到最小值,也就是得到了最有参数 w∗ w ∗ 和 b∗ b ∗ 。
[w, b] = model.layers[1].get_weights()
print(w, b)
[[1.8470368]] [0.06696377]
输出结果显示 w∗=1.847,b∗=0.0669 w ∗ = 1.847 , b ∗ = 0.0669 ,而我们生成数据的函数为 y=1.85x y = 1.85 x 加上均值为0标准差为2的随机扰动项,即 w∗=1.85,b∗=0 w ∗ = 1.85 , b ∗ = 0 ,因此可以认为得到的最优权重非常接近真实值。
通过model.layer可以得到模型中所有的层,并通过索引指定特定层,通过get_weights()函数获取对应层的参数。
plt.scatter(X, y)
plt.xlabel('X')
plt.ylabel('y')
x1 = np.linspace(0, 30, 1000)
y1 = w[0][0]*x1 + b[0]
plt.plot(x1, y1, 'r')
从图可以看出,回归直线与样本数据的变化趋势吻合的非常好!
本文结束。