上传下载notebook
运行第一行
导入库
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import os
import pandas as pd
import sklearn
import sys
import tensorflow as tf
import time
from tensorflow import keras
print(tf.__version__)
print(sys.version_info)
for module in mpl, np, pd, sklearn, tf, keras:
print(module.__name__, module.__version__)
首先定义三个路径
训练集,验证集和label file的路径
读取label
labels = pd.read_csv(label_file, header=0)
print(labels)
读取图片
height = 128
width = 128
channels = 3
batch_size = 64
num_classes = 10
train_datagen = keras.preprocessing.image.ImageDataGenerator(
rescale = 1./255, #归一化到0-1之间
rotation_range = 40, #图片旋转角度
width_shift_range = 0.2, #位移距离0-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,
class_mode = "categorical")
valid_datagen = keras.preprocessing.image.ImageDataGenerator(rescale = 1./255)
valid_generator = valid_datagen.flow_from_directory(valid_dir,
target_size = (height, width),
batch_size = batch_size,
seed = 7,
shuffle = False,
class_mode = "categorical")
train_num = train_generator.samples
valid_num = valid_generator.samples
print(train_num, valid_num)
读取数据
for i in range(2): #遍历两次
x, y = train_generator.next()
print(x.shape, y.shape)
print(y)
这里测试数据不是64*10的,有子文件夹
每个样本的值都是one-hot编码
构建模型
两个卷积加一个pooling构成一个组合,使用三层组合
model = keras.models.Sequential([
keras.layers.Conv2D(filters=32, kernel_size=3, padding='same',
activation='relu', input_shape=[width, height, channels]),
keras.layers.Conv2D(filters=32, kernel_size=3, padding='same',
activation='relu'),
keras.layers.MaxPool2D(pool_size=2),
# 翻倍
keras.layers.Conv2D(filters=64, kernel_size=3, padding='same',
activation='relu'),
keras.layers.Conv2D(filters=64, kernel_size=3, padding='same',
activation='relu'),
keras.layers.MaxPool2D(pool_size=2),
keras.layers.Conv2D(filters=128, kernel_size=3, padding='same',
activation='relu'),
keras.layers.Conv2D(filters=128, kernel_size=3, padding='same',
activation='relu'),
keras.layers.MaxPool2D(pool_size=2),
keras.layers.Flatten(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(num_classes, activation='softmax'),
])
model.compile(loss="categorical_crossentropy",
optimizer="adam", metrics=['accuracy'])
model.summary()
训练
epochs = 10
history = model.fit_generator(train_generator,
steps_per_epoch = train_num // batch_size,
epochs = epochs,
validation_data = valid_generator,
validation_steps = valid_num // batch_size)
打印学习曲线
def plot_learning_curves(history, label, epcohs, min_value, max_value):
data = {}
data[label] = history.history[label]
data['val_'+label] = history.history['val_'+label]
pd.DataFrame(data).plot(figsize=(8, 5))
plt.grid(True)
plt.axis([0, epochs, min_value, max_value])
plt.show()
plot_learning_curves(history, 'accuracy', epochs, 0, 1)
plot_learning_curves(history, 'loss', epochs, 1.5, 2.5)
模型微调
残差网络
修改模型
height = 224
width = 224
channels = 3
batch_size = 24
num_classes = 10
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,
fill_mode = 'nearest',
)
train_generator = train_datagen.flow_from_directory(train_dir,
target_size = (height, width),
batch_size = batch_size,
seed = 7,
shuffle = True,
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,
seed = 7,
shuffle = False,
class_mode = "categorical")
train_num = train_generator.samples
valid_num = valid_generator.samples
print(train_num, valid_num)
修改fit
resnet50_fine_tune = keras.models.Sequential()
# 最后一层去掉 进行训练
resnet50_fine_tune.add(keras.applications.ResNet50(include_top = False,
pooling = 'avg',
weights = 'imagenet'))
# 定义最后一层 全连接层 只调整最后一层的参数
resnet50_fine_tune.add(keras.layers.Dense(num_classes, activation = 'softmax'))
resnet50_fine_tune.layers[0].trainable = False
resnet50_fine_tune.compile(loss="categorical_crossentropy",
optimizer="sgd", metrics=['accuracy'])
resnet50_fine_tune.summary()
微调训练
epochs = 10
history = resnet50_fine_tune.fit_generator(train_generator,
steps_per_epoch = train_num // batch_size,
epochs = epochs,
validation_data = valid_generator,
validation_steps = valid_num // batch_size)
微调学习曲线
训练效果比较好,只有最后一层被进行训练
那么怎么训练最后几层呢?
resnet50 = keras.applications.ResNet50(include_top = False,
pooling = 'avg',
weights = 'imagenet')
resnet50.summary()
得到一个很长的输出,是resnet50的一个网络结构
# 对后五层进行遍历 后面五层可以训练
for layer in resnet50.layers[0:-5]:
layer.trainable = False
resnet50_new = keras.models.Sequential([
resnet50,
keras.layers.Dense(num_classes, activation = 'softmax'),
])
resnet50_new.compile(loss="categorical_crossentropy",
optimizer="sgd", metrics=['accuracy'])
resnet50_new.summary()
可进行训练的参数是一百万多个。
epochs = 10
history = resnet50_new.fit_generator(train_generator,
steps_per_epoch = train_num // batch_size,
epochs = epochs,
validation_data = valid_generator,
validation_steps = valid_num // batch_size)
训练效果
1.可训练参数变多,收敛到一个比较好的效果需要的时间更长。
2.最后五层和最后一层是不一样的,如果设置相同的学习率,学习率比较大的会回调的时间更长。
解决方法:调小学习率,增加迭代次数。
plot_learning_curves(history, 'accuracy', epochs, 0, 1)
plot_learning_curves(history, 'loss', epochs, 0, 2)