文章目录

  • 飞桨深度学习笔记(一)
  • 实践平学习
  • 模型设计
  • 训练配置
  • 训练过程
  • 梯度下降法



模型设计

模型设计是深度学习模型关键要素之一,也称为网络结构设计,相当于模型的假设空间,即实现模型“前向计算”(从输入到输出)的过程。

w = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, -0.1, -0.2, -0.3, -0.4, 0.0]
w = np.array(w).reshape([13, 1])

取出第1条样本数据,观察样本的特征向量与参数向量相乘的结果。

x1=x[0]
t = np.dot(x1, w)
print(t)

完整的线性回归公式,

b = -0.2
z = t + b
print(z)

将上述计算预测输出的过程以“类和对象”的方式来描述,类成员变量有参数pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗pytorch可以在飞浆上面用吗_paddlepaddle_02。通过写一个forward函数(代表“前向计算”)完成上述从特征和参数到输出预测值的计算过程,代码如下所示。

class Network(object):
    def __init__(self, num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,
        # 此处设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights, 1)
        self.b = 0.
        
    def forward(self, x):
        z = np.dot(x, self.w) + self.b
        return z

基于Network类的定义,模型的计算过程如下所示。

net = Network(13)
x1 = x[0]
y1 = y[0]
z = net.forward(x1)
print(z)

训练配置

模型设计完成后,需要通过训练配置寻找模型的最优值,即通过损失函数来衡量模型的好坏。训练配置也是深度学习模型关键要素之一。

通过模型计算pytorch可以在飞浆上面用吗_python_03表示的影响因素所对应的房价应该是pytorch可以在飞浆上面用吗_深度学习_04, 但实际数据告诉我们房价是pytorch可以在飞浆上面用吗_python_05。这时我们需要有某种指标来衡量预测值pytorch可以在飞浆上面用吗_深度学习_04跟真实值pytorch可以在飞浆上面用吗_python_05之间的差距。对于回归问题,最常采用的衡量方法是使用均方误差作为评价模型好坏的指标,具体定义如下:

pytorch可以在飞浆上面用吗_深度学习_08

上式中的pytorch可以在飞浆上面用吗_paddlepaddle_09(简记为: pytorch可以在飞浆上面用吗_python_10)通常也被称作损失函数,它是衡量模型好坏的指标。在回归问题中,均方误差是一种比较常见的形式,分类问题中通常会采用交叉熵作为损失函数,在后续的章节中会更详细的介绍。对一个样本计算损失函数值的实现如下:

Loss = (y1 - z)*(y1 - z)
print(Loss)

因为计算损失函数时需要把每个样本的损失函数值都考虑到,所以我们需要对单个样本的损失函数进行求和,并除以样本总数pytorch可以在飞浆上面用吗_深度学习_11
pytorch可以在飞浆上面用吗_paddlepaddle_12
在Network类下面添加损失函数的计算过程如下:

class Network(object):
    def __init__(self, num_of_weights):
        # 随机产生w的初始值
        # 为了保持程序每次运行结果的一致性,此处设置固定的随机数种子
        np.random.seed(0)
        self.w = np.random.randn(num_of_weights, 1)
        self.b = 0.
        
    def forward(self, x):
        z = np.dot(x, self.w) + self.b
        return z
    
    def loss(self, z, y):
        error = z - y
        cost = error * error
        cost = np.mean(cost)
        return cost

使用定义的Network类,可以方便的计算预测值和损失函数。需要注意的是,类中的变量pytorch可以在飞浆上面用吗_paddlepaddle_13, pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗pytorch可以在飞浆上面用吗_paddlepaddle_02, pytorch可以在飞浆上面用吗_深度学习_04, pytorch可以在飞浆上面用吗_深度学习_17等均是向量。以变量pytorch可以在飞浆上面用吗_paddlepaddle_13为例,共有两个维度,一个代表特征数量(值为13),一个代表样本数量,代码如下所示。

net = Network(13)
# 此处可以一次性计算多个样本的预测值和损失函数
x1 = x[0:3]
y1 = y[0:3]
z = net.forward(x1)
print('predict: ', z)
loss = net.loss(z, y1)
print('loss:', loss)

训练过程

上述计算过程描述了如何构建神经网络,通过神经网络完成预测值和损失函数的计算。接下来介绍如何求解参数pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗pytorch可以在飞浆上面用吗_paddlepaddle_02的数值,这个过程也称为模型训练过程。训练过程是深度学习模型的关键要素之一,其目标是让定义的损失函数pytorch可以在飞浆上面用吗_paddlepaddle_09尽可能的小,也就是说找到一个参数解pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗pytorch可以在飞浆上面用吗_paddlepaddle_02,使得损失函数取得极小值。

我们先做一个小测试:如 图5 所示,基于微积分知识,求一条曲线在某个点的斜率等于函数在该点的导数值。那么大家思考下,当处于曲线的极值点时,该点的斜率是多少?



pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗_24


图5:曲线斜率等于导数值



这个问题并不难回答,处于曲线极值点时的斜率为0,即函数在极值点的导数为0。那么,让损失函数取极小值的pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗pytorch可以在飞浆上面用吗_paddlepaddle_02应该是下述方程组的解:
pytorch可以在飞浆上面用吗_python_27
pytorch可以在飞浆上面用吗_paddlepaddle_28

将样本数据pytorch可以在飞浆上面用吗_paddlepaddle_29带入上面的方程组中即可求解出pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗pytorch可以在飞浆上面用吗_paddlepaddle_02的值,但是这种方法只对线性回归这样简单的任务有效。如果模型中含有非线性变换,或者损失函数不是均方差这种简单的形式,则很难通过上式求解。为了解决这个问题,下面我们将引入更加普适的数值求解方法:梯度下降法。

梯度下降法

在现实中存在大量的函数正向求解容易,但反向求解较难,被称为单向函数,这种函数在密码学中有大量的应用。密码锁的特点是可以迅速判断一个密钥是否是正确的(已知pytorch可以在飞浆上面用吗_paddlepaddle_13,求pytorch可以在飞浆上面用吗_python_05很容易),但是即使获取到密码锁系统,无法破解出正确的密钥是什么(已知pytorch可以在飞浆上面用吗_python_05,求pytorch可以在飞浆上面用吗_paddlepaddle_13很难)。

这种情况特别类似于一位想从山峰走到坡谷的盲人,他看不见坡谷在哪(无法逆向求解出pytorch可以在飞浆上面用吗_paddlepaddle_09导数为0时的参数值),但可以伸脚探索身边的坡度(当前点的导数值,也称为梯度)。那么,求解Loss函数最小值可以这样实现:从当前的参数取值,一步步的按照下坡的方向下降,直到走到最低点。这种方法笔者称它为“盲人下坡法”。哦不,有个更正式的说法“梯度下降法”。

训练的关键是找到一组pytorch可以在飞浆上面用吗_paddlepaddle_37,使得损失函数pytorch可以在飞浆上面用吗_python_10取极小值。我们先看一下损失函数pytorch可以在飞浆上面用吗_python_10只随两个参数pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗_40pytorch可以在飞浆上面用吗_深度学习_41变化时的简单情形,启发下寻解的思路。
pytorch可以在飞浆上面用吗_python_42
这里我们将pytorch可以在飞浆上面用吗_损失函数_43中除pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗_44之外的参数和pytorch可以在飞浆上面用吗_paddlepaddle_02都固定下来,可以用图画出pytorch可以在飞浆上面用吗_paddlepaddle_46的形式。

net = Network(13)
losses = []
#只画出参数w5和w9在区间[-160, 160]的曲线部分,以及包含损失函数的极值
w5 = np.arange(-160.0, 160.0, 1.0)
w9 = np.arange(-160.0, 160.0, 1.0)
losses = np.zeros([len(w5), len(w9)])

#计算设定区域内每个参数取值所对应的Loss
for i in range(len(w5)):
    for j in range(len(w9)):
        net.w[5] = w5[i]
        net.w[9] = w9[j]
        z = net.forward(x)
        loss = net.loss(z, y)
        losses[i, j] = loss

#使用matplotlib将两个变量和对应的Loss作3D图
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)

w5, w9 = np.meshgrid(w5, w9)

ax.plot_surface(w5, w9, losses, rstride=1, cstride=1, cmap='rainbow')
plt.show()

pytorch可以在飞浆上面用吗_损失函数_47


对于这种简单情形,我们利用上面的程序,可以在三维空间中画出损失函数随参数变化的曲面图。从图中可以看出有些区域的函数值明显比周围的点小。

需要说明的是:为什么这里我们选择pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗_40pytorch可以在飞浆上面用吗_深度学习_41来画图?这是因为选择这两个参数的时候,可比较直观的从损失函数的曲面图上发现极值点的存在。其他参数组合,从图形上观测损失函数的极值点不够直观。

观察上述曲线呈现出“圆滑”的坡度,这正是我们选择以均方误差作为损失函数的原因之一。图6 呈现了只有一个参数维度时,均方误差和绝对值误差(只将每个样本的误差累加,不做平方处理)的损失函数曲线图。



pytorch可以在飞浆上面用吗_paddlepaddle_50


图6:均方误差和绝对值误差损失函数曲线图


由此可见,均方误差表现的“圆滑”的坡度有两个好处:

  • 曲线的最低点是可导的。
  • 越接近最低点,曲线的坡度逐渐放缓,有助于通过当前的梯度来判断接近最低点的程度(是否逐渐减少步长,以免错过最低点)。

而绝对值误差是不具备这两个特性的,这也是损失函数的设计不仅仅要考虑“合理性”,还要追求“易解性”的原因。

现在我们要找出一组pytorch可以在飞浆上面用吗_损失函数_51的值,使得损失函数最小,实现梯度下降法的方案如下:

  • 步骤1:随机的选一组初始值,例如:pytorch可以在飞浆上面用吗_python_52
  • 步骤2:选取下一个点pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗_53,使得pytorch可以在飞浆上面用吗_python_54
  • 步骤3:重复步骤2,直到损失函数几乎不再下降。

如何选择pytorch可以在飞浆上面用吗_pytorch可以在飞浆上面用吗_55是至关重要的,第一要保证pytorch可以在飞浆上面用吗_python_10是下降的,第二要使得下降的趋势尽可能的快。微积分的基础知识告诉我们,沿着梯度的反方向,是函数值下降最快的方向,如 图 所示。简单理解,函数在某一个点的梯度方向是曲线斜率最大的方向,但梯度方向是向上的,所以下降最快的是梯度的反方向。



pytorch可以在飞浆上面用吗_python_57