【Pytorch】8. Pytorch中的卷积神经网络

一、初始Pytorch卷积模块

1、卷积神经网络基本结构

在这里插入图片描述
(1)输入层
一般输入层的大小应该是能够以被2整出多次的,常用的数字包括32,64,96,224。可以将图片缩放到常用尺寸,进行输入
(2)卷积层
应该尽可能使用小尺寸的滤波器,比如3×3或5×5,滑动步长1。还有一点就是需要对输入数据进行零填充,这样可以有效的保证卷积层不会改变输入数据体的空间尺寸。如果必须使用更大的滤波器尺寸如7×7,通常用在第一个面对原始图像的卷积层上。
(3)池化层:
负责对输入的数据空间维度进行下采样,常用的设置使用2×2的感受野,步长设置为2。池化层的感受野大小很少超过3。因为这回导致池化过程过于激进,造成特征信息的丢失,使得算法性能变差。
(4)零填充
零填充的使用可以让卷积层的输入和输出在空间上的维度保持一致。除此之外,如果不使用零填充,在不断进行卷积过程中,数据的尺寸会不断减少,造成图像边缘信息的的损失。

2、Pytorch中常用卷积模块

(1)卷积层:nn.Conv2d()

参数含义
in_channels输入数据的深度(图片的通道数)
out_channels输出数据的深度(卷积后输出结果的通道数(神经元个数))
kernal_size卷积核的形式。可以用一个数字表示高和宽相等的卷积核,如kernal size=3;高和宽不同的卷积核,可以表示为kernal size=(3,2)
stride卷积每次移动的步长。默认为1
padding处理边界时使用零填充的像素点个数。默认为1
dilation采样间隔数量,默认为1,表示无间隔采样
group输入与输出通道的分组数量。默认为1(全连接)
bisa是一个布尔值,默认为True,表示有偏置项

(2)池化层:nn.MaxPool2d()

  • nn.MaxPool2d()表示网络中的最大池化
参数含义
kernel_size最大池化操作时的窗口大小
stride最大池化操作时窗口移动的补偿,默认值是kernel_size
padding输入的每一条边补充0的层数
dilation用于控制窗口中元素的步长
return_indices表示是否返回最大值所处的下表,默认为return indices=False
ceil_mode默认为False。如果等于True。在计算输出大小时,将采用向上取整来代替默认的向下取整
  • nn.AvgPool2d()表示均值池化,里面的参数和nn.MaxPool2d()类似,但多一个参数count_include_pad,这个参数表示计算均值的时候是否包含零填充,默认为True
3、构建简单的多层卷积神经网络

(1)代码实现

import numpy as np
import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

#定义简单的四层神经网络
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN,self).__init__()  #输入图像维度 b,3,32,32
        #定义第一层网络:卷积+激活+池化
        layer1 = nn.Sequential()
        layer1.add_module('conv1',nn.Conv2d(3,32,3,1,padding=1)) #卷积层:输入数据的深度为3,输出数据深度为32,卷积核形状3*3,卷积移动步长1
        #卷积后输出维度:b,32,32,32
        layer1.add_module('relu1',nn.ReLU(True))  #relu不改变维度
        layer1.add_module('pool1',nn.MaxPool2d(2,2))  #池化层:池化的窗口形状为2*2
        #池化后输出维度:b,32,16,16
        self.layer1 = layer1
        
        #定义第二层网络:卷积+激活+池化
        layer2 = nn.Sequential()
        layer2.add_module('conv2',nn.Conv2d(32,64,3,1,padding=1))  #卷积层:输入数据深度为32,输出数据深度为64,卷积核形状为3*3,卷积移动步长为1
        #卷积后输出维度:b,64,16,16
        layer2.add_module('rule2',nn.ReLU(True))
        layer2.add_module('pool2',nn.MaxPool2d(2,2))  #池化层:池化的窗口形状为2*2
        #卷积后输出维度:b,64,8,8
        self.layer2 = layer2
        
        #定义第三层网络:卷积+激活+池化
        layer3 = nn.Sequential()
        layer3.add_module('conv3',nn.Conv2d(64,128,3,1))  #卷积层:输入数据深度为64,输出数据深度为128,卷积核形状为3*3,卷积移动步长为1
        #卷积后输出维度:b,128,8,8
        layer3.add_module('relu3',nn.ReLU(True))
        layer3.add_module('pool3',nn.MaxPool2d(2,2))  #池化层:池化的窗口形状为2*2
        #池化后输出维度:b,128,4,4
        self.layer3 = layer3
        
        #定义第四层网络:全连接层+激活层+全连接层+激活层+全连接层
        layer4 = nn.Sequential()
        #输入维度b,2048
        layer4.add_module('fc1',nn.Linear(2048,512))  #输入维度2-48,输出维度512
        #全连接层输出维度:b,512
        layer4.add_module('fc_relu1',nn.ReLU(True))
        layer4.add_module('fc2',nn.Linear(512,64))  #输入维度512,输出维度64
        #全连接层输出维度:b,64
        layer4.add_module('fc_relu2',nn.ReLU(True))
        layer4.add_module('fc3',nn.Linear(64,10))  #输入维度64,输出维度10
        #全连接层输出维度:b,10(例如10分类问题,每个位置表示对应列别的权重大小,如果假如sigmoid函数,则表示对应的概率,一般取最大的最为判断类别)
        self.layer4 = layer4
        
    def forward(self,x):
        conv1 = self.layer1(x)
        conv2 = self.layer2(conv1)
        conv3 = self.layer3(conv2)
        fc_input = conv3.view(conv3.size(0),-1)  #b,128*4*4 = b,2048  将维度展平
        fc_out = self.layer4(fc_input)
        return fc_out
    
model = SimpleCNN()
print(model)

(2)打印层结果如下图,括号里面表示层结构的名字:在这里插入图片描述

二、模型参数的提取

nn.Module的几个重要属性:

  • children():返回下一级代码块的迭代器,比如SimpleCNN()模型,它只会返回self.layer1,self.layer2,self.layer3,self.layer4的迭代器,不会返回他的内部东西。
  • modules():会返回模型中的所有模块的迭代器,可以访问到模型的最内层。比如,self.layer2.conv1模块
  • named children以及named modules分别与上两个属性对应。这两个不仅会返回模块的迭代器,还会返回网络层的名字。
1、从已定义的网路中,提取若干模块作为新的模型
#取出model的前2层网络,构成新的模型new_model
new_model = nn.Sequential(*list(model.children()))[:2]
print(new_model)

在这里插入图片描述

2、只提取model模型中的所有卷积层,构成新的模型conv_model
conv_model = nn.Sequential()
for layer in model.named_modules():
    if isinstance(layer[1],nn.Conv2d):      
        conv_model.add_module(layer[0][-5:],layer[1])
print(conv_model)

在这里插入图片描述

3、提取每层网络的参数
for param in model.named_parameters():
    print(param[0])  #param[1]输出参数值

在这里插入图片描述

三、自定义初始化

for m in model.modules():
    if isinstance(m,nn.Conv2d):   #判断是否为卷积层
        init.normal(m.weight.data)   #如果是卷积层,提取权重数值;使用正态分布对权重初始化
        init.xavier_normal(m.weight.data)  #基本思想是通过网络层是,输入和输出的方差相同,包括前向传播和反向求导。
        init.kaiming_normal(m.weight.data)   #均值为0,方差为(8)或(15)的高斯分布
        m.bias.data.fill_(0)   #偏置项使用0进行初始化
        
    elif isinstance(m,nn.Linear):   #判断是否为全连接层
        m.weight.data.normal_()   #如果是全连接层,使用正态分布对权值初始化

xavier_normal
1、要求激活函数关于0对称,且主要针对于全连接神经网络。适用于tanh、softmoid
2、如果初始化值很小,那么随着层数的传递,方差就会趋于0,此时输入值也变得越来越小,在sigmoid上就是在0附近,接近于线性,失去了非线性
3、如果初始值很大,那么随着层数的传递,方差会迅速增加,此时输入值变得很大,而sigmoid在大输入值写倒数趋近于0,反向传播时会遇到梯度消失的问题

参考文献:《深度学习之Pytorch》

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值