线性回归
输入 输出 0.5 5.0 0.6 5.5 0.8 6.0 1.1 6.8 1.4 7.0 ... y = f(x)
预测函数:y = w0+w1x
x: 输入
y: 输出
w0和w1: 模型参数
5.0 = w0 + w1 × 0.5
5.5 = w0 + w1 × 0.6
单样本误差:
根据预测函数求出输入为x时的预测值:y' = w0 + w1x,单样本误差为1/2(y' - y)2。
总样本误差:
把所有单样本误差相加即是总样本误差:1/2 Σ(y' - y)2
损失函数:
loss = 1/2 Σ(w0 + w1x - y)2
所以损失函数就是总样本误差关于模型参数的函数,该函数属于三维数学模型,即需要找到一组w0 w1使得loss取极小值。
案例:画图模拟梯度下降的过程
1.整理训练集数据,自定义梯度下降算法规则,求出w0 , w1 ,绘制回归线。
import numpy as np import matplotlib.pyplot as mp train_x = np.array([0.5, 0.6, 0.8, 1.1, 1.4]) train_y = np.array([5.0, 5.5, 6.0, 6.8, 7.0]) test_x = np.array([0.45, 0.55, 1.0, 1.3, 1.5]) test_y = np.array([4.8, 5.3, 6.4, 6.9, 7.3]) times = 1000 # 定义梯度下降次数 lrate = 0.01 # 记录每次梯度下降参数变化率 epoches = [] # 记录每次梯度下降的索引 w0, w1, losses = [1], [1], [] for i in range(1, times + 1): epoches.append(i) loss = (((w0[-1] + w1[-1] * train_x) - train_y) ** 2).sum() / 2 losses.append(loss) d0 = ((w0[-1] + w1[-1] * train_x) - train_y).sum() d1 = (((w0[-1] + w1[-1] * train_x) - train_y) * train_x).sum() print('{:4}> w0={:.8f}, w1={:.8f}, loss={:.8f}'.format(epoches[-1], w0[-1], w1[-1], losses[-1])) w0.append(w0[-1] - lrate * d0) w1.append(w1[-1] - lrate * d1) pred_test_y = w0[-1] + w1[-1] * test_x mp.figure('Linear Regression', facecolor='lightgray') mp.title('Linear Regression', fontsize=20) mp.xlabel('x', fontsize=14) mp.ylabel('y', fontsize=14) mp.tick_params(labelsize=10) mp.grid(linestyle=':') mp.scatter(train_x, train_y, marker='s', c='dodgerblue', alpha=0.5, s=80, label='Training') mp.scatter(test_x, test_y, marker='D', c='orangered', alpha=0.5, s=60, label='Testing') mp.scatter(test_x, pred_test_y, c='orangered', alpha=0.5, s=80, label='Predicted') mp.plot(test_x, pred_test_y, '--', c='limegreen', label='Regression', linewidth=1) mp.legend() mp.show()
2.绘制随着每次梯度下降,w0,w1,loss的变化曲线。
w0 = w0[:-1] w1 = w1[:-1] mp.figure('Training Progress', facecolor='lightgray') mp.subplot(311) mp.title('Training Progress', fontsize=20) mp.ylabel('w0', fontsize=14) mp.gca().xaxis.set_major_locator(mp.MultipleLocator(100)) mp.tick_params(labelsize=10) mp.grid(linestyle=':') mp.plot(epoches, w0, c='dodgerblue', label='w0') mp.legend() mp.subplot(312) mp.ylabel('w1', fontsize=14) mp.gca().xaxis.set_major_locator(mp.MultipleLocator(100)) mp.tick_params(labelsize=10) mp.grid(linestyle=':') mp.plot(epoches, w1, c='limegreen', label='w1') mp.legend() mp.subplot(313) mp.xlabel('epoch', fontsize=14) mp.ylabel('loss', fontsize=14) mp.gca().xaxis.set_major_locator(mp.MultipleLocator(100)) mp.tick_params(labelsize=10) mp.grid(linestyle=':') mp.plot(epoches, losses, c='orangered', label='loss') mp.legend()
3.基于三维曲面绘制梯度下降过程中的每一个点。
import mpl_toolkits.mplot3d as axes3d grid_w0, grid_w1 = np.meshgrid( np.linspace(0, 9, 500), np.linspace(0, 3.5, 500)) grid_loss = np.zeros_like(grid_w0) for x, y in zip(train_x, train_y): grid_loss += ((grid_w0 + x*grid_w1 - y) ** 2) / 2 mp.figure('Loss Function') ax = mp.gca(projection='3d') mp.title('Loss Function', fontsize=20) ax.set_xlabel('w0', fontsize=14) ax.set_ylabel('w1', fontsize=14) ax.set_zlabel('loss', fontsize=14) ax.plot_surface(grid_w0, grid_w1, grid_loss, rstride=10, cstride=10, cmap='jet') ax.plot(w0, w1, losses, 'o-', c='orangered', label='BGD') mp.legend()
4.以等高线的方式绘制梯度下降的过程。
mp.figure('Batch Gradient Descent', facecolor='lightgray') mp.title('Batch Gradient Descent', fontsize=20) mp.xlabel('x', fontsize=14) mp.ylabel('y', fontsize=14) mp.tick_params(labelsize=10) mp.grid(linestyle=':') mp.contourf(grid_w0, grid_w1, grid_loss, 10, cmap='jet') cntr = mp.contour(grid_w0, grid_w1, grid_loss, 10, colors='black', linewidths=0.5) mp.clabel(cntr, inline_spacing=0.1, fmt='%.2f', fontsize=8) mp.plot(w0, w1, 'o-', c='orangered', label='BGD') mp.legend() mp.show()
线性回归相关API:
import sklearn.linear_model as lm # 创建模型 model = lm.LinearRegression() # 训练模型 # 输入为一个二维数组表示的样本矩阵 # 输出为每个样本最终的结果 model.fit(输入, 输出) # 通过梯度下降法计算模型参数 # 预测输出 # 输入array是一个二维数组,每一行是一个样本,每一列是一个特征。 result = model.predict(array)
案例:基于线性回归训练single.txt中的训练样本,使用模型预测测试样本。
import numpy as np import sklearn.linear_model as lm import matplotlib.pyplot as mp # 采集数据 x, y = np.loadtxt('../data/single.txt', delimiter=',', usecols=(0,1), unpack=True) x = x.reshape(-1, 1) # 创建模型 model = lm.LinearRegression() # 线性回归 # 训练模型 model.fit(x, y) # 根据输入预测输出 pred_y = model.predict(x) mp.figure('Linear Regression', facecolor='lightgray') mp.title('Linear Regression', fontsize=20) mp.xlabel('x', fontsize=14) mp.ylabel('y', fontsize=14) mp.tick_params(labelsize=10) mp.grid(linestyle=':') mp.scatter(x, y, c='dodgerblue', alpha=0.75, s=60, label='Sample') mp.plot(x, pred_y, c='orangered', label='Regression') mp.legend() mp.show()