文章目录
前向传播和反向传播是在训练神经网络的过程中存在两个过程,从信息流的角度可以直观地解释神经网络的信息传播过程:
前向传播将输入信号通过现有参数矩阵的网络计算,直至输出产生误差,反向传播则根据误差信息更新权重矩阵。神经网络的训练,是一场以代价函数值为主导的反向传播运动,旨在得到最优的参数矩阵,进而将多层神经网络应用到分类或者回归任务中去。
1.前向传播
1.1 原理和计算图
前向传播的过程很容易理解:给定网络一个输入,通过网络计算出输出,并得到代价函数值的过程即为前向传播。
以最典型的多层感知机网络为例。设
w
j
k
l
w^{l}_{jk}
wjkl为第
l
−
1
l-1
l−1 层第
k
k
k个神经元到第
l
l
l层第
j
j
j个神经元的权重,
b
j
l
b^{l}_{j}
bjl为第
l
l
l层第
j
j
j个神经元的偏置,
a
j
l
a^{l}_{j}
ajl为第
l
l
l层第
j
j
j个神经元的输出,则
a
j
l
a^{l}_{j}
ajl的值由上一层神经元传递过来经过网络的计算(
w
w
w和
b
b
b),并经由激活函数输出:
前向传播的过程正是由这样逐层计算,并最终根据
y
y
y和
y
^
\hat{y}
y^确定代价函数,从而提供给后向传播去做梯度计算。
前向传播过程的计算图如下:
1.2 编写forward函数(Pytorch)
Pytorch提供forward函数来定义前向传播的过程。在使用forward函数时,实际上是在Module类中,首先调用__call__方法,并在__call__里面调用module的forward方法。__call__方法在Pytorch的源码定义如下:
def __call__(self, *input, **kwargs):
result = self.forward(*input, **kwargs) #调用forward。
for hook in self._forward_hooks.values():
#将注册的hook拿出来用
hook_result = hook(self, input, result)
...
return result
使用forward描述网络前向传播大致可使用下面的模板:
class Module(nn.Module):
def __init__(self):
super(Module, self).__init__()
......
......
def forward(self, x):
......
......
return x
# 实例化一个对象
module = Module()
# 前向传播
module(data)
下面是定义一个LeNet网络的示例:
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
layer1 = nn.Sequential()
layer1.add_module('conv1', nn.Conv(1, 6, 3, padding=1))
layer1.add_moudle('pool1', nn.MaxPool2d(2, 2))
self.layer1 = layer1
layer2 = nn.Sequential()
layer2.add_module('conv2', nn.Conv(6, 16, 5))
layer2.add_moudle('pool2', nn.MaxPool2d(2, 2))
self.layer2 = layer2
layer3 = nn.Sequential()
layer3.add_module('fc1', nn.Linear(400, 120))
layer3.add_moudle('fc2', nn.Linear(120, 84))
layer3.add_moudle('fc3', nn.Linear(84, 10)) #输出,10分类
self.layer3 = layer3
def forward(self, x):
x = self.layer1(x) #第一层卷积层
x = self.layer2(x) #第二层卷积层
x = x.view(x.size(0), -1) #拉伸为向量提供给全连接层输入
x = self.layer3(x) #全连接层
return x
2.后向传播(BP)
2.1 原理
有了前向传播之后,剩下的一个关键问题是如何训练网络参数(权值和偏置),使得代价函数最小化。网络训练的方法大致分为两种:一是将其他连接权值进行固定,只训练某两层间的连接权值,研究者们已经从数学上证明了这种方法对所有非线性可分的样本集都是收敛的;另一种即是大家所熟知的后向传播(Back Propagation, BP)算法。
BP算法允许来自代价函数的信息通过网络向后流动,其目的是为了给梯度下降算法提供每一层的梯度值。实际上,BP算法不仅适用于多层神经网络,原则上的任意函数的导数都可以通过BP来计算。
BP算法本质上是链式法则的复用,其计算的过程如下:
2.2 Pytorch的自动求导机制
2.3 Pytorch后向传播的实现
3.梯度消失和爆炸
3.1 成因
3.2 解决的办法
参考:
[1] https://blog.csdn.net/u011501388/article/details/84062483