基于Tensorflow2的DenseNet网络搭建

本文会通过两部分来介绍DenseNet网络:DenseNet网络论文的介绍和代码的实现。

    • DenseNet网络介绍

下图是DenseNet的论文中的基本组成部分,如图一所示:

图一:DenseNet网络结构

DenseNet网络结构主要是由Dense Block部分和Convolution、Pooling组成的Transition Layer 这两部分组成。图一中使用了三个Dense Block模块组成了DenseNet网络,本文中代码是采用了四个Dense Block模块,有一点点区别。也就是在图一Prediction前面再加上一组模块 Dense Block和Transition Layer组成四个个DenseNet网络。

1.1 Dense Block 模块介绍

下图是Dense Block模块,如图二所示:

图二:Dense Block模块

图二中Dense Block模块结构是论文中所提到的5层结构,Dense Block中结构的层数是可以自己自定义的,并不是说只能用图二中这样的。具体效果还是要看自己训练后的模型,对应效果。先来说说每一层的结构,第一层Dense Block 输入input层和其他几层有些不同,这里到后面后介绍一下。Dense Block模块中每一层的结构都是有1*1卷积+3*3卷积构成,如下图三所示。

图三:Dense Block结构

图中每个在进行卷积前都要通过BN+RELU处理,也就构成了BN+RELU+CONV的结构,每个卷积对应的filters是固定的(1*1卷积是4K  3*3的是K),每个Dense Block中的都是一样的。在这里有系数k确定,论文中作者给出的是K=32,在论文开始部分三层结构中k=4,也有k=12。也是可以自定义的,看网络效果。我这里程序里使用的k是32。

1.2 Transition Layer 模块介绍

Transition Layer模块由两部分组成1*1卷积和average pool层组成,这里1*1卷积的filter为k,不是上文所提出的4*k,如下图四所示(1*1卷积前面也要bn+relu)。

图四: Transition Layer 结构

接下来是论文中用于imagenet数据集上的结构图,如图五所示。

图五: DenseNet 4种结构

关于图中例如DenseNet-121中 这边的数字 121 169 201 264是网络结构的层数,Dense Block后面1*1卷积和6*6卷积后面×6 说明是用了 6组Dense Block结构。后面x12就代表了用了12组Dense Block结构。

在刚开始,输入图片进行处理的通过7*7卷积还有3*3的max pooling,其中7*7卷积的filter是2k个也就是64,在k=32的时候。使用前也有进行 BN+RELU处理

    • DenseNet 代码

第一部分需要的配置文件

from tensorflow.keras import layers, models, Input
from keras.layers import Conv2D, BatchNormalization, Activation, ZeroPadding2D, AveragePooling2D, MaxPooling2D, Dense
from tensorflow.keras.preprocessing.image import ImageDataGenerator

第二部分代码是关于Dense Block的代码

def DenseConv(featuremap,h):  #h为k也就是filter的
    x = BatchNormalization()(featuremap)
    x = Activation('relu')(x)
    x = Conv2D(filters=4*h, kernel_size=(1, 1), strides=1, padding='same')(x)

    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(filters=h, kernel_size=(3, 3), strides=1, padding='same')(x)
    return x

# 这里部分是1*1卷积和 3*3卷积


def DenseNet1(input_x, f_filters, number1):
    hyj = []
    hyj.append(input_x)
    for i in range(number1):
        x = DenseConv(input_x, f_filters)
        hyj.append(x)
        input_x = layers.concatenate(hyj)
    return input_x

第三部分是关于Transition Layer的代码

def Transition(input_x):
    x = BatchNormalization()(input_x)
    x = Activation('relu')(x)
    x = Conv2D(filters=32, kernel_size=(1, 1), strides=1)(x)
    x = layers.AveragePooling2D(pool_size=(2, 2), strides=2)(x)
    return x

第四部分是网络结构的代码DenseNet-121

def DenseNet_net(input_y):
    x = BatchNormalization()(input_y)
    x = Activation('relu')(x)
    x = Conv2D(64, (7, 7), strides=2, padding='same')(x)
    x = MaxPooling2D(pool_size=[3, 3], strides=2, padding='same')(x)
    x = DenseNet1(x, 32, 6)
    x = Transition(x)
    x = DenseNet1(x, 32, 12)
    x = Transition(x)
    x = DenseNet1(x, 32, 24)
    x = Transition(x)
    x = DenseNet1(x, 32, 16)
    x = layers.GlobalAveragePooling2D()(x)
    x = layers.Dense(5, activation='softmax')(x)   #这里数字5对应的是你要分类物品的种类 比如我这是5种列别的花就是5
    return x

总代码


from tensorflow.keras import layers, models, Input
from keras.layers import Conv2D, BatchNormalization, Activation, ZeroPadding2D, AveragePooling2D, MaxPooling2D, Dense
from tensorflow.keras.preprocessing.image import ImageDataGenerator



def DenseConv(featuremap,h):
    x = BatchNormalization()(featuremap)
    x = Activation('relu')(x)
    x = Conv2D(filters=4*h, kernel_size=(1, 1), strides=1, padding='same')(x)

    x = BatchNormalization()(x)
    x = Activation('relu')(x)
    x = Conv2D(filters=h, kernel_size=(3, 3), strides=1, padding='same')(x)
    return x


def DenseNet1(input_x, f_filters, number1):
    hyj = []
    hyj.append(input_x)
    for i in range(number1):
        x = DenseConv(input_x, f_filters)
        hyj.append(x)
        input_x = layers.concatenate(hyj)
    return input_x


def Transition(input_x):
    x = BatchNormalization()(input_x)
    x = Activation('relu')(x)
    x = Conv2D(filters=32, kernel_size=(1, 1), strides=1)(x)
    x = layers.AveragePooling2D(pool_size=(2, 2), strides=2)(x)
    return x



def DenseNet_net(input_y):
    x = BatchNormalization()(input_y)
    x = Activation('relu')(x)
    x = Conv2D(64, (7, 7), strides=2, padding='same')(x)
    x = MaxPooling2D(pool_size=[3, 3], strides=2, padding='same')(x)
    x = DenseNet1(x, 32, 6)
    x = Transition(x)
    x = DenseNet1(x, 32, 12)
    x = Transition(x)
    x = DenseNet1(x, 32, 24)
    x = Transition(x)
    x = DenseNet1(x, 32, 16)
    x = layers.GlobalAveragePooling2D()(x)
    x = layers.Dense(5, activation='softmax')(x)  #训练自己数据集的时候5要修改改成对应的物品种类
    return x



#下面的代码是用来训练的(分类任务)  如果用自己的数据的话只需要改一下三个地方就行 
train_datagen = ImageDataGenerator(rescale=1./255,
                                   rotation_range=40,
                                   width_shift_range=0.2,
                                   height_shift_range=0.2,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   brightness_range=(0.6, 1.2),
                                   horizontal_flip=True)
valid_datagen = ImageDataGenerator(rescale=1./255)


train_generator = train_datagen.flow_from_directory(
    directory='flowe2-set/train', # 你的数据训练集的位置
    target_size=(224, 224),
    batch_size=10                 #这个大小根据你数据集和显卡显存大小来修改 比如我训练集3000个 那么batch_size*steps_per_epoch最好等于3000 steps_per_epoch这个在下面history里面修改
)
valid_generator = valid_datagen.flow_from_directory(
    directory='flowe2-set/valid', #验证集的位置
    target_size=(224, 224),
    batch_size=10    #同上validation_steps*batch_size
)



input_shape = Input([224, 224, 3])
#input_tensor = Input(shape=(224,224,3))
k = DenseNet_net(input_shape)
model = models.Model(inputs=input_shape, outputs=k)

model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',   #这个loss有问题 所以才会报错 一般报错是[[{{node PyFunc}}]] 改成categorical_crossentropy 就好 如果报错的话
    metrics=['accuracy']
)
history = model.fit_generator(
    train_generator,
    steps_per_epoch=300,
    epochs=50,
    validation_data=valid_generator,
    validation_steps=74,
    verbose=1

)



  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值