week5 8月2日

NiN

为什么要设置多通道?

既然卷积了,换句话就是缩小了图像,那为了保证图像精度最大程度上不丢失,就需要多个卷积核,这样就可以保证在降维的同时不失真。然后CNN的层数越多,越深,理论上整个网络中的参数也就越多,学习到原始图像的特征也就越全面

所以,卷积的时候,通道数都是逐步递增的。也就是说,要把数据映射到更高维空间,在更高维空间里分类数据。至于为什么是一步步增加而不是突然增加到最高维,我觉得这有引入更多非线性的考虑。

全连接层的问题

 收敛很快,但是容易产生过拟合

NiN用1*1卷积代替了全连接

原来的原连接是,把二维像素矩阵展开为一维,然后根据权重参数,进行mlp全连接。

1*1的卷积相当于原来的全连接层。类似于,对每一个像素去做全连接,按照输入像素逐一去做全连接层。 不改变输入输出形状,也不改变通道数 

 


含并行连结的网络 GoogLeNet

 2、3、4都有padding,所以输入和输出图像大小一样,如:都是28*28

 通道数变化

第1条通道:经过1*1卷积后,192的输入通道数压到64输出通道数

第2条:为了让3*3的卷积的输入降低,来降低模型复杂度(卷积层可学习的参数个数是输入通道数*输出通道数*卷积核大小)192输入通道数,经过1*1conv之后,输出通道数降到为96,3*3的输入通道数为96,输出为128

第3条:因为要做5*5卷积,更贵、成本更大,所以要192输入之后,经过1*1conv之后,要降到16的输出。5*5的输入为16,输出通道数为32

第4条:经过maxpool之后输入通道数不改变,经过1*1conv之后,输出通道为32

至于,为什么卷积之后这个需要降到32不是64等之类的,都是调出来的。没有一个特定的原理。

1x1卷积最主要作用是融合不同通道的信息,降低通道数,减少卷积层的权重参数。

 

 

 

 

import d2l.torch
import torch
from torch import nn
from torch.nn import  functional as F
class Inception(nn.Module):
    #c1 - -c4是每条路径的输出通道数
    def __init__(self,in_channels,c1,c2,c3,c4):
        super(Inception, self).__init__()
        # 线路1,单1x1卷积层
        self.p1_1 = nn.Conv2d(in_channels=in_channels,out_channels=c1,kernel_size=1,stride=1,padding=0)
        # 线路2,1x1卷积层后接3x3卷积层
        self.p2_1 = nn.Conv2d(in_channels=in_channels,out_channels=c2[0],kernel_size=1,padding=0,stride=1)
        self.p2_2 = nn.Conv2d(in_channels=c2[0],out_channels=c2[1],kernel_size=3,padding=1,stride=1)
        # 线路3,1x1卷积层后接5x5卷积层
        self.p3_1 = nn.Conv2d(in_channels=in_channels,out_channels=c3[0],kernel_size=1,padding=0,stride=1)
        self.p3_2 = nn.Conv2d(in_channels=c3[0],out_channels=c3[1],kernel_size=5,padding=2,stride=1)
        # 线路4,3x3最大汇聚层后接1x1卷积层,汇聚层主要作用是降低卷积层对位置的敏感性,1x1卷积层主要是融合不同通道的信息,降低通道数,减少卷积层的权重参数
        self.p4_1 = nn.MaxPool2d(kernel_size=3,padding=1,stride=1)
        self.p4_2 = nn.Conv2d(in_channels=in_channels,out_channels=c4,kernel_size=1,padding=0,stride=1)

    def forward(self,X):
        #使用torch.nn.functional中的relu()函数,而不是nn.ReLU()函数
        #错误解决链接:https://discuss.pytorch.org/t/i-am-trying-to-build-a-simple-resnet-model-but-getting-an-error-conv2d-received-an-invalid-combination-of-arguments/134141
        p1 = F.relu(self.p1_1(X))
        p2 = F.relu(self.p2_2(F.relu(self.p2_1(X))))
        p3 = F.relu(self.p3_2(F.relu(self.p3_1(X))))
        p4 = F.relu(self.p4_2(self.p4_1(X)))
        # 在通道维度上连结输出
        return torch.cat((p1,p2,p3,p4),dim=1)
b1 = nn.Sequential(nn.Conv2d(in_channels=1,out_channels=64,kernel_size=7,padding=3,stride=2),
              nn.ReLU(),
              nn.MaxPool2d(kernel_size=3,padding=1,stride=2))
b2 =  nn.Sequential(nn.Conv2d(in_channels=64,out_channels=64,kernel_size=1,padding=0,stride=1),
              nn.ReLU(),
              nn.Conv2d(in_channels=64,out_channels=192,kernel_size=3,padding=1,stride=1),
              nn.ReLU(),
              nn.MaxPool2d(kernel_size=3,padding=1,stride=2))
b3 = 
nn.Sequential(Inception(in_channels=192,c1=64,c2=(96,128),c3=(16,32),c4=32),
              Inception(in_channels=256,c1=128,c2=(128,192),c3=(32,96),c4=64),
              nn.MaxPool2d(kernel_size=3,padding=1,stride=2))
b4 = 
nn.Sequential(Inception(in_channels=480,c1=192,c2=(96,208),c3=(16,48),c4=64),
              Inception(in_channels=512,c1=160,c2=(112,224),c3=(24,64),c4=64),
              Inception(in_channels=512,c1=128,c2=(128,256),c3=(24,64),c4=64),
              Inception(in_channels=512,c1=112,c2=(144,288),c3=(32,64),c4=64),
              Inception(in_channels=528,c1=256,c2=(160,320),c3=(32,128),c4=128),
              nn.MaxPool2d(kernel_size=3,padding=1,stride=2))
b5 = 
nn.Sequential(Inception(in_channels=832,c1=256,c2=(160,320),c3=(32,128),c4=128),
              Inception(in_channels=832,c1=384,c2=(192,384),c3=(48,128),c4=128),
              nn.AdaptiveAvgPool2d((1,1)),
              nn.Flatten())

GoogLeNet模型的计算复杂,而且不如VGG那样便于修改通道数。 为了使Fashion-MNIST上的训练短小精悍,我们将输入的高和宽从224降到96,这简化了计算 

GoogLeNet = nn.Sequential(b1,b2,b3,b4,b5,nn.Linear(1024,10))
#打印模型每一块的输出尺寸大小
X = torch.randn(size=(1,1,96,96))
for layer in GoogLeNet:
    X = layer(X)
    print(layer.__class__.__name__," output shape :\t",X.shape)

  

lr,num_epochs,batch_szie = 0.1,10,128
train_iter,test_iter = d2l.torch.load_data_fashion_mnist(batch_size=batch_szie,resize=96)
d2l.torch.train_ch6(GoogLeNet,train_iter,test_iter,num_epochs,lr,device=d2l.torch.try_gpu())

批量归一化

+ε是为了使结果大于0

u和σ是每一批小批量样本里算出来的均值和方差。

 

 在深度神经网络的训练过程中,上一层参数的调整会导致之后每一层输入值的分布发生变化,这种现象使模型的训练变得很复杂。所以在深度神经网络模型的训练中,通常需要仔细选取初始参数并采取较小的学习率,这不但导致模型训练的效率低下,而且使得饱和非线性模型的训练极为困难。我们把这种现象称为内部协变量转移(covariate shift),并通过归一化(normalizing)每层的输入来解决这个问题。

 神经网络的参数就是协变量,因为它是不可控的且在训练过程中是必须变化的,且对输出值会产生影响,所以当参数发生变化时,就发生了协变量转移。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值