针对标准的CIFAR10 训练集,通过旋转、比例调整、水平/垂直翻转、缩放、信道交换等多种类型的转换来增加图形(生成更多的图片)。这也是针对训练图片数据不足的情况下提升模型性能的一个方法。
为了尽量利用我们有限的训练数据,我们将通过一系列变换堆数据进行提升,这样我们的模型将看不到任何两张完全相同的图片,有利于抑制过拟合,使得模型的泛化能力更好。
Keras中提供了图片预处理生成器:
(1)在训练过程中,设置要施行的随机变换;
(2)通过 .flow 或者 .flow_from_directory(directory) 方法实例化一个针对图像 batch 的生成器;最终把数据按照每个batch进行划分,送到模型进行训练;
datagen = ImageDataGenerator()
datagen.fit(x_train)
(3)ImageDataGenerator()接收numpy数组和标签为参数,生成经过数据提升或标准化后的batch数据,并在一个无限循环中不断的返回batch数据。
图片生成器ImageDataGenerator() 可以用以生成一个 batch的图像数据,支持实时数据提升,训练时该函数会无限生成数据,直到达到规定的 epoch次数为止。
而flow_from_directory(directory):以文件夹路径为参数,生成经过数据提升/归一化后的数据,在一个无限循环中无限产生batch数据。
针对一张输入图片dog.png,进行一系列随机变换生成20张增强图片,并存储在目标文件夹gen_img_list内:
from keras.preprocessing.image import ImageDataGenerator, image_utils
import os
datagen = ImageDataGenerator(
rotation_range=40, # 随机旋转角度(0~180)
width_shift_range=0.2, # 水平方向的随机移动程度
height_shift_range=0.2, # 竖直方向的随机移动程度
rescale=1. / 255, # 将在执行其他处理前乘到整个图像上
shear_range=0.2, # 用来进行剪切变换的程度,参考剪切变换
zoom_range=0.2, # 随机缩放
horizontal_flip=True, # 随机水平翻转
fill_mode='nearest' # 图片翻转或交换后用来填充新像素时采用的策略
)
img_path = 'dog.png'
img = image_utils.load_img(img_path)
x = image_utils.img_to_array(img) # this is a Numpy array with shape (150, 150, 3)
x = x.reshape((1,) + x.shape) # this is a Numpy array with shape (1, 150, 150, 3)
if not os.path.exists('gen_img_list'):
os.mkdir('gen_img_list')
i = 0
for batch in datagen.flow(x, batch_size=1, save_to_dir='gen_img_list', save_prefix='dog', save_format='jpg'):
i += 1
if i > 20:
break
# _*_coding:utf-8_*_
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.preprocessing.image import ImageDataGenerator, image_utils
from keras.models import load_model
import cv2
import numpy as np
def built_model():
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(150, 150, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
# 此处可加多层
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
# -------多分类----------
model.add(Dense(5))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
# -------二分类----------
# model.add(Dense(1))
# model.add(Activation('sigmoid'))
# model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
model.summary()
return model
def generate_data():
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True
)
test_datagen = ImageDataGenerator(rescale=1. / 255)
# 使用 .flow_from_directory() 来从我们的jpgs图片中直接产生数据和标签
train_generator = train_datagen.flow_from_directory(
'data/mytrain',
target_size=(150, 150), # all images will be resized to 150*150
batch_size=32,
class_mode='categorical' # 多分类
# class_mode = 'binary' # 二分类
)
validation_generator = test_datagen.flow_from_directory(
'data/mytest',
target_size=(150, 150),
batch_size=32,
class_mode='categorical' # 多分类
)
return train_generator, validation_generator
def train_model(train_generator, validation_generator):
model = built_model()
model.fit_generator(
train_generator,
samples_per_epoch=2000, # 相当于每个epoch数据量峰值,每个epoch以经过模型的样本数达到samples_per_epoch时,记一个epoch结束
nb_epoch=50,
validation_data=validation_generator,
nb_val_samples=800)
model.save_weights('animal.h5')
def model_predict_batch(model, img_dir, target_size):
img_gen = ImageDataGenerator(rescale=1. / 255)
newsample_generator = img_gen.flow_from_directory(
img_dir,
target_size=target_size,
batch_size=16,
class_mode=None,
shuffle=False)
res = model.predict_generator(newsample_generator)
return res
def model_predict_one(model, img_path, target_size):
img = cv2.imread(img_path)
if img.shape != target_size:
img = cv2.resize(img, target_size)
# print(img.shape)
x = image_utils.img_to_array(img)
x *= 1. / 255 # 相当于ImageDataGenerator(rescale=1. / 255)
x = np.expand_dims(x, axis=0) # 调整图片维度
preds = model.predict(x)
return preds[0]
if __name__ == '__main__':
train_generator, validation_generator = generate_data()
train_model(train_generator, validation_generator)
model_path = 'animal.h5'
model = load_model(model_path)
target_size = (150, 150)
img_dir = 'img_path'
res = model_predict_batch(model, img_dir, target_size)
print(res)
img_path = 'data/test/300.jpg'
res = model.predict(model, img_path, target_size)
print(res)