知识要点
-
迁移学习: 使用别人预训练模型参数时,要注意别人的预处理方式。
-
常见的迁移学习方式:
- 载入权重后训练所有参数.
- 载入权重后只训练最后几层参数.
- 载入权重后在原网络基础上再添加一层全连接层,仅训练最后一个全连接层.
- 训练数据是 10_monkeys 数据: 10种猴子的图片集
- 图片显示: plt.imshow(mokey)
- 读取图片: mokey = plt.imread('./50.jpg')
导入resnet 模型:
- resnet50 = keras.applications.ResNet50(include_top=False, pooling='avg') # 导入模型
- model = keras.models.Sequential() # 开始建模
- model.add(resnet50) # 添加resnet 网络
- model.add(keras.layers.Dense(num_classes=10, activation = 'softmax')) # 添加全连接层
- model.layers[0].trainable = False # 除了最后一个全连接层, 其余部分参数不变
- 模型配置:
model.compile(loss = 'categorical_crossentropy',
optimizer = 'adam',
metrics = ['acc'])
- valid_datagen = keras.preprocessing.image.ImageDataGenerator(preprocessing_function = keras.applications.resnet50.preprocess_input) # 数据初始化处理
- 指定后面几层参数变化:
# 切片指定, 不可调整的层数
for layer in resnet50.layers[0:-5]:
layer.trainable = False
一 迁移学习
1.1 简介
使用迁移学习的优势:
- 能够快速的训练出一个理想的结果
- 当数据集较小时也能训练出理想的效果
注意:使用别人预训练模型参数时,要注意别人的预处理方式。
1.2 常见迁移方式
常见的迁移学习方式:
- 载入权重后训练所有参数.
- 载入权重后只训练最后几层参数.
- 载入权重后在原网络基础上再添加一层全连接层,仅训练最后一个全连接层.
二 代码实现
2.1 导包
from tensorflow import keras
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
cpu=tf.config.list_physical_devices("CPU")
tf.config.set_visible_devices(cpu)
print(tf.config.list_logical_devices())
2.2 迁移模型 (在迁移模型 后加一层)
resnet50 = keras.applications.ResNet50(include_top=False, pooling='avg')
num_classes =10
model = keras.models.Sequential()
model.add(resnet50)
model.add(keras.layers.Dense(num_classes, activation = 'softmax'))
model.summary()
2.3 配置模型 (除最后一层外, 其余参数全部冻结)
# 把除最后一层的参数外, 全部冻结
model.layers[0].trainable = False
model.compile(loss = 'categorical_crossentropy',
optimizer = 'adam',
metrics = ['acc'])
2.4 导入数据
train_dir = '../day 48 resnet/training/training/'
valid_dir = '../day 48 resnet/validation/validation/'
- 原始数据处理
train_datagen = keras.preprocessing.image.ImageDataGenerator(
preprocessing_function = keras.applications.resnet50.preprocess_input,
rotation_range = 40,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True,
vertical_flip = True,
fill_mode = 'nearest')
height = 224
width = 224
channels = 3
batch_size = 32
num_classes = 10
train_generator = train_datagen.flow_from_directory(train_dir,
target_size= (height, width),
batch_size = batch_size,
shuffle= True,
seed = 7,
class_mode= 'categorical')
valid_datagen = keras.preprocessing.image.ImageDataGenerator(
preprocessing_function = keras.applications.resnet50.preprocess_input)
valid_generator = valid_datagen.flow_from_directory(valid_dir,
target_size= (height, width),
batch_size= batch_size,
shuffle= True,
seed = 7,
class_mode= 'categorical')
print(train_generator.samples) # 1098
print(valid_generator.samples) # 272
2.5 模型训练
# 使用迁移学习, 效果较差, 原始数据的处理方式不同
# 修改需处理方式继续执行, 效果较好
histroy = model.fit(train_generator,
steps_per_epoch= train_generator.samples // batch_size,
epochs = 10,
validation_data = valid_generator,
validation_steps= valid_generator.samples // batch_size)
2.6 训练后面几层神经网络参数
resnet50 = keras.applications.ResNet50(include_top=False, pooling='avg', weights='imagenet')
# 切片指定, 不可调整的层数
for layer in resnet50.layers[0:-5]:
layer.trainable = False
# 添加输出层
resnet50_new = keras.models.Sequential([resnet50, keras.layers.Dense(10, activation = 'softmax')])
resnet50_new.compile(loss = 'categorical_crossentropy',
optimizer = 'adam',
metrics = ['acc'])
resnet50_new.summary()
histroy = resnet50_new.fit(train_generator,
steps_per_epoch= train_generator.samples // batch_size,
epochs = 10,
validation_data = valid_generator,
validation_steps= valid_generator.samples // batch_size)
三 图片处理查看
3.1 图片显示
# 预测数据
mokey = plt.imread('./n5020.jpg')
plt.imshow(mokey) # mokey.shape (600, 336, 3)
for i in range(2):
x, y = train_generator.next()
print(type(x), type(y)) # <class 'numpy.ndarray'> <class 'numpy.ndarray'>
print('***', x.shape, y.shape) # *** (32, 224, 224, 3) (32, 10)
3.2 尺寸变换
# 主要是形状和尺寸不对
# 改变尺寸, 再改变形状reshape
from scipy import ndimage # 专门处理图片
# 改变形状
# 224 = 367 * x x = 224/367
# 224 = 550 * y y = 224/550
zoom = (224/mokey.shape[0], 224/mokey.shape[1])
monkey_zoomed = ndimage.zoom(mokey, (224/mokey.shape[0], 224/mokey.shape[1], 1))
monkey_zoomed.shape # (224, 224, 3)
monkey_1 = keras.applications.resnet50.preprocess_input(monkey_zoomed)
monkey_1.min() # -123.68
monkey_1 = monkey_1.reshape(1, 224, 224, 3)
model.predict(monkey_1).argmax(axis = 1) # array([5], dtype=int64)
3.3 resnet 图片处理方式
3.3.1 前景查看
mokey1 = mokey/127.5
plt.imshow(mokey1)
3.3.2 背景查看
mokey1 = mokey1 - 1
plt.imshow(mokey1)
mokey1