赞
踩
以下是我建立的一个简单卷积网络用于识别Minist数据集:
- class My_nn_s(nn.Module):
- def __init__(self):
- super(My_nn_s, self).__init__()
- self.model = nn.Sequential(nn.Conv2d(in_channels=1, out_channels=30, kernel_size=5, padding=0, stride=1),
- nn.ReLU(),
- nn.MaxPool2d(2, 2, 0),
- nn.Flatten(),
- nn.Linear(4320, 100),
- nn.ReLU(),
- nn.Linear(100, 10),
- )
-
- def forward(self, x):
- x = self.model(x)
- return x
网络的结构为:
1、卷积层
2、Relu层
3、Max池化层
4、仿射层
5、Relu层
6、仿射层
需要注意的是,在池化层到仿射层之间有一个Flatten用于将数据展平。
这里是分类问题,输出层一般为Softmanx层并选择交叉熵误差。在Pytorch中,这两个层被打包定义在损失函数中(nn.CrossEntropyLoss)。
下面分别对各层参数进行介绍:
首先是卷积层
由于Minist是黑白照片,没有颜色信息(RGB),输入数据的形状为(N,C,H, W)=(100,1,28,28)这里的C=1,即in_channels = 1, 输入通道数为1(只有一个数字表示灰度,如果是彩色照片则需要3个通道,3个数字分别表示RGB三个灰度);一个batch_size为100(人为确定,卷积层中没有定义,而是在加载数据集时定义batch_size的大小 DataLoader(data_train, batch_size=100)),所以N=100;图片大小为28*28, 所以H=W=28。本例设置out_channels = 30,即卷积核的数量FN = 30,这个参数人为确定,为超参数,这个值会更新为卷积后结果的通道C=FN。卷积核为方阵,即kernel_size=5, 也可是设置为kernel_size=(5, 5), 填充pad=0, 步长为1。因此卷积核的形状(FN, C, FH, FW)=(30, 1, 5, 5)。
对于卷积后的输出形状OH和OW可用下面公式进行计算
OH =1+ (H + 2*pad - FH)/stride
OW = 1+(W + 2*pad - FW)/stride
带入得到OH=OW=1+(28-5)/1=24
所以经过第一层卷积计算后的形状为(N, C, OH, OW)=(100, 30, 24, 24),如上所述,输出的C等于卷积核的数量FN
Relu层不改变形状,所以传递给后面Max池化的形状也是(100, 30, 24, 24)
Max池化层不改变通道数,但是会改变输出图片形状(OH,OW),计算公式为
OH = 1+(H + 2*pad - PH)/stride
OW = 1+(W + 2*pad - PW)/stride
这里PH(卷积核的高)=PW(卷积核的宽)=2, stride=2, pad=0
代入得到OH=OW=1+(24+2*0-2)/2=12
所以经过池化层后的输出形状为(100, 30, 12, 12)
nn.Flatten()是把数据展平,得到输出形状为(N, C*OH*OW) = (100, 4320)
第一个仿射层的输入维度为上一层输出层维度即4320,而这里仿射层输出为人为确定,这里定为100。在经过第一个仿射层后的输出形状为(N, 100)=(100, 100)
Relu层不改变形状,所以传递给后面仿射层的形状也是(100,100)
对于最后一个仿射层,Minist是数据集是对手写10个数字的识别,因此输出为10,输入则为100
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。