卷积神经网络学习笔记(四)—— CNN细枝末节系列之特征图大小处理

pytorch中的2D卷积的函数是:

class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

Parameters:

  • in_channels(int) – 输入信号的通道
  • out_channels(int) – 卷积产生的通道
  • kerner_size(int or tuple) - 卷积核的尺寸
  • stride(int or tuple, optional) - 卷积步长
  • padding(int or tuple, optional) - 输入的每一条边补充0的层数
  • dilation(int or tuple, optional) – 卷积核元素之间的间距
  • groups(int, optional) – 从输入通道到输出通道的阻塞连接数
  • bias(bool, optional) - 如果bias=True,添加偏置
输出和权值的计算公式为:


1. 最基础的情况下:
# 定义一个输入,为了看起来方便,我们定义一个全为1的张量
input = autograd.Variable(torch.ones(1, 1, 5, 5))
>> tensor([[[[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]]]])
>> torch.Size([1, 1, 5, 5])

# 定义一个最基础的2D卷积,卷积核为3 * 3
CNN= nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0, bias=False)

# 为了直观,我们直接先设置卷积和,在实际使用时它是先随机初始化,然后再通过反向来得到
CNN_W = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], dtype='float32') 
# CNN的权值也是张量形式
CNN_W = CNN_W.reshape((1, 1, 3, 3))
CNN.weight.data = torch.from_numpy(CNN_W)

# 卷积计算
print(CNN.weight.data)
print(CNN(input))
np.shape(CNN(input))
>> tensor([[[[ 1.,  1.,  1.],
          [ 1.,  1.,  1.],
          [ 1.,  1.,  1.]]]])

>> tensor([[[[ 9.,  9.,  9.],
          [ 9.,  9.,  9.],
          [ 9.,  9.,  9.]]]])
          
>> torch.Size([1, 1, 3, 3])


2. stride使得卷积核无法走遍整个图时:
# 修改上面的卷积的步数为3,此时,卷积核不能走遍整个图,所以,通过不使用padding时,会舍弃掉部分值
CNN= nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=3, padding=0, bias=False)

print(CNN.weight.data)
print(CNN(input))
np.shape(CNN(input))

>> tensor([[[[ 1.,  1.,  1.],
          [ 1.,  1.,  1.],
          [ 1.,  1.,  1.]]]])

>> tensor([[[[ 9.]]]])
          
>> torch.Size([1, 1, 1, 1])


3. 使用padding时:
# 使用padding=1时,此时输入会在周围包上一层0,也就是原来5 * 5的矩阵变成7 * 7

CNN= nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, stride=3, padding=1, bias=False)

print(CNN.weight.data)
print(CNN(input))
np.shape(CNN(input))

>> tensor([[[[ 1.,  1.,  1.],
          [ 1.,  1.,  1.],
          [ 1.,  1.,  1.]]]])

>> tensor([[[[ 4.,  6.],
          [ 6.,  9.]]]])
          
>> torch.Size([1, 1, 2, 2])


4. 输出通道数不设为1时:
# 使用out_channels =2时,此时其实就是初始化两个卷积核,这里我们不给它设值,直接让其随机初始化

CNN= nn.Conv2d(in_channels=1, out_channels=2, kernel_size=3, stride=3, padding=1, bias=False)

print(CNN.weight.data)
print(CNN(input))
np.shape(CNN(input))

>> tensor([[[[-0.1465,  0.3027,  0.2025],
          [-0.0289, -0.0376,  0.2881],
          [-0.1316,  0.1987,  0.2249]]],


        [[[ 0.0905, -0.1791,  0.3059],
          [ 0.1897,  0.1662,  0.2220],
          [ 0.1330, -0.2048,  0.1505]]]])

>> tensor([[[[ 0.6741,  0.5137],
          [ 1.1793,  0.8724]],

         [[ 0.3340,  0.6567],
          [ 0.4608,  0.8740]]]])
          
>> torch.Size([1, 2, 2, 2])


5. 输入通道数不为1时:
input = autograd.Variable(torch.ones(1, 2, 5, 5))
print(input)
np.shape(input)

>> tensor([[[[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]],

         [[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]]]])
 
 >> torch.Size([1, 2, 5, 5])

# 使用in_channels =2时,其实此时也是随机初始化了两个卷积核对应两个通道,最后将结果相加
CNN= nn.Conv2d(in_channels=2, out_channels=1, kernel_size=3, stride=1, padding=0, bias=False)

# 为了直观,这里我们同样使用自己设的卷积核参数
CNN_W = np.array([[[1, 1, 1], [1, 1, 1], [1, 1, 1]],[[1, 1, 1], [1, 1, 1], [1, 1, 1]]], dtype='float32') 
# CNN的权值也是张量形式
CNN_W = CNN_W.reshape((1, 2, 3, 3))
CNN.weight.data = torch.from_numpy(CNN_W)

# 卷积计算过程
print(CNN.weight.data)
print(CNN(input))
np.shape(CNN(input))

>> tensor([[[[ 1.,  1.,  1.],
          [ 1.,  1.,  1.],
          [ 1.,  1.,  1.]],

         [[ 1.,  1.,  1.],
          [ 1.,  1.,  1.],
          [ 1.,  1.,  1.]]]])

>> tensor([[[[ 18.,  18.,  18.],
          [ 18.,  18.,  18.],
          [ 18.,  18.,  18.]]]])
          
>> torch.Size([1, 1, 3, 3])


6. 输入个数不为1时:
input = autograd.Variable(torch.ones(2, 1, 5, 5))
print(input)
np.shape(input)

>> tensor([[[[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]]],


        [[[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]]]])
 
 >> torch.Size([2, 1, 5, 5])

# 此时卷积还是对应通道数,其实就是生成一个卷积核,去分别作用在两个对象上
CNN= nn.Conv2d(in_channels=1, out_channels=2, kernel_size=3, stride=1, padding=0, bias=False)


# 卷积计算过程
print(CNN.weight.data)
print(CNN(input))
np.shape(CNN(input))

tensor([[[[ 0.4774,  0.4774,  0.4774],
          [ 0.4774,  0.4774,  0.4774],
          [ 0.4774,  0.4774,  0.4774]]],


        [[[ 0.4774,  0.4774,  0.4774],
          [ 0.4774,  0.4774,  0.4774],
          [ 0.4774,  0.4774,  0.4774]]]])  
                  
>> torch.Size([2, 1, 3, 3])

至于dilation就是在卷积核里加0,解释上是说可以扩大感知:

dilation

可以参考:https://blog.csdn.net/cai13160674275/article/details/71155295

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 秋天到了,桂花开了。 整个金陵城就像一个天然的大香炉,空气中到处都燃着桂花沁人心脾的幽幽香气,而人们就快乐地行走在...
    小学生朱提提阅读 338评论 0 3
  • “哈佛大学心理学家提姆•利里首次前往墨西哥试用神圣蘑菇,之后表示他‘在食用神圣蘑菇五小时之后获得有关大脑的认知…超...
    咸叔说阅读 589评论 1 2
  • 这两天搭建了一个优雅智慧学习分享群,虽然过程有些质疑的声音,但是还是有很多朋友对情绪管理,女性礼仪,优雅智慧很感兴...
    Rachel_aa22阅读 139评论 1 2
  • 2017年4月9日晚23:20,我坐在床上奋笔疾书,想在第二天来临前完成自己的作业,有时候我真想就这样放弃了,因为...
    花儿夏阅读 237评论 5 1

友情链接更多精彩内容