实战 迁移学习 VGG19、ResNet50、InceptionV3 实践 猫狗大战 问题

 
参考博客:::https://blog.csdn.net/pengdali/article/details/79050662
 
 
2018年01月13日 12:52:14 pengdali 阅读数 10417
 

一、实践流程

1、数据预处理

主要是对训练数据进行随机偏移、转动等变换图像处理,这样可以尽可能让训练数据多样化

另外处理数据方式采用分批无序读取的形式,避免了数据按目录排序训练

  1.  
    #数据准备
  2.  
    def DataGen(self, dir_path, img_row, img_col, batch_size, is_train):
  3.  
    if is_train:
  4.  
    datagen = ImageDataGenerator(rescale=1./255,
  5.  
    zoom_range=0.25, rotation_range=15.,
  6.  
    channel_shift_range=25., width_shift_range=0.02, height_shift_range=0.02,
  7.  
    horizontal_flip=True, fill_mode='constant')
  8.  
    else:
  9.  
    datagen = ImageDataGenerator(rescale=1./255)
  10.  
     
  11.  
    generator = datagen.flow_from_directory(
  12.  
    dir_path, target_size=(img_row, img_col),
  13.  
    batch_size=batch_size,
  14.  
    shuffle=is_train)
  15.  
     
  16.  
    return generator
2、载入现有模型

这个部分是核心工作,目的是使用ImageNet训练出的权重来做我们的特征提取器,注意这里后面的分类层去掉

  1.  
    base_model = InceptionV3(weights='imagenet', include_top=False, pooling=None,
  2.  
    input_shape=(img_rows, img_cols, color),
  3.  
    classes=nb_classes)

然后是冻结这些层,因为是训练好的

  1.  
    for layer in base_model.layers:
  2.  
    layer.trainable = False

而分类部分,需要我们根据现有需求来新定义的,这里可以根据实际情况自己进行调整,比如这样

  1.  
    x = base_model.output
  2.  
    # 添加自己的全链接分类层
  3.  
    x = GlobalAveragePooling2D()(x)
  4.  
    x = Dense(1024, activation='relu')(x)
  5.  
    predictions = Dense(nb_classes, activation='softmax')(x)

或者

  1.  
    x = base_model.output
  2.  
    #添加自己的全链接分类层
  3.  
    x = Flatten()(x)
  4.  
    predictions = Dense(nb_classes, activation='softmax')(x)
3、训练模型

这里我们用fit_generator函数,它可以避免了一次性加载大量的数据,并且生成器与模型将并行执行以提高效率。比如可以在CPU上进行实时的数据提升,同时在GPU上进行模型训练

  1.  
    history_ft = model.fit_generator(
  2.  
    train_generator,
  3.  
    steps_per_epoch=steps_per_epoch,
  4.  
    epochs=epochs,
  5.  
    validation_data=validation_generator,
  6.  
    validation_steps=validation_steps)

二、猫狗大战数据集

训练数据540M,测试数据270M,大家可以去官网下载

https://www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition/data

下载后把数据分成dog和cat两个目录来存放

三、训练

训练的时候会自动去下权值,比如vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5,但是如果我们已经下载好了的话,可以改源代码,让他直接读取我们的下载好的权值,比如在resnet50.py中

1、VGG19

vgg19的深度有26层,参数达到了549M,原模型最后有3个全连接层做分类器所以我还是加了一个1024的全连接层,训练10轮的情况达到了89%

2、ResNet50

ResNet50的深度达到了168层,但是参数只有99M,分类模型我就简单点,一层直接分类,训练10轮的达到了96%的准确率

3、inception_v3

InceptionV3的深度159层,参数92M,训练10轮的结果

这是一层直接分类的结果

这是加了一个512全连接的,大家可以随意调整测试

四、完整的代码

  1.  
    # -*- coding: utf-8 -*-
  2.  
    import os
  3.  
    from keras.utils import plot_model
  4.  
    from keras.applications.resnet50 import ResNet50
  5.  
    from keras.applications.vgg19 import VGG19
  6.  
    from keras.applications.inception_v3 import InceptionV3
  7.  
    from keras.layers import Dense,Flatten,GlobalAveragePooling2D
  8.  
    from keras.models import Model,load_model
  9.  
    from keras.optimizers import SGD
  10.  
    from keras.preprocessing.image import ImageDataGenerator
  11.  
    import matplotlib.pyplot as plt
  12.  
     
  13.  
    class PowerTransferMode:
  14.  
    #数据准备
  15.  
    def DataGen(self, dir_path, img_row, img_col, batch_size, is_train):
  16.  
    if is_train:
  17.  
    datagen = ImageDataGenerator(rescale=1./255,
  18.  
    zoom_range=0.25, rotation_range=15.,
  19.  
    channel_shift_range=25., width_shift_range=0.02, height_shift_range=0.02,
  20.  
    horizontal_flip=True, fill_mode='constant')
  21.  
    else:
  22.  
    datagen = ImageDataGenerator(rescale=1./255)
  23.  
     
  24.  
    generator = datagen.flow_from_directory(
  25.  
    dir_path, target_size=(img_row, img_col),
  26.  
    batch_size=batch_size,
  27.  
    #class_mode='binary',
  28.  
    shuffle=is_train)
  29.  
     
  30.  
    return generator
  31.  
     
  32.  
    #ResNet模型
  33.  
    def ResNet50_model(self, lr=0.005, decay=1e-6, momentum=0.9, nb_classes=2, img_rows=197, img_cols=197, RGB=True, is_plot_model=False):
  34.  
    color = 3 if RGB else 1
  35.  
    base_model = ResNet50(weights='imagenet', include_top=False, pooling=None, input_shape=(img_rows, img_cols, color),
  36.  
    classes=nb_classes)
  37.  
     
  38.  
    #冻结base_model所有层,这样就可以正确获得bottleneck特征
  39.  
    for layer in base_model.layers:
  40.  
    layer.trainable = False
  41.  
     
  42.  
    x = base_model.output
  43.  
    #添加自己的全链接分类层
  44.  
    x = Flatten()(x)
  45.  
    #x = GlobalAveragePooling2D()(x)
  46.  
    #x = Dense(1024, activation='relu')(x)
  47.  
    predictions = Dense(nb_classes, activation='softmax')(x)
  48.  
     
  49.  
    #训练模型
  50.  
    model = Model(inputs=base_model.input, outputs=predictions)
  51.  
    sgd = SGD(lr=lr, decay=decay, momentum=momentum, nesterov=True)
  52.  
    model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
  53.  
     
  54.  
    #绘制模型
  55.  
    if is_plot_model:
  56.  
    plot_model(model, to_file='resnet50_model.png',show_shapes=True)
  57.  
     
  58.  
    return model
  59.  
     
  60.  
     
  61.  
    #VGG模型
  62.  
    def VGG19_model(self, lr=0.005, decay=1e-6, momentum=0.9, nb_classes=2, img_rows=197, img_cols=197, RGB=True, is_plot_model=False):
  63.  
    color = 3 if RGB else 1
  64.  
    base_model = VGG19(weights='imagenet', include_top=False, pooling=None, input_shape=(img_rows, img_cols, color),
  65.  
    classes=nb_classes)
  66.  
     
  67.  
    #冻结base_model所有层,这样就可以正确获得bottleneck特征
  68.  
    for layer in base_model.layers:
  69.  
    layer.trainable = False
  70.  
     
  71.  
    x = base_model.output
  72.  
    #添加自己的全链接分类层
  73.  
    x = GlobalAveragePooling2D()(x)
  74.  
    x = Dense(1024, activation='relu')(x)
  75.  
    predictions = Dense(nb_classes, activation='softmax')(x)
  76.  
     
  77.  
    #训练模型
  78.  
    model = Model(inputs=base_model.input, outputs=predictions)
  79.  
    sgd = SGD(lr=lr, decay=decay, momentum=momentum, nesterov=True)
  80.  
    model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
  81.  
     
  82.  
    # 绘图
  83.  
    if is_plot_model:
  84.  
    plot_model(model, to_file='vgg19_model.png',show_shapes=True)
  85.  
     
  86.  
    return model
  87.  
     
  88.  
    # InceptionV3模型
  89.  
    def InceptionV3_model(self, lr=0.005, decay=1e-6, momentum=0.9, nb_classes=2, img_rows=197, img_cols=197, RGB=True,
  90.  
    is_plot_model=False):
  91.  
    color = 3 if RGB else 1
  92.  
    base_model = InceptionV3(weights='imagenet', include_top=False, pooling=None,
  93.  
    input_shape=(img_rows, img_cols, color),
  94.  
    classes=nb_classes)
  95.  
     
  96.  
    # 冻结base_model所有层,这样就可以正确获得bottleneck特征
  97.  
    for layer in base_model.layers:
  98.  
    layer.trainable = False
  99.  
     
  100.  
    x = base_model.output
  101.  
    # 添加自己的全链接分类层
  102.  
    x = GlobalAveragePooling2D()(x)
  103.  
    x = Dense(1024, activation='relu')(x)
  104.  
    predictions = Dense(nb_classes, activation='softmax')(x)
  105.  
     
  106.  
    # 训练模型
  107.  
    model = Model(inputs=base_model.input, outputs=predictions)
  108.  
    sgd = SGD(lr=lr, decay=decay, momentum=momentum, nesterov=True)
  109.  
    model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
  110.  
     
  111.  
    # 绘图
  112.  
    if is_plot_model:
  113.  
    plot_model(model, to_file='inception_v3_model.png', show_shapes=True)
  114.  
     
  115.  
    return model
  116.  
     
  117.  
    #训练模型
  118.  
    def train_model(self, model, epochs, train_generator, steps_per_epoch, validation_generator, validation_steps, model_url, is_load_model=False):
  119.  
    # 载入模型
  120.  
    if is_load_model and os.path.exists(model_url):
  121.  
    model = load_model(model_url)
  122.  
     
  123.  
    history_ft = model.fit_generator(
  124.  
    train_generator,
  125.  
    steps_per_epoch=steps_per_epoch,
  126.  
    epochs=epochs,
  127.  
    validation_data=validation_generator,
  128.  
    validation_steps=validation_steps)
  129.  
    # 模型保存
  130.  
    model.save(model_url,overwrite=True)
  131.  
    return history_ft
  132.  
     
  133.  
    # 画图
  134.  
    def plot_training(self, history):
  135.  
    acc = history.history['acc']
  136.  
    val_acc = history.history['val_acc']
  137.  
    loss = history.history['loss']
  138.  
    val_loss = history.history['val_loss']
  139.  
    epochs = range(len(acc))
  140.  
    plt.plot(epochs, acc, 'b-')
  141.  
    plt.plot(epochs, val_acc, 'r')
  142.  
    plt.title('Training and validation accuracy')
  143.  
    plt.figure()
  144.  
    plt.plot(epochs, loss, 'b-')
  145.  
    plt.plot(epochs, val_loss, 'r-')
  146.  
    plt.title('Training and validation loss')
  147.  
    plt.show()
  148.  
     
  149.  
     
  150.  
    if __name__ == '__main__':
  151.  
    image_size = 197
  152.  
    batch_size = 32
  153.  
     
  154.  
    transfer = PowerTransferMode()
  155.  
     
  156.  
    #得到数据
  157.  
    train_generator = transfer.DataGen('data/cat_dog_Dataset/train', image_size, image_size, batch_size, True)
  158.  
    validation_generator = transfer.DataGen('data/cat_dog_Dataset/test', image_size, image_size, batch_size, False)
  159.  
     
  160.  
    #VGG19
  161.  
    #model = transfer.VGG19_model(nb_classes=2, img_rows=image_size, img_cols=image_size, is_plot_model=False)
  162.  
    #history_ft = transfer.train_model(model, 10, train_generator, 600, validation_generator, 60, 'vgg19_model_weights.h5', is_load_model=False)
  163.  
     
  164.  
    #ResNet50
  165.  
    model = transfer.ResNet50_model(nb_classes=2, img_rows=image_size, img_cols=image_size, is_plot_model=False)
  166.  
    history_ft = transfer.train_model(model, 10, train_generator, 600, validation_generator, 60, 'resnet50_model_weights.h5', is_load_model=False)
  167.  
     
  168.  
    #InceptionV3
  169.  
    #model = transfer.InceptionV3_model(nb_classes=2, img_rows=image_size, img_cols=image_size, is_plot_model=True)
  170.  
    #history_ft = transfer.train_model(model, 10, train_generator, 600, validation_generator, 60, 'inception_v3_model_weights.h5', is_load_model=False)
  171.  
     
  172.  
    # 训练的acc_loss图
  173.  
    transfer.plot_training(history_ft)

实战 迁移学习 VGG19、ResNet50、InceptionV3 实践 猫狗大战 问题的更多相关文章

  1. keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完美案例(五)

    引自:http://blog.csdn.net/sinat_26917383/article/details/72982230 之前在博客<keras系列︱图像多分类训练与利用bottlenec ...

  2. 基于深度学习和迁移学习的识花实践——利用 VGG16 的深度网络结构中的五轮卷积网络层和池化层,对每张图片得到一个 4096 维的特征向量,然后我们直接用这个特征向量替代原来的图片,再加若干层全连接的神经网络,对花朵数据集进行训练(属于模型迁移)

    基于深度学习和迁移学习的识花实践(转)   深度学习是人工智能领域近年来最火热的话题之一,但是对于个人来说,以往想要玩转深度学习除了要具备高超的编程技巧,还需要有海量的数据和强劲的硬件.不过 Tens ...

  3. 1、VGG16 2、VGG19 3、ResNet50 4、Inception V3 5、Xception介绍——迁移学习

    ResNet, AlexNet, VGG, Inception: 理解各种各样的CNN架构 本文翻译自ResNet, AlexNet, VGG, Inception: Understanding va ...

  4. 1 如何使用pb文件保存和恢复模型进行迁移学习(学习Tensorflow 实战google深度学习框架)

    学习过程是Tensorflow 实战google深度学习框架一书的第六章的迁移学习环节. 具体见我提出的问题:https://www.tensorflowers.cn/t/5314 参考https:/ ...

  5. Google Tensorflow 迁移学习 Inception-v3

    附上代码加数据地址 https://github.com/Liuyubao/transfer-learning ,欢迎参考. 一.Inception-V3模型 1.1 详细了解模型可参考以下论文: [ ...

  6. 【深度学习系列】迁移学习Transfer Learning

    在前面的文章中,我们通常是拿到一个任务,譬如图像分类.识别等,搜集好数据后就开始直接用模型进行训练,但是现实情况中,由于设备的局限性.时间的紧迫性等导致我们无法从头开始训练,迭代一两百万次来收敛模型, ...

  7. 迁移学习︱艺术风格转化:Artistic style-transfer+ubuntu14.0+caffe(only CPU)

    说起来这门技术大多是秀的成分高于实际,但是呢,其也可以作为图像增强的工具,看到一些比赛拿他作训练集扩充,还是一个比较好的思路.如何在caffe上面实现简单的风格转化呢? 好像网上的博文都没有说清楚,而 ...

  8. TensorFlow从1到2(九)迁移学习

    迁移学习基本概念 迁移学习是这两年比较火的一个话题,主要原因是在当前的机器学习中,样本数据的获取是成本最高的一块.而迁移学习可以有效的把原有的学习经验(对于模型就是模型本身及其训练好的权重值)带入到新 ...

  9. 『TensorFlow』迁移学习

    完全版见github:TransforLearning 零.迁移学习 将一个领域的已经成熟的知识应用到其他的场景中称为迁移学习.用神经网络的角度来表述,就是一层层网络中每个节点的权重从一个训练好的网络 ...

随机推荐

  1. 原生JS获取所有标签的数量并统计每个标签的数量

    <script type="text/javascript"> var tags = document.getElementsByTagName('*'); var t ...

  2. Day9 - F - Monkey and Banana HDU - 1069

    一组研究人员正在设计一项实验,以测试猴子的智商.他们将挂香蕉在建筑物的屋顶,同时,提供一些砖块给这些猴子.如果猴子足够聪明,它应当能够通过合理的放置一些砖块建立一个塔,并爬上去吃他们最喜欢的香蕉.   ...

  3. Window Server 2019 配置篇(8)- 利用MDT定制自动加入域的脚本

    我们要更改我们的镜像文件,使得自动安装完成后,计算机已经自动在域中 删除在WDS-server上做的自动部署,我们在上面安装一下MDT和ADK文件,这两个文件如果需要的话可以评论,我会在随后上传 之后 ...

  4. kubernetes集群全栈监控报警方案kube-prometheus

    参考文档 http://www.servicemesher.com/blog/prometheus-operator-manual/ https://github.com/coreos/prometh ...

  5. 【转置】使用mysql转置表格行和列

    1.原始表 2.查询结果表 3.查询语句 1 SELECT 2 year1, 3 SUM( CASE WHEN mon= 1 THEN account END ) AS m1, 4 SUM( CASE ...

  6. R WLS矫正方差非齐《回归分析与线性统计模型》page115

    rm(list = ls()) A = read.csv("data115.csv") fm = lm(y~x1+x2,data = A) coef(fm) A.cooks = c ...

  7. python 关于异常处理 try...except... 的两个案例

    输入若干个成绩,求所有成绩的平均分.每输入一个成绩后询问是否继续输入下一个成绩,回答“yes”就继续输入下一个成绩,回答“no”就停止输入成绩. numbers = [] #使用列表存放临时数据 wh ...

  8. Day6 - 牛客203E

    https://ac.nowcoder.com/acm/contest/203/E 埋坑不会做

  9. System.Data.SqlClient.SqlException: 'Incorrect syntax near 'OFFSET'.

    https://www.nopcommerce.com/boards/t/54586/410-not-running-on-local-system.aspx#209684 Hello, I was ...

  10. [转]SparkSQL – 有必要坐下来聊聊Join

    转载自网易范欣欣http://hbasefly.com Join背景介绍 Join是数据库查询永远绕不开的话题,传统查询SQL技术总体可以分为简单操作(过滤操作-where.排序操作-limit等), ...