多维梯度下降

在了解了一维梯度下降之后,我们再考虑一种更广义的情况:目标函数的输入为向量,输出为标量。假设目标函数 的输入是一个 d 维向量 。目标函数 f(x) 有关 x 的梯度是一个由 d 个偏导数组成的向量:

为表示简洁,我们用 ∇f(x) 代替 ∇xf(x) 。梯度中每个偏导数元素 ∂f(x)/∂xi 代表着 f 在 x 有关输入 xi 的变化率。为了测量 f 沿着单位向量 u (即 ‖u‖=1 )方向上的变化率,在多元微积分中,我们定义 f 在 x 上沿着 u 方向的方向导数为

依据方向导数性质,以上方向导数可以改写为

方向导数 给出了 f 在 x 上沿着所有可能方向的变化率。为了最小化 f ,我们希望找到 f 能被降低最快的方向。因此,我们可以通过单位向量 u 来最小化方向导数

由于 , 其中 θ 为梯度 ∇f(x) 和单位向量 u 之间的夹角,当 θ=π 时, cos(θ) 取得最小值 −1 。因此,当 u 在梯度方向 ∇f(x) 的相反方向时,方向导数 被最小化。因此,我们可能通过梯度下降算法来不断降低目标函数 f 的值:

同样,其中 η (取正数)称作学习率。
下面我们构造一个输入为二维向量 和输出为标量的目标函数 。那么,梯度。我们将观察梯度下降从初始位置 [−5,−2] 开始对自变量 x 的迭代轨迹。我们先定义两个辅助函数,第一个函数使用给定的自变量更新函数,从初始位置 [−5,−2] 开始迭代自变量 x 共20次,第二个函数对自变量 x 的迭代轨迹进行可视化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def train_2d(trainer):  # 本函数将保存在d2lzh包中方便以后使用
x1, x2, s1, s2 = -5, -2, 0, 0 # s1和s2是自变量状态,本章后续几节会使用
results = [(x1, x2)]
for i in range(20):
x1, x2, s1, s2 = trainer(x1, x2, s1, s2)
results.append((x1, x2))
print('epoch %d, x1 %f, x2 %f' % (i + 1, x1, x2))
return results

def show_trace_2d(f, results): # 本函数将保存在d2lzh包中方便以后使用
d2l.plt.plot(*zip(*results), '-o', color='#ff7f0e')
x1, x2 = np.meshgrid(np.arange(-5.5, 1.0, 0.1), np.arange(-3.0, 1.0, 0.1))
d2l.plt.contour(x1, x2, f(x1, x2), colors='#1f77b4')
d2l.plt.xlabel('x1')
d2l.plt.ylabel('x2')

然后,观察学习率为 0.1 时自变量的迭代轨迹。使用梯度下降对自变量 x 迭代20次后,可见最终 x 的值较接近最优解 [0,0] 。

1
2
3
4
5
6
7
8
9
eta = 0.1

def f_2d(x1, x2): # 目标函数
return x1 ** 2 + 2 * x2 ** 2

def gd_2d(x1, x2, s1, s2):
return (x1 - eta * 2 * x1, x2 - eta * 4 * x2, 0, 0)

show_trace_2d(f_2d, train_2d(gd_2d))

epoch 20, x1 -0.057646, x2 -0.000073

随机梯度下降

在深度学习里,目标函数通常是训练数据集中有关各个样本的损失函数的平均。设 是有关索引为 i 的训练数据样本的损失函数, n 是训练数据样本数, x 是模型的参数向量,那么目标函数定义为

目标函数在 x 处的梯度计算为

如果使用梯度下降,每次自变量迭代的计算开销为 O(n) ,它随着 n 线性增长。因此,当训练数据样本数很大时,梯度下降每次迭代的计算开销很高。

随机梯度下降(stochastic gradient descent,SGD)减少了每次迭代的计算开销。在随机梯度下降的每次迭代中,我们随机均匀采样的一个样本索引 i∈{1,…,n} ,并计算梯度 来迭代 x :

这意味着,平均来说,随机梯度是对梯度的一个良好的估计。

下面我们通过在梯度中添加均值为0的随机噪声来模拟随机梯度下降,以此来比较它与梯度下降的区别。

1
2
3
4
5
def sgd_2d(x1, x2, s1, s2):
return (x1 - eta * (2 * x1 + np.random.normal(0.1)),
x2 - eta * (4 * x2 + np.random.normal(0.1)), 0, 0)

show_trace_2d(f_2d, train_2d(sgd_2d))

epoch 20, x1 -0.286388, x2 -0.076428

可以看到,随机梯度下降中自变量的迭代轨迹相对于梯度下降中的来说更为曲折。这是由于实验所添加的噪声使模拟的随机梯度的准确度下降。在实际中,这些噪声通常指训练数据集中的无意义的干扰。

小结

当训练数据集的样本较多时,梯度下降每次迭代的计算开销较大,因而随机梯度下降通常更受青睐。