笔记写的越来越敷衍(嘻嘻)
男神笑容开篇
经典网络
LeNet-5
LeNet-5任务是手写数字识别(灰度图像)
补充一点pytorch构建这个网络的代码。
构造函数__init__()里面,只写“具有可学习参数的层”,因为池化层是不用learning的(这个在池化层和卷积神经网络实例的笔记里面讲了),所以看不到池化层的参数。
import torch.nn as nn
import torch.nn.functional as F
#继承nn.Model
class Net(nn.Module):
#网络中具有可学习参数的层放在构造函数中
def __init__(self):
super(Net,self).__init__()
#1是通道数,6是输出的通道数,5是filter的大小
self.conv1 = nn.Conv2d(1,6,5)
self.conv2 = nn.Conv2d(6,16,5)
#全连接层
#16*5*5是输入的神经元个数,120是输出的神经元个数
self.fc1 = nn.Linear(16*5*5,120)
self.fc2 = nn.Linear(120,84)
self.fc3 = nn.Linear(84,10)
def forward(self,x):
#卷积--激活--池化
x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))
x = F.max_pool2d(F.relu(self.conv2(x)),(2,2))
#进入全连接
x = x.view(x.size()[0],-1)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
print(net)
和之前跟着一本书做手写数字识别实战的模型对比了一下,还是不太一样的:
AlexNet
和LeNet很像但是网络更大,而且比其更优的地方是用ReLu激活。
VGG-16
它的网络结构更简单。真正地简化了网络结构。它的卷积层过滤器都是3*3,步长为1,用same padding,池化层都是用了max pooling,尺寸2*2,步长2。
残差网络
通常我们的计算是这样的(如下图),这个过程又叫“主路径”。
残差网络是这样的:
a[l]还直接加到了第二次ReLU的前面,这被称作“shortcut”或“skip connection”。下面这个从a[l]到a[l+2]部分的网络,就是残差块。
下面这个图说明了为什么出现了“残差网络”。
理论上,随着网络加深,训练错误会随之降低。但是实际上,使用普通网络,训练错误却会回升。网络太深反而会导致训练误差更糟。但是ResNets的表现符合理论上的表现,对训练很深的网络很有效。
找了下资料,在很深的神经网络里面会出现的问题:
reference 知乎专栏
以下都是引用自上面的链接:
所以引入了可以改善退化问题的残差网络。
残差网络为什么会那么有效呢?
先看下图绿字:如果权重和偏置单元的值就跟绿字一样,那么最后使用ReLU激活之后,得到的值仍为a[l]。即a[l+2]=a[l]。这个就是上面那张图结尾说的恒等映射。这说明,残差块比较容易学习恒等函数。所以加上这样的两层并不会太影响神经网络的能力。
还有是普通网络在随着网络加深时,会越来越难选择参数来学习。而残差网络有效主要是因为,这些“额外层”学习恒等函数非常简单。使得这个网络至少表现不会越来越差。
还有一个细节是(看下面红字):ResNets的卷积经常使用“same padding”来保持维度,来保证下图两个红点的地方维度相同。如果维度不一样了,如下图a[l+2]是256,a[l]是128,还可以通过增加额外的矩阵Ws(256*128)来保证维度相同。