您的位置:首页 > 其它

机器学习之线性回归和梯度下降算法

2018-12-30 18:56 239 查看

一般来说,我们根据机器学习的任务把不同的业务模型划分为四种基本问题。
回归问题,分类问题,聚类问题和降维问题。
回归问题 \ 都是在有监督条件下,根据已知的输入和输出,构建
分类问题 / 预测模型,对未知输出的输入给出大概率的输出
我们举个例子:
输入 输出
1 2
2 4
3 6
4 8
------- y = x * 2
5 ? -> 10
输出是一个连续值,回归问题。
我们再看一个例子:
输入 输出
1 1
2 0
3 1
4 0
5 1
6 0
------- 奇数->1,偶数->0
7 ? -> 1
输出是一个离散值,分类问题。
聚类问题:在无监督模式下,根据输入的特征划分族群。
降维问题:在无监督模式下,对输入特征进行取舍以降低维度。
输入 输出
x1 y1
x2 y2

xm ym
y = w0+w1x - 通过线性方程描述输出和输入之间的关系,已解决回归问题,这就是线性回归。

预测函数:y = w0+w1x
预测输出为:
x1 -> y1’=w0+w1x1
x2 -> y2’=w0+w1x2

xm->ym’=w0+w1xm
y1 y2 … ym : 实际输出
(y1 - y1’) ^ 2 : 单样本误差

总样本误差:
(y1−y1′)2+(y2−y2′)2+...+(ym−ym′)22=E\frac{(y1-y1') ^ 2 + ( y2-y2') ^ 2 + ... + (ym-ym') ^ 2}{2} = E 2(y1−y1′)2+(y2−y2′)2+...+(ym−ym′)2​=E
损失函数:E = Loss(w0, w1)
损失函数体现了总样本误差即损失值随着模型参数的变化而变化。回归问题的等价问题就是求损失函数的极小值,即是E达到极小值的w0和w1。

模型参数的迭代公式:
w0=w0−n∂E∂w0w0 = w0 - n \frac {∂E} {∂w0}w0=w0−n∂w0∂E​
w1=w1−n∂E∂w1w1 = w1 - n \frac{∂E}{∂w1}w1=w1−n∂w1∂E​
通过公式推导求微分,我们可以得到:

∂E / ∂w0 = 1/2 [2(y1-y1’)(-1) + 2(y2-y2’)(-1) + …]
= -[(y1-y1’) + (y2-y2’) + …]
∂E / ∂w1 = -[(y1-y1’)x1 + (y2-y2’)x2 + …]

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as mp
from mpl_toolkits.mplot3d import axes3d
#已知输入
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])
#迭代次数,以此计算梯度
n_epoches = 1000
#求反向梯度时取学习率,公式中的n,谨慎起见我们取0.01
lrate = 0.01
#epoches实际步数,losses记录每一步的误差
epoches, losses = [], []
#模型参数的初始值,追加的元素我们添加到列表的最后一个元素
w0, w1 = [1], [1]
#我们做一个1到1000的循环
for epoch in range(1, n_epoches + 1):
epoches.append(epoch)
#误差等于实际输出减去预测输出求平方和再除以2
losses.append(((train_y - (w0[-1] + w1[-1] * train_x)) ** 2).sum() / 2)
#我们把对应的模型参数和对应的值都打印在终端上
print('{:4}> w0={:.8f}, w1={:.8f}, loss={:.8f}'.format(epoches[-1], w0[-1], w1[-1], losses[-1]))
#计算∂E / ∂w0的偏微分
d0 = -(train_y - (w0[-1] + w1[-1] * train_x)).sum()
#计算∂E / ∂w1的偏微分
d1 = -((train_y - (w0[-1] + w1[-1] * train_x)) * train_x).sum()
#模型参数迭代
w0.append(w0[-1] - lrate * d0)
w1.append(w1[-1] - lrate * d1)
#第1001个元素切掉
w0 = np.array(w0[:-1])
w1 = np.array(w1[:-1])
#间接索引,升序排列
sorted_indices = train_x.argsort()
#x测试集,保证x是升序排列
test_x = train_x[sorted_indices]
test_y = train_y[sorted_indices]
#把test_x带入公式,可以得到预测输出
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.legend()
mp.show()


在上面的基础上我们再画一条测试图形

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.figure('Training Progress', facecolor='lightgray')
#第一幅子图
mp.subplot(311)
mp.title('Training Progress', fontsize=20)
mp.ylabel('w0', fontsize=14)
# x轴刻度
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()


下面,我们把损失函数的曲面画出来。

#数据生成,w0取0-9,500个点,w1取0-3.5,500个点
grid_w0, grid_w1 = np.meshgrid(np.linspace(0, 9, 500), np.linspace(0, 3.5, 500))
#网格平面化
flat_w0, flat_w1 = grid_w0.ravel(), grid_w1.ravel()
#flat_w0 + np.outer(train_x, flat_w1)得到预测值矩阵
#每个样本的预测值输出减去实际输出的差求平方,沿着纵向求和再除以2,算出损失值。
flat_loss = ((flat_w0 + np.outer(train_x, flat_w1) - train_y.reshape( -1, 1)) ** 2).sum(axis=0) / 2
#损失值和w0维度保持一致
grid_loss = flat_loss.reshape(grid_w0.shape)

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(loc='lower left')


我们用二维图看下梯度下降

mp.figure('Batch Gradient Desent')
mp.title('Batch Gradient Desent', fontsize=20)
mp.xlabel('w0', fontsize=14)
mp.ylabel('w1', fontsize=14)
#取1000阶,颜色映射还是用jet
mp.contourf(grid_w0, grid_w1, grid_loss,1000, cmap='jet')
#间隔取10
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=10)

mp.plot(w0, w1, 'o-', c='orangered', label='BGD')
mp.legend()


基于模型的机器学习实际上就是要找到一个函数,通过实际输出与预测输出之间的误差,表现模型的精度,在求该函数的极小值的过程中,寻找最优的模型参数
但是并不是损失函数越小越好,我们把一些过于完美的称之为过拟合,一般我们会给它一个惩罚项(超参数)

E = Loss(w0, w1) - 正则项 x 正则强度©
C 我们称为惩罚系数,正则力度

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: