【第15天】训练模型-ResNet152V2

摘要

  1. ResNet152V2

    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. 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情况,降低模型效能。

      ※ 详细请参考论文Page8 Exploring Over 1000 layers

    • 观察VGG NET与达到Residual Net在ImageNet上的表现,Residual Net优於VGG Net,且复杂度明显低於VGG Net。

  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 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. 模型训练结果

    3.1 训练epochs:31 epochs。

    3.2 耗费时间:4小时17分32秒(15452秒)。

    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. ResNet为深度学习带来新的启发,现在许多主流模型都采Residual learning概念。
  2. 下一章目标是:介绍第三个预训练模型DenseNet201,与分享训练成果」。

让我们继续看下去...


参考资料

  1. Deep Residual Learning for Image Recognition
  2. Residual Leaning: 认识ResNet与他的冠名後继者ResNeXt、ResNeSt
  3. Identity Mappings in Deep Residual Networks
  4. [论文] Deep Residual Learning for Image Recognition
  5. 梯度弥散与梯度爆炸

<<:  D30 - 如何看自己需要哪篇 Apps Script 的功能?三十天 Apps Script 旅程的总整理

>>:  Day 24: AI机器学习 — TensorFlow初探(上)

[前端暴龙机,Vue2.x 进化 Vue3 ] Day29.Vue3 网页小游戏(一) | ♾ 台版鱿鱼游戏,玩?还是不玩?

免责声明: 最近跟着中了"鱿鱼游戏"的毒,哈哈哈 这个游戏,相信大多数的人都有...

Day 15 - 苹果生态圈探讨

本文重点 因为我觉得要开发,不应该是一昧的写,了解系统也是很重要的!所以在这篇我会讲一些我自己对苹果...

[18] [烧瓶里的部落格] 08. 撰写测试

写单元测试可以检查程序是否按预期执行,Flask 可以模拟发送请求并回传资料 应当尽可能多进行测试,...

Day 04-选择MongoDB

!小补充! SQL资料库: 关联式资料库,需在资料库中建立Table,并在Table与Table之间...

Day 17:Layout Using Grid

介绍了 juce::Rectangle 以及 juce::FlexBox 这两个拉版工具後,这篇介绍...