特征提取尽量微调
全连接层自己做
数据量小,全冻
数据量中,10000左右,冻前边的
数据量大,冻的少
Resnet论文:Deep Residual Learnling for Image Recognition,Kaiming He
tensorflow.keras.applications
里面有很多现成训练好的模型可以直接利用
如:tf.keras.applications.ResNet152
迁移学习
用人家训练好模型的权重参数当做咱们的初始化
一般全连接层需要自己训练,可以选择是否训练别人训练好的特征提取层
主代码
import os
import warnings
warnings.filterwarnings("ignore")
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers
from tensorflow.keras import Model
base_dir = './data/cats_and_dogs'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')
train_cats_dir = os.path.join(train_dir, 'cats')
train_dogs_dir = os.path.join(train_dir, 'dogs')
validation_cats_dir = os.path.join(validation_dir, 'cats')
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
### 导入模型
from tf.keras.applications.resnet import ResNet50
from tensorflow.keras.applications.resnet import ResNet101
from tensorflow.keras.applications.inception_v3 import InceptionV3
pre_trained_model = ResNet101(input_shape = (75, 75, 3), # 输入大小
include_top = False, # 不要最后的全连接层
weights = 'imagenet')
可先用网址下载(运行后出现)
地址一般在C:\用户\Administrator.keras\models
一个.h5文件
大小设置
input_shape: optional shape tuple, only to be specified if include_top is False (otherwise the input shape has to be (224, 224, 3) (with ‘channels_last’ data format) or (3, 224, 224) (with ‘channels_first’ data format). It should have exactly 3 inputs channels, and width and height should be no smaller than 32. E.g. (200, 200, 3) would be one valid value.
不小于32
要不要加入全连接层
include_top: whether to include the fully-connected layer at the top of the network.
全连接层一般自己做
**
权重参数
weights: one of None (random initialization), ‘imagenet’ (pre-training on ImageNet), or the path to the weights file to be loaded.
可以选择训练哪些层
for layer in pre_trained_model.layers:
layer.trainable = False #不做更新的层,冻
相当于一个监视器,在训练过程中可以设置一些自定义项,比如提前停止,改变学习率等
callbacks = [
如果连续两个epoch还没降低就停止:
tf.keras.callbacks.EarlyStopping(patience=2, monitor=‘val_loss’),
可以动态改变学习率:
tf.keras.callbacks.LearningRateScheduler
保存模型:
tf.keras.callbacks.ModelCheckpoint
自定义方法:
tf.keras.callbacks.Callback
]
class myCallback(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs={}):
if(logs.get('acc')>0.95): #准确率
print("\nReached 95% accuracy so cancelling training!")
self.model.stop_training = True
from tensorflow.keras.optimizers import Adam
# 为全连接层准备
x = layers.Flatten()(pre_trained_model.output) #最后一层结果当做输入
# 加入全连接层,这个需要重头训练的
x = layers.Dense(1024, activation='relu')(x) #拉长
x = layers.Dropout(0.2)(x)
# 输出层
x = layers.Dense(1, activation='sigmoid')(x) #0-1概率值
# 构建模型序列
model = Model(pre_trained_model.input, x)
model.compile(optimizer = Adam(lr=0.001),
loss = 'binary_crossentropy',
metrics = ['acc'])
train_datagen = ImageDataGenerator(rescale = 1./255., #数据增强
rotation_range = 40,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True)
test_datagen = ImageDataGenerator( rescale = 1.0/255. )
train_generator = train_datagen.flow_from_directory(train_dir,
batch_size = 20,
class_mode = 'binary',
target_size = (75, 75))
validation_generator = test_datagen.flow_from_directory( validation_dir,
batch_size = 20,
class_mode = 'binary',
target_size = (75, 75))
Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.
训练模型
加入Callback()模块
callbacks = myCallback()
history = model.fit_generator( #
train_generator,
validation_data = validation_generator,
steps_per_epoch = 100,
epochs = 100,
validation_steps = 50,
verbose = 2,
callbacks=[callbacks]) #传入
绘图展示
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))
plt.plot(epochs, acc, 'b', label='Training accuracy')
plt.plot(epochs, val_acc, 'r', label='Validation accuracy')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs, loss, 'b', label='Training Loss')
plt.plot(epochs, val_loss, 'r', label='Validation Loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
也可以自己选择需要的层,也就是取到哪一层
last_layer = pre_trained_model.get_layer(‘层的名字’)