【深度学习框架Keras】在⼩数据集上训练图⽚分类模型的技巧说明:
1.主要参考Francois Chollet《Deep Learning with Python》;
2.代码运⾏环境为kaggle中的kernels;
3.数据集和预训练模型VGG-16需要⼿动添加;
4.卷积神经⽹络请参考:
# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python docker image: github/kaggle/docker-python
# For example, here's several helpful packages to load in
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
# Input data files are available in the "../input/" directory.
# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory
import os,shutil
print(os.listdir("../input"))
# Any results you write to the current directory are saved as output.
⼀、创建训练、验证和测试样本的⽬录
base_dir ='..'
# 创建训练样本⽬录
train_dir = os.path.join(base_dir,'train')
os.mkdir(train_dir)
# 创建验证样本⽬录
validation_dir = os.path.join(base_dir,'validation')
os.mkdir(validation_dir)
# 创建测试样本⽬录
test_dir = os.path.join(base_dir,'test')
os.mkdir(test_dir)
# 创建训练样本⽬录中的cats⽬录
train_cats_dir = os.path.join(train_dir,'cats')
os.mkdir(train_cats_dir)
# 创建训练样本⽬录中的dogs⽬录
train_dogs_dir = os.path.join(train_dir,'dogs')
os.mkdir(train_dogs_dir)
# 创建验证样本⽬录中的cats⽬录
validation_cats_dir = os.path.join(validation_dir,'cats')
os.mkdir(validation_cats_dir)
# 创建验证样本⽬录中的dogs⽬录
validation_dogs_dir = os.path.join(validation_dir,'dogs')
os.mkdir(validation_dogs_dir)
# 创建测试样本⽬录中的cats⽬录
test_cats_dir = os.path.join(test_dir,'cats')
os.mkdir(test_cats_dir)
# 创建测试样本⽬录中的dogs⽬录
test_dogs_dir = os.path.join(test_dir,'dogs')
os.mkdir(test_dogs_dir)
⼆、拷贝数据到对应的⽬录
2000张训练图⽚,1000张验证图⽚,1000张测试图⽚,其中猫和狗各占⼀半original_dataset_dir ='../input/dogs-vs-cats/train/train'
# 拷贝前1000张猫的图⽚到train_cats_dir中
fnames =['cat.{}.jpg'.format(i)for i in range(1000)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(train_cats_dir,fname)
# 拷贝接下来的500张猫的图⽚到validation_cats_dir
fnames =['cat.{}.jpg'.format(i)for i in range(1000,1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(validation_cats_dir,fname)
# 拷贝再接下来的500张猫的图⽚到test_cats_dir
fnames =['cat.{}.jpg'.format(i)for i in range(1500,2000)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(test_cats_dir,fname)
fnames =['dog.{}.jpg'.format(i)for i in range(1000)]
# 拷贝前1000张狗的图⽚到train_cats_dir中
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(train_dogs_dir,fname)
# 拷贝接下来的500张狗的图⽚到validation_cats_dir
fnames =['dog.{}.jpg'.format(i)for i in range(1000,1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(validation_dogs_dir,fname)
# 拷贝再接下来的500张狗的图⽚到test_cats_dir
fnames =['dog.{}.jpg'.format(i)for i in range(1500,2000)]
for fname in fnames:
src = os.path.join(original_dataset_dir,fname)
dst = os.path.join(test_dogs_dir,fname)
三、构建神经⽹络
from keras import layers
from keras import models
from keras import optimizers
model = models.Sequential()
# 输⼊的图形尺⼨为150*150,channel为3
# filter尺⼨为3*3,深度为32
# 该层的输出为:148*148*32
# 参数数量为:3*3*3*32+32=896
model.add(layers.Conv2D(32,(3,3),activation='relu',input_shape=(150,150,3)))
# 该层输出为:74*74*32
model.add(layers.MaxPool2D(2,2))
# filter尺⼨为3*3,深度为64
# 该层的输出为:72*72*64
# 参数的数量为:3*3*32*64+64=18496
model.add(layers.Conv2D(64,(3,3),activation='relu'))
# 该层的输出为:36*36*64
model.add(layers.MaxPool2D(2,2))
# filter尺⼨为3*3,深度为128
# 该层的输出为:34*34*128
# 参数的数量为:3*3*64*128+128=73856
model.add(layers.Conv2D(128,(3,3),activation='relu'))
# 该层的输出为:17*17*128
model.add(layers.MaxPool2D(2,2))
# filter尺⼨为3*3,深度为128
# 该层的输出为:15*15*128
# 参数的数量为:3*3*128*128+128=147584
model.add(layers.Conv2D(128,(3,3),activation='relu'))
# 该层的输出为:7*7*128
model.add(layers.MaxPool2D(2,2))
model.add(layers.Flatten())
# 全连接层,参数的数量为:7*7*128*512+512 = 321176
model.add(layers.Dense(512,activation='relu'))
# 由于是⼆分类问题,最后⼀层只有⼀个激活函数为sigmoid的神经元
model.add(layers.Dense(1,activation='sigmoid'))
modelpile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(lr=1e-4),
metrics=['acc'])
四、数据预处理
通常在数据被喂给神经⽹络前,应该将数据处理成类型为float的tensor。我们的数据是位于磁盘中的JPEG图⽚,因此需要做⼀些转换的⼯作:
⾸先,读取图⽚⽂件到内存中;
然后,解码JPEG图⽚使其转变为RGB像素⽹格;
再后,将其转换成类型为float的tensor;
将像素值缩放到[0,1]区间
上⾯说的这些操作在keras.preprocessing.image中有提供,其中ImageDataGenerator可以⼀步到位将上⾯的操作完成。
generator是⼀个迭代器,可以迭代的产⽣出数据。
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255)# 将原始数据缩放到原来的1/255
test_datagen = ImageDataGenerator(rescale=1./255)
# 从指定的⽬录中产⽣批量的格式化数据
# target_size:所有图⽚经过处理后的尺⼨
# 该generator每次返回⼀个20*150*150*3的张量和binary类型的标签(shape(20,))
train_generator = train_datagen.flow_from_directory(train_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(validation_dir,
target_size=(150,150),
batch_size=20,
class_mode='binary')
Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.
五、训练模型与保存模型
使模型拟合generator要使⽤fit_generator()⽅法
在fit时,要使模型知道经过多少个batch后是⼀整个epoch,这个值由steps_per_epoch给定。由于我们的例⼦中有2000样本,batch_size为20,因此steps_per_epoch为1000
如果参数validation_data传⼊的也是generator,那么同样也要指定⼀整个epoch有多少个batch,这个值由参数validation_steps指定。我们的例⼦中验证样本有1000张图⽚,batch_size为20,因此validation_steps为50.
history = model.fit_generator(train_generator,
steps_per_epoch=100,
epochs=30,
validation_data=validation_generator,
validation_steps=50)
model.save('cats_and_dogs_small_1.h5')
Epoch 1/30
100/100 [==============================] - 14s 140ms/step - loss: 0.6885 - acc: 0.5440 - val_loss: 0.6912 - val_acc: 0.5020
...
Epoch 30/30
100/100 [==============================] - 10s 104ms/step - loss: 0.0409 - acc: 0.9885 - val_loss: 1.0625 - val_acc: 0.7210
六、绘制准确率和损失曲线
import matplotlib.pyplot as plt
%matplotlib inline
def plot_curve(history):
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs =range(1,len(acc)+1)
plt.plot(epochs,acc,'bo',label='Training acc')
plt.plot(epochs,val_acc,'b',label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs,loss,'bo',label='Training loss')
validation框架plt.plot(epochs,val_loss,'b',label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plot_curve(history)
观察上⾯的曲线,发现准确率⼤约在0.73左右,⽽且明显出现了过拟合。由于我们的训练样本只有2000张,过拟合⾮常的正常。通常我们解决过拟合的⽅法是dropout和权重衰减,但下⾯我们使⽤“数据增强”的⽅式来抵抗过拟合。
七、数据增强
数据增强的思想就是使⽤已有的训练样本产⽣更多的训练样本。
1.配置ImageDataGenerator的数据增强参数来产⽣更多的样本数据
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论