首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >深度学习基础:3.反向传播和梯度下降

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

作者头像
zstar
发布2022-06-14 14:00:26
发布2022-06-14 14:00:26
6080
举报
文章被收录于专栏:往期博文往期博文

动态计算图

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

反向传播

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

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

输出:

代码语言:javascript
复制
tensor(2.)

梯度下降

梯度下降的代数表示

令多元线性回归方程为

f(x) = w_1x_1+w_2x_2+...+w_dx_d+b

\hat w = (w_1,w_2,...,w_d,b)
\hat x = (x_1,x_2,...,x_d,1)

出于加快迭代收敛速度的目标,我们在定义梯度下降的损失函数L时,在原SSE基础上进行比例修正,新的损失函数

L(w_1,w_2,...,w_d,b) = \frac{1}{2m}SSE

,其中,m为样本个数。

损失函数有:

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

并且,根据此前描述过程,在开始梯度下降求解参数之前,我们首先需要设置一组参数的初始取值

(w_1, w_2..., w_d, b)

,以及学习率\alpha ,然后即可执行迭代运算,其中每一轮迭代过程需要执行以下三步

Step 1.计算梯度表达式

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

\frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b)

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

\alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b)

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

w_i = w_i - \alpha \frac{\partial}{\partial w_i}L(w_1, w_2..., w_d, b)

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

举例说明

有数据集表示如下:

x

y

1

2

2

4

3

6

假设,我们使用

y = wx

进行拟合,则SSE为:

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

\frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2) = 0
w=2

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

grad^* = \frac{\partial{SSE_{(a)}}}{\partial{(a)}} = 14(2w-4) = 28(w-2)

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

grad = w-2

设步长$\alpha=

0.5,初始值点取为

w_0=0$,则迭代过程如下:

第一轮迭代:

grad(w_0)=grad(0)=-2,w_0=0,w_1=w_0-\alpha*grad(w_0)=0-\frac{1}{2}(-2)=1

第二轮迭代:

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(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(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}

依次类推:

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}; ...
w_n=\frac{2^n-1}{2^{n-1}} = 2-\frac{1}{2^{n-1}}
\lim_{n→\infty} (w_n) = \lim_{n→\infty} (2-\frac{1}{2^{n-1}}) = 2

梯度下降的矩阵表示

令多元线性回归方程为

f(x) = w_1x_1+w_2x_2+...+w_dx_d+b

\hat w = (w_1,w_2,...,w_d,b)
\hat x = (x_1,x_2,...,x_d,1)

因此,方程可表示为

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

另外,我们将所有自变量的值放在一个矩阵中,有

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]
y = \left [\begin{array}{cccc} y_1 \\ y_2 \\ . \\ . \\ . \\ y_m \\ \end{array}\right]

此时,SSE可表示为:

SSE = ||y - X\hat w^T||_2^2 = (y - X\hat w^T)^T(y - X\hat w^T) = E(\hat w)

梯度下降损失函数为:

L(\hat w) = \frac{1}{2m} SSE =\frac{1}{2m} (y - X\hat w^T)^T(y - X\hat w^T)

同样,我们需要设置初始化参数

(w_1, w_2..., w_d, b)

,以及学习率\alpha ,然后即可开始执行迭代过程,同样,每一轮迭代需要有三步计算:

Step 1.计算梯度表达式

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

\frac{\partial}{\partial \hat w}L(\hat w) = \frac{1}{m}X^T(X\hat w ^T - Y)

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

\alpha \frac{\partial}{\partial \hat w}L(\hat w)

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

\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)

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

编程实现

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

代码语言:javascript
复制
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
代码语言:javascript
复制
X = torch.tensor([[1.,1],[3, 1]], requires_grad = True)
X
代码语言:javascript
复制
tensor([[1., 1.],
        [3., 1.]], requires_grad=True)
代码语言:javascript
复制
y = torch.tensor([2.,4], requires_grad = True).reshape(2,1)
y
代码语言:javascript
复制
tensor([[2.],
        [4.]], grad_fn=<ViewBackward>)
代码语言:javascript
复制
gradDescent(X, y)
代码语言:javascript
复制
tensor([[1.0372],
        [0.9102]], grad_fn=<SubBackward0>)
代码语言:javascript
复制
weights = gradDescent(X, y, numIt = 10000)
weights
代码语言:javascript
复制
tensor([[1.0000],
        [1.0000]], grad_fn=<SubBackward0>)
SSE =(y - X\hat w^T)^T(y - X\hat w^T)
代码语言:javascript
复制
torch.mm((torch.mm(X,weights)-y).t(), torch.mm(X,weights)-y)
代码语言:javascript
复制
tensor([[2.8518e-10]], grad_fn=<MmBackward>)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态计算图
  • 反向传播
  • 梯度下降
    • 梯度下降的代数表示
    • 举例说明
    • 梯度下降的矩阵表示
    • 编程实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档