这份数据集来源于Kaggle。原数据集有12500只猫和12500只狗,我们只取了各个类的前1000张图片。另外我们还从各个类中取了400张额外图片用于测试。
下面是数据集的一些示例图片,图片的数量非常少,这对于图像分类来说是个大麻烦。但现实是,很多真实世界图片获取是很困难的,我们能得到的样本数目确实很有限(比如医学图像,每张正样本都意味着一个承受痛苦的病人。
针对小数据集的深度学习
运用数据提升技术:
为了尽量利用我们有限的训练数据,我们将通过一系列随机变换堆数据进行提升,这样我们的模型将看不到任何两张完全相同的图片,这有利于我们抑制过拟合,使得模型的泛化能力更好。
在Keras中,这个步骤可以通过keras.preprocessing.image.ImageGenerator来实现,这个类使你可以:
在训练过程中,设置要施行的随机变换
通过.flow或.flow_from_directory(directory)方法实例化一个针对图像batch的生成器,这些生成器可以被用作keras模型相关方法的输入,如fit_generator,evaluate_generator和predict_generator
先生成一些图片试试水
1.下载图片集,并保存到路径下https://www.kaggle.com/c/dogs-vs-cats/data
import os
os.chdir('C:/Users/ZWT/Desktop/1/cat_dog_keras/train/train')
先试试水,看一下图片尺寸大小和样子
也是熟悉一下PIL的操作
from PIL import Image
img=Image.open('cat.0.jpg')
print img.format, img.size, img.mode#img.shape是不行的,shape针对的是array格式
img.show()
2.试了一下用图片生成器预处理图片:也就是用一张图片,通过变换,加噪声,偏移….生成更多图片,对图片进行提升
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
#初始化图片生成器,说明按照什么方式生成
datagen = ImageDataGenerator(
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')
img = load_img('cat.20.jpg') # this is a PIL image
print img.format,img.size,img.mode
#输出:None (500, 374) RGB,可以看到和Image.open的差别(JPEG和None)
解释一下参数:
1. rotation_range是一个0~180的度数,用来指定随机选择图片的角度。
2. width_shift和height_shift用来指定水平和竖直方向随机移动的程度,这是两个0~1之间的比例。
3. rescale值将在执行其他处理前乘到整个图像上,我们的图像在RGB通道都是0~255的整数,这样的操作可能使图像的值过高或过低,所以我们将这个值定为0~1之间的数。
4. shear_range是用来进行剪切变换的程度,参考剪切变换
5. zoom_range用来进行随机的放大
6. horizontal_flip随机的对图片进行水平翻转,这个参数适用于水平翻转不影响图片语义的时候
7. fill_mode用来指定当需要进行像素填充,如旋转,水平和竖直位移时,如何填充新出现的像素
#图像转成array格式
x = img_to_array(img)# this is a Numpy array with shape (3, 150, 150)
print x.shape
x=x.reshape((1,)+x.shape)
print x.shape
%%输出了:
(3L, 374L, 500L)
(1L, 3L, 374L, 500L)
现在正式开始生成图片了
i=0
for batch in datagen.flow(x,batch_size=1,save_to_dir='preview',save_prefix='cat', save_format='jpeg'):
i+=1
if i>20:
break
#生成20个,这里我在train下建了一个名字为preview的文件夹,生成图片就存在里面
3.
数据提升是对抗过拟合,但还不够,因为提升过的数据仍然是高度相关的。对抗过拟合的你应该主要关注的是模型的“熵容量”——模型允许存储的信息量。也就是特征数量,把没用特征去掉,利用有用特征。
调整模型的“熵容量”方法:
1.调整模型的参数数目,即模型的层数和每层的规模。
2.对权重进行正则化约束,如L1或L2.这种约束会使模型的权重偏向较小的值。
搭建一个只有少量样本的模型
'''
This script goes along the blog post
"Building powerful image classification models using very little data"
from blog.keras.io.
It uses data that can be downloaded at:
https://www.kaggle.com/c/dogs-vs-cats/data
In our setup, we:
- created a data/ folder
- created train/ and validation/ subfolders inside data/
- created cats/ and dogs/ subfolders inside train/ and validation/
- put the cat pictures index 0-999 in data/train/cats
- put the cat pictures index 1000-1400 in data/validation/cats
- put the dogs pictures index 12500-13499 in data/train/dogs
- put the dog pictures index 13500-13900 in data/validation/dogs
So that we have 1000 training examples for each class, and 400 validation examples for each class.
In summary, this is our directory structure:
目录格式
C:/Users/ZWT/Desktop/1/mini_dog_cat/
train/
dogs/
dog001.jpg
dog002.jpg
...
cats/
cat001.jpg
cat002.jpg
...
validation/
dogs/
dog001.jpg
dog002.jpg
...
cats/
cat001.jpg
cat002.jpg
...
与上面的程序不同,这个是对于一个文件夹中所有图片都进行数据提升。一个文件夹中存放几个子文件夹,子文件名相当于类别数,也就是标签。
这里有几个地方:
图片生成器中的batch_size,指的是每次向模型中输入一个batch内所包含图片的多少
达到samples_per_epoch时,一个epoch完成。
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
import h5py
from keras.models import load_model
# dimensions of our images.
img_width, img_height = 150, 150
train_data_dir = 'train'
validation_data_dir = 'validation'
nb_train_samples = 2000
nb_validation_samples = 800
nb_epoch = 50
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(3, img_width, img_height)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(64, 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(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# 实例化图片生成器,说明图片是咋变化的
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# 验证的数据不用变,只需要像素变成0-1区间的
test_datagen = ImageDataGenerator(rescale=1./255)
# 对这个实例化的生成器使用方法,说明它要干什么,从文件夹读图,标签。以及设置要生成目标的参数
train_generator = train_datagen.flow_from_directory(
train_data_dir,#从这个目录里面读取图片
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
#categorical会返回2D的one-hot编码标签,binary返回1D的二值标签
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
model.fit_generator(
train_generator,
samples_per_epoch=nb_train_samples,#2000
nb_epoch=nb_epoch,#50
validation_data=validation_generator,
nb_val_samples=nb_validation_samples)#800
model.save('mini_dog_cat.h5')