【2021-2022 春学期】人工智能-作业1:配置PyTorch环境并利用PyTorch实现反向传播

【2021-2022 春学期】人工智能-作业1:配置PyTorch环境并利用PyTorch实现反向传播,第1张

1. 安装Python运行环境和Pycharm

安装Pycharm, 配置好Python开发环境。
由于之前使用Django框架进行Web开发时,已经安装过Pycharm并且配置过Python3的环境,在此就不再次配置了,只做一下展示~,Python版本为3.6.3。

2.安装PyTorch

(1) 安装PyTorch
首先,进入PyTorch的官网,找到对应的下载位置。 *** 作系统根据自己的系统进行选择,我的是Window10,于是选择Windows,安装方式我选择的是pip方法,语言自然选择Python,因为我的显卡是因特尔的显卡,所以选择CUDA11.3,然后复制下方的链接到本机的控制台进行安装。

将安装命令粘贴到控制台后,按下回车就开始下载了,时间可能会有些长,需要多等一会儿~。

经过耐心的等待后,安装终于结束了。。。

然后,进行测试,验证是否成功安装。
经过验证,安装成功!

3. 实现反向传播 1. 反向传播算法介绍

在开始写代码之前,我们先简单介绍一下反向传播算法。

简介

无论是机器学习还是深度学习,都绕不开一个梯度下降。深度学习的大致步骤为:

  • 构建神经网络
  • 数据拟合
  • 选出最佳模型

其中,选出最佳模型的方式,其实就是利用梯度下降算法,选出损失函数最小的那个。在传统的机器学习中,这个比较容易实现。但是在深度学习中,由于存在输入层,隐藏层,输出层,且隐藏层到底有多深,这些都是未知数,因此计算也会更加繁琐。如果,在输出层输出的数据和我们设定的目标及标准相差比较大,这个时候,就需要反向传播。利用反向传播,逐层求出目标函数对各神经元权值的偏函数,构成目标函数对权值向量的梯度,之所以算这个,是为了对权值的优化提供依据,等权值优化了之后,再转为正向传播,直到输出的结果达到设定的标准。

反向传播原理 (1) 导数的链式法则

反向传播的原理其实很好理解,主要的理论就是我们在高等数字中学的导数计算:
假 设 y = f ( x ) , z = g ( y ) , 那 么 有 : d z d x = d z d y d y d x 假设 y = f(x), z = g(y), 那么有:\frac {dz} {dx} = \frac {dz} {dy} \frac {dy} {dx} y=f(x),z=g(y),dxdz=dydzdxdy
假 设 有 x = f ( u ) , y = g ( u ) , z = h ( x , y ) , 那 么 有 : d z d u = δ z δ x d x d u + δ z δ y d y d u 假设有 x = f(u), y = g(u), z = h(x, y), 那么有: \frac {dz} {du} = \frac {\delta z} {\delta x} \frac {dx} {du} + \frac {\delta z} {\delta y} \frac {dy} {du} x=f(u),y=g(u),z=h(x,y),dudz=δxδzdudx+δyδzdudy

(2) 正向传播与反向传播

正向传播(forward propagation) 是指对神经网络沿着从输入层到输出层的顺序,依次计算并存储模型的中间变量(包括输出)。
以逻辑回归中的神经元为例:

在这个神经元中, z = w 1 x 1 + w 2 x 2 + b z = w_1 x_1 + w_2 x_2 + b z=w1x1+w2x2+b S i g m o i d 函 数 : y = σ ( z ) Sigmoid函数: y = \sigma(z) Sigmoidy=σ(z)
我们知道,无论是机器学习还是深度学习,计算之后都会产生一定的损失值,我们把这个损失函数记为 l l l
反向传播的最终目的是修正权值 w w w,我们让 l l l w w w求偏导,根据链式法则:
δ l δ w = δ l δ z δ z δ w \frac {\delta l} {\delta w} = \frac {\delta l} {\delta z} \frac {\delta z} {\delta w} δwδl=δzδlδwδz


计算结果:
δ z δ w 1 = x 1 , δ z δ w 2 = x 2 \frac {\delta z} {\delta w _1} = x_1, \frac {\delta z} {\delta w_2} = x_2 δw1δz=x1,δw2δz=x2
x 1 x_1 x1, x 2 x_2 x2其实就是最开始的输入值,可以当做已知的,这个计算过程就是正向传播。

但是,计算反向传播就会很复杂,反向传播(back-propagation)指的是计算神经网络参数梯度的方法。总的来说,反向传播依据微积分中的链式法则,沿着从输出层到输入层的顺序,依次计算并存储对输入或输出目标函数有关神经网络各层的中间变量以及参数的梯度。对输入或输出 X , Y , Z X, Y, Z X,Y,Z为任意形状张量的函数 Y = f ( X ) 和 Z = g ( Y ) Y = f(X)和Z = g(Y) Y=f(X)Z=g(Y), 通过链式法则,我们有:
δ Z δ X = p r o d ( δ Z δ Y , δ Y δ X ) \frac {\delta Z} {\delta X} = prod(\frac {\delta Z} {\delta Y}, \frac {\delta Y} {\delta X}) δXδZ=prod(δYδZ,δXδY)
首先,分别计算目标函数 J = L + s J = L + s J=L+s 有关损失项L和正则项s的梯度。
δ J δ L = 1 , δ J δ s = 1. \frac {\delta J} {\delta L} = 1, \frac {\delta J} {\delta s} = 1. δLδJ=1,δsδJ=1.
其次,依据链式法则计算目标函数有关输出层的梯度 δ J δ o \frac {\delta J} {\delta o} δoδJ
δ J δ o = p r o d ( δ J δ L , δ L δ o ) = δ L δ o \frac {\delta J} {\delta o} = prod(\frac {\delta J} {\delta L}, \frac {\delta L} {\delta o}) = \frac {\delta L} {\delta o} δoδJ=prod(δLδJ,δoδL)=δoδL
接下来,计算正则项有关两个参数的梯度:
δ s δ W ( 1 ) = λ W ( 1 ) , δ s δ W ( 2 ) = λ W ( 2 ) , \frac {\delta s} {\delta W^{(1)}} = \lambda W^{(1)}, \frac {\delta s} {\delta W^{(2)}} = \lambda W^{(2)}, δW(1)δs=λW(1),δW(2)δs=λW(2),
现在,我们可以计算最靠近输出层的模型参数的梯度 δ J δ W \frac {\delta J} {\delta W} δWδJ, 依据链式法则,得到:
δ J δ W ( 2 ) = p r o d ( δ J δ o , δ o δ W ( 2 ) ) + p r o d ( δ J δ s , δ s δ W ( 2 ) ) = δ J δ o h T + λ W ( 2 ) \frac {\delta J} {\delta W^{(2)}} = prod(\frac {\delta J} {\delta o}, \frac {\delta o} {\delta W^{(2)}}) + prod(\frac {\delta J} {\delta s}, \frac {\delta s} {\delta W^{(2)}}) = \frac {\delta J} {\delta o} h^{T} + \lambda W^{(2)} δW(2)δJ=prod(δoδJ,δW(2)δo)+prod(δsδJ,δW(2)δs)=δoδJhT+λW(2)
沿着输出层向隐藏层继续反向传播,隐藏层变量的梯度 δ J δ h \frac {\delta J} {\delta h} δhδJ可以这样计算:
δ J δ h = p r o d ( δ J δ o , δ o δ h ) = W ( 2 ) δ J δ o \frac {\delta J} {\delta h} = prod(\frac {\delta J} {\delta o}, \frac {\delta o} {\delta h}) = W^{(2)} \frac {\delta J} {\delta o} δhδJ=prod(δoδJ,δhδo)=W(2)δoδJ
最终,我们可以得到最靠近输入层的模型参数的梯度 δ J \delta J δJ \ δ W ( 1 ) \delta W^{(1)} δW(1), 依据链式法则,得到
δ J δ W ( 1 ) = p r o d ( δ J δ z , δ z δ W ( 1 ) ) + p r o d ( δ J δ s , δ s δ W ( 1 ) ) = δ J δ z x T + λ W ( 1 ) \frac {\delta J} {\delta W^{(1)}} = prod(\frac {\delta J} {\delta z}, \frac {\delta z} {\delta W^{(1)}}) + prod(\frac {\delta J} {\delta s}, \frac {\delta s} {\delta W^{(1)}}) = \frac {\delta J} {\delta z} x^{T} + \lambda W^{(1)} δW(1)δJ=prod(δzδJ,δW(1)δz)+prod(δsδJ,δW(1)δs)=δzδJxT+λW(1)

2. 打开Pycharm

首先,打开我们强大好用的Pycharm!!!

3. 创建项目

新建一个Python项目,命名为AI,为了可以使用刚才在终端使用pip指令安装的PyTorch包,选择使用继承全局站点包,然后单击创建。

打开main.py,然后开始写代码:

import torch
import matplotlib.pyplot as plt

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

w = torch.Tensor([3.0])  # 初始化权重
w.requires_grad = True  # 说明w需要计算梯度


# 注意其中w是tensor,在实际运算中开始进行数乘。
def forward(x):
    return w * x


# 损失函数的求解,构建计算图,并不是乘法或者乘方运算
def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y) ** 2


print("Predict before training", 4, forward(4).item())  ## 打印学习之前的值,.item表示输出张量的值

learning_rate = 0.01
epoch_list = []
loss_list = []
# 训练
for epoch in range(100):
    for x, y in zip(x_data, y_data):
        l = loss(x, y)
        l.backward()  # 向后传播
        print('\tgrad', x, y, w.grad.item())  # 将梯度存到w之中,随后释放计算图,w.grad.item():取出数值
        w.data = w.data - learning_rate * w.grad.data  # 张量中的grad也是张量,所以取张量中的data,不去建立计算图
        w.grad.data.zero_()  # 释放data
    print("process:", epoch, l.item())
    epoch_list.append(epoch)
    loss_list.append(l.item())

print('Predict after training', 4, forward(4).item())

# 绘制可视化
plt.plot(epoch_list, loss_list)
plt.xlabel("epoch")
plt.ylabel("Loss")
plt.show()

运行结果:

4.参考资料:

1 代码来源
2 深度学习——反向传播
3. 《动手学深度学习》—— 李沐
4. PyTorch安装教程

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/868499.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存