本文参考:《DIVE INTO DEEP LEARNING》
LeNet
LeNet是进行手写数字识别的网络
LeNet分为卷积层块和全连接层块两个部分,激活函数都使用sigmoid
。
在卷积层块中,每个卷积核的stride均为1,padding均为0。第一个卷积层输出通道数为6,第二个卷积层输出通道数则增加到16。这是因为第二个卷积层比第一个卷积层的输入的高和宽要小,所以增加输出通道使两个卷积层的参数尺寸类似。
卷积层块的两个最大池化层的窗口形状均为 ,且步幅为2。
全连接层块含3个全连接层。它们的输出个数分别是120、84和10,其中10为输出的类别个数。
# 以(1, 28, 28)的Mnist手写数字数据集为例
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 6, 5),
nn.Sigmoid(),
nn.MaxPool2d(2, 2),
nn.Conv2d(6, 16, 5),
nn.Sigmoid(),
nn.MaxPool2d(2, 2)
)
self.classifier = nn.Sequential(
nn.Linear(16 * 4 * 4, 120),
nn.Sigmoid(),
nn.Linear(120, 84),
nn.Sigmoid(),
nn.Linear(84, 10)
)
def forward(self, x):
x = self.features(x)
x = x.view(x.shape[0], -1)
x = self.classifier(x)
return x
AlexNet
AlexNet与LeNet的设计理念非常相似,但也有显著的区别
- 激活函数全部使用
ReLU
,相比sigmoid
计算更简单且缓解了梯度消失问题 - 与相对较小的LeNet相比,AlexNet包含8层变换,其中有5层卷积和2层全连接隐藏层,以及1个全连接输出层。
- AlexNet第一层中的卷积窗口形状是 。因为ImageNet中绝大多数图像的高和宽均比MNIST图像的高和宽大10倍以上,ImageNet图像的物体占用更多的像素,所以需要更大的卷积窗口来捕获物体。 同时使用步幅4来较大幅度减小输出高和宽。而且相比于LeNet,输出的通道数也要大很多.
- 第二层中的卷积窗口形状减小到
- 之后的卷积核都采用
- 紧接着最后一个卷积层的是两个输出个数为4096的全连接层。这两个巨大的全连接层带来将近1GB的模型参数。同时每个全连接层后还添加了
Dropout
层 - 最后一个全连接输出层输出个数为类别数
- AlexNet引入了大量的图像增广,如翻转、裁剪和颜色变化,从而进一步扩大数据集来缓解过拟合
# 以(1, 28, 28)的Mnist手写数字数据集为例
# 这里在加入网络训练之前先要把图片更改大小为与ImageNet中图片相同的224*224 (torchvision.transforms.Resize)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 96, 11, 4),
nn.ReLU(inplace=True),
nn.MaxPool2d(3, 2),
nn.Conv2d(96, 256, 5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(3, 2),
nn.Conv2d(256, 384, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 384, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(384, 256, 3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(3, 2),
)
self.classifier = nn.Sequential(
nn.Linear(256 * 5 * 5, 4096),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5, inplace=False),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5, inplace=False),
nn.Linear(4096, 10)
)
def forward(self, x):
x = self.features(x)
x = x.view(x.shape[0], -1)
x = self.classifier(x)
return x