用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 。具体网络结构如下图:
tensorflow2.x --------------------DenseNet------------------------------LMLPHP
具体代码如下:

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.c1=Conv2D(filters=filters,kernel_size=(7,7),strides=2)
        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.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()


11-20 06:37