在进行图像识别等任务时,由于输入图像的尺寸较大、同一列邻近的像素在这个向量中可能相距较远,难以识别等问题,因此不适合用全连接层进行网络构建,而应当在神经网络中添加卷积层,具体的好处有:
- 卷积层可以保留输入形状
- 卷积层通过滑动窗口将同一卷积核与不同位置的输入重复计算,从而避免参数尺寸过大。
LeNet 模型
LeNet的输入是2828的灰度图
LeNet分为卷积层块和全连接层块两个部分
图像为2828像素的图片,经过第一个卷积层,通道数变为6,因为在输入通道添加了padding,输出通道的宽和高可以保持2828,在卷积层块中,每个卷积层都使用5×5的窗口,并在输出上使用sigmoid激活函数,然后经过一个池化层,池化步幅为2,宽和高变成了1414;
然后再经过一个卷积层,输出通道增加到16,再经过一个池化层,最后通过三个全连接层,它们的输出个数分别是120、84和10,其中10为输出的类别个数。通过全连接层之前有一个过渡操作,是对三维数据进行展平,变成一维。
下面我们通过Sequential类来实现LeNet模型。
import
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
import torch
import torch.nn as nn
import torch.optim as optim
import time
#net
class Flatten(torch.nn.Module): #展平操作
def forward(self, x):
return x.view(x.shape[0], -1)
class Reshape(torch.nn.Module): #将图像大小重定型
def forward(self, x):
return x.view(-1,1,28,28) #(B x C x H x W)
net = torch.nn.Sequential( #Lelet
Reshape(),
nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, padding=2), #b*1*28*28 =>b*6*28*28
nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2), #b*6*28*28 =>b*6*14*14
nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5), #b*6*14*14 =>b*16*10*10
nn.Sigmoid(),
nn.AvgPool2d(kernel_size=2, stride=2), #b*16*10*10 => b*16*5*5
Flatten(