神经网络基础--什么是正向传播??什么是方向传播??
前言
- 本专栏更新神经网络的一些基础知识;
- 这个是本人初学神经网络做的笔记,仅仅堆正向传播、方向传播就行了了一个讲解,更加系统的讲解,本人后面会更新《李沐动手学习深度学习》,会更有详细讲解;
- 案例代码基于pytorch;
- 欢迎收藏 + 关注, 本人将会持续更新。
文章目录
- 正向传播与反向传播
- 梯度下降法
- 简介
- 不同梯度下降法区别
- 前向传播
- 反向传播算法
- 简介
- 案例介绍原理
- 代码展示
正向传播与反向传播
梯度下降法
简介
表达式:
w i j n e w = w i j o l d − η ∂ E ∂ w i j w_{ij}^{new}= w_{ij}^{old} - \eta \frac{\partial E}{\partial w_{ij}} wijnew=wijold−η∂wij∂E
其中 n \text{n} n 是学习率,控制梯度收敛的快慢。
深度学习几个基础概念:
- Eopch:使用数据对模型进行完整训练,一次
- Batch:使用训练集中小部分样本对模型权重进行方向传播更新
- Iteration:使用一个 Batch 数据对模型进行一次参数更新
不同梯度下降法区别
梯度下降方式 | Training Set Size | Batch Size | Number of Batches |
---|---|---|---|
BGD(批量梯度下降) | N | N | 1 |
SGD(随机梯度下降) | N | 1 | N |
Mini-Batch(小批量梯度下降) | N | B | N / B + 1 |
- 批量梯度下降法是最原始的形式,它是指在每一次迭代时使用所有样本来进行梯度的更新;
- 随机梯度下降法不同于批量梯度下降,随机梯度下降是在每次迭代时使用一个样本来对参数进行更新;
- 小批量梯度下降相当于是前两个的总和。
- 具体优缺点:后面更新**李沐老师《动手学习深度学习》**会有更详细解释。
前向传播
前向传播就是输入x,在神经网络中一直向前计算,一直到输出层为止,图像如下:
在网络的训练过程中经过前向传播后得到的最终结果跟训练样本的真实值总是存在一定误差,这个误差便是损失函数。想要减小这个误差,就用损失函数Loss,从后往前,依次求各个参数的偏导,这就是反向传播.
反向传播算法
简介
BP 算法也叫做误差反向传播算法,它用于求解模型的参数梯度,从而使用梯度下降法来更新网络参数。它的基本工作流程如下:
- 通过正向传播得到误差,正向传播指的是数据从输入–> 隐藏层–>输出层,经过层层计算得到预测值,并利用损失函数得到预测值和真实值之前的误差。
- 通过反向传播把误差传递给模型的参数,从而调整神经网络参数,缩小预测值和真实值之间的误差。
- 反向传播算法是利用链式法则进行梯度求解,然后进行参数更新。
案例介绍原理
- 网络结构:
- 输入层:两个神经元
- 隐藏层:一共两层,每一层两个神经元
- 输出层:输出两个值
- 输入:
- i1:0.05,i2:0.10
- 目标值:
- 0.01,0.99
- 初始化权重:
- w1: 0.15
- w2: 0.20
- w3: 0.25
- w4:0.30
- w5:0.40
- w6:0.45
- w7:0.50
- w8:0.55
- 由下向上看,最下层绿色的两个圆代表两个输入值
- 右侧的8个数字,最下面4个表示 w1、w2、w3、w4 的参数初始值,最上面的4个数字表示 w5、w6、w7、w8 的参数初始值
- b1 值为 0.35,b2 值为 0.60
- 预测结果分别为: 0.7514、0.7729
接下来就是梯度更新
方向传播中梯度跟新流程:
w5、w7为例:
计算出偏导后,运用梯度下降法进行更新,这里学习率为0.5:
接下来跟新w1:
梯度更新:
代码展示
该代码就是将上面的神经网络代码实现,牢记对神经网络理解很有用
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 定义神经网络结构
self.linear1 = nn.Linear(2, 2)
self.linear2 = nn.Linear(2, 2)
# 神经网络参数初始化,设置权重和偏置
self.linear1.weight.data = torch.tensor([[0.15, 0.20], [0.25, 0.30]]) # 权重
self.linear2.weight.data = torch.tensor([[0.40, 0.45], [0.50, 0.55]])
self.linear1.bias.data = torch.tensor([0.35, 0.35]) # 偏置
self.linear2.bias.data = torch.tensor([0.60, 0.60])
def forward(self, x):
x = self.linear1(x) # 经过第一次线性变换
x = torch.sigmoid(x) # 经过激活函数,进行非线性变换
x = self.linear2(x) # 经过第二层线性变换
x = torch.sigmoid(x) # 经过激活函数,进行非线性变换
return x
if __name__ == '__main__':
# 输入变量和目标变量
inputs = torch.tensor([0.05, 0.10])
target = torch.tensor([0.01, 0.99])
# 创建神经网络
net = Net()
# 训练
outputs = net(inputs)
# 计算误差,梯度下降法,********* 公式实现 ***********
loss = torch.sum((target - outputs) ** 2) / 2
# 计算梯度下降
optimizer = optim.SGD(net.parameters(), lr=0.5)
# 清除梯度
optimizer.zero_grad()
# 反向传播
loss.backward()
# 打印 w5、w7、w1 的梯度值
print(net.linear1.weight.grad.data)
print(net.linear2.weight.grad.data)
# 更新权重,梯度下降更新
optimizer.step()
# 打印网络参数
print(net.state_dict())
输出:
tensor([[0.0004, 0.0009],
[0.0005, 0.0010]])
tensor([[ 0.0822, 0.0827],
[-0.0226, -0.0227]])
OrderedDict([('linear1.weight', tensor([[0.1498, 0.1996],
[0.2498, 0.2995]])), ('linear1.bias', tensor([0.3456, 0.3450])), ('linear2.weight', tensor([[0.3589, 0.4087],
[0.5113, 0.5614]])), ('linear2.bias', tensor([0.5308, 0.6190]))])