深度学习基础:3.反向传播和梯度下降

动态计算图

计算图可以用来表示两个变量之间的关系。例如,构建 y = x 2 y=x^2 y=x2,则可用一张简单计算图进行表示。
pytorch支持动态计算图,动态意义在于,当创建其它由计算图中变量而来的新变量时,新变量会自动添加到计算图内。
而Tensorflow v1仅支持静态计算图,需要提前定义各个变量的关系,灵活性不如动态计算图。

反向传播

通过反向传播,可以计算各变量的导数。

x = torch.tensor(1.,requires_grad = True) #requires_grad=True表示x可导
y = x ** 2
y.backward()
# 在y=x**2函数关系基础上,x取值为1时的导数值
x.grad

输出:

tensor(2.)

梯度下降

梯度下降的代数表示

令多元线性回归方程为
f ( x ) = w 1 x 1 + w 2 x 2 + . . . + w d x d + b f(x) = w_1x_1+w_2x_2+...+w_dx_d+b f(x)=w1​x1​+w2​x2​+...+wd​xd​+b

w ^ = ( w 1 , w 2 , . . . , w d , b ) \hat w = (w_1,w_2,...,w_d,b) w^=(w1​,w2​,...,wd​,b)
x ^ = ( x 1 , x 2 , . . . , x d , 1 ) \hat x = (x_1,x_2,...,x_d,1) x^=(x1​,x2​,...,xd​,1)

出于加快迭代收敛速度的目标,我们在定义梯度下降的损失函数L时,在原SSE基础上进行比例修正,新的损失函数 L ( w 1 , w 2 , . . . , w d , b ) = 1 2 m S S E L(w_1,w_2,...,w_d,b) = \frac{1}{2m}SSE L(w1​,w2​,...,wd​,b)=2m1​SSE,其中,m为样本个数。

损失函数有:

L ( w 1 , w 2 , . . . , w d , b ) = 1 2 m ∑ j = 0 m ( f ( x 1 ( j ) , x 2 ( j ) , . . . 1 ) − y j ) 2 L(w_1,w_2,...,w_d,b) = \frac{1}{2m}\sum_{j=0}^{m}(f(x_1^{(j)}, x_2^{(j)}, ...1) - y_j)^2 L(w1​,w2​,...,wd​,b)=2m1​j=0∑m​(f(x1(j)​,x2(j)​,...1)−yj​)2

并且,根据此前描述过程,在开始梯度下降求解参数之前,我们首先需要设置一组参数的初始取值 ( w 1 , w 2 . . . , w d , b ) (w_1, w_2..., w_d, b) (w1​,w2​...,wd​,b),以及学习率 α \alpha α,然后即可执行迭代运算,其中每一轮迭代过程需要执行以下三步

Step 1.计算梯度表达式

对于任意一个参数 w i w_i wi​,其梯度计算表达式如下:

∂ ∂ w i L ( w 1 , w 2 . . . , w d , b ) \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) ∂wi​∂​L(w1​,w2​...,wd​,b)

Step 2.用学习率乘以损失函数梯度,得到迭代移动距离

α ∂ ∂ w i L ( w 1 , w 2 . . . , w d , b ) \alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) α∂wi​∂​L(w1​,w2​...,wd​,b)

Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w

w i = w i − α ∂ ∂ w i L ( w 1 , w 2 . . . , w d , b ) w_i = w_i - \alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b) wi​=wi​−α∂wi​∂​L(w1​,w2​...,wd​,b)

更新完所有参数,即完成了一轮的迭代,接下来就能以新的一组 w i w_i wi​参与下一轮迭代。

举例说明

有数据集表示如下:

x y
1 2
2 4
3 6

假设,我们使用 y = w x y = wx y=wx进行拟合,则SSE为:

S S E = ( 2 − 1 ∗ w ) 2 + ( 4 − 2 ∗ w ) 2 + ( 6 − 3 ∗ w ) 2 = w 2 − 4 w + 4 + 4 w 2 − 16 w + 16 + 9 w 2 − 36 w + 36 = 14 w 2 − 56 w + 56 = 14 ( w 2 − 4 w + 4 ) SSE = (2-1*w)^2 + (4-2*w)^2 + (6-3*w)^2 \\ = w^2-4w+4+4w^2-16w+16+9w^2-36w+36 \\ = 14w^2-56w+56 \\ = 14(w^2-4w+4) SSE=(2−1∗w)2+(4−2∗w)2+(6−3∗w)2=w2−4w+4+4w2−16w+16+9w2−36w+36=14w2−56w+56=14(w2−4w+4)

此时,SSE就是一个关于w的一元函数。当使用最小二乘法进行求解时,SSE就是损失函数,并且SSE对于w求导为0的点就是最小值点,因此有:

∂ S S E ( a ) ∂ ( a ) = 14 ( 2 w − 4 ) = 28 ( w − 2 ) = 0 \frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2) = 0 ∂(a)∂SSE(a)​​=14(2w−4)=28(w−2)=0

w = 2 w=2 w=2

但我们使用梯度下降求解时:

g r a d ∗ = ∂ S S E ( a ) ∂ ( a ) = 14 ( 2 w − 4 ) = 28 ( w − 2 ) grad^* = \frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2) grad∗=∂(a)∂SSE(a)​​=14(2w−4)=28(w−2)

由于梯度表示方向,在某些情况下我们可以对其绝对数值进行一定程度上的“缩放”,此时我们规定有效梯度是原梯度的1/28,则有

g r a d = w − 2 grad = w-2 grad=w−2

设步长$\alpha= 0.5 , 初 始 值 点 取 为 0.5,初始值点取为 0.5,初始值点取为w_0=0$,则迭代过程如下:

第一轮迭代:

g r a d ( w 0 ) = g r a d ( 0 ) = − 2 , w 0 = 0 , w 1 = w 0 − α ∗ g r a d ( w 0 ) = 0 − 1 2 ( − 2 ) = 1 grad(w_0)=grad(0)=-2,w_0=0,w_1=w_0-\alpha*grad(w_0)=0-\frac{1}{2}(-2)=1 grad(w0​)=grad(0)=−2,w0​=0,w1​=w0​−α∗grad(w0​)=0−21​(−2)=1

第二轮迭代:

g r a d ( w 1 ) = g r a d ( 1 ) = − 1 , w 1 = 1 , w 2 = w 1 − α ∗ g r a d ( w 1 ) = 1 − 1 2 ( − 1 ) = 3 2 grad(w_1)=grad(1)=-1,w_1=1,w_2=w_1-\alpha*grad(w_1)=1-\frac{1}{2}(-1)=\frac{3}{2} grad(w1​)=grad(1)=−1,w1​=1,w2​=w1​−α∗grad(w1​)=1−21​(−1)=23​

第三轮迭代:

g r a d ( w 2 ) = g r a d ( 3 2 ) = − 1 2 , w 2 = 3 2 , w 3 = w 2 − α ∗ g r a d ( w 2 ) = 3 2 − 1 2 ( − 1 2 ) = 7 4 grad(w_2)=grad(\frac{3}{2})=-\frac{1}{2},w_2=\frac{3}{2},w_3=w_2-\alpha*grad(w_2)=\frac{3}{2}-\frac{1}{2}(-\frac{1}{2})=\frac{7}{4} grad(w2​)=grad(23​)=−21​,w2​=23​,w3​=w2​−α∗grad(w2​)=23​−21​(−21​)=47​

第四轮迭代:

g r a d ( w 3 ) = g r a d ( 7 4 ) = − 1 4 , w 3 = 7 4 , w 4 = w 3 − α ∗ g r a d ( w 3 ) = 7 4 − 1 2 ( − 1 4 ) = 15 8 grad(w_3)=grad(\frac{7}{4})=-\frac{1}{4},w_3=\frac{7}{4},w_4=w_3-\alpha*grad(w_3)=\frac{7}{4}-\frac{1}{2}(-\frac{1}{4})=\frac{15}{8} grad(w3​)=grad(47​)=−41​,w3​=47​,w4​=w3​−α∗grad(w3​)=47​−21​(−41​)=815​

依次类推:

w 5 = 15 8 + 1 16 = 31 16 ; w 6 = 31 16 + 1 32 = 63 32 ; w 7 = 63 32 + 1 64 = 127 64 ; . . . w_5 = \frac{15}{8}+\frac{1}{16} = \frac{31}{16}; w_6 = \frac{31}{16}+\frac{1}{32} = \frac{63}{32}; w_7 = \frac{63}{32}+\frac{1}{64} = \frac{127}{64}; ... w5​=815​+161​=1631​;w6​=1631​+321​=3263​;w7​=3263​+641​=64127​;...

w n = 2 n − 1 2 n − 1 = 2 − 1 2 n − 1 w_n=\frac{2^n-1}{2^{n-1}} = 2-\frac{1}{2^{n-1}} wn​=2n−12n−1​=2−2n−11​

lim ⁡ n → ∞ ( w n ) = lim ⁡ n → ∞ ( 2 − 1 2 n − 1 ) = 2 \lim_{n→\infty} (w_n) = \lim_{n→\infty} (2-\frac{1}{2^{n-1}}) = 2 n→∞lim​(wn​)=n→∞lim​(2−2n−11​)=2

梯度下降的矩阵表示

令多元线性回归方程为
f ( x ) = w 1 x 1 + w 2 x 2 + . . . + w d x d + b f(x) = w_1x_1+w_2x_2+...+w_dx_d+b f(x)=w1​x1​+w2​x2​+...+wd​xd​+b

w ^ = ( w 1 , w 2 , . . . , w d , b ) \hat w = (w_1,w_2,...,w_d,b) w^=(w1​,w2​,...,wd​,b)
x ^ = ( x 1 , x 2 , . . . , x d , 1 ) \hat x = (x_1,x_2,...,x_d,1) x^=(x1​,x2​,...,xd​,1)
因此,方程可表示为

f ( x ) = w ^ ∗ x ^ T f(x) = \hat w * \hat x^T f(x)=w^∗x^T

另外,我们将所有自变量的值放在一个矩阵中,有
X = [ x 11 x 12 . . . x 1 d 1 x 21 x 22 . . . x 2 d 1 . . . . . . . . . . . . 1 x m 1 x 12 . . . x m d 1 ] X = \left [\begin{array}{cccc} x_{11} &x_{12} &... &x_{1d} &1 \\ x_{21} &x_{22} &... &x_{2d} &1 \\ ... &... &... &... &1 \\ x_{m1} &x_{12} &... &x_{md} &1 \\ \end{array}\right] X=⎣⎢⎢⎡​x11​x21​...xm1​​x12​x22​...x12​​............​x1d​x2d​...xmd​​1111​⎦⎥⎥⎤​

y = [ y 1 y 2 . . . y m ] y = \left [\begin{array}{cccc} y_1 \\ y_2 \\ . \\ . \\ . \\ y_m \\ \end{array}\right] y=⎣⎢⎢⎢⎢⎢⎢⎡​y1​y2​...ym​​⎦⎥⎥⎥⎥⎥⎥⎤​

此时,SSE可表示为:

S S E = ∣ ∣ y − X w ^ T ∣ ∣ 2 2 = ( y − X w ^ T ) T ( y − X w ^ T ) = E ( w ^ ) SSE = ||y - X\hat w^T||_2^2 = (y - X\hat w^T)^T(y - X\hat w^T) = E(\hat w) SSE=∣∣y−Xw^T∣∣22​=(y−Xw^T)T(y−Xw^T)=E(w^)

梯度下降损失函数为:

L ( w ^ ) = 1 2 m S S E = 1 2 m ( y − X w ^ T ) T ( y − X w ^ T ) L(\hat w) = \frac{1}{2m} SSE =\frac{1}{2m} (y - X\hat w^T)^T(y - X\hat w^T) L(w^)=2m1​SSE=2m1​(y−Xw^T)T(y−Xw^T)

同样,我们需要设置初始化参数 ( w 1 , w 2 . . . , w d , b ) (w_1, w_2..., w_d, b) (w1​,w2​...,wd​,b),以及学习率 α \alpha α,然后即可开始执行迭代过程,同样,每一轮迭代需要有三步计算:

Step 1.计算梯度表达式

对于参数向量 w ^ \hat w w^,其梯度计算表达式如下:

∂ ∂ w ^ L ( w ^ ) = 1 m X T ( X w ^ T − Y ) \frac{\partial}{\partial \hat w}L(\hat w) = \frac{1}{m}X^T(X\hat w ^T - Y) ∂w^∂​L(w^)=m1​XT(Xw^T−Y)

Step 2.用学习率乘以损失函数梯度,得到迭代移动距离

α ∂ ∂ w ^ L ( w ^ ) \alpha \frac{\partial}{\partial \hat w}L(\hat w) α∂w^∂​L(w^)

Step 3.用原参数减Step 2中计算得到的距离,更新所有的参数w

w ^ = w ^ − α ∂ ∂ w ^ L ( w ^ ) = w ^ − α m X T ( X w ^ T − Y ) \hat w = \hat w - \alpha \frac{\partial}{\partial \hat w}L(\hat w) = \hat w - \frac{\alpha}{m}X^T(X\hat w ^T - Y) w^=w^−α∂w^∂​L(w^)=w^−mα​XT(Xw^T−Y)

更新完所有参数,即完成了一轮的迭代,接下来就能以新的 w ^ \hat w w^参与下一轮迭代。

编程实现

编写一个函数求梯度,默认学习率为0.01,迭代次数为1000次。

def gradDescent(X, y, eps = torch.tensor(0.01, requires_grad = True), numIt = 1000):
    m, n = X.shape
    weights = torch.zeros(n, 1, requires_grad = True)
    for k in range(numIt):
        grad = torch.mm(X.t(), (torch.mm(X, weights) - y))/2
        weights = weights - eps * grad
    return weights
X = torch.tensor([[1.,1],[3, 1]], requires_grad = True)
X
tensor([[1., 1.],
        [3., 1.]], requires_grad=True)
y = torch.tensor([2.,4], requires_grad = True).reshape(2,1)
y
tensor([[2.],
        [4.]], grad_fn=<ViewBackward>)
gradDescent(X, y)
tensor([[1.0372],
        [0.9102]], grad_fn=<SubBackward0>)
weights = gradDescent(X, y, numIt = 10000)
weights
tensor([[1.0000],
        [1.0000]], grad_fn=<SubBackward0>)

S S E = ( y − X w ^ T ) T ( y − X w ^ T ) SSE =(y - X\hat w^T)^T(y - X\hat w^T) SSE=(y−Xw^T)T(y−Xw^T)

torch.mm((torch.mm(X,weights)-y).t(), torch.mm(X,weights)-y)
tensor([[2.8518e-10]], grad_fn=<MmBackward>)
上一篇:全连接单次更新


下一篇:【面试题必考题】从零实现神经网络的梯度反向传播算法