Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

4.6 梯度下降

梯度下降的目标是找到最优权重,即最小化为模型定义的损失函数。在式 4.21 中,我们明确表示交叉熵损失 LCEL_{\mathrm{CE}} 由权重参数化。机器学习中通常用 θ\theta 表示待学习参数;对逻辑回归而言,θ={w,b}\theta=\{\mathbf w,b\}。因此,将 y^(i)\hat y^{(i)} 写成 f(x(i);θ)f(x^{(i)};\theta),以凸显它对 θ\theta 的依赖。我们的目标是找到使所有样本平均损失最小的参数:

θ^=argminθ1mi=1mLCE(f(x(i);θ),y(i))(4.21)\hat\theta=\underset\theta{\operatorname{argmin}}\frac1m\sum_{i=1}^mL_{\mathrm{CE}}(f(x^{(i)};\theta),y^{(i)})\tag{4.21}

怎样找到这个或任何损失函数的最小值?梯度下降(gradient descent)先确定函数在参数空间中上升最快的方向,再向相反方向移动,从而寻找函数的最小值。直观地说,就像身处峡谷、想尽快下到谷底河边:环顾四周,找到地面最陡的方向,然后沿下坡走去。

逻辑回归的损失函数恰好是凸函数(convex function)。凸函数至多有一个最小值,不存在会使算法受困的局部最小值,因此从任意点出发的梯度下降都能找到该最小值。相比之下,多层神经网络的损失是非凸的,训练时梯度下降可能陷入局部最小值,无法找到全局最优解。

虽然算法和梯度概念是为方向向量设计的,先来看图 4.3 所示的单标量参数 ww 情形。随机将 ww 初始化为 w1w^1,并假设损失函数 LL 具有图中的形状。算法需要判断下一步应向左移动(使 w2<w1w^2<w^1)还是向右移动(使 w2>w1w^2>w^1),才能到达最小值。

梯度下降通过求损失函数在当前点的梯度,并沿相反方向移动来回答这个问题。多变量函数的梯度(gradient)是指向函数增长最快方向的向量,是斜率在多变量情形下的推广。对图 4.3 这样的单变量函数,可把梯度直观地理解为斜率。图中虚线表示 w=w1w=w^1 处的斜率,它为负,因此要寻找最小值就应沿相反方向,即向 ww 增大的方向移动。

移动量由斜率 ddwL(f(x;w),y)\frac d{dw}L(f(x;w),y)学习率(learning rate)η\eta 的乘积决定。学习率越高,每一步对 ww 的改变量越大:

wt+1=wtηddwL(f(x;w),y)(4.22)w^{t+1}=w^t-\eta\frac d{dw}L(f(x;w),y)\tag{4.22}

现在把这种直觉从一个标量推广到多个变量。我们不仅要判断向左或向右,还要决定在构成 θ\thetaNN 个参数所形成的 NN 维空间中向哪里移动。梯度正是这样的向量:它给出沿每个维度的最陡斜率分量。若只有两个权重维度(例如权重 ww 和偏置 bb),梯度就是包含两个正交分量的向量,分别表示地面沿 wwbb 维度的斜率。图 4.4 展示了红点处二维梯度向量的值。

图 4.3 迭代寻找损失函数最小值的第一步:沿函数斜率的反方向移动 ww。斜率为负,因此需要向右、即 ww 的正方向移动。这里上标表示学习步骤,w1w^1ww 的初始值(0),w2w^2 是第二步的值,依此类推。

实际逻辑回归中的参数向量 w\mathbf w 远不止一两个元素,因为输入特征向量 x\mathbf x 可能很长,每个 xix_i 都需要一个权重 wiw_i。对 w\mathbf w 中的每个维度 wiw_i(以及偏置 bb),梯度都有一个分量表示相对于该变量的斜率。沿 wiw_i 维度的斜率写成损失函数的偏导数 wi\frac{\partial}{\partial w_i};它回答的是:“变量 wiw_i 的微小变化会在多大程度上影响总损失 LL?”

形式上,多变量函数 ff 的梯度是一个向量,每个分量都是 ff 对某个变量的偏导数。我们用倒三角符号 \nabla 表示梯度,并将 y^\hat y 写成 f(x;θ)f(x;\theta)

图 4.4 红点处关于 wwbb 的二维梯度向量。红色箭头表示寻找最小值时要移动的方向,即梯度的反方向(梯度指向函数增大而非减小的方向)。

L(f(x;θ),y)=[w1L(f(x;θ),y)w2L(f(x;θ),y)wnL(f(x;θ),y)bL(f(x;θ),y)](4.23)\nabla L(f(x;\boldsymbol\theta),y)=\left[\begin{array}{c}\frac{\partial}{\partial w_1}L(f(x;\boldsymbol\theta),y)\\\frac{\partial}{\partial w_2}L(f(x;\boldsymbol\theta),y)\\\vdots\\\frac{\partial}{\partial w_n}L(f(x;\boldsymbol\theta),y)\\\frac{\partial}{\partial b}L(f(x;\boldsymbol\theta),y)\end{array}\right]\tag{4.23}

因此,根据梯度更新 θ\theta 的最终方程为:

θt+1=θtηL(f(x;θ),y)(4.24)\theta^{t+1}=\theta^t-\eta\nabla L(f(x;\theta),y)\tag{4.24}

4.6.1 逻辑回归的梯度

要更新 θ\theta,需要定义梯度 L(f(x;θ),y)\nabla L(f(x;\theta),y)。回顾逻辑回归的交叉熵损失:

LCE(y^,y)=[ylogσ(wx+b)+(1y)log(1σ(wx+b))](4.25)L_{\mathrm{CE}}(\hat y,y)=-[y\log\sigma(\mathbf w\cdot\mathbf x+b)+(1-y)\log(1-\sigma(\mathbf w\cdot\mathbf x+b))]\tag{4.25}

对单个观测向量 x\mathbf x,该函数的导数为式 4.26(推导见第 4.15 节):

LCE(y^,y)wj=[σ(wx+b)y]xj=(y^y)xj(4.26)\begin{array}{rcl}\frac{\partial L_{\mathrm{CE}}(\hat y,y)}{\partial w_j}&=&[\sigma(\mathbf w\cdot\mathbf x+b)-y]x_j\\&=&(\hat y-y)x_j\end{array}\tag{4.26}

也常写成等价形式:

LCE(y^,y)wj=(yy^)xj(4.27)\frac{\partial L_{\mathrm{CE}}(\hat y,y)}{\partial w_j}=-(y-\hat y)x_j\tag{4.27}

这个结果很直观:对单个权重 wjw_j 的梯度,等于真实值 yy 与估计值 y^=σ(wx+b)\hat y=\sigma(\mathbf w\cdot\mathbf x+b) 之差,再乘以对应输入值 xjx_j。对偏置 bb 的偏导数为:

LCE(y^,y)b=σ(wx+b)y=y^y(4.28)\begin{array}{rl}\frac{\partial L_{\mathrm{CE}}(\hat y,y)}{\partial b}&=\sigma(\mathbf w\cdot\mathbf x+b)-y\\&=\hat y-y\end{array}\tag{4.28}

4.6.2 随机梯度下降算法

随机梯度下降(stochastic gradient descent, SGD)是一种在线算法:处理每个训练样本后都计算损失函数的梯度,并将 θ\theta 沿正确方向(梯度的反方向)微调。在线算法(online algorithm)逐个处理输入样本,而不等待全部输入到齐。SGD 之所以称为“随机”,是因为它每次随机选择一个样本;第 4.6.4 节将讨论一次成批处理多个样本的版本。算法见图 4.5。

function STOCHASTIC GRADIENT DESCENT(L(), f(), x, y) returns $\theta$

# L:损失函数 # f:由 \theta 参数化的函数 # x:训练输入集合 x^{(1)},x^{(2)},\ldots,x^{(m)} # y:训练输出(标签)集合 y^{(1)},y^{(2)},\ldots,y^{(m)} \theta\leftarrow0 #(或较小的随机值)

repeat til done # 见图注 For each training tuple (x^{(i)},y^{(i)}) (in random order) 1. 可选(用于报告): Compute \hat y^{(i)}=f(x^{(i)};\theta) Compute the loss L(\hat y^{(i)},y^{(i)}) 2. g\leftarrow\nabla_\theta L(f(x^{(i)};\theta),y^{(i)}) 3. \theta\leftarrow\theta-\eta g return \theta

图 4.5 随机梯度下降算法。第 1 步(计算损失)主要用于报告当前样本上的表现;计算梯度并不要求先计算损失。算法可在收敛(梯度范数 <ϵ<\epsilon)时终止,也可在进展停止时终止(例如留出集上的损失开始上升)。逻辑回归的权重初始化为 0;神经网络则初始化为较小的随机值,第 6 章将对此加以说明。

学习率 η\eta 是需要调节的超参数(hyperparameter)。学习率过高时,每一步过大,会越过损失函数的最小值;过低时,每一步太小,到达最小值所需时间过长。常见做法是以较高学习率开始,随后缓慢降低,使其成为训练迭代次数 kk 的函数;可用 ηk\eta_k 表示第 kk 次迭代的学习率。

第 6 章将更详细地讨论超参数。简言之,它们是一类特殊的模型参数:普通参数(如 w\mathbf wbb)由算法从训练集学得,而超参数由算法设计者选择,用来影响算法的运行方式。

4.6.3 完整推演一个例子

下面演示梯度下降的一次更新。使用图 4.2 的简化版本:单个观测 xx 的正确标签为 y=1y=1(正面评论),特征向量 x=[x1,x2]\mathbf x=[x_1,x_2] 包含:

x1=3(正面词典词的数量)x2=2(负面词典词的数量)\begin{array}{ll}x_1=3&\text{(正面词典词的数量)}\\x_2=2&\text{(负面词典词的数量)}\end{array}

假设 θ0\theta^0 中的初始权重和偏置均为 0,初始学习率为 0.1:

w1=w2=b=0η=0.1\begin{array}{rl}w_1=w_2=b&=0\\\eta&=0.1\end{array}

一次更新需要计算梯度并乘以学习率:

θt+1=θtηθL(f(x(i);θ),y(i))\theta^{t+1}=\theta^t-\eta\nabla_\theta L(f(x^{(i)};\theta),y^{(i)})

这个小例子有 w1,w2,bw_1,w_2,b 三个参数,因此梯度向量有三个维度:

w,bL=[(σ(wx+b)y)x1(σ(wx+b)y)x2σ(wx+b)y]=[(σ(0)1)x1(σ(0)1)x2σ(0)1]=[1.51.00.5]\nabla_{w,b}L=\left[\begin{array}{c}(\sigma(\mathbf w\cdot\mathbf x+b)-y)x_1\\(\sigma(\mathbf w\cdot\mathbf x+b)-y)x_2\\\sigma(\mathbf w\cdot\mathbf x+b)-y\end{array}\right]=\left[\begin{array}{c}(\sigma(0)-1)x_1\\(\sigma(0)-1)x_2\\\sigma(0)-1\end{array}\right]=\left[\begin{array}{c}-1.5\\-1.0\\-0.5\end{array}\right]

有了梯度,就沿其反方向移动 θ0\theta^0,得到新参数向量 θ1\theta^1

θ1=[w1w2b]η[1.51.00.5]=[.15.1.05]\theta^1=\left[\begin{array}{c}w_1\\w_2\\b\end{array}\right]-\eta\left[\begin{array}{c}-1.5\\-1.0\\-0.5\end{array}\right]=\left[\begin{array}{c}.15\\.1\\.05\end{array}\right]

一次梯度下降后,权重变为 w1=.15w_1=.15w2=.1w_2=.1,偏置为 b=.05b=.05。注意,这个观测恰好是正例;看到更多负面词计数较高的负例后,可以预期权重 w2w_2 会转为负值。

4.6.4 小批量训练

SGD 每次随机选择一个样本,并调整权重以改善该样本上的表现,因而移动轨迹可能十分跳跃。实践中通常对一批训练实例而非单个实例计算梯度。

批量训练(batch training)中,梯度基于整个数据集计算。大量样本可以非常准确地估计权重的移动方向,代价是每次都要处理训练集中的全部样本。

折中方案是小批量训练(mini-batch training):每次使用少于整个数据集的一组 mm 个样本(如 512 或 1024 个)。若 mm 等于数据集大小,就是批量梯度下降;若 m=1m=1,就回到了随机梯度下降。小批量训练还有计算效率上的优势:可以根据计算资源选择批量大小,并轻松地向量化,同时并行处理一个小批量中的所有样本,再累积损失。

下面把第 4.5 节的交叉熵损失和第 4.6.1 节的梯度扩展到小批量。仍用 x(i)x^{(i)}y(i)y^{(i)} 表示第 ii 个训练特征和标签,并假设训练样本彼此独立:

logp(training labels)=logi=1mp(y(i)x(i))=i=1mlogp(y(i)x(i))=i=1mLCE(y^(i),y(i))(4.29)\begin{array}{l}\log p(\text{training labels})=\log\prod_{i=1}^m p(y^{(i)}\mid x^{(i)})\\=\sum_{i=1}^m\log p(y^{(i)}\mid x^{(i)})\\=-\sum_{i=1}^mL_{\mathrm{CE}}(\hat y^{(i)},y^{(i)})\end{array}\tag{4.29}

mm 个样本的小批量代价函数就是各样本损失的平均值:

Cost(y^,y)=1mi=1mLCE(y^(i),y(i))=1mi=1m[y(i)logσ(wx(i)+b)+(1y(i))log(1σ(wx(i)+b))](4.30)\begin{array}{l}\operatorname{Cost}(\hat y,y)=\frac1m\sum_{i=1}^mL_{\mathrm{CE}}(\hat y^{(i)},y^{(i)})\\=-\frac1m\sum_{i=1}^m[y^{(i)}\log\sigma(\mathbf w\cdot\mathbf x^{(i)}+b)+(1-y^{(i)})\log(1-\sigma(\mathbf w\cdot\mathbf x^{(i)}+b))]\end{array}\tag{4.30}

小批量梯度是式 4.26 中各样本梯度的平均值:

Cost(y^,y)wj=1mi=1m[σ(wx(i)+b)y(i)]xj(i)(4.31)\frac{\partial\operatorname{Cost}(\hat y,y)}{\partial w_j}=\frac1m\sum_{i=1}^m[\sigma(\mathbf w\cdot\mathbf x^{(i)}+b)-y^{(i)}]x_j^{(i)}\tag{4.31}

还可沿用第 100 页的向量化写法,以形状为 [m×f][m\times f] 的矩阵 X\mathbf X 表示批内 mm 个输入,以形状为 [m×1][m\times1] 的向量 y\mathbf y 表示正确输出,从而更高效地计算:

Cost(y^,y)w=1m(y^y)TX=1m(σ(Xw+b)y)TX(4.32)\begin{array}{rcl}\frac{\partial\operatorname{Cost}(\hat y,y)}{\partial\mathbf w}&=&\frac1m(\hat{\mathbf y}-\mathbf y)^T\mathbf X\\&=&\frac1m(\sigma(\mathbf X\mathbf w+\mathbf b)-\mathbf y)^T\mathbf X\end{array}\tag{4.32}