当前位置:   article > 正文

Keras基于VGG对五种图片类别识别的迁移学习_图像识别 迁移学习

图像识别 迁移学习

/

  1. 案例效果

2. 数据集以及迁移需求

数据集是某场景下5个类别图片的识别

我们利用现有的VGG模型去进行微调

  1. 思路和步骤
  • 读取本地的图片数据以及类别
    • keras.preprocessing.image import ImageDataGenerator提供了读取转换功能
  • 模型的结构修改(添加我们自定的分类层)
  • freeze掉原始VGG模型
  • 编译以及训练和保存模型方式
  • 输入数据进行预测

  1. train_datagen = ImageDataGenerator(
  2. rescale=1./255,
  3. shear_range=0.2,
  4. zoom_range=0.2,
  5. horizontal_flip=True)
  6. test_datagen = ImageDataGenerator(rescale=1./255)
  7. train_generator = train_datagen.flow_from_directory(
  8. 'data/train',
  9. target_size=(150, 150),
  10. batch_size=32,
  11. class_mode='binary')
  12. validation_generator = test_datagen.flow_from_directory(
  13. 'data/validation',
  14. target_size=(150, 150),
  15. batch_size=32,
  16. class_mode='binary')
  17. 使用fit_generator
  18. model.fit_generator(
  19. train_generator,
  20. steps_per_epoch=2000,
  21. epochs=50,
  22. validation_data=validation_generator,
  23. validation_steps=800)

  1. def __init__(self):
  2. # 定义训练和测试图片的变化方式,标准化以及数据增强
  3. self.train_generator = ImageDataGenerator(rescale=1.0 / 255)
  4. self.test_generator = ImageDataGenerator(rescale=1.0 / 255)
  5. # 指定训练集和测试集的目录
  6. self.train_dir = "./data/train"
  7. self.test_dir = "./data/test"
  8. # 定义图片训练的相关网络参数
  9. self.image_size = (224, 224)
  10. self.batch_size = 32
  11. def get_local_data(self):
  12. """
  13. 读取本地的图片数据以及类别
  14. :return:训练数据和测试数据迭代器
  15. """
  16. # 使用flow_from_derectory
  17. train_gen = self.train_generator.flow_from_directory(self.train_dir,
  18. target_size=self.image_size,
  19. batch_size=self.batch_size,
  20. class_mode='binary',
  21. shuffle=True)
  22. test_gen = self.test_generator.flow_from_directory(self.test_dir,
  23. target_size=self.image_size,
  24. batch_size=self.batch_size,
  25. class_mode='binary',
  26. shuffle=True)
  27. return train_gen, test_gen
'
运行

# 定义迁移学习的基类模型 # 不包含VGG当中3个全连接层的模型加载并且加载了参数 self.batch_model = VGG16(weights='imagenet', include_top=False)

模型源码:

  1. if include_top:
  2. # Classification block
  3. x = layers.Flatten(name='flatten')(x)
  4. x = layers.Dense(4096, activation='relu', name='fc1')(x)
  5. x = layers.Dense(4096, activation='relu', name='fc2')(x)
  6. x = layers.Dense(classes, activation='softmax', name='predictions')(x)
  7. else:
  8. if pooling == 'avg':
  9. x = layers.GlobalAveragePooling2D()(x)
  10. elif pooling == 'max':
  11. x = layers.GlobalMaxPooling2D()(x)

  • 使用前提:迁移学习不需要大量的参数去微调

  1. def refine_vgg_model(self):
  2. 添加尾部全连接层
  3. :return:
  4. # [<tf.Tensor 'block5_pool/MaxPool:0' shape=(?, ?, ?, 512) dtype=float32>]
  5. x = self.base_model.outputs[0]
  6. # 输出到全连接层,加上全局池化 [None, ?, ?, 512]---->[None, 1 * 512]
  7. x = keras.layers.GlobalAveragePooling2D()(x)
  8. x = keras.layers.Dense(1024, activation=tf.nn.relu)(x)
  9. y_predict = keras.layers.Dense(5, activation=tf.nn.softmax)(x)
  10. model = keras.Model(inputs=self.base_model.inputs, outputs=y_predict)
  11. return model

keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)

  1. modelckpt = keras.callbacks.ModelCheckpoint('./ckpt/fine_tuning/weights.{epoch:02d}.hdf5',
  2. monitor='val_acc',
  3. save_weights_only=True,
  4. save_best_only=True,
  5. mode='auto',
  6. period=1)
  7. model.fit_generator(train_gen, epochs=3, validation_data=test_gen, callbacks=[modelckpt])

  1. def fit_generator(self, model, train_gen, test_gen):
  2. """
  3. 训练模型,model.fit_generator()不是选择model.fit()
  4. :param model:
  5. :param train_gen:
  6. :param test_gen:
  7. :return:
  8. """
  9. # 每一次迭代准确率记录的h5文件
  10. modelckpt = keras.callbacks.ModelCheckpoint('./hdf5/transfer_{epoch:02d}-{accuracy:.2f}.h5',
  11. monitor='accuracy',
  12. save_weights_only=True,
  13. save_best_only=True,
  14. mode='auto',
  15. period=1)
  16. model.fit_generator(train_gen, epochs=3, validation_data=test_gen, callbacks=[modelckpt])
  17. # 保存模型
  18. # model.save_weights("./model/Transfer.h5")
  19. return None
'
运行

fit_generator()可以使用callbacks中的ModelCheckpoints

  1. if __name__ == "__main__":
  2. tm = TransferModel()
  3. train_gen, test_gen = tm.get_local_data()
  4. model = tm.refine_base_model()
  5. tm.freeeze_model()
  6. tm.compile(model)
  7. tm.fit_generator(model, train_gen, test_gen)

  1. def predict(self, model):
  2. '''
  3. 预测类型
  4. :param model:
  5. :return:
  6. '''
  7. # 加载模型,transfer_model
  8. model.load_weights("./hdf5/transfer_03-0.98.h5")
  9. # 读取图片, 处理
  10. image = load_img("./data/test/dinosaurs/400.jpg", target_size=(224, 224))
  11. image = img_to_array(image)
  12. # 三维转换为4维 (224, 224, 3)--->(1, 224, 224, 3)
  13. img = image.reshape([1, image.shape[0], image.shape[1], image.shape[2]])
  14. print(img)
  15. # 预测结果进行处理
  16. image = preprocess_input(img)
  17. predictions = model.predict(image)
  18. print(predictions)
  19. res = np.argmax(predictions, axis=1)
  20. print(self.label_dict[str(res[0])])
'
运行

完整代码:

  1. import numpy as np
  2. import tensorflow as tf
  3. from tensorflow import keras
  4. from tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array
  5. from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input
  6. tf.compat.v1.disable_eager_execution()
  7. class TransferModel(object):
  8. def __init__(self):
  9. # 定义训练和测试图片的变化方式,标准化以及数据增强
  10. self.train_generator = ImageDataGenerator(rescale=1.0 / 255)
  11. self.test_generator = ImageDataGenerator(rescale=1.0 / 255)
  12. # 指定训练集和测试集的目录
  13. self.train_dir = "./data/train"
  14. self.test_dir = "./data/test"
  15. # 定义图片训练的相关网络参数
  16. self.image_size = (224, 224)
  17. self.batch_size = 32
  18. # 定义迁移学习的基类模型
  19. # 不包含VGG当中3个全连接层的模型加载并且加载了参数
  20. self.base_model = VGG16(weights='imagenet', include_top=False)
  21. self.label_dict = {
  22. '0': 'bus',
  23. '1': 'dinosaurs',
  24. '2': 'eleplants',
  25. '3': 'flowers',
  26. '4': 'horse'
  27. }
  28. def get_local_data(self):
  29. """
  30. 读取本地的图片数据以及类别
  31. :return:训练数据和测试数据迭代器
  32. """
  33. # 使用flow_from_derectory
  34. train_gen = self.train_generator.flow_from_directory(self.train_dir,
  35. target_size=self.image_size,
  36. batch_size=self.batch_size,
  37. class_mode='binary',
  38. shuffle=True)
  39. test_gen = self.test_generator.flow_from_directory(self.test_dir,
  40. target_size=self.image_size,
  41. batch_size=self.batch_size,
  42. class_mode='binary',
  43. shuffle=True)
  44. return train_gen, test_gen
  45. def refine_base_model(self):
  46. """
  47. 微调VGG结构,5blocks后面+全局平均池化(减少迁移学习的参数数量)+两个全连接层
  48. :return:
  49. """
  50. # 1. 获取原notop模型得出
  51. # [?, ?, ?, 512]
  52. x = self.base_model.outputs[0]
  53. # 2。 在输出后面增加我们的结构
  54. # [?, ?, ?, 512]----》[?, 1*1*512]
  55. x = keras.layers.GlobalAveragePooling2D()(x)
  56. # 3. 定义新的迁移模型
  57. x = keras.layers.Dense(1024, activation=tf.compat.v1.nn.relu)(x)
  58. y_predict = keras.layers.Dense(5, activation=tf.compat.v1.nn.softmax)(x)
  59. # model定义新模型
  60. # VGG模型的输入,输出,y_predict
  61. transfer_model = keras.models.Model(inputs=self.base_model.inputs, outputs=y_predict)
  62. return transfer_model
  63. def freeeze_model(self):
  64. """
  65. 冻结VGG模型(5blocks)
  66. 冻结VGG的多少根据数据量
  67. :return:
  68. """
  69. # 获取所有层, 返回层的列表
  70. for layer in self.base_model.layers:
  71. layer.trainable = False
  72. def compile(self, model):
  73. '''
  74. 编译模型
  75. :return:
  76. '''
  77. model.compile(optimizer=keras.optimizers.Adam(),
  78. loss=keras.losses.sparse_categorical_crossentropy,
  79. metrics=['accuracy'])
  80. return None
  81. def fit_generator(self, model, train_gen, test_gen):
  82. """
  83. 训练模型,model.fit_generator()不是选择model.fit()
  84. :param model:
  85. :param train_gen:
  86. :param test_gen:
  87. :return:
  88. """
  89. # 每一次迭代准确率记录的h5文件
  90. modelckpt = keras.callbacks.ModelCheckpoint('./hdf5/transfer_{epoch:02d}-{accuracy:.2f}.h5',
  91. monitor='accuracy',
  92. save_weights_only=True,
  93. save_best_only=True,
  94. mode='auto',
  95. period=1)
  96. model.fit_generator(train_gen, epochs=3, validation_data=test_gen, callbacks=[modelckpt])
  97. # 保存模型
  98. # model.save_weights("./model/Transfer.h5")
  99. return None
  100. def predict(self, model):
  101. '''
  102. 预测类型
  103. :param model:
  104. :return:
  105. '''
  106. # 加载模型,transfer_model
  107. model.load_weights("./hdf5/transfer_03-0.98.h5")
  108. # 读取图片, 处理
  109. image = load_img("./data/test/dinosaurs/400.jpg", target_size=(224, 224))
  110. image = img_to_array(image)
  111. # 三维转换为4维 (224, 224, 3)--->(1, 224, 224, 3)
  112. img = image.reshape([1, image.shape[0], image.shape[1], image.shape[2]])
  113. print(img)
  114. # 预测结果进行处理
  115. image = preprocess_input(img)
  116. predictions = model.predict(image)
  117. print(predictions)
  118. res = np.argmax(predictions, axis=1)
  119. print(self.label_dict[str(res[0])])
  120. if __name__ == "__main__":
  121. tm = TransferModel()
  122. # 训练
  123. # train_gen, test_gen = tm.get_local_data()
  124. # # print(train_gen, test_gen)
  125. # # # for data in train_gen:
  126. # # # print(train_gen) print(tm.batch_model.summary())
  127. # model = tm.refine_base_model()
  128. # # print(model)
  129. # tm.freeeze_model()
  130. # tm.compile(model)
  131. # tm.fit_generator(model, train_gen, test_gen)
  132. """测试"""
  133. model = tm.refine_base_model()
  134. tm.predict(model)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/880904
推荐阅读
相关标签
  

闽ICP备14008679号