学习一下迁移学习。。。
1.inceptionV3
"""
python=3.6
tf=2.3.1
"""
import os
import tensorflow as tf
from tensorflow.keras.models import *
from tensorflow.keras.layers import *
from tensorflow.keras.applications import *
from tensorflow.keras.preprocessing.image import *
from tensorflow import keras as keras
import numpy as np
# import cv2
from PIL import Image
import matplotlib.pyplot as plt
#2.加载数据
train_normal = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train\normal"
train_phone = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train\calling"
train_smoke = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train\smoking"
train_dir = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train"
val_dir = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val"#验证集用01_train_test_splict.py生成
val_normal = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val\normal"
val_phone = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val\calling"
val_smoke = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val\smoking"
test_dir = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\test"#测试集是需要我们预测结果
train_normal_num = len(os.listdir(train_normal))
train_phone_num = len(os.listdir(train_phone))
train_smoke_num = len(os.listdir(train_smoke))
val_normal_num = len(os.listdir(val_normal))
val_phone_num = len(os.listdir(val_phone))
val_smoke_num = len(os.listdir(val_smoke))
train_all = train_normal_num + train_phone_num + train_smoke_num
val_all = val_normal_num + val_phone_num + val_smoke_num
test_num = len(os.listdir(test_dir))
print("train normal number: ", train_normal_num)
print("train phone_num: ", train_phone_num)
print("train_smoke_num: ", train_smoke_num)
print("all train images: ", train_all)
print("val normal number: ", val_normal_num)
print("val phone_num: ", val_phone_num)
print("val_smoke_num: ", val_smoke_num)
print("all val images: ", val_all)
print("all test images: ", test_num)
# 3.设置超参数
batch_size = 512 #显存内存允许的情况下尽量大
epochs = 1000 #有早停技术,尽量大
height = 299
width = 299
num_classes = 3
# 4.数据增强
# 读取训练数据并作数据增强
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
# 给resnet50预处理图像的函数
preprocessing_function = tf.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,
# 对图片做处理时需要填充图片,用最近的像素点填充
fill_mode = "nearest"
)
# 读取训练数据
train_generator = train_datagen.flow_from_directory(
train_dir,
# 读取后将图片存什么大小
target_size = (height, width),
batch_size = batch_size,
seed = 7,
shuffle = True,
# label的编码格式:这里为one-hot编码
class_mode = 'categorical')
# 读取验证数据
valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
preprocessing_function = tf.keras.applications.resnet50.preprocess_input)
valid_generator = valid_datagen.flow_from_directory(
val_dir,
# 读取后将图片存什么大小
target_size = (height, width),
batch_size = batch_size,
seed = 7,
shuffle = False,
# label的编码格式:这里为one-hot编码
class_mode = 'categorical')
#5.搭建模型
imagenet_weight = "./model/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5"
base_model = InceptionV3(input_tensor=Input(shape=(299, 299, 3)), weights=imagenet_weight, include_top=False)
base_model.summary()
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(num_classes, activation='softmax')(x)
model = Model(base_model.input, predictions)
for layer in base_model.layers:
layer.trainable = False
model.compile(keras.optimizers.SGD(lr=0.001, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])
#6.添加callbacks:早停,检查点,tensorboard,训练记录
stop_callback = tf.keras.callbacks.EarlyStopping(
monitor='val_loss', min_delta=0.0001,
patience=13
)
# 在文件名中包含 epoch (使用 `str.format`)
checkpoint_path = "saved_model/best_incptionv3.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
# 创建一个回调,每 5 个 epochs 保存模型的权重
cp_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_path,
verbose=1,
save_weights_only=False,
save_best_only=True)
# # 使用 `checkpoint_path` 格式保存权重
# model_new.save_weights(checkpoint_path.format(epoch=0))
logdir = "./model/inceptionv3"
tb_callback = tf.keras.callbacks.TensorBoard(log_dir=logdir), #log_dir将输出的日志保存在所要保存的路径中
log_callback = tf.keras.callbacks.CSVLogger(
"training_log_inceptionv3", separator=',', append=False
)
callbacks = [stop_callback,cp_callback,*tb_callback,log_callback]#tb_callback是元组,加*展开
# print(type(stop_callback),type(cp_callback),type(tb_callback),type(log_callback))
#7.训练
#数据是generator出来的,所以不能直接用fit
history = model.fit_generator(train_generator,
steps_per_epoch = train_all // batch_size,
epochs=epochs,
validation_data = valid_generator,
validation_steps = val_all // batch_size,
callbacks=callbacks,
verbose=2
)
model.save('./saved_model/inceptionV3_model.h5')
print("模型保存成功")
2.resnet50迁移学习
"""
tf2.3.0
python3.6
"""
# 1.导入包
import numpy as np
import os
import tensorflow as tf
from tensorflow.keras.applications.resnet50 import ResNet50
# # 2.加载数据
train_normal = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train\normal"
train_phone = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train\calling"
train_smoke = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train\smoking"
train_dir = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\train"
val_dir = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val"#验证集用01_train_test_splict.py生成
val_normal = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val\normal"
val_phone = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val\calling"
val_smoke = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\val\smoking"
test_dir = r"C:\Users\Administrator\PycharmProjects\pythonProject\01_tf2_somking_calling\data\test"#测试集是需要我们预测结果
train_normal_num = len(os.listdir(train_normal))
train_phone_num = len(os.listdir(train_phone))
train_smoke_num = len(os.listdir(train_smoke))
val_normal_num = len(os.listdir(val_normal))
val_phone_num = len(os.listdir(val_phone))
val_smoke_num = len(os.listdir(val_smoke))
train_all = train_normal_num + train_phone_num + train_smoke_num
val_all = val_normal_num + val_phone_num + val_smoke_num
test_num = len(os.listdir(test_dir))
print("train normal number: ", train_normal_num)
print("train phone_num: ", train_phone_num)
print("train_smoke_num: ", train_smoke_num)
print("all train images: ", train_all)
print("val normal number: ", val_normal_num)
print("val phone_num: ", val_phone_num)
print("val_smoke_num: ", val_smoke_num)
print("all val images: ", val_all)
print("all test images: ", test_num)
# 3.设置超参数
batch_size = 512 #显存内存允许的情况下尽量大
epochs = 500 #有早停技术,尽量大
height = 224
width = 224
num_classes = 3
# 8.数据增强
# 读取训练数据并作数据增强
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
# 给resnet50预处理图像的函数
preprocessing_function = tf.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,
# 对图片做处理时需要填充图片,用最近的像素点填充
fill_mode = "nearest"
)
# 读取训练数据
train_generator = train_datagen.flow_from_directory(
train_dir,
# 读取后将图片存什么大小
target_size = (height, width),
batch_size = batch_size,
seed = 7,
shuffle = True,
# label的编码格式:这里为one-hot编码
class_mode = 'categorical')
# 读取验证数据
valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
preprocessing_function = tf.keras.applications.resnet50.preprocess_input)
valid_generator = valid_datagen.flow_from_directory(
val_dir,
# 读取后将图片存什么大小
target_size = (height, width),
batch_size = batch_size,
seed = 7,
shuffle = False,
# label的编码格式:这里为one-hot编码
class_mode = 'categorical')
# 4. 搭建模型
imagenet_weight = "./model/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5"
resnet50_fine_tune = tf.keras.models.Sequential()
# resnet50最后一层有1000类,所以在本例中把最后一层去掉(include_top = False)
# resnet的倒数第二层是一个三维矩阵,所以无法与全连接层连接,故要pooling
# weights = 'imagenet': 下载一个模型,然后在这个模型的基础上进行训练
# weights = 'None':从头开始训练
resnet50_fine_tune.add(ResNet50(include_top = False,
pooling = 'avg',
weights = imagenet_weight
))
resnet50_fine_tune.add(tf.keras.layers.Dense(num_classes,activation = 'softmax'))
resnet50_fine_tune.layers[0].trainable = False
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)#自定义,便于修改学习率
resnet50_fine_tune.compile(loss="categorical_crossentropy",
optimizer=optimizer,
metrics = ["accuracy"])
resnet50_fine_tune.summary()
#添加callbacks:早停,检查点,tensorboard,训练记录
stop_callback = tf.keras.callbacks.EarlyStopping(
monitor='val_loss', min_delta=0.0001,
patience=10
)
# 在文件名中包含 epoch (使用 `str.format`)
checkpoint_path = "saved_model/resnet50_best.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
# 创建一个回调,每 5 个 epochs 保存模型的权重
cp_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=checkpoint_path,
verbose=1,
save_weights_only=False,
save_best_only=True)
# # 使用 `checkpoint_path` 格式保存权重
# model_new.save_weights(checkpoint_path.format(epoch=0))
logdir = "./model/resnet50"
tb_callback = tf.keras.callbacks.TensorBoard(log_dir=logdir), #log_dir将输出的日志保存在所要保存的路径中
log_callback = tf.keras.callbacks.CSVLogger(
"training_log_resnet50", separator=',', append=False
)
callbacks = [stop_callback,cp_callback,*tb_callback,log_callback]#tb_callback是元组,加*展开
# print(type(stop_callback),type(cp_callback),type(tb_callback),type(log_callback))
# 数据是generator出来的,所以不能直接用fit
history = resnet50_fine_tune.fit_generator(train_generator,
steps_per_epoch = train_all // batch_size,
epochs=epochs,
validation_data = valid_generator,
validation_steps = val_all // batch_size,
callbacks=callbacks,
verbose=2
)
resnet50_fine_tune.save('./saved_model/resnet50_fine_tune_model.h5')
print("模型保存成功")
3.对比:
1. 几乎没调参
2. 效果来看在跑50epoch下,resnet50在线上准确率85%左右,前几十名都在九十几。。。
3. 图像增强小技巧用的也少,见过其他版本用图像模糊,马赛克增强等技巧效果可能会好些,期待AIers友们的代码,我自己写的太简单了,只是参考tf2官网上的猫狗分类代码;
4.复赛增加了吸烟&打电话一起的图片,可能目标检测网络会好些
补上数据20210205: