【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

这篇具有很好参考价值的文章主要介绍了【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

各位同学好,今天和大家分享一下 TensorFlow 深度学习中如何搭载 Resnet18 和 Resnet34 残差神经网络,残差网络利用 shotcut 的方法成功解决了网络退化的问题,在训练集和校验集上,都证明了的更深的网络错误率越小。

论文中给出的具体的网络结构如下:

【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

Resnet50 网络结构我已经在之前的博客中复现过,感兴趣的可以看一下:https://blog.csdn.net/dgvv4/article/details/121878494

感谢简书大佬画的残差网络结构图:https://www.jianshu.com/p/085f4c8256f1

【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码


1. 构建单个残差块

一个残差单元的结构如下。输入为X ;weight layer 代表卷积层,这里是指 convolution卷积层 + batch normalization批标准化层 ;relu 是激活函数 ; identity 是将输入 X 经过变换后与卷积层的输出结果相加,下面会详细说明。

【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

残差块中的第一个卷积层 self.conv1,主要用于下采样特征提取

如果步长 strides=1,由于padding='same',该层的输入和输出特征图的size不变。属于结构图中左侧蓝色部分。

如果步长 strides=2,表示该层输出的特征图的 size 是输入的特征图 size 的一半。由于卷积核的size是 3*3 ,卷积核移动时会出现滑窗无法覆盖所有的像素格的现象。可能会出现,该层的输出特征图size不等于输入size的一半。通过padding='same'自动填充输入图像,让输出size等于一半的输入size。属于结构图中的左侧后三种颜色的部分

残差块中的第二个卷积层 self.conv2,主要用于进一步提取特征,不进行下采样

规定其步长 stride=1,由于padding='same',该层的输入和输出特征图的size不变

完成卷积部分convblock之后,接下来看短接部分identityblock

identity 负责将输入 X的shape 变换到和卷积部分的输出的shape相同

如果第一个卷积层 self.conv1 步长 strides=1,那么输入特征图的 shape 和卷积层输出的特征图的 shape 相同,这时 identity 不需要变换输入特征图 X 的shape。

如果第一个卷积层 self.conv1 步长 strides=2,那么输入特征图的 size 变成了原来的一半。这时,为了能将输入 X 和 卷积层输出结果相加,需要通过 identity 重塑输入 X 的shape。这里使用的是 1*1 卷积传递特征1*1的卷积核遍历所有的像素格后不会改变特征图的size,设置步长strides=2,成功将特征图的size变成原来的一半。属于结构图中的左侧后三种颜色的部分。

这样,我们就完成了对单个残差块中所有层的初始化,接下来将层之间的前向传播过程写在 call() 函数中。这里需要注意的就是 layers.add([out, identity]) ,将卷积层的输出特征图的结果和输入的特征图相加identity 只负责将输入特征图的 shape 变换成和卷积部分输出特征图的 shape 相同

该部分的代码如下:

# Basic Bolck 残差块
# x--> 卷积 --> bn --> relu --> 卷积 --> bn --> 输出 
# |---------------Identity(短接)----------------|

# 定义子类,一个残差块
class BasicBlock(layers.Layer):  # 继承父类的方法和属性
    
    #(1)子类初始化
    # filter_num 代表传入卷积核数量,将输入图像的通道数变成残差块的规定的通道数
    # stride 代表步长,默认为1,代表不对输入图片的size采样,如果不做padding,得到的图像的size就略小,做padding后输入和输出的size保持一致
    # strdie=2时,代表二分采样,输出的size只有输入size的一半
    
    def __init__(self, filter_num, stride=1):
        
        # 继承父类的初始化方法,
        # super()中的第一个参数是子类名称,第二个是子类的实例化对象
        super(BasicBlock, self).__init__()
        
        # 在父类初始化的基础上添加新的属性
        
        # 卷积层1,传入卷积核数量,卷积核size,步长
        # 如果stride=1,为避免输出小于输入,设置padding='same',使输入等于输出
        # 如果stride=2,若输入为32*32,由于卷积核3*3的影响,使输出不等于16*16,这时通过padding=same在输入图像上自动补全,如果输出小于16会自动补成16
        self.conv1 = layers.Conv2D(filter_num, (3,3), strides=stride, padding='same')
        
        # 标准化层batchnormalizeation
        self.bn1 = layers.BatchNormalization()
        
        # relu激活函数层,没有其他参数,可以作为一个函数使用多次。而有参数设置的一些层,只能单独对应使用
        self.relu = layers.Activation('relu')
        
        # 卷积层2,如果上一个卷积层stride=2完成下采样,那么这里的卷积层就不进行下采样了,保持stride=1
        self.conv2 = layers.Conv2D(filter_num, (3,3), strides=1, padding='same')
        
        # 标准化层
        self.bn2 = layers.BatchNormalization()
        
        
        # identity层需进行维度变换,将原始输入图像和卷积后的图像相匹配
        # 进行1*1卷积匹配通道数,通过stride匹配图像的size
        self.downsample = Sequential()  # 设置容器
        
        # 在容器中添加1*1卷积和步长变换
        # stride保持和第一个卷积层一致,保证convblock和identityblock能直接相加
        # 如果第一个卷积层的stride=1时,那么输入和输出的shape保持一致
        self.downsample.add(layers.Conv2D(filter_num, (1,1), strides=stride))
        
        
    #(2)前向传播
    # 定义类方法,self为类实例化对象
    def call(self, inputs, training=None):
        
        # 卷积层1,调用初始化后的属性
        x = self.conv1(inputs)  # 输入原始图像
        x = self.bn1(x)
        x = self.relu(x)
        
        # 卷积层2
        x = self.conv2(x)
        out = self.bn2(x)

        # identity层,输入的是原始输入图像
        identity = self.downsample(inputs)
        
        # 将convblock和identityblock相加得到最终的残差块的输出结果
        output = layers.add([out, identity])
        
        # 最终结果经过一个非线性函数
        output = tf.nn.relu(output)
        
        # 返回残差块的输出结果
        return output

2. 叠加多个残差块

上面我们已经成功完成了一个残差块,然而一个残差结构是由多个残差块叠加而成的。下面是放大了的结构图,可见 resnet18 每一个残差结构是由 2 个残差单元组合而成

【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码   【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

我们定义一个函数 build_resblock 用来组合残差结构。这里需要注意的是,blocks 代表一个残差结构需要堆叠几个残差单元resnet18 和 32 中是2个。看结构图可知,在残差结构中只有第一个残差单元具备下采样改变特征图 size 的能力。因此第一个残差块的步长 stride,需要根据输入来确定。而除第一个以外的残差块都不会改变特征图的size,因此固定步长stride=1每一个残差结构的卷积核个数都是相同的,要通过输入来确定。 

    # 利用单个已定义的残差块,叠加多个残差块
    # filter_num,代表当前图像的特征图个数
    # blocks,需要代表堆叠几个残差块
    # stride,代表当前的步长,等于1
    def build_resblock(self, filter_num, blocks, strides=1):
        
        # 使用Sequential容器装填网络结构
        res_blocks = Sequential()
        
        # 在ResNet类中对BasicBlock类实例化,构成组合关系
        # ResNet类可调用BasicBlock类中的所有属性和方法
        
        # 添加网络层
        # 第一个残差块有下采样功能,stride可能等于2
        res_blocks.add(BasicBlock(filter_num, strides))
        
        # 每个残差结构中剩余的残差块不具备下采样功能,stride=1
        for _ in range(1, blocks):
            
            # 残差结构中剩余的残差块保持图像的shape不变
            res_blocks.add(BasicBlock(filter_num, stride=1))
        
        # 返回构建的残差结构
        return res_blocks

3. 构建残差网络

上面我们已经完成了残差块的构建,现在我们需要做的就是将这些残差结构按顺序堆叠在一起就能组建残差网络。

首先我们看初始化函数中的代码。self.stem 是用来处理原始输入图像的,假设原始输入的shape[224, 224, 3],根据网络结构图设置预处理卷积层的各个参数。通过最大池化 layers.MaxPool2D 指定步长为2,将预处理卷积层的特征图的size减半 

【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

接下去就可以根据每个残差结构的配置参数,第一个残差结构 self.layer1 由图可知,没有进行下采样,因此步长 stride=1,第一个残差结构中的卷积核个数统一是64个,每个残差结构由2个残差单元组成 layer_dims=[2,2,2,2],初始化时都是调用的上面定义的残差结构函数 build_resblock。

第二个残差结构 self.layer2 由图可知,第一个残差块进行了下采样,因此,要指定步长 strides=2,特征图的 size 减半,特征图的个数统一都是128。同理其他两个残差结构。

 【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码   【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

最后将残差层的输出结果经过全局平均池化后放入全连接层,得出分类结果。 layers.GlobalAveragePooling2D() 在通道维度上对w和h维度求平均值。将特征图的shape从 [b, w, h, c] 变成 [b, 1, 1, c] 

【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

完成对所有层的初始化 __init__ 之后,在 call() 方法中定义层与层之间的前向传播的方法。

# 定义子类ResNet,继承父类keras.Model
class ResNet(keras.Model):
    
    #(1)初始化
    # layer_dims=[2,2,2,2],resnet18包含4个残差结构res_blocks,每个残差结构中有2个残差块
    # num_classes 代表最终的输出的分类数
    def __init__(self, layer_dims, num_classes=1000):  
        
        # 调用父类的初始化方法
        super(ResNet, self).__init__(self)
        
        # 分配属性
        # 原始图像输入的预处理卷积和池化
        self.stem = Sequential([layers.Conv2D(64, (7,7), strides=(2,2), padding='same'),  # 3*3卷积提取特征
                                layers.BatchNormalization(),      # 标准化 
                                layers.Activation('relu'),        # 激活函数
                                layers.MaxPool2D(pool_size=(3,3), strides=(2,2), padding='same')])  # 最大池化,输入图像的size减半
        
        # 创建4个残差结构,layer_dims=[2,2,2,2]
        self.layer1 = self.build_resblock(64, layer_dims[0])  # 第一个残差结构指定64个卷积核,包含2个残差块
        self.layer2 = self.build_resblock(128, layer_dims[1], strides=2)  # 第二个残差结构128个卷积核,包含2个残差块,步长为2,图像的size减半
        self.layer3 = self.build_resblock(256, layer_dims[2], strides=2)
        self.layer4 = self.build_resblock(512, layer_dims[3], strides=2)
        
        # 全局平均池化,不管卷积层输出的长和宽是多少,在channel维度上将所有的长和宽加起来取均值
        # [b, w, h, c] ==> [b,c]
        self.avgpool = layers.GlobalAveragePooling2D()

        # 全连接层用于图像分类
        self.fc = layers.Dense(num_classes)


    #(2)定义前向传播的类方法
    def call(self, inputs, training=None):
        
        # 原始输入经过预处理卷积层
        x = self.stem(inputs)
        
        # 经过4个残差结构
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        
        # 输出层
        x = self.avgpool(x)  # 输出shape[b,c] --> [None, 512]
        x = self.fc(x)       # 输出[b,1000]
        
        # 返回分类结果
        return x

4. 打印查看网络结构

resnet18 和 resnet34 的差别就在每个残差结构所包含的残差块的个数不同,因此,只需稍作修改修改。我们再看一下这张网络结构表。

【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码

resnet18 网络的每个残差层的残差块个数都是2,因此设置参数 ResNet([2, 2, 2, 2]) ,即可返回网络结构。同理,只需要指定 resnet34 网络中每个残差层的残差块个数 ResNet([3, 4, 6, 3]) 。返回得到了输出层的结果,这时只需设置网络输入层的输入维度 model.build(),那么整个网络就构建完了。

# 构造resnet18,传入参数
def resnet18():
    # 实例化网络结构,一共有4个残差结构,每个残差结构由2个残差块组成
    return ResNet([2, 2, 2, 2]) 
        
# 构造resnet34,传入参数
def resnet34():
    # 实例化,一共有4个残差结构,每个残差结构有如下个数的残差单元
    return ResNet([3, 4, 6, 3])        


# 主函数
def main():
    
    # 构造网络resnet18
    model18 = resnet18() 
    # 确定输入层
    model18.build(input_shape=(None,224,224,3))
    # 查看网络结构
    model18.summary()
    
    # 构造网络resnet34
    model34 = resnet34()
    # 确定输入层
    model34.build(input_shape=(None,224,224,3))
    # 查看网络结构
    model34.summary()    

if __name__ == '__main__':
    
    main()

利用 model.summary() 查看网络具体的结构,其中第一个 multiple 的值等于 [None, 512]第二个 multiple 的值等于 [None, 1000]。下表中,layer 是 sequential 的 Output Shape 代表每一个残差层的输出 shape

resnet18 网络结构如下:

_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 sequential (Sequential)     (None, 56, 56, 64)        9728      
                                                                 
 sequential_1 (Sequential)   (None, 56, 56, 64)        157056    
                                                                 
 sequential_4 (Sequential)   (None, 28, 28, 128)       543488    
                                                                 
 sequential_7 (Sequential)   (None, 14, 14, 256)       2168320   
                                                                 
 sequential_10 (Sequential)  (None, 7, 7, 512)         8662016   
                                                                 
 global_average_pooling2d (G  multiple                 0         
 lobalAveragePooling2D)                                          
                                                                 
 dense (Dense)               multiple                  513000    
                                                                 
=================================================================
Total params: 12,053,608
Trainable params: 12,045,800
Non-trainable params: 7,808
_________________________________________________________________

resnet34 网络结构如下:文章来源地址https://www.toymoban.com/news/detail-405295.html

_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 sequential_13 (Sequential)  (None, 56, 56, 64)        9728      
                                                                 
 sequential_14 (Sequential)  (None, 56, 56, 64)        235584    
                                                                 
 sequential_18 (Sequential)  (None, 28, 28, 128)       1168896   
                                                                 
 sequential_23 (Sequential)  (None, 14, 14, 256)       7160320   
                                                                 
 sequential_30 (Sequential)  (None, 7, 7, 512)         13648384  
                                                                 
 global_average_pooling2d_1   multiple                 0         
 (GlobalAveragePooling2D)                                        
                                                                 
 dense_1 (Dense)             multiple                  513000    
                                                                 
=================================================================
Total params: 22,735,912
Trainable params: 22,720,680
Non-trainable params: 15,232
_________________________________________________________________

完整代码:

# 类方法写resnet18、34 
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, Sequential

# Basic Bolck 残差块
# x--> 卷积 --> bn --> relu --> 卷积 --> bn --> 输出 
# |---------------Identity(短接)----------------|


# 定义子类,一个残差块
class BasicBlock(layers.Layer):  # 继承父类的方法和属性
    
    #(2)子类初始化
    # filter_num 代表传入卷积核数量,将输入图像的通道数变成残差块的规定的通道数
    # stride 代表步长,默认为1,代表不对输入图片的size采样,如果不做padding,得到的图像的size就略小,做padding后输入和输出的size保持一致
    # strdie=2时,代表二分采样,输出的size只有输入size的一半
    
    def __init__(self, filter_num, stride=1):
        
        # 继承父类的初始化方法,
        # super()中的第一个参数是子类名称,第二个是子类的实例化对象
        super(BasicBlock, self).__init__()
        
        # 在父类初始化的基础上添加新的属性
        
        # 卷积层1,传入卷积核数量,卷积核size,步长
        # 如果stride=1,为避免输出小于输入,设置padding='same',使输入等于输出
        # 如果stride=2,若输入为32*32,由于卷积核3*3的影响,使输出不等于16*16,这时通过padding=same在输入图像上自动补全,如果输出小于16会自动补成16
        self.conv1 = layers.Conv2D(filter_num, (3,3), strides=stride, padding='same')
        
        # 标准化层batchnormalizeation
        self.bn1 = layers.BatchNormalization()
        
        # relu激活函数层,没有其他参数,可以作为一个函数使用多次。而有参数设置的一些层,只能单独对应使用
        self.relu = layers.Activation('relu')
        
        # 卷积层2,如果上一个卷积层stride=2完成下采样,那么这里的卷积层就不进行下采样了,保持stride=1
        self.conv2 = layers.Conv2D(filter_num, (3,3), strides=1, padding='same')
        
        # 标准化层
        self.bn2 = layers.BatchNormalization()
        
        
        # identity层需进行维度变换,将原始输入图像和卷积后的图像相匹配
        # 进行1*1卷积匹配通道数,通过stride匹配图像的size
        self.downsample = Sequential()  # 设置容器
        
        # 在容器中添加1*1卷积和步长变换
        # stride保持和第一个卷积层一致,保证convblock和identityblock能直接相加
        # 如果第一个卷积层的stride=1时,那么输入和输出的shape保持一致
        self.downsample.add(layers.Conv2D(filter_num, (1,1), strides=stride))
        
        
    #(2)前向传播
    # 定义类方法,self为类实例化对象
    def call(self, inputs, training=None):
        
        # 卷积层1,调用初始化后的属性
        x = self.conv1(inputs)  # 输入原始图像
        x = self.bn1(x)
        x = self.relu(x)
        
        # 卷积层2
        x = self.conv2(x)
        out = self.bn2(x)

        # identity层,输入的是原始输入图像
        identity = self.downsample(inputs)
        
        # 将convblock和identityblock相加得到最终的残差块的输出结果
        output = layers.add([out, identity])
        
        # 最终结果经过一个非线性函数
        output = tf.nn.relu(output)
        
        # 返回残差块的输出结果
        return output


#(3)多个残差块叠加
# 定义子类ResNet,继承父类keras.Model
class ResNet(keras.Model):
    
    # 初始化
    # layer_dims=[2,2,2,2],resnet18包含4个残差结构res_blocks,每个残差结构中有2个残差块
    # num_classes 代表最终的输出的分类数
    def __init__(self, layer_dims, num_classes=1000):  
        
        # 调用父类的初始化方法
        super(ResNet, self).__init__(self)
        
        # 分配属性
        # 原始图像输入的预处理卷积和池化
        self.stem = Sequential([layers.Conv2D(64, (7,7), strides=(2,2), padding='same'),  # 3*3卷积提取特征
                                layers.BatchNormalization(),      # 标准化 
                                layers.Activation('relu'),        # 激活函数
                                layers.MaxPool2D(pool_size=(3,3), strides=(2,2), padding='same')])  # 最大池化,输入图像的size减半
        
        # 创建4个残差结构,layer_dims=[2,2,2,2]
        self.layer1 = self.build_resblock(64, layer_dims[0])  # 第一个残差结构指定64个卷积核,包含2个残差块
        self.layer2 = self.build_resblock(128, layer_dims[1], strides=2)  # 第二个残差结构128个卷积核,包含2个残差块,步长为2,图像的size减半
        self.layer3 = self.build_resblock(256, layer_dims[2], strides=2)
        self.layer4 = self.build_resblock(512, layer_dims[3], strides=2)
        
        # 全局平均池化,不管卷积层输出的长和宽是多少,在channel维度上将所有的长和宽加起来取均值
        # [b, w, h, c] ==> [b,c]
        self.avgpool = layers.GlobalAveragePooling2D()

        # 全连接层用于图像分类
        self.fc = layers.Dense(num_classes)
        

    
    # 定义前向传播的类方法
    def call(self, inputs, training=None):
        
        # 原始输入经过预处理卷积层
        x = self.stem(inputs)
        
        # 经过4个残差结构
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        
        # 输出层
        x = self.avgpool(x)  # 输出shape[b,c]  
        x = self.fc(x)       # 输出[b,1000]
        
        # 返回分类结果
        return x
        
    
    # 利用单个已定义的残差块,叠加多个残差块
    # filter_num,代表当前图像的特征图个数
    # blocks,需要代表堆叠几个残差块
    # stride,代表当前的步长,等于1
    def build_resblock(self, filter_num, blocks, strides=1):
        
        # 使用Sequential容器装填网络结构
        res_blocks = Sequential()
        
        # 在ResNet类中对BasicBlock类实例化,构成组合关系
        # ResNet类可调用BasicBlock类中的所有属性和方法
        
        # 添加网络层
        # 第一个残差块有下采样功能,stride可能等于2
        res_blocks.add(BasicBlock(filter_num, strides))
        
        # 每个残差结构中剩余的残差块不具备下采样功能,stride=1
        for _ in range(1, blocks):
            
            # 残差结构中剩余的残差块保持图像的shape不变
            res_blocks.add(BasicBlock(filter_num, stride=1))
        
        # 返回构建的残差结构
        return res_blocks
        

# 构造resnet18,传入参数
def resnet18():
    # 实例化网络结构,一共有4个残差结构,每个残差结构由2个残差块组成
    return ResNet([2, 2, 2, 2]) 
        

# 构造resnet34,传入参数
def resnet34():
    # 实例化,一共有4个残差结构,每个残差结构有如下个数的残差单元
    return ResNet([3, 4, 6, 3])        
    

# 主函数
def main():
    
    # 构造网络resnet18
    model18 = resnet18() 
    # 确定输入层
    model18.build(input_shape=(None,224,224,3))
    # 查看网络结构
    model18.summary()
    
    
    # 构造网络resnet34
    model34 = resnet34()
    # 确定输入层
    model34.build(input_shape=(None,224,224,3))
    # 查看网络结构
    model34.summary()    

if __name__ == '__main__':
    
    main()

到了这里,关于【神经网络】(10) Resnet18、34 残差网络复现,附python完整代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深度学习技巧应用2-神经网络中的‘残差连接’

    大家好,我是微学AI,今天给大家介绍 深度学习技巧应用2-神经网络中的‘残差连接’。 一、残差连接介绍 残差连接 是一种神经网络中的一种运用技巧。由于深层网络容易出现梯度消失或梯度爆炸的问题,因此可以通过残差连接的方式,将网络的深度扩展到数十层以上,从

    2023年04月22日
    浏览(24)
  • 【深度学习随笔】神经网络中去掉残差连接的工作

    刚刚有个同学问我:“深层神经网络如果去掉一部分残差,到底还能不能正常训练呀?”这个问题着实很好,我也没思考过,也没尝试过,然后试着去Google Scholar检索了一下“without shorcut”,于是看到了以下的文章。让我比较惊奇的是,这是个很多人研究的方向,并且

    2024年02月15日
    浏览(43)
  • 现代卷积神经网络(ResNet)

    专栏:神经网络复现目录 本章介绍的是现代神经网络的结构和复现,包括深度卷积神经网络(AlexNet),VGG,NiN,GoogleNet,残差网络(ResNet),稠密连接网络(DenseNet)。 文章部分文字和代码来自《动手学深度学习》 残差网络(Residual Network,简称 ResNet)是由微软研究院于

    2024年02月07日
    浏览(31)
  • 62、python - 全手写搭建 resnet50 神经网络

    如果将上篇文章中涉及到的算法都自己手写完一遍后,我们开始尝试利用自己手写的算法,搭建一个完整的 resnet50 神经网络。 网络结构就参考这个链接中的网络结构,是在之前下载模型的章节中,下载的模型。 为了搭建一个完整的神经网络,定义一个 Resnet 的类,这个类就

    2024年01月24日
    浏览(33)
  • ResNet50卷积神经网络输出数据形参分析-笔记

    ResNet50卷积神经网络输出数据形参分析-笔记 ResNet50包含多个模块,其中第2到第5个模块分别包含3、4、6、3个残差块 50=49个卷积(3+4+6+3)*3+1和一个全连接层 分析结果为: 输入数据形状:[10, 3, 224, 224] 最后输出结果:linear_0 [10, 1] [2048, 1] [1] ResNet50包含多个模块,其中第2到第5个模

    2024年02月14日
    浏览(34)
  • MATLAB卷积神经网络——基于ResNet-50进行图像分类

    一、ResNet50工具箱安装 (1)下载工具箱 https://ww2.mathworks.cn/matlabcentral/fileexchange/64626-deep-learning-toolbox-model-for-resnet-50-network (2)在matlab打开下载的resnet50.mlpkginstall文件 (3)使用下面代码进行测试,出现结果说明安装成功 二、训练猫狗数据集 (1)数据集下载链接:    http

    2024年02月21日
    浏览(40)
  • 深度学习实战——卷积神经网络/CNN实践(LeNet、Resnet)

          忆如完整项目/代码详见github: https://github.com/yiru1225 (转载标明出处 勿白嫖 star for projects thanks) 本系列博客重点在深度学习相关实践(有问题欢迎在评论区讨论指出,或直接私信联系我)。 第一章  深度学习实战——不同方式的模型部署(CNN、Yolo)_如何部署cnn_

    2023年04月11日
    浏览(33)
  • FPGA上利用Vitis AI部署resnet50 TensorFlow神经网络模型

    参考Xilinx官方教程快速入门 • Vitis AI 用户指南 (UG1414) 克隆 Vitis AI 存储库以获取示例、参考代码和脚本(连接github失败可能需要科学上网)。 安装Docker如何在 Ubuntu 20.04 上安装和使用 Docker 安装完docker后,下载最新Vitis AI Docker, 将官方的指令 docker pull xilinx/vitis-ai-pytorch/tensorfl

    2024年02月04日
    浏览(36)
  • 人工智能(Pytorch)搭建模型6-使用Pytorch搭建卷积神经网络ResNet模型

    大家好,我是微学AI,今天给大家介绍一下人工智能(Pytorch)搭建模型6-使用Pytorch搭建卷积神经网络ResNet模型,在本文中,我们将学习如何使用PyTorch搭建卷积神经网络ResNet模型,并在生成的假数据上进行训练和测试。本文将涵盖这些内容:ResNet模型简介、ResNet模型结构、生成假

    2024年02月06日
    浏览(41)
  • 【AI】《动手学-深度学习-PyTorch版》笔记(十九):卷积神经网络模型(GoogLeNet、ResNet、DenseNet)

    发布时间:2014年 GoogLeNet的贡献是如何选择合适大小的卷积核,并将不同大小的卷积核组合使用。 之前介绍的网络结构都是串行的,GoogLeNet使用并行的网络块,称为“Inception块” “Inception块”前后进化了四次,论文链接: [1]https://arxiv.org/pdf/1409.4842.pdf [2]https://arxiv.org/pdf/150

    2024年02月12日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包