keras+tensorflow实现迁移学习

coding=utf-8

“”"
author:lei
function:迁移学习
“”"

import tensorflow as tf
from tensorflow.python import keras
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array
from tensorflow.python.keras.applications.vgg16 import VGG16, preprocess_input
import numpy as np

class TransforModel(object):

def __init__(self):
    # 定义训练和测试图片的变化方法,标准化和数据增强
    self.train_generator = ImageDataGenerator(rescale=1.0/255.0)  # 标准化,其他自定义
    self.test_gengerator = ImageDataGenerator(rescale=1.0/255.0)

    # 指定训练数据和测试数据的目录
    self.train_dir = "./data/train"
    self.test_dir = "./data/test"

    # 定义图片训练相关训练参数
    self.image_size = (224, 224)
    self.batch_size = 32

    # 定义迁移学习的基类模型  include_top=不包含最后的全连接层的参数
    self.base_model = VGG16(include_top=False)

    self.label_dict = {'0': 'bus', '1': 'dinosaurs', '2': 'elephants', '3': 'flowers', '4': 'horse'}

def get_local_data(self):
    """
        读取本地的图片数据以及类别
    :return: 返回训练数据和测试数据迭代器
    """
    # 使用flow_from_derectory
    train_gen = self.train_generator.flow_from_directory(self.train_dir, target_size=self.image_size, batch_size=self.batch_size, class_mode="binary", shuffle=True)

    test_gen = self.test_gengerator.flow_from_directory(self.test_dir, target_size=self.image_size, batch_size=self.batch_size, class_mode="binary", shuffle=True)

    return train_gen, test_gen

def refine_base_model(self):
    """
        微调vgg结构,5个blocks后面+全局平均池化(减少迁移学习的参数数量)+ 两个全连接层
    :return:
    """
    # 1、获取原notop模型的输出
    x = self.base_model.outputs[0]
    # print(x)  shape=(?, ?, ?, 512)

    # 2、再输出后面增加我们自己定义的结构  先进行全局池化
    # [?, ?, ?, 512] --> [?, 1*1*512]
    x = keras.layers.GlobalAveragePooling2D()(x)

    # 3、先定义新的迁移模型  上一层的输入要输入当中
    x = keras.layers.Dense(1024, activation=tf.nn.relu)(x)
    y_predict = keras.layers.Dense(5, activation=tf.nn.softmax)(x)

    # model定义新模型
    transfer_model = keras.models.Model(inputs=self.base_model.inputs, outputs=y_predict)

    return transfer_model

def freeze_model(self):
    """
        冻结vgg模型
        冻结vgg的多少,根据你的数据量
    :return:
    """
    # self.base_model.layers 获取所有层,返回层的列表
    for layer in self.base_model.layers:
        layer.trainable = False

def compile(self, model):
    """
        编译模型
    :return:
    """
    model.compile(optimizer=keras.optimizers.Adam(), loss=keras.losses.sparse_categorical_crossentropy, metrics=["accuracy"])

    return None

def fit(self, model, train_gen, test_gen):
    """
        训练模型  model.fit_generator() 而不是model.fit()
    :return:
    """
    # 保存文件
    model_ckpt = keras.callbacks.ModelCheckpoint("./ckpt/transfer_{epoch:02d}--{val_acc:.2f}.h5", monitor="val_acc", save_weights_only=True, save_best_only=True, mode="auto", period=1)

    model.fit(train_gen, epochs=3, validation_data=test_gen, callbacks=[model_ckpt])

    return None

def predict(self, model):
    """
        预测类别
    :return:
    """
    # 加载模型,transfer_model
    model.load_weights("./ckpt/transfer_03--0.95.h5")

    # 读取图片,处理
    image = load_img("./bus/300.jpg", target_size=(224, 224))
    image = img_to_array(image)
    print(image.shape)

    # 转换成4维函数 (224, 224, 3) --> (1, 224, 224, 1)
    image = image.reshape([1, image.shape[0], image.shape[1], image.shape[2]])
    print(image)
    # model.predict()

    # 预测结果进行处理
    image = preprocess_input(image)
    predictions = model.predict(image)
    print(predictions)

    index = np.argmax(predictions, axis=1)

    # 返回预测的结果
    print(self.label_dict[str(index[0])])

if name == ‘main’:
tm = TransforModel()
# 训练
# train_gen, test_gen = tm.get_local_data()
# print(train_gen)
# print(test_gen)
# # 通过迭代器 打印
# # for data in train_gen:
# # print(data[0].shape, data[1].shape)
# print(tm.base_model.summary())
#
# model = tm.refine_base_model()
# print(model)
# # 冻结模型
# tm.freeze_model()
#
# tm.compile(model)
#
# tm.fit(model, train_gen, test_gen)

# 测试
model = tm.refine_base_model()
tm.predict(model)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值