keras实现goolenet模型的训练
#导出需要的库
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.keras import regularizers
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Input, Flatten, Dense, Dropout, BatchNormalization
from tensorflow.keras.layers import Conv2D, MaxPooling2D, AveragePooling2D, ZeroPadding2D
from tensorflow.keras.layers import Concatenate
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import Adam, SGD
#定义参数
#类别数目
CLASS_NUM = 5
# 每次喂入神经网络的数据个数
BATCH_SIZE = 16
#把所有数据训练一遍需要的步数
EPOCH_STEPS = int(4323/BATCH_SIZE)
#喂入神经网络需要的维度
IMAGE_SHAPE = (224, 224, 3)
#训练数据文件路径
IMAGE_TRAIN = './Dataset/Flowers'
#保存模型的名称
MODEL_NAME = 'googlenet_flower.h5'
# 准备数据
#数据增强
train_datagen = ImageDataGenerator(
rescale=1./255,#对图像进行缩放
rotation_range=30,#旋转角度
width_shift_range=0.2,#水平平移,相对总宽度的比例
height_shift_range=0.2,#垂直平移,相对总高度的比例
shear_range=0.2,#随机错切换角度
zoom_range=0.2,#随机缩放范围
horizontal_flip=True#水平翻转
)
#从训练数据文件中按批次读取数据
generator_main = train_datagen.flow_from_directory(
IMAGE_TRAIN,#训练数据文件
target_size=(IMAGE_SHAPE[0], IMAGE_SHAPE[1]),#模型需要的尺度
batch_size=BATCH_SIZE,#批次大小
class_mode='categorical'#类别模式选择
)
#数据生成器,从generator中批次取出数据与标签
def my_generator(generator):
while True:
data = next(generator)#生成(x_train, y_label
x = data[0]#训练数据
y = data[1]#对应标签
yield x, y
#给定generator,调用生成器
train_generator = my_generator(generator_main)
# 创建模型
def inception(x, filters):
# 1x1
path1 = Conv2D(filters=filters[0], kernel_size=(1,1), strides=1, padding='same', activation='relu')(x)
# 1x1->3x3
path2 = Conv2D(filters=filters[1][0], kernel_size=(1,1), strides=1, padding='same', activation='relu')(x)
path2 = Conv2D(filters=filters[1][1], kernel_size=(3,3), strides=1, padding='same', activation='relu')(path2)
# 1x1->5x5
path3 = Conv2D(filters=filters[2][0], kernel_size=(1,1), strides=1, padding='same', activation='relu')(x)
path3 = Conv2D(filters=filters[2][1], kernel_size=(5,5), strides=1, padding='same', activation='relu')(path3)
# 3x3->1x1
path4 = MaxPooling2D(pool_size=(3,3), strides=1, padding='same')(x)
path4 = Conv2D(filters=filters[3], kernel_size=(1,1), strides=1, padding='same', activation='relu')(path4)
return Concatenate(axis=-1)([path1,path2,path3,path4])
def auxiliary(x, name=None):
layer = AveragePooling2D(pool_size=(5,5), strides=3, padding='valid')(x)
layer = Conv2D(filters=128, kernel_size=(1,1), strides=1, padding='same', activation='relu')(layer)
layer = Flatten()(layer)
layer = Dense(units=256, activation='relu')(layer)
layer = Dropout(0.4)(layer)
layer = Dense(units=CLASS_NUM, activation='softmax', name=name)(layer)
return layer
def googlenet():
layer_in = Input(shape=IMAGE_SHAPE)
# stage-1
layer = Conv2D(filters=64, kernel_size=(7,7), strides=2, padding='same', activation='relu')(layer_in)
layer = MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(layer)
layer = BatchNormalization()(layer)
# stage-2
layer = Conv2D(filters=64, kernel_size=(1,1), strides=1, padding='same', activation='relu')(layer)
layer = Conv2D(filters=192, kernel_size=(3,3), strides=1, padding='same', activation='relu')(layer)
layer = BatchNormalization()(layer)
layer = MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(layer)
# stage-3
layer = inception(layer, [ 64, (96,128), (16,32), 32]) #3a
layer = inception(layer, [128, (128,192), (32,96), 64]) #3b
layer = MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(layer)
# stage-4
layer = inception(layer, [192, (96,208), (16,48), 64]) #4a
aux1 = auxiliary(layer, name='aux1')
layer = inception(layer, [160, (112,224), (24,64), 64]) #4b
layer = inception(layer, [128, (128,256), (24,64), 64]) #4c
layer = inception(layer, [112, (144,288), (32,64), 64]) #4d
aux2 = auxiliary(layer, name='aux2')
layer = inception(layer, [256, (160,320), (32,128), 128]) #4e
layer = MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(layer)
# stage-5
layer = inception(layer, [256, (160,320), (32,128), 128]) #5a
layer = inception(layer, [384, (192,384), (48,128), 128]) #5b
layer = AveragePooling2D(pool_size=(7,7), strides=1, padding='valid')(layer)
# stage-6
layer = Flatten()(layer)
layer = Dropout(0.4)(layer)
layer = Dense(units=256, activation='linear')(layer)
main = Dense(units=CLASS_NUM, activation='softmax', name='main')(layer)
model = Model(inputs=layer_in, outputs=[main, aux1, aux2])
return model
#模型训练
model = googlenet()
#模型日志开启
model.summary()
#优化器选择
optimizer = ['Adam', 'SGD', 'Adam', 'SGD']
#轮次与对应的优化器
epochs = [20, 30, 20, 30]
history_all = {}
for i in range(len(optimizer)):
print('Usnig optimizer: ' + optimizer[i] + ', Epoch: ' + str(epochs[i]))
#编译模型。给额外的损失赋0.3,0.3的权重。
#可以通过关键字参数loss_weights或loss来为不同的输出设置不同的损失函数或权值。
model.compile(loss='categorical_crossentropy',
loss_weights={'main': 1.0, 'aux1': 0.3, 'aux2': 0.3},
optimizer=optimizer[i], metrics=['accuracy'])
#编译完成后,传递训练数据和目标值训练该模型
train_history = model.fit_generator(
train_generator,
steps_per_epoch=EPOCH_STEPS,
epochs=epochs[i],
#callbacks=[checkpoint]
shuffle=True
)
#保存日志
if len(history_all) == 0:
history_all = {key: [] for key in train_history.history}
for key in history_all:
history_all[key].extend(train_history.history[key])
model.save(MODEL_NAME)
#可视化日志信息
def show_train_history(history, xlabel, ylabel, train):
for item in train:
plt.plot(history[item])
plt.title('Train History')
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.legend(train, loc='upper left')
plt.show()
show_train_history(history_all, 'Epoch', 'Accuracy', ('main_acc', 'aux1_acc', 'aux2_acc'))
show_train_history(history_all, 'Epoch', 'Loss', ('main_loss', 'aux1_loss', 'aux2_loss'))