【第18天】训练模型-InceptionResNetV2

摘要

  1. InceptionResNetV2

    1.1 来源
    1.2 架构
    1.3 特性

  2. 训练过程

    2.1 预训练模型
    2.2 设置Callbacks
    2.3 设置训练集
    2.4 开始训练模型
    2.5 储存模型与纪录学习曲线

  3. 模型训练结果

    3.1 学习曲线
    3.2 Accuracy与Loss

  4. 验证模型准确度

    4.1 程序码
    4.2 验证结果


内容

  1. InceptionResNetV2

    1.1 来源

    • 简介:
      • ResNet提出的残差直连通路,可透过堆叠的方式加深网路,提升模型表现。
      • 故InceptionResNetV2结合了Inception Module与残差直连通路,设计新的Inception-ResNet-A、B、C,期望透过加深网路,获得更好的模型准确度。
    • 时程:ResNet於2016年提出,同年,结合InceptionV3与ResNet发表了3个新模型。
    • 论文名称:Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning

    1.2 架构

    • 完整架构:

      图片来自於:http://yeephycho.github.io/2016/08/31/A-reminder-of-algorithms-in-Convolutional-Neural-Networks-and-their-influences-III/

    • Stem:与InceptionV4中Stem相同。

    • Inception-ResNet:

      • 使用不对称卷积层
      • 使用1 * 1卷积层降低维度(下图-A处)或统一维度(下图-B处)。
      • Inception-ResNet-A
      • Inception-ResNet-B
      • Inception-ResNet-C
    • Reduction:缓慢地降低特徵图的尺寸,避免特徵信息流失。

      • Reduction-A:
      • Reduction-A与InceptionV4中Reduction-A结构相同,仅参数数量不同。(如下表)
      • Reduction-B:
    • Activation scaling

      • 原因:使用Inception-ResNet时,若filter数量超过1000个,会出现网路不稳定的现象。
      • 方法:在Inception-ResNet使用element-wise Addition(残差值相加)前,先经过Activation Scaling缩小残差,能改善网路不稳定的现象。
      • Activation Scaling系数:论文中建议将缩放系数设定在0.1~0.3。

    1.3 特性

    • 引入残差直连概念到Inception架构,Inception架构的模型训练速度显着提升。
    • InceptionResNetV2使用极深的网路架构时,遭遇梯度弥散的可能性降低,模型更容易收敛。
  2. 训练过程:

    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 InceptionResNetV2
    
    # -----------------------------1.客制化模型--------------------------------
    # 载入keras模型(更换输出图片尺寸)
    model = InceptionResNetV2(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('InceptionResNetV2_checkpoint_v2.h5', verbose=1,
                              monitor='val_loss', save_best_only=True,
                              mode='min')
    
    # 设定lr降低条件(0.001 → 0.0005 → 0.00025 → 0.000125 → 0.0001)
    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('./InceptionResNetV2_retrained_v2.h5')
    print('已储存InceptionResNetV2_retrained_v2.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. 模型训练结果

    3.1 训练epochs:30 epochs。

    3.2 耗费时间:2小时48分47秒(10127秒)。

    3.3 学习曲线

    3.4 Accuary与Loss

  4. 验证准确度

    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 验证结果


小结

下一章,预计和大家分享模型验证方法,并比较五个预训练模型迁移学习的成果。

让我们继续看下去...


参考资料

  1. Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning
  2. Inception 系列 — InceptionV4, Inception-ResNet-v1, Inception-ResNet-v2
  3. InceptionV4与Inception-ResNet-v2架构图比较

<<:  Day18 React-Router(三)路由跳转

>>:  [Q&A] 03 资安健诊/弱点检测报告不被重视

Fluentd Bit

在 Fluentd Bit 中可以使用 read 或 socket 方式处理日志 read 用於读容...

大共享时代系列_021_远端桌面软件(远端连线)

虽然不能进行人与人的连结 但我们可以进行装置与装置的连结~(^ω^)人(^ω^) 爲什麽要让你连进我...

Day03 - Gem-strip_attributes 介绍与应用

前言 当使用者输入资料时,若不小心输入跳脱字元 Escape Character,如 \n or \...

[NestJS 带你飞!] DAY18 - Lifecycle Hooks

什麽是 Lifecycle Hook? 在开始介绍之前,先来了解一下何谓 生命周期 (Lifecyc...

从链接/URL 下载在线影片的 5 种最佳方式

如今,YouTube、TikTok、Dailymotion 等在线网站越来越受欢迎,并吸引了全球大量...