CNN代码-Residule Block 实现

模块图示

在这里插入图片描述

模块介绍

如图左所示,假设输入为x,然后来了一个‘并联’,假设x经过虚线框操作后输出的结果为x1,在汇合的地方输出结果为out,那么out=x+x1。为了使x和x1能够相加,其两者维度需相同,也就是x1的维度要与x相同。

模块作用

解决VGG由于层数过多,网络过深产生的梯度爆炸、过拟合问题

代码实现

下面实现上图左边的Residule block。

import torch
import torch.nn as nn
import torch.nn.functional as F
class ResNet_basic_block(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels = in_channels,
                              out_channels = out_channels,
                              kernel_size = 3,  #3*3卷积
                              padding = 1,  #通过padding操作使x维度不变
                              bias = False)
        self.bn1 = nn.BatchNorm2d(num_features = out_channels)
        self.conv2 = nn.Conv2d(in_channels = out_channels,
                              out_channels = out_channels,
                              kernel_size = 3,   #3*3卷积
                              padding = 1,   #通过padding操作使x维度不变
                              bias = False)
        self.bn2 = nn.BatchNorm2d(num_features = out_channels)
    def forward(self, x):
        residual = x,
        out = self.conv1(x)
        out = self.bn1(out)
        out = F.relu(self.bn1(out), inplace = True)
        out = self.conv2(out)
        out = self.bn2(out)
        return out

模块使用实例

net = ResNet_basic_block(in_channels=3, out_channels=3) 
x = torch.rand((1,3,128,128), requires_grad=True)  
## 试验用的输入数据
## 不加requires_grad=True,那样会报错的
print(x)
>>>
tensor([[[[0.1748, 0.7122, 0.5482,  ..., 0.3072, 0.5013, 0.3448],
          [0.9843, 0.9961, 0.2204,  ..., 0.7938, 0.0166, 0.4661],
          [0.0247, 0.0084, 0.0705,  ..., 0.2160, 0.4828, 0.5090],
          ...,
          [0.9613, 0.8825, 0.5579,  ..., 0.0887, 0.8651, 0.5624],
          [0.9226, 0.5717, 0.7671,  ..., 0.9176, 0.2652, 0.0017],
          [0.3222, 0.0448, 0.1637,  ..., 0.4346, 0.4602, 0.1887]],

         [[0.6197, 0.8704, 0.3110,  ..., 0.9539, 0.3757, 0.4366],
          [0.8575, 0.0412, 0.8464,  ..., 0.5786, 0.8352, 0.1744],
          [0.0278, 0.0901, 0.1685,  ..., 0.1698, 0.1893, 0.8004],
          ...,
          [0.9396, 0.6551, 0.0380,  ..., 0.8259, 0.5549, 0.8349],
          [0.2380, 0.9816, 0.4802,  ..., 0.0942, 0.5014, 0.6619],
          [0.2772, 0.9087, 0.0889,  ..., 0.3405, 0.0918, 0.7940]]]],
       requires_grad=True)
a = net(x) 
print(a)
tensor([[[[ 2.6107e+00,  4.9241e+00,  4.4753e+00,  ...,  3.0504e+00,
            2.5287e+00,  1.6026e+00],
          [ 4.4550e-01, -1.5947e+00, -1.3323e+00,  ..., -2.5174e+00,
           -2.5517e+00, -1.4408e+00],
          [ 3.1338e-01,  3.2004e-01,  5.9879e-01,  ..., -1.4324e+00,
            1.4006e+00, -1.9084e-01],
          ...,
          [ 4.8046e-01,  1.2165e+00,  1.5494e+00,  ...,  1.1277e+00,
           -1.0431e+00, -8.0495e-01],
          [-1.9110e+00, -1.5171e+00,  3.0137e-03,  ...,  4.9892e-01,
            1.4297e+00,  1.3426e-02],
          [-1.1890e+00, -4.4962e-01, -1.2672e+00,  ..., -1.8782e+00,
           -1.7202e+00, -2.0879e+00]]]], grad_fn=<NativeBatchNormBackward>)

如何在一个CNN中加入Residule block----代码

-------定义网络模型------

## 定义一个建立了一个卷积--池化--卷积--池化--
## 卷积--池化--全连接--全连接--全连接(4分类)
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.bn1 = nn.BatchNorm2d(32)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.bn2 = nn.BatchNorm2d(64)
        self.conv3 = nn.Conv2d(64, 64, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.bn3 = nn.BatchNorm2d(64)
        self.conv3 = nn.Conv2d(64, 64, 3)
        self.drop1d = nn.Dropout(0.2)
        self.bn4 = nn.BatchNorm2d(64)
        self.fc1 = nn.Linear(64 * 14 * 14, 1024)
        self.fc2 = nn.Linear(1024, 256)
        self.fc3 = nn.Linear(256, 4)
    
    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.bn1(x)
        x = self.pool(F.relu(self.conv2(x)))
        x = self.bn2(x)
        x = self.pool(F.relu(self.conv3(x)))
        x = self.bn3(x)
        x = x.view(-1, x.size(1) * x.size(2) * x.size(3))
        x = F.relu(self.fc1(x))
        x = self.drop1d(x)
        x = F.relu(self.fc2(x))
        x = self.drop1d(x)
        x = self.fc3(x)
        return x

建立了一个卷积–池化–卷积–池化–卷积–池化–全连接–全连接–全连接(输出为4分类)

##测试模型
Model = Net()
x = torch.randn(32, 3, 128, 128)
model(x)
>>>
tensor([[ 2.4648, -0.1044, -0.0207,  ..., -1.5143, -0.0301,  0.4112],
        [-1.1457,  1.1705, -1.1644,  ..., -0.6782,  1.5006,  0.6034],
        [ 1.8320,  2.3075,  0.9986,  ..., -0.7777, -0.5291,  0.7829],
        ...,
        [-0.4622, -0.6317,  0.4479,  ...,  2.8768, -0.5076,  2.9432],
        [-0.9910, -0.6667,  0.5861,  ..., -0.1901, -2.6266,  0.2797],
        [-1.4598, -0.4183, -1.2018,  ..., -2.0129,  1.1534,  1.2424]],
       grad_fn=<AddmmBackward>)

现在问题是如何在普通的CNN网络中添加Residule block

## 定义网络模型
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 32, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.bn1 = nn.BatchNorm2d(32)
        ## 此处添加Residule block,记得写in_channels和out_channels两个参数
        self.res = ResNet_basic_block(in_channels=32, out_channels=32)
        self.conv2 = nn.Conv2d(32, 64, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.bn2 = nn.BatchNorm2d(64)
        self.conv3 = nn.Conv2d(64, 64, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.bn3 = nn.BatchNorm2d(64)
        self.conv3 = nn.Conv2d(64, 64, 3)
        self.drop1d = nn.Dropout(0.2)
        self.bn4 = nn.BatchNorm2d(64)
        self.fc1 = nn.Linear(64 * 14 * 14, 1024)
        self.fc2 = nn.Linear(1024, 256)
        self.fc3 = nn.Linear(256, 4)
    

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.bn1(x)
        x = self.res(x) ## 使用residule block
        x = self.pool(F.relu(self.conv2(x)))
        x = self.bn2(x)
        x = self.pool(F.relu(self.conv3(x)))
        x = self.bn3(x)
        x = x.view(-1, x.size(1) * x.size(2) * x.size(3))
        x = F.relu(self.fc1(x))
        x = self.drop1d(x)
        x = F.relu(self.fc2(x))
        x = self.drop1d(x)
        x = self.fc3(x)
        return x
Model = Net()
x = torch.randn(32, 3, 128, 128)
model(x)
>>>
tensor([[ 1.5100e+00, -7.4613e-01,  8.7256e-01,  ...,  3.0170e+00,
         -3.0221e-01, -1.8396e+00],
        [-6.5097e-01, -9.8755e-03, -1.5788e-01,  ...,  1.6645e+00,
          9.5299e-01,  8.2736e-01],
        [-1.8710e+00,  2.0923e-01,  4.7972e-01,  ...,  1.8698e-01,
          1.8506e-01,  1.6153e-04],
        ...,
        [ 5.4644e+00,  1.8698e+00, -7.3383e-01,  ...,  6.9908e-01,
         -1.3000e+00,  1.7883e+00],
        [-6.2972e-02, -2.3328e+00, -2.5254e-01,  ...,  1.5666e+00,
          8.7195e-01, -2.8013e-01],
        [-1.5590e+00, -2.7793e+00, -1.5177e+00,  ..., -1.2423e+00,
         -4.3381e-01, -6.5499e-01]], grad_fn=<AddmmBackward>)

模型输出结果了,大工完成

欢迎关注gzh:故障诊断与python学习

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故障诊断与python学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值