从代码进阶到原理。一步步深入 torch
的 CNN
世界。
环境介绍
- python3.6
- pytorch 1.3.1
- 不同的版本差距非常大,要注意版本
相关资料
讲述 CNN 原理
pytorch 的代码案例
从案例入手
常规 CNN 网络结构
1 | import torch |
网络结构图
我们解析这个图「MNIST」,以及中间数据的变化。
首先,输入的数据维度为 N * 1 * 32 * 32
其中 N
代表的是 batch_size
。 1
代表的通道为 1
「灰度图」, 32 * 32 代表一张图片的矩阵大小
。第一个卷积层是 nn.Conv2d(1, 6, 5)
代表的是,输出的通道是 6
,卷积核的大小是 5 * 5
。所以,卷积之后图片的大小是 32 - 5 + 1 = 28
,也就是数据变成了 N * 6 * 28 * 28
。最大池化为 2 * 2
,经过最大池化的维度是 28 / 2 = 14
此时,数据变成了 N * 6 * 14 * 14
,然后,第二个卷积层 nn.Conv2d(6, 16, 5)
,输出的通道是 16
,卷积核的大小是 5 * 5
,所以,卷积后的图片大小变成了 14 - 5 + 1 = 10
,数据变成了 N * 16 * 10 * 10
,然后最大池化是 2 * 2
,也就是,数据维度变成了 10 / 2 = 5
,最后数据变成了 N * 16 * 5 * 5
。
此时,来到了链接层,首先把数据变成 1
维的。变成一维后,使用链接层
1 | self.fc1 = nn.Linear(16 * 5 * 5, 120) |
最后的结果是十分类。
非常规 CNN 网络结构
1 | class ConvAutoEncoder(nn.Module): |
这是一个简单的 U-Net
网络结构,我们只看前面的 encoder
环节。
首先输入的数据是 N * 1 * 4 * 300
,第一个卷积层是 nn.Conv2d(1, 8, (4, 7), stride=1, padding=(0, 3))
,首先,先给 input
增加 padding
。根据代码,是在上下两侧分别增加 3
列,所以,原始数据变成了 N * 1 * 4 * 306
,卷积核的大小是 4 * 7
,步长为 1
,所以,经过卷积的维度变成了 306 - 7 + 1 = 300
,输出维度为 8
,最后,输出的数据为 N * 8 * 1 * 300
,然后最大池化 2 * 2
,数据变成了 300 / 2 = 150
,即数据为 N * 8 * 1 * 150
,接着,第二个卷积层是 nn.Conv2d(8, 4, 3, stride=1, padding=1)
,首先是增加 padding
,在上下左右分别增加 1
,所以,输入的数据变成了 N * 8 * 3 * 152
,其卷积核是 3 * 3
,所以,其维度是 152 - 3 + 1 = 150
,输出维度是 4
,最后,数据变成了 N * 4 * 1 * 150
,最大池化是 2 * 2
,所以,最后数据变成了 N * 4 * 1 * 75
。
关于使用的方法,可以查看