专栏首页AI算法与图像处理CNN输出大小公式 | PyTorch系列(二十)

CNN输出大小公式 | PyTorch系列(二十)

文 |AI_study

原标题:CNN Output Size Formula - Bonus Neural Network Debugging Session

  • 准备数据
  • 建立模型
    • 了解前向传递的转换
  • 训练模型
  • 分析模型的结果

网络概述

我们将使用的CNN是我们在过去几篇文章中一直使用的,它有六层。

  1. 输入层
  2. 隐藏的卷积层
  3. 隐藏的卷积层
  4. 隐藏的 linear 层
  5. 隐藏的 linear 层
  6. 输出层

我们使用PyTorch的nn.Module类构建了该网络,网络类的定义如下:

class Network(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5)
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=12, kernel_size=5)
        
        self.fc1 = nn.Linear(in_features=12*4*4, out_features=120)
        self.fc2 = nn.Linear(in_features=120, out_features=60)
        self.out = nn.Linear(in_features=60, out_features=10)
        
    def forward(self, t):
        # (1) input layer
        t = t
        
        # (2) hidden conv layer
        t = self.conv1(t)
        t = F.relu(t)
        t = F.max_pool2d(t, kernel_size=2, stride=2)
        
        # (3) hidden conv layer
        t = self.conv2(t)
        t = F.relu(t)
        t = F.max_pool2d(t, kernel_size=2, stride=2)
        
        # (4) hidden linear layer
        t = t.reshape(-1, 12 * 4 * 4)
        t = self.fc1(t)
        t = F.relu(t)
        
        # (5) hidden linear layer
        t = self.fc2(t)
        t = F.relu(t)
        
        # (6) output layer
        t = self.out(t)
        #t = F.softmax(t, dim=1)
        
        return t

传递一个 batch大小为1(单张图像 )

在前一节中,我们了解了如何使用PyTorch的unsqueeze()方法添加批处理维度来传递单个图像。我们将再次将这个张量传递给网络,但是这次我们将使用调试器逐步执行forward()方法。这将允许我们在进行变换时检查我们的张量。

让我们开始:

> network = Network()
> network(image.unsqueeze(0))

# 1 输入层

当张量进入输入层,有如下:

> t.shape
torch.Size([1, 1, 28, 28])

在这些维度中的各个值代表下面的含义:

(batch size, color channels, height, width)

因为输入层只是恒等函数,所以输出形状不会改变。

The input layer can be regarded as the trivial identity function, output of the layer is equal to the input.

#2 卷积层 1

当张量进入这一层时,我们有:

> t.shape
torch.Size([1, 1, 28, 28])

在第一个卷积操作 self.conv1后 ,我们有:

> t.shape
torch.Size([1, 6, 24, 24])

批大小仍然是1。这是有意义的,因为我们不会期望我们的批大小会改变,这将是整个前向传递的情况。

The batch_size is fixed as we move through the forward pass.

彩色通道的数量从1个增加到6个。在我们通过了第一个卷积层之后,我们不再认为通道是彩色通道。我们只是把它们当做输出通道。我们有6个输出通道的原因是由于在创建self.conv1时指定的out_channels数量。

使用滤波器的卷积运算

如我们所见,这个数字6是任意的。out_channels参数指示nn.Conv2d层类生成六个过滤器(也称为卷积核),形状为5×5,并具有随机初始化的值。这些滤波器用于生成六个输出通道。

The out_channels parameter determines how many filters will be created.

过滤器是张量,当张量传递到层实例self.conv1时,它们用于对输入张量进行卷积。滤波器张量内部的随机值是卷积层的权重。不过请记住,实际上我们没有六个不同的张量。所有六个过滤器都包装在一个高度和宽度为五个的单个权重张量中。

The filters are the weight tensors.

在使用权重张量(滤波器)对输入张量进行卷积后,结果就是输出通道。

引用输出通道的另一种方法是调用特征图(feature map)。这是由于以下事实:随着权重的更新而出现的图案检测代表了诸如边缘和其他更复杂图案的特征。

算法:

  1. 颜色通道已传入。
  2. 使用权重张量(滤波器)进行卷积。
  3. 生成要素图并将其前向传递。

从概念上讲,我们可以认为权重张量是不同的。但是,我们在代码中真正拥有的是具有out_channels(过滤器)维的单个权重张量。我们可以通过检查权重张量的形状来看到这一点:

> self.conv1.weight.shape
torch.Size([6, 1, 5, 5])

张量的形状由下式给出:

(number of filters, number of input channels, filter height, filter width)

relu() 激活函数

对relu() 函数的调用将删除所有负值并将其替换为零。我们可以通过在调用之前和之后检查张量的min()来验证这一点。

> t.min().item()
-1.1849982738494873

> t = F.relu(t)
> t.min().item()
0.0

relu() 函数可以用数学方式表示为

最大池化操作

池化操作通过从张量中的每个2x2位置提取最大值来进一步减小张量的形状。

> t.shape
torch.Size([1, 6, 24, 24])

> t = F.max_pool2d(t, kernel_size=2, stride=2)
> t.shape
torch.Size([1, 6, 12, 12])

卷积层总结

卷积层输入和输出的张量的形状由下式给出:

  • 输入形状:[1, 1, 28, 28]
  • 输出形状:[1, 6, 12, 12]

发生的每个操作的摘要:

  • 卷积层使用六个随机初始化的5x5滤波器对输入张量进行卷积。
    • 这样可以将高度和宽度尺寸减少四倍。
  • relu激活功能操作将所有负值映射为0。
    • 这意味着张量中的所有值现在都为正。
  • 最大池化操作从由卷积创建的六个特征图的每个2x2部分中提取最大值。
    • 这样将高度和宽度尺寸减少了十二。

CNN输出大小公式

让我们看一下在执行卷积和池化操作之后计算张量的输出大小的公式。

一、CNN输出大小公式(平方)

  • 假设有一个 n * n 输入。
  • 假设有一个 f*f 的滤波器。
  • 假设填充大小为 p 和步长为 s

输出尺寸 O 由以下公式给出:

二、CNN输出大小公式(非平方)

  • 假设有一个 nh×nw 的输入
  • 假设有一个 fh×fw 的滤波器
  • 假设填充大小为 p 和步长为 s

输出大小Oh 的高度由以下公式给出:

输出大小Ow 的高度由以下公式给出:

#3 卷积层(2)

第二个隐藏的卷积层self.conv2在与self.conv1相同的方式转换张量,并进一步减小了高度和宽度尺寸。在进行这些转换之前,让我们检查一下self.conv2的权重张量的形状:

self.conv2.weight.shape
torch.Size([12, 6, 5, 5])

这次,我们的权重张量有12个高度为5且宽度为5的过滤器,但不是只有一个输入通道,而是有6个通道,这为过滤器提供了深度。这说明了来自第一卷积层的六个输出通道。结果输出将具有十二个通道。

现在运行这些操作。

> t.shape
torch.Size([1, 6, 12, 12])

> t = self.conv2(t)
> t.shape
torch.Size([1, 12, 8, 8])

> t.min().item()
-0.39324113726615906

> t = F.relu(t)
> t.min().item()
0.0

> t = F.max_pool2d(t, kernel_size=2, stride=2)
> t.shape
torch.Size([1, 12, 4, 4])

self.conv2 输出结果的形状使我们能够了解为什么在将张量传递到第一线性层self.fc1之前使用12 * 4 * 4 重构张量。

正如我们过去所看到的,这种特殊的重构称为 展平张量。展平操作将所有张量元素置于一个维中。输出

> t = t.reshape(-1, 12*4*4)
> t.shape
torch.Size([1, 192])

产生的形状为1x192。在这种情况下,1表示批处理大小,而192表示张量中现在处于相同维度的元素数。

#4#5#6 Linear 层

现在,我们只有一系列线性层,然后是非线性激活函数,直到到达输出层。

> t = self.fc1(t)

> t.shape
torch.Size([1, 120])

> t = self.fc2(t)
> t.shape
torch.Size([1, 60])

> t = self.out(t)
> t.shape
torch.Size([1, 10])

> t
tensor([[ 0.1009, -0.0842,  0.0349, -0.0640,  0.0754, -0.0057,  0.0878,  0.0296,  0.0345,  0.0236]])

下表总结了形状更改操作以及每种形状的结果形状:

下一步训练CNN

现在,我们应该对卷积神经网络如何转换输入张量,如何在PyTorch中调试神经网络以及如何检查所有层的权重张量有一个很好的了解。

文章中内容都是经过仔细研究的,本人水平有限,翻译无法做到完美,但是真的是费了很大功夫,希望小伙伴能动动你性感的小手,分享朋友圈或点个“在看”,支持一下我 ^_^

英文原文链接是:

https://deeplizard.com/learn/video/cin4YcGBh3Q

本文分享自微信公众号 - AI算法与图像处理(AI_study),作者:AI_study

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • PyTorch中CNN的Forward方法 | PyTorch系列(十七)

    我们通过扩展nn.Module PyTorch基类来创建网络,然后在类构造函数中将网络层定义为类属性。现在,我们需要实现网络的 forward() 方法,最后,...

    AI算法与图像处理
  • CNN中张量的输入形状和特征图 | Pytorch系列(三)

    在这个神经网络编程系列中,我们正在努力构建卷积神经网络(CNN),所以让我们看看在CNN中的张量输入。

    AI算法与图像处理
  • PyTorch,TensorFlow和NumPy中Stack Vs Concat | PyTorch系列(二十四)

    原标题:Stack Vs Concat In PyTorch, TensorFlow & NumPy - Deep Learning Tensor Ops

    AI算法与图像处理
  • LNMP平台的搭建

    LNMP指的是多款软件的集合。L指的是Linux系统,N指的是Nginx网站服务器,M指的是Mariadb数据库软件,P指的是php软件。Linux目前是一款最...

    魏豪
  • 基于Django的电子商务网站开发(连载22)

    表3-4为商品信息列表的测试用例。测试目的是把测试数据中的商品信息插入到数据库中,检验这个商品的列表信息是否可以正确地被显示出来。

    小老鼠
  • 2019年腾讯云服务器爆品抢购进行中1核1G1年仅168元

    活动时间:2018年12月12日至2019年1月25日,每天两场秒杀,时间分别为:9:00-12:00,14:00-18:00。

    聚优云惠
  • 测试开发进阶(二十七)

    projects.serializer.ProjectModelSerializer中添加

    zx钟
  • 多维张量的几何理解

    Tensor是Tensorflow中最基础的数据结构,常常翻译为张量,可以理解为n维数组或矩阵,相关函数:

    于小勇
  • 深度学习(二)--tensor张量

    关于“tensorflow”这个专栏,我打算一直更新下去,文章基本都是随着我的进度来的,我也是查找了一些资料并根据自己的一些理解写的,可能内容偶尔会...

    Python进击者
  • 源码分析Dubbo服务提供者启动流程-上篇

    本节将详细分析Dubbo服务提供者的启动流程,请带着如下几个疑问进行本节的阅读,因为这几个问题将是接下来几篇文章分析的重点内容。

    丁威

扫码关注云+社区

领取腾讯云代金券