zoukankan      html  css  js  c++  java
  • 以图搜图之模型篇: 基于 InceptionV3 的模型 finetune

    在以图搜图的过程中,需要以来模型提取特征,通过特征之间的欧式距离来找到相似的图形。

    本次我们主要讲诉以图搜图模型创建的方法。

    图片预处理方法,看这里: https://keras.io/zh/preprocessing/image/

    本文主要参考了这位大神的文章, 传送门在此: InceptionV3进行fine-tuning

    训练模型代码如下:

    # 基本流程
    # 
    import os
    import sys
    import glob
    import argparse
    import matplotlib.pyplot as plt
    
    from keras.applications.inception_v3 import InceptionV3, preprocess_input
    from keras.models import Model
    from keras.layers import Dense, GlobalAveragePooling2D
    from keras.preprocessing.image import ImageDataGenerator
    from keras.optimizers import SGD
    
    # 一、定义函数
    IM_WIDTH, IM_HEIGHT = 299, 299   # inceptionV3 指定图片尺寸
    FC_SIZE = 1024                   # 全连接层的数量
    
    # 二、数据处理
    # 图片归类放在不同文件夹下
    train_dir = 'E:/Project/Image/data/finetune/train'  # 训练集数据
    val_dir = 'E:/Project/Image/data/finetune/test' # 验证集数据
    nb_epoch = 1
    batch_size = 15
    nb_classes = len(glob.glob(train_dir + "/*"))  # 分类数
    
    
    # 图片增强
    # ImageDataGenerator 会自动根据路径下的文件夹创建标签,所以在代码中只看到输入的 x, 看不到 y
    train_datagen = ImageDataGenerator(
        preprocessing_function=preprocess_input,
        rotation_range=30,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True
    )
    
    train_generator = train_datagen.flow_from_directory(
        train_dir, target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size, class_mode='categorical'
    )
    
    validation_generator = train_datagen.flow_from_directory(
        val_dir, target_size=(IM_WIDTH, IM_HEIGHT),batch_size=batch_size, class_mode='categorical'
    )
    
    # 三、使用 bottleneck finetune
    # 去掉 模型最外层的全连接层,添加上自己的 全连接层
    # 添加新层函数
    def add_new_last_layer(base_model, nb_classes):
        x = base_model.output
        x = GlobalAveragePooling2D()(x) # 下采样
        x = Dense(FC_SIZE, activation='relu')(x)
        predict_bottle_feat = Dense(nb_classes, activation='softmax')(x)
        model = Model(input=base_model.input, output=predict_bottle_feat)
        return model
    
    # 冻结 base_model 所有层
    def setup_to_transfer_learn(model, base_model):
        for layer in base_model.layers:
            layer.trainable = False
        model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
    
    # 定义网络框架
    base_model = InceptionV3(weights='imagenet', include_top=False)
    model = add_new_last_layer(base_model, nb_classes)
    setup_to_transfer_learn(model, base_model)
    
    # 训练
    # 模式一训练
    steps = 20 # 可以自由定义,越大结果越精准,但过大容易过拟合
    history_tl = model.fit_generator(
      train_generator,
      epochs=nb_epoch,
      steps_per_epoch=steps,
      validation_data=validation_generator,
      validation_steps=steps,
      class_weight='auto')
    
    # 保存模型
    model.save("my_inceptionV3.h5")
    View Code

    使用模型提取指定层的特征: 

    from keras.preprocessing import image
    from keras_applications.inception_v3 import preprocess_input
    from keras.models import Model, load_model
    import numpy as np
    
    target_size = (229, 229) #fixed size for InceptionV3 architecture
    base_model = load_model(filepath="my_inceptionV3.h5")
    
    # 需要提取那一层的特征,此处就写入指定层的名称
    model = Model(input=base_model.input, output=base_model.get_layer('block4_pool').output)
    
    img_path = "C:/Users/Administrator/Pictures/搜图/horse.jpg"
    img = image.load_img(img_path, target_size=target_size)
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    
    block4_pool_features = model.predict(x)
    View Code

    使用模型进行预测:

    from keras.preprocessing import image
    from  keras.models import load_model
    import numpy as np
    import json
    from keras_applications.imagenet_utils import decode_predictions
    
    
    def predict(model, img, target_size):
      """Run model prediction on image
      Args:
        model: keras model
        img: PIL format image
        target_size: (w,h) tuple
      Returns:
        list of predicted labels and their probabilities
      """
      if img.size != target_size:
        img = img.resize(target_size)
    
      x = image.img_to_array(img)
      x = np.expand_dims(x, axis=0)
      x = preprocess_input(x)
      preds = model.predict(x)   # 此处获取的为
      return preds[0]            # 返回 numpy array [classes, ]
    
    def decode_predict(probalities_list):
      with open("img_classes.json", 'r') as load_f:
        load_dict = json.load(load_f)
      index = probalities_list.index(max(probalities_list))
      target_class = load_dict[str(index)]
      return target_class
    
    target_size = (229, 229) #fixed size for InceptionV3 architecture
    model = load_model(filepath="my_inceptionV3.h5")
    img = image.load_img("C:/Users/Administrator/Pictures/搜图/horse.jpg")
    
    res_numpy = predict(model, img, target_size=target_size)
    res_list = res_numpy.tolist()
    target_class = decode_predict(res_list)
    print(target_class)
    View Code
  • 相关阅读:
    instanceof方法
    Java 实现接口计算圆柱的体积和面积并添加颜色
    Java代码执行顺序
    Java饿汉单例模式
    斐波那契数(动态规划和递归)
    Java 接口实现计算器加减乘除(字符交互界面)
    局部内部类详解_转载
    Java引用类型
    递归打印字符串
    时间复杂度
  • 原文地址:https://www.cnblogs.com/yaolin1228/p/9978508.html
Copyright © 2011-2022 走看看