反向传播

【学习参考链接】,讲得非常棒,视频更详细。

# 只需 shift+回车 运行本单元格,就可以让jupyter notebook宽屏显示
from IPython.core.display import display, HTML
display(HTML('<style>.container { width:100% !important; }</style>'))

1 神经网络结构介绍

x 1 , x 2 , x 3 , x 4 x_1,x_2,x_3,x_4 x1,x2,x3,x4为输入层所输入的参数, h i j h_{ij} hij为隐藏层中所对应的输入,其维度与每一层的个数有关。如这里 x ∈ R 4 x\in \mathbb{R}^4 xR4 h i d d e n 1 ∈ R 5 hidden_1 \in \mathbb{R}^5 hidden1R5,由 h i d d e n 1 = ω X hidden_1 = \omega X hidden1=ωX可以确定其维度为: ω 5 × 4 \omega_{5 \times 4} ω5×4。由此规律可得 I n p u t Input Input h i d d e n 1 hidden_1 hidden1之间的权重是 ω 5 × 4 \omega_{5 \times 4} ω5×4 h i d d e n 1 hidden_1 hidden1 h i d d e n 2 hidden_2 hidden2之间的权重是 ω 4 × 5 \omega_{4 \times 5} ω4×5 h i d d e n 2 hidden_2 hidden2 O u t p u t Output Output之间的权重为 ω 3 × 4 \omega_{3 \times 4} ω3×4。即每相邻两层之间的权重维度为后一层的个数作为行数与前一层的个数作为列数。

在这里插入图片描述

2 计算图的构建

假设有一个两层的神经网络的表达式为: y ^ = W 2 ( W 1 ⋅ X + b 1 ) + b 2 \hat y = W_2(W_1\cdot X + b_1) + b_2 y^=W2(W1X+b1)+b2

W 1 ⋅ X + b 1 W_1\cdot X + b_1 W1X+b1看作为第一层,整体但作为第二层。其中 b 1 b_1 b1 b 2 b_2 b2为偏置,为非线性函数根据输入所计算出的值,假设非线性函数为: s i g m o i d = 1 1 + e − x sigmoid = \frac1{1 + e^{-x}} sigmoid=1+ex1,则 x 1 x_1 x1所对应的偏置为 1 1 + e − x 1 \frac1{1 + e^{-x_1}} 1+ex11,通过计算每一个输入所对应的值构成列向量相加即可。第二层同理,其计算图如下所示:

加入非线性函数的原因就是防止能够将原表达式展开,导致增加的权重的没有意义,因此需要加入非线性函数使其不能够展开进行线性运算。

矩阵相关计算公式参考书

3 前馈和反馈的计算练习

4 Pytorch实现前馈和反馈

Tensor:用来存储数据的,前面的图中的所有数据,存的数据包括标量、矩阵、向量和高阶数据。
Data:储存权重值 w w w;grad:损失函数对权重的导数。

y ^ = x w \hat y = x w y^=xw

# 导入torch库 
import torch
# GPU与CPU的切换:如果你系统中没有可用的cuda,直接切换到cpu来运行
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 
# 查看GPU的名称 
torch.cuda.get_device_name()
'GeForce RTX 2060'
# 构建数据集
x_data = [1,2,3]
y_data = [2,4,6]
# 选择初始权重,这里权重为一个数,也要用数组表示
w = torch.Tensor([1]) # 相当于Numpy数组
# 设置需要计算随机梯度
w.requires_grad = True
def forward(x):
    return x * w 
# w 是一个Tensor ,通过*自动将x转为Tensor,从而构成一个计算图
def loss(x,y):
    y_pred = forward(x)
    return (y_pred - y) ** 2
# 调动loss即构建出了计算图,看见代码见计算图

计算梯度用张量,更新梯度用标量。

print("predic(before training)",4,forward(4).item())
for epoch in range(100):
    for x,y in zip(x_data,y_data):
        # 前馈过程只需要计算loss,l表示算出的张量Tensor
        l = loss(x,y) 
        # 通过调用backward,获取计算图中的所有梯度变量
        l.backward() # 只要一做backward,计算图就释放了
        # 这也是Pytorch的一个特点,w.grad.item()表示将其变为Python的标量,防止产生张量
        print("\tgrad:",x,y,w.grad.item())
        # 获取所需要的梯度,w.data表示取的标量,避免计算张量
        w.data = w.data - 0.01 * w.grad.data
        # 权重中的梯度数据清零,若不清零则为梯度的累加
        w.grad.data.zero_() 
    print("pregress:",epoch,l.item())
print("predic(after training)",4,forward(4).item())

结果太多,这里删掉了一些。

predic(before training) 4 4.0
pregress: 95 9.094947017729282e-13
	grad: 1 2 -7.152557373046875e-07
	grad: 2 4 -2.86102294921875e-06
	grad: 3 6 -5.7220458984375e-06
pregress: 96 9.094947017729282e-13
	grad: 1 2 -7.152557373046875e-07
	grad: 2 4 -2.86102294921875e-06
	grad: 3 6 -5.7220458984375e-06
pregress: 97 9.094947017729282e-13
	grad: 1 2 -7.152557373046875e-07
	grad: 2 4 -2.86102294921875e-06
	grad: 3 6 -5.7220458984375e-06
pregress: 98 9.094947017729282e-13
	grad: 1 2 -7.152557373046875e-07
	grad: 2 4 -2.86102294921875e-06
	grad: 3 6 -5.7220458984375e-06
pregress: 99 9.094947017729282e-13
predic(after training) 4 7.999998569488525

视频课后练习:

# 导入torch库 
import torch
# GPU与CPU的切换:如果你系统中没有可用的cuda,直接切换到cpu来运行
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") 
# 查看GPU的名称 
print(torch.cuda.get_device_name())

# 构建数据集
x_data = [1,2,3]
y_data = [2,4,6]
# 选择初始权重,这里权重为一个数,也要用数组表示
w1 = torch.Tensor([1])
w2 = torch.Tensor([1])
b = torch.Tensor([1])
# 设置需要计算随机梯度
w1.requires_grad = True
w2.requires_grad = True
b.requires_grad = True
GeForce RTX 2060
# 构建计算图
def forward(x):
    return w1 * x * x + w2 * x + b

def loss(x,y):
    y_pred = forward(x)
    return (y_pred - y) ** 2
print("predic(before training)",4,forward(4).item())
for epoch in range(100):
    for x,y in zip(x_data,y_data):
        # 前馈过程只需要计算loss,l表示算出的张量Tensor
        l = loss(x,y) 
        # 通过调用backward,获取计算图中的所有梯度变量
        l.backward() # 只要一做backward,计算图就释放了
        # 这也是Pytorch的一个特点,w.grad.item()表示将其变为Python的标量,防止产生张量
        print(f"x:{x}\ty:{y}\tw1:{w1.grad.item()}\tw2:{w2.grad.item()}\tb:{b.grad.item()}")
        # 获取所需要的梯度,w.data表示取的标量,避免计算张量
        w1.data = w1.data - 0.01 * w1.grad.data
        w2.data = w2.data - 0.01 * w2.grad.data
        b.data = b.data - 0.01 * b.grad.data
        # 权重中的梯度数据清零,若不清零则为梯度的累加
        w1.grad.data.zero_()
        w2.grad.data.zero_() 
        b.grad.data.zero_() 
    print("pregress:",epoch,l.item())
print("predic(after training)",4,forward(4).item())

结果太多,这里删除一些。

predic(before training) 4 21.0
x:1	y:2	w1:2.0	w2:2.0	b:2.0
x:2	y:4	w1:22.880001068115234	w2:11.440000534057617	b:5.720000267028809
x:3	y:6	w1:77.04720306396484	w2:25.682401657104492	b:8.560800552368164
pregress: 0 18.321826934814453
x:1	y:2	w1:0.31661510467529297	w2:0.31661510467529297	b:0.31661510467529297
x:2	y:4	w1:-1.7297420501708984	w2:-0.8648710250854492	b:-0.4324355125427246
x:3	y:6	w1:1.4307546615600586	w2:0.47691822052001953	b:0.15897274017333984
pregress: 99 0.00631808303296566
predic(after training) 4 8.544172286987305
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

而又何羡乎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值