目录
一.多元分类模型
1.准备数据集
2.数据集处理
3.模型构建
4.模型编译
5.模型训练
6.模型保存
7.模型训练结果分析
8.模型预测(验证)
9.模型结果显示
二.注释
1.fit与fit_generator区别
这里以剪刀石头布为例。具体一些细节已经在CV1-CV3中详细解释过。
一.多元分类模型
1.准备数据集
下载代码:
训练集数据
wget --no-check-certificate \ https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps.zip
测试集数据
wget --no-check-certificate \ https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps-test-set.zip
2.数据集处理
#石头剪刀布(无优化版)
#用GPU跑的话记得需要设置为仅在需要时申请显存。(使用了tensorflow-GPU版本)
import tensorflow as tf
config = tf.compat.v1.ConfigProto(gpu_options=tf.compat.v1.GPUOptions(allow_growth=True))
sess = tf.compat.v1.Session(config=config)
import tensorflow as tf
import keras_preprocessing
from keras_preprocessing import image
from keras_preprocessing.image import ImageDataGenerator
#归一化数据以及数据增强
TRAINING_DIR = "F:/deeplearning/rps/rps"
training_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,
fill_mode='nearest')
#训练集数据不用做数据增强,只归一化数据即可
VALIDATION_DIR = "F:/deeplearning/rps/rps-test-set"
validation_datagen = ImageDataGenerator(rescale=1. / 255)
#分类数据集(指向训练集数据)
train_generator = training_datagen.flow_from_directory(
TRAINING_DIR,
target_size=(150, 150),
class_mode='categorical' #这里的分类模式注意一下
)
# 分类数据集(指向测试集数据)
validation_generator = validation_datagen.flow_from_directory(
VALIDATION_DIR,
target_size=(150, 150),
class_mode='categorical'
)
3.模型构建
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(150, 150, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(3, activation='softmax')
])
#查看模型网络结构
model.summary()
4.模型编译
#模型编译
#注意损失函数
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
5.模型训练
#模型训练,fit_generator和fit的区别可看注释1
history = model.fit_generator(train_generator, epochs=5, validation_data=validation_generator, verbose=1)
6.模型保存
#模型保存
model.save("E:/rps.h5")
7.模型训练结果分析
#模型训练结果分析(以训练集的精确度和测试集的精确度变化作图)
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, 'r', label='Training accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
plt.title('Training and validation accuracy')
plt.legend(loc=0)
plt.figure()
plt.show()
8.模型预测(验证)
注意另创建一个新的python脚本,在这个新的脚本中调用之前保存的model。
#模型预测(验证)
import numpy as np
from keras.preprocessing import image
from tensorflow import keras
import os
#模型加载
model = keras.models.load_model('E:/rps.h5')
#模型预测(可批量图片预测)
path='F:/rps-test/'
for file in os.listdir(path):
img = image.load_img(path+file, target_size=(150, 150))#加载图像
x = image.img_to_array(img) #转换成向量
x = np.expand_dims(x, axis=0) #扩展维度
images = np.vstack([x]) #拉直
classes = model.predict(images, batch_size=10)
print(file)
print(classes)
9.模型结果显示
scissors-hires1.png
[[ 0. 0. 1.]]
paper4.png
[[ 2.77571414e-38 0.00000000e+00 1.00000000e+00]]
paper6.png
[[ 1. 0. 0.]]
scissors1.png
[[ 0. 0. 1.]]
scissors3.png
[[ 0. 0. 1.]]
scissors2.png
[[ 0. 0. 1.]]
scissors9.png
[[ 0. 0. 1.]]
rock7.png
[[ 0. 1. 0.]]
rock9.png
[[ 0. 1. 0.]]
rock8.png
[[ 0. 1. 0.]]
paper-hires1.png
[[ 1. 0. 0.]]
rock4.png
[[ 0. 1. 0.]]
paper5.png
[[ 0. 0. 1.]]
rock2.png
[[ 0. 1. 0.]]
paper9.png
[[ 0. 0. 1.]]
paper1.png
[[ 1. 0. 0.]]
rock6.png
[[ 0. 1. 0.]]
rock5.png
[[ 0. 1. 0.]]
scissors4.png
[[ 0. 0. 1.]]
rock-hires2.png
[[ 0. 1. 0.]]
scissors-hires2.png
[[ 0. 0. 1.]]
paper8.png
[[ 1. 0. 0.]]
paper-hires2.png
[[ 1. 0. 0.]]
rock3.png
[[ 0. 1. 0.]]
rock1.png
[[ 0. 1. 0.]]
paper3.png
[[ 0. 0. 1.]]
paper2.png
[[ 1. 0. 0.]]
scissors5.png
[[ 0. 0. 1.]]
scissors7.png
[[ 0. 0. 1.]]
scissors6.png
[[ 0. 0. 1.]]
rock-hires1.png
[[ 0. 1. 0.]]
scissors8.png
[[ 0. 0. 1.]]
paper7.png
[[ 1. 0. 0.]]
从上述的结果中我们知道训练的结果不算很理想,因为训练集的精度比测试集的精度低并趋于稳定,这说明我们的程序无法获得充分的图像特征,而测试集样本比较少,准确度容易高。而一般来说训练集的精度是要比测试集的精度高的(注意过拟合是训练集的精度在不断升高,但是测试集的精度趋于不变),我们可以通过增加训练集数据或者优化网络结构或者增加训练次数来获得更加理想的结构,在CV5中我们将对这一程序进行优化,从之后的预测结果中我们知道第一个位置如果为1代表布,第二个位置如果为1代表石头,第三个位置如果为1代表剪刀
二.注释
1.fit与fit_generator区别
注意:如果在比较新的tensorflow版本中这俩函数可不用区分,fit_generator直接被废弃,他的功能集合在fit里。
当你使用fit函数的前提条件是
- 训练数据可以完整的放入到内存(RAM)里(数据不算特别多)
- 数据已经不需要再处理了
fit与fit_generator方法的区别主要在于generator上,之前我们把整个数据都输入到fit()里,我们也不需要考虑batch的细节。现在我们使用一个generator,每次生成一个batch送给fit_generator训练。(核心区别)
step_per_epochs参数:由于generator方法的循环没有终止条件,fit_generator也不知道需要一个epoch需要多少batch才结束,所以我们需要手动指定step_per_epochs参数,一般的数值即为len(y)/batch_size。如果数据集大小不能整除batch_size,而且 们打算使用最后一个batch的数据(该batch比batch_size要小),此时使用np.ceil(len(y)/batch_size)。