zoukankan      html  css  js  c++  java
  • torch_06_卷积神经网络

    1.概述

      卷积神经网络的参数,由一些可学习的滤波器集合构成的,每个滤波器在空间上都计较小,但是深度和输入数据的深度保持一致。在前向传播中,让每个滤波器都在输入数据的宽度和高度上滑动(卷积),然后计算整个滤波器和输入数据任意一处的内积。当滤波器沿着输入数据的宽度和高度滑动时,会生成一个二维的激活图,激活图上的每个空间位置表示了原图片对于该滤波器的反应。

    2. 三种思想

    2-1 局部性

      对于一张图片,需要检测图片中的特征来决定图片的类别,通常情况下这些特征都不是由整张图片决定的,而是由局部的区域决定。

    2-2 相同性

      对于不同的图片,如果他们具有相同的特征,这些特征会出现在图片的不同位置,也就是说可以用同样的检测模型去检测不同图片的相同特征,只不过这些特征处于图片中不同的位置,但是特征检测所做的操作几乎一样。

    2-3 不变性

      对于一张大图片,如果我们进行下采样,图片的性质基本保持不变。

    3.全连接网络

      由一系列隐藏层构成,每个隐藏层中由若干个神经元构成,其中每个神经元都和前一层的所有神经元相关联,但是每一层中的神经元是相互独立的。

      存在的问题:比如在MNIST数据集,图片大小为28*28,那么第一个隐藏层的单个神经元的权重数目是28*28 = 784个(权重矩阵的一行为一个神经元,一行有784列)

    4.卷积神经网络:一个滤波器就相当于一个神经元

    卷积层:

      4.1 局部区域连接:

      是一个3D的容量神经元,也就是说神经元是以三个维度来排列的:宽度,高度,深度。

      主要的层结构:卷积层,池化层和全连接层,通过堆叠这些层结构形成了一个完整的卷积神经网络结构。卷积神经网络将原始图片转换成最后的类别得分,其中一些层包含参数,一些层没有包含参数,比如卷积层和全连接层有参数,激活层和池化层不含参数,这些参数通过梯度下降法来更新,最后使得模型尽可能正确的识别类别。

       与神经元连接的空间大小叫做神经元的感受野。它的大小是滤波器的宽和高。

      例如:输入的数据尺寸:32*32*3,感受野(滤波器尺寸):5*5,卷积层中每个神经元会有输入数据中5*5*3区域的权重,一共有75个权重。

      4.2 空间排列:

      卷积层的输出深度是一个超参数,与使用的滤波器数量一致,每种滤波器所做的就是输入数据中寻找一种特征。比如输入一张原始图片,卷积层输出的深度是20,这说明有20个滤波器对数据进行处理,每种滤波器寻找一种特征进行激活。

      4.3 边界填充:保证输入和输出再空间上的尺寸一致。

      一般的,当步长S =1,零填充的值为 P = (F-1)/2 (F为滤波器的宽度)

      4.4 参数共享

      输出数据再深度切片上所有的权重都是用同一个权重向量,那么卷积层在向前传播的过程中,每个深度切片都可以看成是神经元的权重对输入数据体做卷积

      卷积核的输出是一副修改后的图像,在深度学习中经常被称作feature map。对每个颜色通道都有一个feature map

    池化层

      池化层和卷积层一样也有一个空间窗口,通常采用的是取这些窗口的最大值作为输出结果 ,然后不断滑动窗口,对输入的每个深度切片单独处理,减少它的空间尺寸。图片特征具有不变性,也就是通过下采样不会丢失图片拥有的特征,由于这种特性,我们可以将图片缩小再进行卷积处理,这样大大降低卷积运算的时间。

    多通道的卷积:

      输入通道:

      每个输入通道的图片都是用同一个卷积核进行卷积操作,生成与输入通道匹配的feature map,然后再把这几张feature map相同位置的值加起来,生成一张feature map

      输出通道:

      想要输出几个feature map,就放几个卷积核,就是几个输出通道。

    5 Pytorch卷积模块

    5.1 nn.Conv2d():

      in_channels:输入数据体的深度

      out_channels:输出数据体的深度

      kernel_size:滤波器(卷积核)的大小,可以用一个数字来表示高和宽相同的卷积核,也可以用不同的数字

      stride:滑动的步长

      padding:=0表示四周不进行零填充,=1,表示四周进行1个像素点的零填充

      dilation 表示卷积对于输入数据体的空间间隔,默认 dilation =1

      groups 表示输出数据体深度上和输入数据体深度上的联系,默认 groups=l ,也就是所有的输入和输出都是相关联的,如果 groups=2 ,这表示输入的深度被分割成两份,输出的深度也被分割成两份,他们之间分别对应起来,所以要求输出和输入都必 要能被 groups 整除;

      bias:默认为True,表示使用偏置

     6.代码实现简单的多层网络以及提取层结构

     6.1模型层

    1 """
     2 torch.nn.sequential():一个时序容器,Model 会以他们传入的顺序被添加到容器中
     3 add_module(name,module):将一个child module添加到当前model,被添加的module可以通过name属性来获取。
     4 """
     5 import torch.nn as nn
     6 
     7 
     8 class SimpleCNN(nn.Module):
     9     def __init__(self):
    10         super(SimpleCNN,self).__init__()
    11         layer1 = nn.Sequential()#时序容器
    12         layer1.add_module('conv1',nn.Conv2d(3,32,3,1,padding=1))
    13         layer1.add_module('relu1',nn.ReLU(True))
    14         layer1.add_module('pool1',nn.MaxPool2d(2,2))
    15         self.layer1 = layer1
    16 
    17         layer2 = nn.Sequential()  # 时序容器
    18         layer2.add_module('conv2', nn.Conv2d(32, 64, 3, 1, padding=1))
    19         layer2.add_module('relu2', nn.ReLU(True))
    20         layer2.add_module('pool2', nn.MaxPool2d(2, 2))
    21         self.layer2 = layer2
    22 
    23         layer3 = nn.Sequential()  # 时序容器
    24         layer3.add_module('conv3', nn.Conv2d(64, 128, 3, 1, padding=1))
    25         layer3.add_module('relu3', nn.ReLU(True))
    26         layer3.add_module('pool3', nn.MaxPool2d(2, 2))
    27         self.layer3 = layer3
    28 
    29         layer4 = nn.Sequential()
    30         #  第三层后的输入体为:4×4×128=2048
    31         # 进入全连接层时,需要有2048个权重,输出的样本大小512
    32         layer4.add_module('fc1',nn.Linear(2048,512))
    33         layer4.add_module('fc_relu1',nn.ReLU(True))
    34         layer4.add_module('fc2',nn.Linear(512,64))
    35         layer4.add_module('fc_relu2',nn.ReLU(True))
    36         layer4.add_module('fc3',nn.Linear(64,10))
    37         self.layer4 = layer4
    38 
    39     def forward(self, x):
    40         conv1 = self.layer1(x)
    41         conv2 = self.layer2(conv1)
    42         conv3 = self.layer3(conv2)
    43         fc_input = conv3.view(conv3.size(0),-1)#conv3.size(0)表示样本个数,对数据体4×4×128重新排列,进入全连接层
    44         fc_output = self.layer4(fc_input)
    45         return fc_output
    

     6.2 named_children(),named_modules(),提取网络前两层

    48 model = SimpleCNN()
    59 for name,module in model.named_children():
    60     print('children module:',name)  # 只输出,layer1,layer2,layer3,layer4
    61 for name,module in model.named_modules():
    62     print('module:',name)  # layer1.conv1,layer1.relu1 layer1.pool1
    63 # print('提取前两层')
    64 # new_model = nn.Sequential(*list(model.children())[:2])
    65 # print(new_model)
    

    7.提取参数及定义初始化

      7.1 提取参数

      nn.Module中两个特别重要的关于参数的属性

      name_parameters():给出网络的名字和参数的迭代器

      parameters():给出一个网络的全部参数的迭代器

    1 for param in model.named_parameters():
    2      print(param[0])  # layer1.conv1.weight layer1.conv1.bias layer2.conv2.weight layer2.conv2.bias
    3 for param in model.parameters():
    4     print(param)  # 全部参数,具体的值

      7.2 参数初始化

      权重是一个Variable,所以只需要取出其中的data属性,然后对它进行需要的处理。

     1 #对变量进行初始化:
     2 # 使用torch.nn.init
     3 # import numpy as np
     4 # import torch
     5 for m in model.modules():
     6     if isinstance(m,nn.Conv2d):
     7         nn.init.normal_(m.weight.data)
     8         print(m.weight.shape)  # torch.Size([32, 3, 3, 3])
     9         m.bias.data.fill_(0)  # torch.Size([32, 3, 3, 3])
    10         break
    11     elif isinstance(m,nn.Linear):
    12         m.weight.data.normal_()
    13         break
    14         #直接赋值
    15         # param_shape = m.weight.shape
    16         # m.weight.data = torch.from_numpy((np.random.uniform(3,5,size = param_shape)))
    17 
    18 # 在使用Sequential时直接对参数进行修改
    19 net1 = nn.Sequential(
    20     nn.Linear(30,40),
    21     nn.ReLU(),
    22     nn.Linear(40,50),
    23     nn.ReLU(),
    24     nn.Linear(50,10)
    25 )
    26 net1[0].weight.data = torch.from_numpy(np.random.uniform(3,5,size=(30,40)))
  • 相关阅读:
    nanoPI kernel compile record
    Golang go get第三方库的坑
    Python解析Linux命令行
    Linux:dd命令
    Golang异常处理
    Golang自定义包导入
    Golang覆盖写入文件的小坑
    Golang数据类型总结及其转换
    ASP.NET学习之页面传值(8)_Application传值
    ASP.NET学习之页面传值(7)_Cookie传值
  • 原文地址:https://www.cnblogs.com/shuangcao/p/11722624.html
Copyright © 2011-2022 走看看