深度学习之路=====6=====>>DenseNet(tensorflow2)

用tensorflow2.4实现了DenseNet-121,训练基于ImageNet图像数据集,图片输入大小为 224x224 。网络结构采用包含4个DenseBlock的DenseNet-BC,每个DenseNet-BC由若干个 BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv(Dense_layer)且每个DenseBlock的特征图大小分别为56,28,14,7,DenseNet中每个DenseBlock分别有 [6,12,24,16] 个Dense_layer,在每个DenseBlock后连接Transition module,Transition module 包括一个1x1的卷积和2x2的AveragePooling,具体结构为BN+ReLU+1x1 Conv+2x2 AveragePooling,Transition module层还可以起到压缩模型的作用,假定Transition module的上层DenseBlock得到的特征图channels数为 m ,Transition层可以产生m*n个channels,其中 n 是压缩系数(compression rate)。当 n=1 时,channelss数经过Transition层没有变化,即没有压缩模型,文中使用n=0.5 。具体网络结构如下图:
在这里插入图片描述
这里需要注意一点的是:DenseNet网络层中的第一个卷积层的填充步长为3,即在行和列各填充3行,padding参数只有’same’和‘valid’,所以需要单独对输入值进行填充,使用tensorflow.keras.layers中的ZeroPadding2D()对输入进行单独填充处理。具体使用下面命令:

self.padding=ZeroPadding2D(((2,1),(2,1)))

这一点可以通过输入输出尺寸公式得到验证。
具体代码如下:

import tensorflow as tf
import numpy as np
import os
from tensorflow.keras.layers import *
from tensorflow.keras import Model
class  DenseLayer(Model):
    def __init__(self,bottleneck_size,growth_rate):
        super().__init__()
        self.filters=growth_rate
        self.bottleneck_size=bottleneck_size
        self.b1=BatchNormalization()
        self.a1=Activation('relu')
        self.c1=Conv2D(filters=self.bottleneck_size,kernel_size=(1,1),strides=1)
        self.b2=BatchNormalization()
        self.a2=Activation('relu')
        self.c2=Conv2D(filters=32,kernel_size=(3,3),strides=1,padding='same')
    def call(self,*x):
        x=tf.concat(x,2)
        x=self.b1(x)
        x=self.a1(x)
        x=self.c1(x)
        x=self.b2(x)
        x=self.a2(x)
        y=self.c2(x)    
        return y
class DenseBlock(Model):
    def __init__(self,Dense_layers_num,growth_rate):#Dense_layers_num每个denseblock中的denselayer数,growth
        super().__init__()
        self.Dense_layers_num=Dense_layers_num
        self.Dense_layers=[]
        bottleneck_size=4*growth_rate
        for i in range(Dense_layers_num):
            layer=DenseLayer(bottleneck_size,growth_rate)
            self.Dense_layers.append(layer)
    def call(self,input):
        x=[input]
        for layer in self.Dense_layers:
            output=layer(*x)
            x.append(output)
        y=tf.concat(x,2)
        return y
class Transition(Model):
    def __init__(self,filters):
        super().__init__()
        self.b=BatchNormalization()
        self.a=Activation('relu')
        self.c=Conv2D(filters=filters,kernel_size=(1,1),strides=1)
        self.p=AveragePooling2D(pool_size=(2,2),strides=2)
        
    def call(self,x):
        x=self.b(x)
        x=self.a(x)
        x=self.c(x)
        y=self.p(x)
        return y 
class DenseNet(Model):
    def __init__(self,block_list=[6,12,24,16],compression_rate=0.5,filters=64):
        super().__init__()
        growth_rate=32
        self.padding=ZeroPadding2D(((1,2),(1,2)))
        self.c1=Conv2D(filters=filters,kernel_size=(7,7),strides=2,padding='valid')
        self.b1=BatchNormalization()
        self.a1=Activation('relu')
        self.p1=MaxPooling2D(pool_size=(3,3),strides=2,padding='same')
        self.blocks=tf.keras.models.Sequential()
        input_channel=filters
        for i,layers_in_block in enumerate(block_list):
            if i<3 :
                self.blocks.add(DenseBlock(layers_in_block,growth_rate))
                block_out_channels=input_channel+layers_in_block*growth_rate
                self.blocks.add(Transition(filters=block_out_channels*0.5))
            if i==3:
                self.blocks.add(DenseBlock(Dense_layers_num=layers_in_block,growth_rate=growth_rate))
        self.p2=GlobalAveragePooling2D()
        self.d2=Dense(1000,activation='softmax') 
    def call(self,x):
        x=self.padding(x)
        x=self.c1(x)
        x=self.b1(x)
        x=self.a1(x)
        x=self.p1(x)
        x=self.blocks(x)
        x=self.p2(x)
        y=self.d2(x)
        return y
model=DenseNet()


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值