美文网首页
基于pytorch的CNN计算简介

基于pytorch的CNN计算简介

作者: 打杂算法工程师 | 来源:发表于2020-02-29 21:44 被阅读0次

1. CNN简介

本文主要介绍利用pytorch对CNN的计算有一个直观的认识,在此认为你已经对CNN有了一些理解,但是对如何计算还有一些迷糊。
卷积神经网络的结构一般用在图像处理领域,优化了全连接神经网络的参数过多问题。CNN的结构图如下所示,一个卷积神经网络由若干卷积层、Pooling层、全连接层组成。常用的架构模式为:
INPUT -> [[conv]*N -> Pooling?]*M -> [FC]*K
其中Pooling层不一定要有,参考如下的架构图。关于CNN的细节不做太多介绍,具体可以参考这篇文章

卷积图.png

2. pytorch计算卷积CNN

2.1 pytorch的cnn实现函数介绍

首先介绍一下pytorch实现cnn的函数
class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

  • in_channels, out_channels为输入输出信号的通道;
  • kernel_size为卷积核的大小,可以为int or (height, width),int时表示卷积核是高宽相等的,为touple表示卷积核的高度和宽度不相等;
  • stride 同样可以为int or touple,参考kernel_size,卷积步长高度和宽度两个方向不等时候,采用touple;
  • padding int or (height, width) 输入的每一条边补充0的层数;
  • dilation(int or tuple, `optional``) – 卷积核元素之间的间距,默认为1,为2时候,卷积核元素之间的间距拉大,相当于放大了卷积核看到的区域;
  • bias bias为True,添加偏置;
  • groups(int, optional) – 从输入通道到输出通道的阻塞连接数
    举个例子:
import torch as t
from torch import nn
m = nn.Conv2d(in_channels=8,out_channels=3,kernel_size= 3)
input = t.randn(10, 8,5,5 )
output = m(input)
output.shape
>>>
torch.Size([10, 2, 3, 3])

这里的input为batch10,深度为8,高度和宽度都为5的三维矩阵(在此解释一下,明明是3维矩阵,却为啥是conv2d,二维的呢,个人理解是,这里的2d是针对有高度和宽度,卷积核在这两个方向上移动,所以虽然输入的是三维矩阵,但是只在两个方向上移动,所以是Conv2d)。通过卷积核为355的卷积核后,output的高度和宽度为3(5-3+1)。
卷积变换的高度和宽度的计算公式为:
W_2 = (W_1-F+2P)/S+1 \\H_2 = (H_1-F+2P)/S+1
其中W_2为卷积变换之后的高度,F为卷积核的宽度,P为补0的圈数。

2.2 理解卷积的计算方法

卷积神经网络是如何计算的呢,下面是一张非常经典的图,input是一个深度为3的7*7的数据,2channel的filter,filter的深度要和input的深度 一致,因此CNN输出矩阵的大小和filter有如下规范:

  • filter 的深度要和input的深度一致;
  • 卷积神经网络的输出的channel是由filter的channel数决定的;
  • 输出的高度和宽度由卷积核的高度和宽度、卷积的步长straddle、补零padding的圈数决定的;
    卷积的计算方法可以参考下方的动态图,画的非常清晰,filter和input做element-wise的相乘,不同层之间进行求和,最后加上bias,得到output。
2256672-958f31b01695b085.gif

接下来,我们再继续使用pytorch实践一下计算过程:

import torch.nn.functional as f
input = t.randn(1,3,3,3) # 输入为batch为2,深度为2的3*3矩阵
filter1 = t.randn(2,3,2,2) # 卷积核即filter为(3,2,2,2),即channel为3,卷积核的深度为2,高宽为2*2
o1 = f.conv2d(input, filter1,stride=1) #因此输出的维度为(2,3,2,2)
input
>>>
Out[18]:
tensor([[[[-0.1759, -0.3417,  1.4123],
          [-1.6696,  0.9701, -2.3805],
          [-0.7241, -0.2209, -0.8992]],

         [[-1.3623,  0.8210,  0.7222],
          [ 0.5904,  0.0083, -1.5792],
          [ 0.3217, -0.8068,  0.7589]],

         [[-0.5402,  1.2805,  0.7455],
          [-0.8920, -1.0816,  1.1012],
          [-0.0124, -1.6899,  1.2731]]]])
filter1
>>>
tensor([[[[-1.8587e+00,  1.2517e+00],
          [-6.4202e-01,  5.6213e-01]],

         [[-2.1839e-01, -1.9386e-01],
          [ 7.2792e-01, -1.9432e+00]],

         [[-1.7671e+00, -1.4224e+00],
          [-1.5365e+00, -1.1106e+00]]],


        [[[ 1.8957e+00,  5.6250e-01],
          [-1.9311e+00, -8.1737e-02]],

         [[ 7.7985e-01, -1.3875e-01],
          [-8.8998e-01, -1.1328e+00]],

         [[ 5.6669e-01, -1.1629e+00],
          [ 3.2056e-01, -7.1626e-04]]]])
o1
>>>
Out[19]:
tensor([[[[ 3.7735,  0.3129],
          [11.3403, -5.3765]],

         [[-1.1724,  0.3006],
          [ 0.6336, -1.3521]]]])

如上可以看到第一个元素o1[0,0,0,0]是3.7735,接下来我们人肉计算一下第一个元素:

import torch as t
t.sum(input[0,:,0:2,0:2]*filter1[0,:,:,:])
>>>
out[20]
tensor(3.7735)

结果和利用nn.functional.Conv2d计算出的结果一致。
nn.Conv2d和nn.functional.Conv2很相似,但是在构建模型的时候一般采用nn.Conv2d来实现。

相关文章

网友评论

      本文标题:基于pytorch的CNN计算简介

      本文链接:https://www.haomeiwen.com/subject/stzphhtx.html