ResNet网络

ResNet网络诞生背景

在这里插入图片描述
来源:百度百科
孙剑(1976年10月—2022年6月14日),男,出生于西安 [6],人工智能领域科学家 [7],生前为旷视科技首席科学家、旷视研究院院长、西安交通大学人工智能学院首任院长 [6]。
孙剑于1997年在西安交通大学获工学学士学位,2000年在西安交通大学获工学硕士学位,2003年在西安交通大学获工学博士学位 [4];2003年在微软亚洲研究院担任首席研究员,2016年7月加入旷视科技任首席科学家和旷视研究院(Megvii Research)负责人;2022年6月14日,因突发疾病抢救无效逝世,年仅45岁。 [6]
孙剑主要研究方向是计算机视觉和计算摄影学、人脸识别和基于深度学习的图像理解。 [6]

网络加深带来的问题是什么呢

在这里插入图片描述
模型退化的原因在于:
1.不可能让w永远保持为1
2.每一层经过激活函数的处理,会带来特征的信息损失(有效特征或者冗余特征)

ResNet网络创新的地方-残差块

在这里插入图片描述

批量规范化层(归一化,是含有网络参数的),是需要通过反向传播来更新参数的。

之前的GoogLeNet网络中的局部归一化是不含网络参数的。
2种残差块结构(一种含有1*1卷积,保证与输入具有相同的宽高和通道数,进而方便和输入进行相加运算,一种是不含的)
在这里插入图片描述

1X1卷积(通过改变步长来和批量规范化层输出的特征大小保持一致卷积核的数量,来保证通道数是一致的,以便进行相加操作)

具体的搭建

在这里插入图片描述

import torch
from torch import nn
from torchsummary import summary


#借鉴GoogLeNet网络的Inception模块的搭建,因此可以先搭建一个残差块(模板式,后续直接调用即可)
class Residual(nn.Module):
    #定义初始化函数
     def __init__(self,input_channels,num_channels,use_1conv =False,strides=1):
         super(Residual).__init__()
         self.ReLu = nn.ReLU()
         self.conv1 = nn.Conv2d(in_channels=input_channels ,out_channels=num_channels,kernel_size=3,padding=1,stride=strides)
         self.conv2 = nn.Conv2d(in_channels=num_channels ,out_channels= num_channels,kernel_size=3,padding=1)
         self.bn1 = nn.BatchNorm2d(num_channels)
         self.bn2 = nn.BatchNorm2d(num_channels)
         ##两种残差块,有参数的是有1*1卷积的,use_1conv为真时,有1*1卷积块,为假时,为空,一般填充为0,会发现参数不够用
         if use_1conv:
             self.conv3 = nn.Conv2d(in_channels=input_channels ,out_channels= num_channels,kernel_size=1,stride=strides)
         else:
             self.conv3 = None
     #利用前向传播,来进行一个模型的构建
     def forward(self,x):
        y = self.ReLu(self.bn1(self.conv1(x)))
        y = self.bn2(self.conv2(y))
        #条件判断,是否有conv3,conv3 = None,条件为假,则没有
        if self.conv3:
            x = self.conv3(x)
        y =self.ReLu(y+x)

        return y

ResNet网络创新的地方-BN操作

在这里插入图片描述
在这里插入图片描述

归一化处理,消除了物理量纲对结果的影响(同一起跑线,那个特征对结果的影响较大,对应的w就多一些更新)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第四步的作用在于普遍性(而不是单纯的几个激活函数的效果比较好)
既要收敛速度快,还不要近似于线性函数使得弱化网络性能。
第四步得到的性能是最差的情况是和没有处理的性能是一样的。
在这里插入图片描述

ResNet网络参数详解

以ResNet-18为例

网络结构,巧妙,简单,这才是真正厉害的地方

3*3最大池化的作用是降低分辨率(尺寸变为原来的一半)

在这里插入图片描述
在这里插入图片描述

步幅为1,填充为13*3的卷积核,特征图大小是不变的
计算特征图大小的公式不要忘了哦!

在这里插入图片描述
在这里插入图片描述

上图中右括号处写的3个(表示带有1*1卷积+不带有的构成一个小结构,3个就是共有3个这样的小结构)

在这里插入图片描述
在这里插入图片描述
注意一下,这个1*1的卷积层,填充一般为0,步幅的大小,与刚进入残差块的第一个卷积核的步幅大小一致。即1*1卷积的卷积核个数和步长是根据实时的变换而变换,不是固定不变的步长。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
全局平均池化模块,在上一篇GoogLeNet中强调了,这里就不再提了。
在这里插入图片描述

ResNet网络模型搭建

import torch
from torch import nn
from torchsummary import summary


#借鉴GoogLeNet网络的Inception模块的搭建,因此可以先搭建一个残差块(模板式,后续直接调用即可)
class Residual(nn.Module):
    #定义初始化函数,use_1conv =False默认为假,是不存在1*1卷积函数的。
     def __init__(self, input_channels,num_channels,use_1conv =False,strides=1):
         super(Residual,self).__init__()
         self.ReLu = nn.ReLU()
         self.conv1 = nn.Conv2d(in_channels=input_channels ,out_channels=num_channels,kernel_size=3,padding=1,stride=strides)
         self.conv2 = nn.Conv2d(in_channels=num_channels ,out_channels= num_channels,kernel_size=3,padding=1)
         self.bn1 = nn.BatchNorm2d(num_channels)
         self.bn2 = nn.BatchNorm2d(num_channels)
         ##两种残差块,有参数的是有1*1卷积的,use_1conv为真时,有1*1卷积块,为假时,为空,一般填充为0,会发现参数不够用
         if use_1conv:
             self.conv3 = nn.Conv2d(in_channels=input_channels ,out_channels= num_channels,kernel_size=1,stride=strides)
         else:
             self.conv3 = None


     #利用前向传播,来进行一个模型的构建
     def forward(self,x):
        y = self.ReLu(self.bn1(self.conv
### ResNet101网络结构的Verilog实现 ResNet101是一种深层残差网络,具有101层深度,在图像分类和其他视觉任务上表现出色。要将其转换为FPGA上的硬件实现,通常会采用高层次综合(HLS)工具来简化开发过程。 #### 设计思路 对于ResNet101这样的大型网络,完整的硬件映射并不现实,因为这将消耗大量的FPGA资源。相反,可以针对特定部分进行优化并部署于FPGA平台上[^2]。具体来说: - **模块化设计**:将复杂的ResNet101分解成多个独立的功能模块,比如卷积单元、批标准化(BN)处理以及激活函数等。 - **流水线技术**:引入管道机制以增加吞吐量,减少延迟时间。 - **量化策略**:应用低精度表示形式(如8位整数),从而降低存储需求和带宽压力的同时保持较高的准确性。 #### 关键组件实例——卷积操作 下面展示了一个简单的卷积核计算模板作为例子,适用于ResNet中的基本构建块之一。请注意实际项目可能更复杂,并且需要额外考虑边界条件等问题。 ```verilog module conv_layer ( input wire clk, input wire reset_n, // Input feature map interface input wire [IN_CHANNEL-1:0][BITWIDTH-1:0] in_data, // 输入特征图 output reg [OUT_CHANNEL-1:0][BITWIDTH-1:0] out_data,// 输出特征图 ... ); // 卷积权重矩阵 (假设已经加载完毕) reg [WEIGHT_BITWIDTH-1:0] weights[KERNEL_SIZE*KERNEL_SIZE*IN_CHANNEL]; always @(posedge clk or negedge reset_n) begin if (!reset_n) begin // Reset logic here... end else begin // Convolution operation implementation goes here. // Example pseudo-code for a single point convolution: /* For each channel i from 0 to IN_CHANNEL do { sum += in_data[i] * weights[index++]; } out_data = activation_function(sum); */ end end endmodule ``` 此代码片段展示了如何定义一个基础的卷积层接口及其内部状态更新规则。真正的卷积运算还需要遍历输入张量的不同位置,并累加乘积累次结果直到完成整个滤波器响应面的扫描。 #### 激活与偏置处理 类似于MobileNet-SSD的设计方案,可以在每次执行完一次卷积之后立即施加ReLU非线性变换,并根据具体情况决定是否加入偏移项调整输出范围。这部分可以通过编写专门的`bias_relu_module`来高效地完成。 ```verilog module bias_relu_module( input wire clk, input wire reset_n, input wire signed [INPUT_WIDTH-1:0] data_in, output reg signed [OUTPUT_WIDTH-1:0] data_out ); localparam BIAS_VALUE = 3'b000; always @(posedge clk or negedge reset_n) begin if (!reset_n) begin data_out <= 'b0; end else begin integer temp_result; temp_result = data_in + BIAS_VALUE; if(temp_result > OUTPUT_MAX) data_out <= OUTPUT_MAX; else if(temp_result < 0) data_out <= 'b0; // ReLU effect else data_out <= temp_result; end end endmodule ``` 这段代码实现了带有偏置添加功能的ReLU激活函数,其中包含了必要的溢出保护措施以防止数值超出允许区间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值