在《提升模型性能,你能够尝试这几招...》一文中,咱们给出了几种提升模型性能的方法,但这篇文章是在训练数据集不变的前提下提出的优化方案。其实对于深度学习而言,数据量的多寡一般对模型性能的影响更大,因此扩充数据规模通常状况是一个很是有效的方法。python
对于Google、Facebook来讲,收集几百万张图片,训练超大规模的深度学习模型,天然不在话下。可是对于我的或者小型企业而言,收集现实世界的数据,特别是带标签的数据,将是一件很是费时费力的事。本文探讨一种技术,在现有数据集的基础上,进行数据加强(data augmentation),增长参与模型训练的数据量,从而提高模型的性能。git
所谓数据加强,就是采用在原有数据上随机增长抖动和扰动,从而生成新的训练样本,新样本的标签和原始数据相同。这个也很好理解,对于一张标签为“狗”的图片,作必定的模糊、裁剪、变形等处理,并不会改变这张图片的类别。数据加强也不只局限于图片分类应用,好比有以下图所示的数据,数据知足正态分布:github
咱们在数据集的基础上,增长一些扰动处理,数据分布以下:web
数据就在原来的基础上增长了几倍,但总体上仍然知足正态分布。有人可能会说,这样的出来的模型不是没有原来精确了吗?考虑到现实世界的复杂性,咱们采集到的数据很难彻底知足正态分布,因此这样增长数据扰动,不只不会下降模型的精确度,然而加强了泛化能力。算法
对于图片数据而言,可以作的数据加强的方法有不少,一般的方法是:bash
上面几种方法,可能切变(shearing)比较难以理解,看一张图就明白了:微信
咱们要亲自编写这些数据加强算法吗?一般不须要,好比keras就提供了批量处理图片变形的方法。post
keras中提供了ImageDataGenerator类,其构造方法以下:性能
ImageDataGenerator(featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization = False,
samplewise_std_normalization = False,
zca_whitening = False,
rotation_range = 0.,
width_shift_range = 0.,
height_shift_range = 0.,
shear_range = 0.,
zoom_range = 0.,
channel_shift_range = 0.,
fill_mode = 'nearest',
cval = 0.0,
horizontal_flip = False,
vertical_flip = False,
rescale = None,
preprocessing_function = None,
data_format = K.image_data_format(),
)
复制代码
参数不少,经常使用的参数有:学习
完整的参数说明请参考keras文档。
下面一段代码将1张给定的图片扩充为10张,固然你还能够扩充更多:
image = load_img(args["image"])
image = img_to_array(image)
image = np.expand_dims(image, axis=0)
aug = ImageDataGenerator(rotation_range=30, width_shift_range=0.1, height_shift_range=0.1,
shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode="nearest")
aug.fit(image)
imageGen = aug.flow(image, batch_size=1, save_to_dir=args["output"], save_prefix=args["prefix"],
save_format="jpeg")
total = 0
for image in imageGen:
# increment out counter
total += 1
if total == 10:
break
复制代码
须要指出的是,上述代码的最后一个迭代是必须的,否在不会在output目录下生成图片,另外output目录必须存在,不然会出现一下错误:
Traceback (most recent call last):
File "augmentation_demo.py", line 35, in <module>
for image in imageGen:
File "/data/ai/anaconda3/envs/keras/lib/python3.6/site-packages/keras_preprocessing/image.py", line 1526, in __next__
return self.next(*args, **kwargs)
File "/data/ai/anaconda3/envs/keras/lib/python3.6/site-packages/keras_preprocessing/image.py", line 1704, in next
return self._get_batches_of_transformed_samples(index_array)
File "/data/ai/anaconda3/envs/keras/lib/python3.6/site-packages/keras_preprocessing/image.py", line 1681, in _get_batches_of_transformed_samples
img.save(os.path.join(self.save_to_dir, fname))
File "/data/ai/anaconda3/envs/keras/lib/python3.6/site-packages/PIL/Image.py", line 1947, in save
fp = builtins.open(filename, "w+b")
FileNotFoundError: [Errno 2] No such file or directory: 'output/image_0_1091.jpeg'
复制代码
以下一张狗狗的图片:
通过数据加强技术处理以后,能够获得以下10张形态稍微不一样的狗狗的图片,这至关于在原有数据集上增长了10倍的数据,其实咱们还能够扩充得最多:
咱们以MiniVGGNet模型为例,说明在其在17flowers数据集上进行训练的效果。17flowers是一个很是小的数据集,包含17中品类的花卉图案,每一个品类包含80张图片,这对于深度学习而言,数据量实在是过小了。通常而言,要让深度学习模型有必定的精确度,每一个类别的图片至少须要1000~5000张。这样的数据集能够很好的说明数据加强技术的必要性。
从网站上下载的17flowers数据,全部的图片都放在一个目录下,而咱们一般训练时的目录结构为:
{类别名}/{图片文件}
复制代码
为此我写了一个organize_flowers17.py脚本。
在没有使用数据加强的状况下,在训练数据集和验证数据集上精度、损失随着训练轮次的变化曲线图:
能够看到,大约通过十几轮的训练,在训练数据集上的准确率很快就达到了接近100%,然而在验证数据集上的准确率却没法再上升,只能达到60%左右。这个图能够明显的看出模型出现了很是严重的过拟合。
若是采用数据加强技术呢?曲线图以下:
从图中能够看到,虽然在训练数据集上的准确率有所降低,但在验证数据集上的准确率有比较明显的提高,说明模型的泛化能力有所加强。
也许在咱们看来,准确率从60%多增长到70%,只有10%的提高,并非什么了不起的成绩。但要考虑到咱们采用的数据集样本数量实在是太少,可以达到这样的提高已是很是可贵,在实际项目中,有时为了提高1%的准确率,都会花费很多的功夫。
数据加强技术在必定程度上可以提升模型的泛化能力,减小过拟合,但在实际中,咱们若是可以收集到更多真实的数据,仍是要尽可能使用真实数据。另外,数据加强只需应用于训练数据集,验证集上则不须要,毕竟咱们但愿在验证集上测试真实数据的准确。
以上实例均有完整的代码,点击阅读原文,跳转到我在github上建的示例代码。
另外,我在阅读《Deep Learning for Computer Vision with Python》这本书,在微信公众号后台回复“计算机视觉”关键字,能够免费下载这本书的电子版。