摘要
-
ResNet152V2
1.1 来源
1.2 架构
1.3 特性 -
训练过程
2.1 预训练模型
2.2 设置Callbacks
2.3 设置训练集
2.4 开始训练模型
2.5 储存模型与纪录学习曲线 -
模型训练结果
3.1 学习曲线
3.2 Accuracy与Loss -
验证模型准确度
4.1 程序码
4.2 验证结果
内容
-
ResNet152V2
1.1 来源:
- 简介:网路结构的深度,与影像识别效果关系密切。然而随着网路加到极深,模型准确度却提升有限。故ResNet引入residual learning的概念,尝试解决训练过程中梯度弥散的现象。
※ 注:梯度弥散的详细解释可参考此处 - 时程:於2015年提出深度残差网路概念,并於2016年发表论文,同年收录在CVPR。
- 论文名称:Deep Residual Learning for Image Recognition
1.2 架构
-
Resnet34:Residual Block
- 启发:比较34层卷积网路(VGG19)与34层残差网路。
※ 注:详细架构图请参考论文Page4 Figure3
- Residual Block
-
ResNet50/101/152:Bottleneck Block
-
参照Inception module的概念,将3 * 3卷积拆分成两个1 * 1与一个3 * 3卷积,减少模型参数量。後续在增加模型深度的同时,不会增加过多的运算量。
-
Inception module
-
ResNet50/101/152
-
1.3 特性
-
ResNet的残差直连通路,在训练过程中不容易梯度弥散,使极深层的网路结构更容易收敛。
-
模型稳定性佳,可透过堆叠的方式加深网路,论文中作者探索在1000层以下,影像识别效果会随着网路加深,提升模型表现。而超过1000层(1202层),可能训练效率低下或发生Overfitting情况,降低模型效能。
-
观察VGG NET与达到Residual Net在ImageNet上的表现,Residual Net优於VGG Net,且复杂度明显低於VGG Net。
- 简介:网路结构的深度,与影像识别效果关系密切。然而随着网路加到极深,模型准确度却提升有限。故ResNet引入residual learning的概念,尝试解决训练过程中梯度弥散的现象。
-
训练过程:
2.1 预训练模型
# IMPORT MODULES from keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau from keras.layers import Input, Dense, GlobalAveragePooling2D from keras.preprocessing.image import ImageDataGenerator from keras.optimizers import Adam import matplotlib.pyplot as plt from keras.models import Model from keras.applications import ResNet152V2 # -----------------------------1.客制化模型-------------------------------- # 载入keras模型(更换输出图片尺寸) model = ResNet152V2(include_top=False, weights='imagenet', input_tensor=Input(shape=(80, 80, 3)) ) # 定义输出层 x = model.output x = GlobalAveragePooling2D()(x) predictions = Dense(800, activation='softmax')(x) model = Model(inputs=model.input, outputs=predictions) # 编译模型 model.compile(optimizer=Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
2.2 设置Callbacks
# ---------------------------2.设置callbacks---------------------------- # 设定earlystop条件 estop = EarlyStopping(monitor='val_loss', patience=10, mode='min', verbose=1) # 设定模型储存条件 checkpoint = ModelCheckpoint('ResNet152V2_checkpoint_v1.h5', verbose=1, monitor='val_loss', save_best_only=True, mode='min') # 设定lr降低条件(0.001 → 0.0002 → 0.00004 → 0.00001) reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, mode='min', verbose=1, min_lr=1e-5)
2.3 设置训练集
# -----------------------------3.设置资料集-------------------------------- # 设定ImageDataGenerator参数(路径、批量、图片尺寸) train_dir = './workout/train/' valid_dir = './workout/val/' test_dir = './workout/test/' batch_size = 64 target_size = (80, 80) # 设定批量生成器 train_datagen = ImageDataGenerator(rescale=1./255, rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.5, fill_mode="nearest") val_datagen = ImageDataGenerator(rescale=1./255) test_datagen = ImageDataGenerator(rescale=1./255) # 读取资料集+批量生成器,产生每epoch训练样本 train_generator = train_datagen.flow_from_directory(train_dir, target_size=target_size, batch_size=batch_size) valid_generator = val_datagen.flow_from_directory(valid_dir, target_size=target_size, batch_size=batch_size) test_generator = test_datagen.flow_from_directory(test_dir, target_size=target_size, batch_size=batch_size, shuffle=False)
2.4 重新训练模型权重
# -----------------------------4.开始训练模型------------------------------ # 重新训练权重 history = model.fit_generator(train_generator, epochs=50, verbose=1, steps_per_epoch=train_generator.samples//batch_size, validation_data=valid_generator, validation_steps=valid_generator.samples//batch_size, callbacks=[checkpoint, estop, reduce_lr])
2.5 储存模型与纪录学习曲线
# -----------------------5.储存模型、纪录学习曲线------------------------ # 储存模型 model.save('./ResNet152V2_retrained_v1.h5') print('已储存ResNet152V2_retrained_v1.h5') # 画出acc学习曲线 acc = history.history['accuracy'] epochs = range(1, len(acc) + 1) val_acc = history.history['val_accuracy'] plt.plot(epochs, acc, 'bo', label='Training acc') plt.plot(epochs, val_acc, 'r', label='Validation acc') plt.title('Training and validation accuracy') plt.legend(loc='lower right') plt.grid() # 储存acc学习曲线 plt.savefig('./acc.png') plt.show() # 画出loss学习曲线 loss = history.history['loss'] val_loss = history.history['val_loss'] plt.plot(epochs, loss, 'bo', label='Training loss') plt.plot(epochs, val_loss, 'r', label='Validation loss') plt.title('Training and validation loss') plt.legend(loc='upper right') plt.grid() # 储存loss学习曲线 plt.savefig('loss.png') plt.show()
-
模型训练结果
3.1 训练epochs:31 epochs。
3.2 耗费时间:4小时17分32秒(15452秒)。
3.3 学习曲线
3.4 Accuary与Loss
-
验证准确度
4.1 程序码
# -------------------------6.验证模型准确度-------------------------- # 以vali资料夹验证模型准确度 test_loss, test_acc = model.evaluate_generator(test_generator, steps=test_generator.samples//batch_size, verbose=1) print('test acc:', test_acc) print('test loss:', test_loss)
4.2 验证结果
小结
- ResNet为深度学习带来新的启发,现在许多主流模型都采Residual learning概念。
- 下一章目标是:介绍第三个预训练模型DenseNet201,与分享训练成果」。
让我们继续看下去...
参考资料
- Deep Residual Learning for Image Recognition
- Residual Leaning: 认识ResNet与他的冠名後继者ResNeXt、ResNeSt
- Identity Mappings in Deep Residual Networks
- [论文] Deep Residual Learning for Image Recognition
- 梯度弥散与梯度爆炸