美文网首页
基于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