飞桨 | 基于 Paddle 从零开始实现 Resnet18 之 模型结构

7 篇文章 1 订阅
订阅专栏

Resnet18 是何恺明在论文 Deep Residual Learning for Image Recognition 中提出的一个卷积神经网络。本文将带你根据论文基于百度深度学习框架 paddle 从头开始实现 Resnet18 模型结构。

一、网络结构

首先,我们来看一下要实现的目标 Resnet18 的整体结构。然后,再将 Resnet18 拆成几个主要部件分别进行代码实现。

Resnet18 的整体结构

Resnet18 的整体结构如下图所示,共有 18 个有权重的层(卷积层和全连接层),池化层和 BN 层不计入层数。Resnet18 图片来源自 PyTorch实现ResNet18。

在这里插入图片描述

Resnet 18 的主要部件

Resnet18 主要包括 stem、block 和 head 三种部件。它们的结构如下图所示:

Block + Stem + Head
在这里插入图片描述

二、代码实现

那么如何用 stem、block 和 head 构成 Resnet18 呢?
为了简化代码,将两个 block 封装成一个 layer,所有 layer 组成 body。因此 Resnet18 由 stem、body 和 head 三个部分组成。
其中,

  • stem 包括一个 7x7 的卷积层,一个 3x3 的最大池化层
  • body 包括 4 个 layer,每个 layer 由两个 Block 组成
  • head 包括一个 average pool 层 和 fc 层

Resnet18 各层的具体参数如下,下面我们依照下图利用 paddle 开始实现 Resnet18。
在这里插入图片描述

利用 paddle 实现 Resnet18,首先需要导入必要的库

import paddle
import paddle.nn as nn

然后分别实现 block , stem 和 head 结构。在实现这些结构之前,先写一个 Identity 类,它的作用是保持输入和输出一致,直接返回输入

 # 定义一个类,直接返回输入,不对输入做任何操作
class Identity(nn.Layer):
    def __init_(self):
        super().__init__()

    def forward(self, x):
        return x

1. 定义 Block

残差块 block 的结构如下图所示,由两个卷积层和一个 shortcut 组成。shortcut 分为实线 shortcut 和 虚线 shortcut。

  • 实线 shortcut 的输入输出有相同的维度,故对输入特征执行 identity 保持输入输出一致即可
  • 虚线 shortcut 的输入输出有不同的维度,输出维度增加,故需要将输入维度扩展到输出维度大小,同时伴随特征图大小减半操作

在这里插入图片描述
Block 的代码实现如下:
先做两次卷积操作,再将 shortcut h 和 block 的输出 x 求和,返回二者之和即可。

# 定义残差块 Block
# 一个 Block 由两个卷积层组成
class Block(nn.Layer):
    def __init__(self, in_dim, out_dim, stride):
        super().__init__()
        self.conv1 = nn.Conv2D(in_dim, out_dim, 3, stride=stride, padding=1,bias_attr=False)
        self.bn1 = nn.BatchNorm2D(out_dim)
        self.conv2 = nn.Conv2D(out_dim, out_dim, 3, stride=1,padding=1,bias_attr=False)
        self.bn2 = nn.BatchNorm2D(out_dim)
        self.relu = nn.ReLU()

        # shortcut 分为 实线 shortcut 和 虚线 shortcut
        # 实线 shortcut 的输入输出有相同的维度,故无需处理
        # 虚线 shortcut 的输出维度增加,故需要将输入维度扩展到输出维度大小,同时令 stride=2 减小特征图大小
        
        # 当 滑动步长为 2 或者 特征图输入输出维度不相等时,为虚线 shortcut,需要下采样 
        if stride == 2 or in_dim != out_dim:
            # 增加维度 + 下采样调整大小
            self.downsample = nn.Sequential(*[
                nn.Conv2D(in_dim, out_dim, 1, stride = stride),
                nn.BatchNorm2D(out_dim)])
        else:
            # 实线 shortcut 不做操作,保持不变
            self.downsample = Identity()

    def forward(self, x):
        # shortcut
        h = x
        # 做两次卷积
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = self.bn2(x)
        # 对 shortcut h 做处理,方便连接 x
        identity = self.downsample(h)
        x = x + identity 
        x = self.relu(x)
        return x

2. 定义 Layer 层

body 中一共包括 4 个 layer,每个 layer 由两个 block 组成。第一个 block 可能会对特征图下采样(stride=2 或 stride=1),第二个 block 不会改变特征图大小(stride=1)。因此先将第一个 block 加入 layer,之后再循环加入剩余的 block。

def _make_layer(self, out_dim, n_blocks, stride):
    layers = []
    # 先加入一个 stride 不为 1 的 block,对特征图进行下采样
    layers.append(Block(self.in_dim,out_dim,stride=stride))
    self.in_dim = out_dim
    # 再加入 stride 为 1 的若干 block,特征图大小保持不变
    for i in range(1, n_blocks):
        layers.append(Block(self.in_dim, out_dim, stride=1))
    return nn.Sequential(*layers)

在这里插入图片描述
参考上图,layer1 —— layer4 的维度分别为

self.layer1 = self._make_layer(out_dim=64,  n_blocks=2, stride=1)
self.layer2 = self._make_layer(out_dim=128, n_blocks=2, stride=2)
self.layer3 = self._make_layer(out_dim=256, n_blocks=2, stride=2)
self.layer4 = self._make_layer(out_dim=512, n_blocks=2, stride=2) 

3. 定义 stem 和 head

stem 包括一个 7x7 的卷积层,一个 3x3 的最大池化层。

        self.in_dim = in_dim
        self.conv1 = nn.Conv2D(in_channels=3, 
                        out_channels=in_dim, 
                        kernel_size=7,  
                        stride=2, 
                        padding=3,
                        bias_attr=False)

        self.bn1 = nn.BatchNorm2D(in_dim)
        self.relu = nn.ReLU()

        self.maxpool = nn.MaxPool2D(kernel_size=3, stride=2, padding=1)

head 包括一个 average pool 层 和 fc 层。

        self.avgpool = nn.AdaptiveAvgPool2D(1)
        self.classifier = nn.Linear(512, num_classes)   

ResNet18 类的整体代码实现如下:

# 定义 ResNet18 类
# Resnet18 由 stem、body 和 head 三个部分组成
# 其中,stem 包括一个 7x7 的卷积层,一个 3x3 的最大池化层
# body 包括 4 个 layer,每个 layer 由两个 Block 组成
# head 包括一个 average pool 层 和 fc 层

class ResNet18(nn.Layer):
    def __init__(self, in_dim=64, num_classes=1000):
        super().__init__()
        self.in_dim = in_dim
        self.conv1 = nn.Conv2D(in_channels=3, 
                        out_channels=in_dim, 
                        kernel_size=7,  
                        stride=2, 
                        padding=3,
                        bias_attr=False)

        self.bn1 = nn.BatchNorm2D(in_dim)
        self.relu = nn.ReLU()

        self.maxpool = nn.MaxPool2D(kernel_size=3, stride=2, padding=1)

        self.layer1 = self._make_layer(out_dim=64,  n_blocks=2, stride=1)
        self.layer2 = self._make_layer(out_dim=128, n_blocks=2, stride=2)
        self.layer3 = self._make_layer(out_dim=256, n_blocks=2, stride=2)
        self.layer4 = self._make_layer(out_dim=512, n_blocks=2, stride=2)  

        self.avgpool = nn.AdaptiveAvgPool2D(1)
        self.classifier = nn.Linear(512, num_classes)   

    def _make_layer(self, out_dim, n_blocks, stride):
        layers = []
        # 先加入一个 stride 不为 1 的 block,对特征图进行下采样
        layers.append(Block(self.in_dim,out_dim,stride=stride))
        self.in_dim = out_dim
        # 再加入 stride 为 1 的若干 block,特征图大小保持不变
        for i in range(1, n_blocks):
            layers.append(Block(self.in_dim, out_dim, stride=1))
        return nn.Sequential(*layers)
        

    def forward(self, x):
        ## stem
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)
        ## body
        x = self.layer1(x)
        x = self.layer2(x)        
        x = self.layer3(x)
        x = self.layer4(x)        
        ## head
        x = self.avgpool(x)
        # 为了连接全连接层 fc, 即 classifier ,需要将特征展成一维
        x = x.flatten(1)
        x = self.classifier(x)
        return x

4. 输出模型结构

# 测试代码
def main():
    model = ResNet18()
    print(model)
    paddle.summary(model, (2, 3, 32, 32))
    # x = paddle.randn([2, 3, 32, 32])
    # out = model(x)
    # print(out.shape)

if __name__ == "__main__":
    main()

输出结果如下所示:

ResNet18(
  (conv1): Conv2D(3, 64, kernel_size=[7, 7], stride=[2, 2], padding=3, data_format=NCHW)
  (bn1): BatchNorm2D(num_features=64, momentum=0.9, epsilon=1e-05)
  (relu): ReLU()
  (maxpool): MaxPool2D(kernel_size=3, stride=2, padding=1)
  (layer1): Sequential(
    (0): Block(
      (conv1): Conv2D(64, 64, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=64, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(64, 64, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=64, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Identity()
    )
    (1): Block(
      (conv1): Conv2D(64, 64, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=64, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(64, 64, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=64, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Identity()
    )
  )
  (layer2): Sequential(
    (0): Block(
      (conv1): Conv2D(64, 128, kernel_size=[3, 3], stride=[2, 2], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=128, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(128, 128, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=128, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Sequential(
        (0): Conv2D(64, 128, kernel_size=[1, 1], stride=[2, 2], data_format=NCHW)
        (1): BatchNorm2D(num_features=128, momentum=0.9, epsilon=1e-05)
      )
    )
    (1): Block(
      (conv1): Conv2D(128, 128, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=128, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(128, 128, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=128, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Identity()
    )
  )
  (layer3): Sequential(
    (0): Block(
      (conv1): Conv2D(128, 256, kernel_size=[3, 3], stride=[2, 2], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=256, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(256, 256, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=256, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Sequential(
        (0): Conv2D(128, 256, kernel_size=[1, 1], stride=[2, 2], data_format=NCHW)
        (1): BatchNorm2D(num_features=256, momentum=0.9, epsilon=1e-05)
      )
    )
    (1): Block(
      (conv1): Conv2D(256, 256, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=256, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(256, 256, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=256, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Identity()
    )
  )
  (layer4): Sequential(
    (0): Block(
      (conv1): Conv2D(256, 512, kernel_size=[3, 3], stride=[2, 2], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=512, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(512, 512, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=512, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Sequential(
        (0): Conv2D(256, 512, kernel_size=[1, 1], stride=[2, 2], data_format=NCHW)
        (1): BatchNorm2D(num_features=512, momentum=0.9, epsilon=1e-05)
      )
    )
    (1): Block(
      (conv1): Conv2D(512, 512, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn1): BatchNorm2D(num_features=512, momentum=0.9, epsilon=1e-05)
      (conv2): Conv2D(512, 512, kernel_size=[3, 3], padding=1, data_format=NCHW)
      (bn2): BatchNorm2D(num_features=512, momentum=0.9, epsilon=1e-05)
      (relu): ReLU()
      (downsample): Identity()
    )
  )
  (avgpool): AdaptiveAvgPool2D(output_size=1)
  (classifier): Linear(in_features=512, out_features=1000, dtype=float32)
)
-------------------------------------------------------------------------------
   Layer (type)         Input Shape          Output Shape         Param #    
===============================================================================
     Conv2D-61        [[2, 3, 32, 32]]     [2, 64, 16, 16]         9,408     
  BatchNorm2D-61     [[2, 64, 16, 16]]     [2, 64, 16, 16]          256      
      ReLU-28        [[2, 64, 16, 16]]     [2, 64, 16, 16]           0       
    MaxPool2D-4      [[2, 64, 16, 16]]      [2, 64, 8, 8]            0       
     Conv2D-62        [[2, 64, 8, 8]]       [2, 64, 8, 8]         36,864     
  BatchNorm2D-62      [[2, 64, 8, 8]]       [2, 64, 8, 8]           256      
      ReLU-29         [[2, 64, 8, 8]]       [2, 64, 8, 8]            0       
     Conv2D-63        [[2, 64, 8, 8]]       [2, 64, 8, 8]         36,864     
  BatchNorm2D-63      [[2, 64, 8, 8]]       [2, 64, 8, 8]           256      
    Identity-16       [[2, 64, 8, 8]]       [2, 64, 8, 8]            0       
     Block-25         [[2, 64, 8, 8]]       [2, 64, 8, 8]            0       
     Conv2D-64        [[2, 64, 8, 8]]       [2, 64, 8, 8]         36,864     
  BatchNorm2D-64      [[2, 64, 8, 8]]       [2, 64, 8, 8]           256      
      ReLU-30         [[2, 64, 8, 8]]       [2, 64, 8, 8]            0       
     Conv2D-65        [[2, 64, 8, 8]]       [2, 64, 8, 8]         36,864     
  BatchNorm2D-65      [[2, 64, 8, 8]]       [2, 64, 8, 8]           256      
    Identity-17       [[2, 64, 8, 8]]       [2, 64, 8, 8]            0       
     Block-26         [[2, 64, 8, 8]]       [2, 64, 8, 8]            0       
     Conv2D-66        [[2, 64, 8, 8]]       [2, 128, 4, 4]        73,728     
  BatchNorm2D-66      [[2, 128, 4, 4]]      [2, 128, 4, 4]          512      
      ReLU-31         [[2, 128, 4, 4]]      [2, 128, 4, 4]           0       
     Conv2D-67        [[2, 128, 4, 4]]      [2, 128, 4, 4]        147,456    
  BatchNorm2D-67      [[2, 128, 4, 4]]      [2, 128, 4, 4]          512      
     Conv2D-68        [[2, 64, 8, 8]]       [2, 128, 4, 4]         8,320     
  BatchNorm2D-68      [[2, 128, 4, 4]]      [2, 128, 4, 4]          512      
     Block-27         [[2, 64, 8, 8]]       [2, 128, 4, 4]           0       
     Conv2D-69        [[2, 128, 4, 4]]      [2, 128, 4, 4]        147,456    
  BatchNorm2D-69      [[2, 128, 4, 4]]      [2, 128, 4, 4]          512      
      ReLU-32         [[2, 128, 4, 4]]      [2, 128, 4, 4]           0       
     Conv2D-70        [[2, 128, 4, 4]]      [2, 128, 4, 4]        147,456    
  BatchNorm2D-70      [[2, 128, 4, 4]]      [2, 128, 4, 4]          512      
    Identity-18       [[2, 128, 4, 4]]      [2, 128, 4, 4]           0       
     Block-28         [[2, 128, 4, 4]]      [2, 128, 4, 4]           0       
     Conv2D-71        [[2, 128, 4, 4]]      [2, 256, 2, 2]        294,912    
  BatchNorm2D-71      [[2, 256, 2, 2]]      [2, 256, 2, 2]         1,024     
      ReLU-33         [[2, 256, 2, 2]]      [2, 256, 2, 2]           0       
     Conv2D-72        [[2, 256, 2, 2]]      [2, 256, 2, 2]        589,824    
  BatchNorm2D-72      [[2, 256, 2, 2]]      [2, 256, 2, 2]         1,024     
     Conv2D-73        [[2, 128, 4, 4]]      [2, 256, 2, 2]        33,024     
  BatchNorm2D-73      [[2, 256, 2, 2]]      [2, 256, 2, 2]         1,024     
     Block-29         [[2, 128, 4, 4]]      [2, 256, 2, 2]           0       
     Conv2D-74        [[2, 256, 2, 2]]      [2, 256, 2, 2]        589,824    
  BatchNorm2D-74      [[2, 256, 2, 2]]      [2, 256, 2, 2]         1,024     
      ReLU-34         [[2, 256, 2, 2]]      [2, 256, 2, 2]           0       
     Conv2D-75        [[2, 256, 2, 2]]      [2, 256, 2, 2]        589,824    
  BatchNorm2D-75      [[2, 256, 2, 2]]      [2, 256, 2, 2]         1,024     
    Identity-19       [[2, 256, 2, 2]]      [2, 256, 2, 2]           0       
     Block-30         [[2, 256, 2, 2]]      [2, 256, 2, 2]           0       
     Conv2D-76        [[2, 256, 2, 2]]      [2, 512, 1, 1]       1,179,648   
  BatchNorm2D-76      [[2, 512, 1, 1]]      [2, 512, 1, 1]         2,048     
      ReLU-35         [[2, 512, 1, 1]]      [2, 512, 1, 1]           0       
     Conv2D-77        [[2, 512, 1, 1]]      [2, 512, 1, 1]       2,359,296   
  BatchNorm2D-77      [[2, 512, 1, 1]]      [2, 512, 1, 1]         2,048     
     Conv2D-78        [[2, 256, 2, 2]]      [2, 512, 1, 1]        131,584    
  BatchNorm2D-78      [[2, 512, 1, 1]]      [2, 512, 1, 1]         2,048     
     Block-31         [[2, 256, 2, 2]]      [2, 512, 1, 1]           0       
     Conv2D-79        [[2, 512, 1, 1]]      [2, 512, 1, 1]       2,359,296   
  BatchNorm2D-79      [[2, 512, 1, 1]]      [2, 512, 1, 1]         2,048     
      ReLU-36         [[2, 512, 1, 1]]      [2, 512, 1, 1]           0       
     Conv2D-80        [[2, 512, 1, 1]]      [2, 512, 1, 1]       2,359,296   
  BatchNorm2D-80      [[2, 512, 1, 1]]      [2, 512, 1, 1]         2,048     
    Identity-20       [[2, 512, 1, 1]]      [2, 512, 1, 1]           0       
     Block-32         [[2, 512, 1, 1]]      [2, 512, 1, 1]           0       
AdaptiveAvgPool2D-4   [[2, 512, 1, 1]]      [2, 512, 1, 1]           0       
     Linear-4            [[2, 512]]           [2, 1000]           513,000    
===============================================================================
Total params: 11,700,008
Trainable params: 11,680,808
Non-trainable params: 19,200
-------------------------------------------------------------------------------
Input size (MB): 0.02
Forward/backward pass size (MB): 2.53
Params size (MB): 44.63
Estimated Total Size (MB): 47.19
-------------------------------------------------------------------------------

三、相关API

1. Conv2D

class paddle.nn.Conv2D(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, padding_mode='zeros', weight_attr=None, bias_attr=None, data_format='NCHW')

2. BatchNorm

class paddle.nn.BatchNorm(num_channels, act=None, is_test=False, momentum=0.9, epsilon=1e-05, param_attr=None, bias_attr=None, dtype='float32', data_layout='NCHW', in_place=False, moving_mean_name=None, moving_variance_name=None, do_model_average_for_mean_and_var=False, use_global_stats=False, trainable_statistics=False)

3. Relu

paddle.nn.functional.relu(x, name=None)

4. AdaptiveAvgPool2D

paddle.nn.AdaptiveAvgPool2D(output_size, data_format='NCHW', name=None)

5. MaxPool2D

paddle.nn.MaxPool2D(kernel_size, stride=None, padding=0, ceil_mode=False, return_mask=False, data_format='NCHW', name=None)

6. nn.Sequential(*layers)

针对顺序的线性网络结构可以直接使用Sequential来快速完成组网,可以减少类的定义等代码编写。

下面 paddle 上的一个示例

import paddle

# Sequential形式组网
mnist = paddle.nn.Sequential(
    paddle.nn.Flatten(),
    paddle.nn.Linear(784, 512),
    paddle.nn.ReLU(),
    paddle.nn.Dropout(0.2),
    paddle.nn.Linear(512, 10)
)

参考链接

  1. PyTorch实现ResNet18
  2. 从零开始学视觉Transformer
resnet_18_structure.pdf
09-25
resnet 18 网络结构(摘要需要大于50个字节,所以请自动忽略这个括号。。。)
paddle实现resnet-18
11-04
paddle实现resnet-18
读pytroch使用resnet18网络的代码
airleaya的博客
10-11 2844
读读pytorch中调用resnet18的代码
NNDL 实验六 卷积神经网络(4)ResNet18实现MNIST
zhenjiteng的博客
11-01 757
这我还是写的很细,并且感觉这次用到了好多上一个实验的东西,遇到了一个问题研究好长时间,感觉解决的不是很好,请个老师和各位大佬多教教我首先,我这次同样写的很细,但是,我那个解决问题的方法感觉并不是很好,所以希望,各老师和各位大佬多教教我。
Resnet 18网络模型
Chenzhinan1219的博客
12-20 5万+
1. 残差网络:(Resnet) 残差块: 让我们聚焦于神经网络局部:如左侧所示,假设我们的原始输入为x,而希望学出的理想映射为f(x)(作为上方激活函数的输入)。左虚线框中的部分需要直接拟合出该映射f(x),而右虚线框中的部分则需要拟合出残差映射f(x)−x。 残差映射在现实中往往更容易优化。 以本节开头提到的恒等映射作为我们希望学出的理想映射f(x),我们只需将右虚线框内上方的加权运算(如仿射)的权重和偏置参数设成0,那么f(x)即为恒等映射。 实际中,当理想映射f(x)极接近于恒等映..
ResNet 18 网络结构
S20144144的博客
09-25 1万+
import torch from torchvision import models resnet = models.resnet18(pretrained=True) print(resnet) """ ResNet( (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False...
ResNet-18結構
gesshoo的博客
02-27 5472
残差块⾥⾸先有 2 个有相同输出通道数的 3 × 3 卷积层。每 个卷积层后接⼀个批量归⼀化层和 ReLU 激活函数。然后我们通过跨层数据通路,跳过这 2 个卷积运算,将输⼊直接加在最后的 ReLU 激活函数前。这样的设计要求 2 个卷积层的输出与输⼊形状⼀样,从而可以相加。 如 果想改变通道数,就需要引⼊⼀个额外的 1 × 1 卷积层来将输⼊变换成需要的形状后再做相加运算。 import torch from torch import nn from torch....
像识别-ResNet-18网络结构示及解读
算法之美
05-22 3万+
像识别-ResNet-18网络结构示及解读
深度学习入门】Paddle实现人脸检测和表情识别(基于TinyYOLO和ResNet18
12-20
Paddle实现人脸检测和表情识别(基于YOLO和ResNet18)一、先看效果:训练及测试结果:UI 界面及其可视化:二、AI Studio 简介:平台简介:创建项目:三、创建AI Studio项目:创建并启动环境:下载数据:下载预训练...
基于百度飞桨paddle实现语音情感识别源码+项目说明.zip
05-15
模型 Params(M) 预处理方法 数据集 类别数量 准确率 获取模型 BidirectionalLSTM 1.8 Flank RAVDESS 8 0.95193 加入知识星球获取 说明: RAVDESS数据集只使用Audio_Speech_Actors_01-24.zip 安装环境 首先安装的是...
使用飞桨PaddleHub实现皮影戏创作
05-10
使用飞桨PaddleHub实现皮影戏创作
基于python的X2Paddle飞桨深度学习模型转换工具
03-26
基于python的X2Paddle飞桨深度学习模型转换工具
初始PyTorch(六+):ResNet18网络结构
sleepinghm的博客
03-27 4905
使用ResNet18网络结构,为了更好适配Cifar-10数据集【h*w=32*32】,所以不是完全按照renset18的参数写的。 下ResNet18的内部结构。 先写内部结构:有两层的weight layer。 class ResBlk(nn.Module): def __init__(self, ch_in, ch_out, stride=1): s...
经典网络结构resnet18结构
BigCowPeking
10-14 2万+
Resnet 网络结构: layer { name: "res2c" type: "Eltwise" bottom: "res2b" bottom: "res2c_branch2c" top: "res2c" } layer { name: "res2c_relu" type: "ReLU" bottom: "res2c&q
自己实现resnet18网络结构
qq_43620727的博客
01-24 788
import torch import torch.nn as nn # 定义一个Residual模块 class Residual(nn.Module): def __init__(self,in_channels,out_channels,stride=1): super(Residual, self).__init__() self.stride = stride self.conv1 = nn.Conv2d(in_channels,out..
经典CNN网络:Resnet18网络结构输入和输出
热门推荐
weixin_43999691的博客
06-15 8万+
前言 每当看到一个新的网络,总会思考,这个网络提出来有什么意义,解决了什么问题?Resnet18的提出,解决
resnet18 结构
keyanxiaocaicai的专栏
05-18 302
可以看到在fc层之前的一层是avgpool层其实就是卷积只有alenet才是3个全连接吧
PaddlePaddle——论文复现:使用高层API复现Resnet18
Irving.Gao的博客
11-24 481
文章目录Resnet论文精读Resnet网络结构PaddlePaddle复现 目前在看《从零开始学视觉Transformer》,第一课的作业是一个warmup,复现Resnet18。在课程中,老师在讲解的过程中没有完全按照论文的形式进行组网搭建,所以这里我将会按照论文的形式进行相同的组网复现,并对其中的结构进行解释,同时锻炼自己的网络复现能力,为研究工作奠定基础。 Resnet论文精读 那必须是沐神的视频,大家可以自行观看:
[数据集][目标检测]伤口检测数据集VOC+YOLO格式2760张1类别
最新发布
FL1623863129的博客
05-27 421
数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg片以及对应的VOC格式xml文件和yolo格式txt文件)特别声明:本数据集不对训练的模型或者权重文件精度作任何保证,数据集只提供准确且合理标注。重要说明:大部分是脚本伤口,也有一小部分是其他部分伤口。片数量(jpg文件个数):2760。标注数量(xml文件个数):2760。标注数量(txt文件个数):2760。使用标注工具:labelImg。标注规则:对类别进行画矩形框。
使用paddle框架写一段resnet网络代码
05-15
好的,以下是使用 PaddlePaddle 框架实现 ResNet 网络的代码: ```python import paddle import paddle.nn as nn class BasicBlock(nn.Layer): expansion = 1 def __init__(self, in_channels, out_channels, stride=1, downsample=None): super(BasicBlock, self).__init__() self.conv1 = nn.Conv2D(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias_attr=False) self.bn1 = nn.BatchNorm2D(out_channels) self.relu = nn.ReLU() self.conv2 = nn.Conv2D(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias_attr=False) self.bn2 = nn.BatchNorm2D(out_channels) self.downsample = downsample self.stride = stride def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out class Bottleneck(nn.Layer): expansion = 4 def __init__(self, in_channels, out_channels, stride=1, downsample=None): super(Bottleneck, self).__init__() self.conv1 = nn.Conv2D(in_channels, out_channels, kernel_size=1, bias_attr=False) self.bn1 = nn.BatchNorm2D(out_channels) self.conv2 = nn.Conv2D(out_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias_attr=False) self.bn2 = nn.BatchNorm2D(out_channels) self.conv3 = nn.Conv2D(out_channels, out_channels * self.expansion, kernel_size=1, bias_attr=False) self.bn3 = nn.BatchNorm2D(out_channels * self.expansion) self.relu = nn.ReLU() self.downsample = downsample self.stride = stride def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) out = self.relu(out) out = self.conv3(out) out = self.bn3(out) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out class ResNet(nn.Layer): def __init__(self, block, layers, num_classes=1000): super(ResNet, self).__init__() self.in_channels = 64 self.conv1 = nn.Conv2D(3, 64, kernel_size=7, stride=2, padding=3, bias_attr=False) self.bn1 = nn.BatchNorm2D(64) self.relu = nn.ReLU() self.maxpool = nn.MaxPool2D(kernel_size=3, stride=2, padding=1) self.layer1 = self._make_layer(block, 64, layers[0]) self.layer2 = self._make_layer(block, 128, layers[1], stride=2) self.layer3 = self._make_layer(block, 256, layers[2], stride=2) self.layer4 = self._make_layer(block, 512, layers[3], stride=2) self.avgpool = nn.AdaptiveAvgPool2D((1, 1)) self.fc = nn.Linear(512 * block.expansion, num_classes) def _make_layer(self, block, out_channels, blocks, stride=1): downsample = None if stride != 1 or self.in_channels != out_channels * block.expansion: downsample = nn.Sequential( nn.Conv2D(self.in_channels, out_channels * block.expansion, kernel_size=1, stride=stride, bias_attr=False), nn.BatchNorm2D(out_channels * block.expansion) ) layers = [] layers.append(block(self.in_channels, out_channels, stride, downsample)) self.in_channels = out_channels * block.expansion for _ in range(1, blocks): layers.append(block(self.in_channels, out_channels)) return nn.Sequential(*layers) def forward(self, x): x = self.conv1(x) x = self.bn1(x) x = self.relu(x) x = self.maxpool(x) x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.layer4(x) x = self.avgpool(x) x = paddle.flatten(x, 1) x = self.fc(x) return x def resnet18(num_classes=1000): return ResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes) def resnet34(num_classes=1000): return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes) def resnet50(num_classes=1000): return ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes) def resnet101(num_classes=1000): return ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes) def resnet152(num_classes=1000): return ResNet(Bottleneck, [3, 8, 36, 3], num_classes=num_classes) ``` 以上代码定义了 BasicBlock 和 Bottleneck 两个块,并使用它们构建了 ResNet 模型。其中,ResNet 可以选择使用不同的块和层数来构建不同版本的网络。通过调用 `resnet18()`,`resnet34()`,`resnet50()`,`resnet101()` 和 `resnet152()` 函数可以得到不同版本的 ResNet 网络。

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 问题解决之 AttributeError: ‘NoneType‘ object has no attribute ‘astype‘ 27252
  • Win10 查看 DLL 中的函数 26508
  • 问题解决之 RuntimeError: Couldn‘t load custom C++ ops. This can happen if your PyTorch XXX 22846
  • 【亲测有效】解决 Ubuntu 虚拟机无法共享文件夹的问题 19585
  • 解决pycharm缓存文件过大问题 19070

分类专栏

  • 问题解决 27篇
  • 设计模式 1篇
  • C++程序设计 17篇
  • 深度学习数学基础 9篇
  • 行人重识别 21篇
  • 数据结构 22篇
  • 编译基础 3篇
  • Python基础 7篇
  • 网络编程 1篇
  • Git 1篇
  • MySQL 3篇
  • 摄像头图像获取 1篇

最新评论

  • 解决 重装 Visual Studio 2017,Visual Studio Installer 闪退

    jiangpinglu: 博主你好,我想问一下我是这种问题怎么解决呀 [4/25/2024, 15:14:11] The entire Box execution exiting with result code: 0x0 [4/25/2024, 15:14:11] Launched extracted application exiting with result code: 0xc000041d

  • 解决pycharm缓存文件过大问题

    今天读论文了吗: 建议不要随便使用此方法,会出现各种问题

  • 解决 from . import _imaging as core ImportError: DLL load failed: 找不到指定的模块。

    weixin_44718503: 感觉是有用的,先卸载再安装后就可以了,我这里相对于上个版本是升级了

  • 使用 Visio 绘制卷积示意图

    qq_42347591: 2024.1.23 没用

  • 解决 from . import _imaging as core ImportError: DLL load failed: 找不到指定的模块。

    Roger1___: 降低版本就好了,感谢

您愿意向朋友推荐“博客详情页”吗?

  • 强烈不推荐
  • 不推荐
  • 一般般
  • 推荐
  • 强烈推荐
提交

最新文章

  • 设计模式之简单工厂模式、工厂方法模式、抽象工厂模式(C++)
  • 用 C语言、C++、C#、Java、Python 输出 Hello world
  • 问题解决 之 转成PDF后Visio图中虚线看不清
2022年25篇
2021年88篇
2020年2篇
2018年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

两个鬼故事金鳞开四书五经起名爸爸去哪儿4期2020唐姓男孩起名海鲜品牌起名婴儿4字起名免费起店铺人名网戴姓女孩子的起名姓韩的起什么名字中日在线互译十大经典女主重生小说属猴吗起名取起名姓童中北品阁女神的超级赘婿电脑截图是ctrl加什么键起名者说给企业起名字的软件宁 起名姓王女孩仕字辈起名北冥有鱼原文及翻译水果蔬菜公司取名起名大全钟南山谈何时中国可以完全开放美国起重机排名傲软抠图女儿起名字大全2021免费子弹少女药品起名社区特色楼道起名休闲食品店起名少年生前被连续抽血16次?多部门介入两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”淀粉肠小王子日销售额涨超10倍高中生被打伤下体休学 邯郸通报单亲妈妈陷入热恋 14岁儿子报警何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言张家界的山上“长”满了韩国人?男孩8年未见母亲被告知被遗忘中国拥有亿元资产的家庭达13.3万户19岁小伙救下5人后溺亡 多方发声315晚会后胖东来又人满为患了张立群任西安交通大学校长“重生之我在北大当嫡校长”男子被猫抓伤后确诊“猫抓病”测试车高速逃费 小米:已补缴周杰伦一审败诉网易网友洛杉矶偶遇贾玲今日春分倪萍分享减重40斤方法七年后宇文玥被薅头发捞上岸许家印被限制高消费萧美琴窜访捷克 外交部回应联合利华开始重组专访95后高颜值猪保姆胖东来员工每周单休无小长假男子被流浪猫绊倒 投喂者赔24万小米汽车超级工厂正式揭幕黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发当地回应沈阳致3死车祸车主疑毒驾恒大被罚41.75亿到底怎么缴妈妈回应孩子在校撞护栏坠楼外国人感慨凌晨的中国很安全杨倩无缘巴黎奥运校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变王树国卸任西安交大校长 师生送别手机成瘾是影响睡眠质量重要因素国产伟哥去年销售近13亿阿根廷将发行1万与2万面值的纸币兔狲“狲大娘”因病死亡遭遇山火的松茸之乡“开封王婆”爆火:促成四五十对奥巴马现身唐宁街 黑色着装引猜测考生莫言也上北大硕士复试名单了德国打算提及普京时仅用姓名天水麻辣烫把捣辣椒大爷累坏了

两个鬼故事 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化