八、ResNet的网络结构及其代码实现(花的三分类)
目录
- 前文
- 数据生成器+数据部分展示
- 构建ResNet模型
- 首先构建残差学习模块之前的网络结构。
- 接着构建残差学习模块,其中利用循环的方法进行构建完整的ResNet_50网络结构。
- conv2——x
- conv3——x
- conv4——x
- conv5——x
- ResNet模型构建完成
- ResNet模型编译
- ResNet 模型拟合
- GitHub下载地址:
前文
数据生成器+数据部分展示
# 读取数据
#利用ImageDataGenerator构造数据生成器
from keras.preprocessing.image import ImageDataGenerator
IMSIZE = 224
# 根据花的图片数据,构造训练集数据生成器和验证集数据生成器
train_generator = ImageDataGenerator(rescale=1. / 255).flow_from_directory('../../data/data_res/train',
target_size=(IMSIZE, IMSIZE),
batch_size=5,
class_mode='categorical'
)
validation_generator = ImageDataGenerator(rescale=1. / 255).flow_from_directory('../../data/data_res/validation',
target_size=(IMSIZE, IMSIZE),
batch_size=5,
class_mode='categorical')
#显示数据
from matplotlib import pyplot as plt
plt.figure()
fig, ax = plt.subplots(2, 5)
fig.set_figheight(7)
fig.set_figwidth(15)
ax = ax.flatten()
X, Y = next(train_generator)
for i in range(10): ax[i].imshow(X[i, :, :, :])
构建ResNet模型
首先构建残差学习模块之前的网络结构。
# 构建模型。
from keras.layers import Dense, Flatten
from keras.layers import Input
from keras.layers import Activation, Conv2D, BatchNormalization, add, MaxPooling2D, AveragePooling2D
from keras import Model
NB_CLASS = 3
IM_WIDTH = 224
IM_HEIGHT = 224
input_shape = Input(shape=(IM_WIDTH, IM_HEIGHT, 3))
x = Conv2D(64, (7, 7), padding='same', strides=(2, 2), activation='relu')(input_shape)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding='same')(x)
x0 = x
x0
接着构建残差学习模块,其中利用循环的方法进行构建完整的ResNet_50网络结构。
conv2——x
# 一个block,第一个block里面需要更改步长
for i in range(3):
x = Conv2D(64, (1, 1), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(64, (3, 3), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(256, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
#下面两步为了把输入64通道的数据转换为256个通道,用来让x0和x维数相同
#可以进行加法计算,文章中虚线得得部分
x0 = Conv2D(256, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x0 = BatchNormalization()(x0)
#add把输入的x和经过一个block之后输出的结果加在一起
x = add([x, x0])
#求和之后的结果再做一次relu
x = Activation('relu')(x)
x0 = x
x0
conv3——x
#第一个block
x = Conv2D(128, (1, 1), padding='same', strides=(2, 2), activation='relu')(x0)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(128, (3, 3), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(512, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x1 = Conv2D(512, (1, 1), padding='same', strides=(2, 2), activation=None)(x0)
x1 = BatchNormalization()(x1)
#一个卷积层加一个batch normalization
#add把输入的x和经过一个block之后输出的结果加在一起
x = add([x, x1])
#求和之后的结果再做一次relu
x = Activation('relu')(x)
#把输入存到另外一个变量中
x1 = x
x1
#第2-4个block
for i in range(3):
x = Conv2D(128, (1, 1), padding='same', strides=(1, 1), activation='relu')(x1)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(128, (3, 3), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(512, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
#下面两步为了把输入64通道的数据转换为256个通道,用来让x0和x维数相同
#可以进行加法计算,文章中虚线得得部分
#可以不用
#x1 = Conv2D(256, (1, 1), padding='same', strides=(1, 1), activation=None)(x1)
#x1 = BatchNormalization()(x1)
#add把输入的x和经过一个block之后输出的结果加在一起
x = add([x, x1])
#求和之后的结果再做一次relu
x = Activation('relu')(x)
#把输入存到另外一个变量中
x1 = x
x1
conv4——x
#conv4——x
#第一个block
x = Conv2D(256, (1, 1), padding='same', strides=(2, 2), activation='relu')(x1)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(256, (3, 3), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(1024, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x2 = Conv2D(1024, (1, 1), padding='same', strides=(2, 2), activation=None)(x1)
x2 = BatchNormalization()(x2)
#一个卷积层加一个batch normalization
#add把输入的x和经过一个block之后输出的结果加在一起
x = add([x, x2])
#求和之后的结果再做一次relu
x = Activation('relu')(x)
#把输入存到另外一个变量中
x2 = x
x2
#第2-6个block
for i in range(5):
x = Conv2D(256, (1, 1), padding='same', strides=(1, 1), activation='relu')(x2)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(256, (3, 3), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(1024, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
#下面两步为了把输入64通道的数据转换为256个通道,用来让x0和x维数相同
#可以进行加法计算,文章中虚线得得部分
#可以不用
#x2 = Conv2D(256, (1, 1), padding='same', strides=(1, 1), activation=None)(x2)
#x2 = BatchNormalization()(x2)
#add把输入的x和经过一个block之后输出的结果加在一起
x = add([x, x2])
#求和之后的结果再做一次relu
x = Activation('relu')(x)
#把输入存到另外一个变量中
x2 = x
x2
conv5——x
#conv5——x
#第一个block
x = Conv2D(512, (1, 1), padding='same', strides=(2, 2), activation='relu')(x2)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(512, (3, 3), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(2048, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x3 = Conv2D(2048, (1, 1), padding='same', strides=(2, 2), activation=None)(x2)
x3 = BatchNormalization()(x3)
#一个卷积层加一个batch normalization
#add把输入的x和经过一个block之后输出的结果加在一起
x = add([x, x3])
#求和之后的结果再做一次relu
x = Activation('relu')(x)
#把输入存到另外一个变量中
x3 = x
x3
#第2-6个block
for i in range(2):
x = Conv2D(512, (1, 1), padding='same', strides=(1, 1), activation='relu')(x3)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(512, (3, 3), padding='same', strides=(1, 1), activation='relu')(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
x = Conv2D(2048, (1, 1), padding='same', strides=(1, 1), activation=None)(x)
x = BatchNormalization()(x)
#一个卷积层加一个batch normalization
#下面两步为了把输入64通道的数据转换为256个通道,用来让x0和x维数相同
#可以进行加法计算,文章中虚线得得部分
#可以不用
#x3 = Conv2D(256, (1, 1), padding='same', strides=(1, 1), activation=None)(x3)
#x3 = BatchNormalization()(x3)
#add把输入的x和经过一个block之后输出的结果加在一起
x = add([x, x3])
#求和之后的结果再做一次relu
x = Activation('relu')(x)
#把输入存到另外一个变量中
x3 = x
x3
ResNet模型构建完成
#在reset最后的部分添加一个dense层,并输出一个二维的结果用来分类
x = x3
x = AveragePooling2D(pool_size=(7, 7), padding="same")(x)
x = Flatten()(x)
predictions = Dense(NB_CLASS, activation='softmax')(x)
model_res = Model(inputs=input_shape, outputs=predictions)
model_res.summary()
ResNet模型编译
# 模型编译。利用compile函数实现。
from keras.optimizers import Adam
model_res.compile(loss='categorical_crossentropy', optimizer=Adam(lr=0.001), metrics=['accuracy'])
ResNet 模型拟合
#模型拟合。利用fit_generator进行拟合,并观察循环过程中,参数的变化。
model_res.fit_generator(train_generator,
steps_per_epoch=100,
epochs=5,
validation_data=validation_generator,
validation_steps=100)
GitHub下载地址:
Tensorflow1.15深度学习