yueguizhilin 2019-12-10
全文共4496字,预计学习时长13分钟
图源:Unsplash
在机器学习中,决定因素往往不是算法而是数据集的大小。——吴恩达
图像分类即根据固定类别对输入的图像设置标签。尽管计算机视觉过于简单,但是它在实际中仍有广泛的应用,而图像分类就是其中的核心问题之一。
在本文中,小芯将示范如何在数据不足的情况下应用深度学习。现已创建特制汽车和巴士分类器两个数据集,每个数据集包含100个图像。其中,训练集有70个图像,验证集有30个。
挑战
1. 视点变化:基于相机,单一对象实例可以从多个视角聚焦。
2. 尺度变化:视觉分类常常存在尺度变化(这里的尺度指的是现实世界中的物体的大小,而不仅仅就图像而言)。
3. 图片变形:许多目标对象并非刚体(指在运动中和受力作用后,形状和大小不变,而且内部各点的相对位置不变的物体),可能会产生极端变形。
4. 图片遮挡:目标对象可能会被遮挡,所以有时只会显示对象的一小部分(最少时可能只有一些像素点)。
5. 光照条件:光照影响在像素级别上非常明显。
猫vs 狗图像分类
应用
1. 图片库和视频网站:促成图片网站每日数十亿的搜索量。为用户提供工具,通过搜索找到可视化内容。
2. 为改善产品可寻性提供可视化搜索:采用可视化搜索,用户可以将自行拍摄的图像或网上下载的图像作为参考搜寻相似的图像或产品。
3. 安保行业:这项新兴技术在安保行业举足轻重,已用于研发多种安保设备,如:无人机、监控摄像头和用于面部识别的生物特征识别设备等等。
4. 医疗行业:医疗行业中,机器人驱动的显微外科手术就利用了计算机视觉和图像识别技术。
5. 汽车行业:这项技术可以减少道路交通事故,促进人们遵守交通规则、维护交通秩序等。
数据量函数模型性能
环境和工具:
1. Matplotlib
2. keras
数据
这是一个二进制分类的问题。小芯下载了200个图像,其中100个为巴士图像,剩下的是汽车图像。现将数据分解如下所示:
dataset train
car
car1.jpg
car2.jpg
//
bus
bus1.jpg
bus2.jpg
// validation
car
car1.jpg
car2.jpg
//
bus
bus1.jpg
bus2.jpg
//...
汽车
巴士
图像分类
正式且完整的图像分类路径如下:
· 输入包含N个图像的训练集,每个图像均由单一类别标记,总共有两种不同类别。
· 随后,利用该训练集训练分类器辨认各个类别的特征。
· 最后,要求分类器对之前从未接触过的新图像进行标签预测,随后对比这些图像的实际标签和分类器预测的标签,以此来评估分类器的性能。
首先是编写代码。
一开始先加载keras及其各层,这些将用于后面的模型构建。
from keras.models import Sequential
from keras.layers import Convolution2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
viewrawimports6.py hostedwith ❤ by GitHub
接下来,构建模型,可分为3步完成。
1.使用2个由卷积层和最大池化层组成的卷积块,将线性整流函数(Rectified LinearUnit, ReLU)作为卷积层的激活函数。
2.最顶部使用flatten层,下面是分别由线性整流函数和S型函数作为激活函数的两个完全连接层。
3.使用Adam优化器,交叉熵(cross-entropy)作为损失函数。
classifier = Sequential()
# Step 1 - Convolution
classifier.add(Convolution2D(32, 3, 3, input_shape= (64, 64, 3), activation='relu'))
# Step 2 - Pooling
classifier.add(MaxPooling2D(pool_size= (2, 2)))
# Adding a second convolutional layer
classifier.add(Convolution2D(32, 3, 3, activation='relu'))
classifier.add(MaxPooling2D(pool_size= (2, 2)))
# Step 3 - Flattening
classifier.add(Flatten())
# Step 4 - Full connection
classifier.add(Dense(output_dim=128, activation='relu'))
classifier.add(Dense(output_dim=1, activation='sigmoid'))
# Compiling the CNN
classifier.compile(optimizer='adam', loss='binary_crossentropy', metrics= ['accuracy'])
viewrawmodel2.py hostedwith ❤ by GitHub
数据增强
数据增强是扩大训练集规模的有效途径。增强训练样例可以使网络在训练中获取更多多样化但仍具代表性的数据点。
下列代码可以为训练集定义一组增强操作:旋转、平移、剪切、翻转以及缩放。
如果数据集规模太小,就应该使用数据增强创建其它的训练数据。
同时,小芯创建了一个数据生成器,以便自动从文件夹中获取数据并转入Keras。Keras为此提供了便捷的python生成器函数。
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
width_shift_range=0.2,
height_shift_range=0.2,
rotation_range=15,
vertical_flip=True,
fill_mode='reflect',
data_format='channels_last',
brightness_range=[0.5, 1.5],
featurewise_center=True,
featurewise_std_normalization=True)
test_datagen = ImageDataGenerator(rescale=1./255)
training_set = train_datagen.flow_from_directory('dataset/train',
target_size= (64, 64),
batch_size=32,
class_mode='binary')
test_set = test_datagen.flow_from_directory('dataset/validation',
target_size= (64, 64),
batch_size=32,
class_mode='binary')
viewrawsplit_data.py hostedwith ❤ by GitHub
随后,该模型训练了50个epoch,每个epoch共32个批次。
Batch size(批尺寸)是深度学习十分重要的超级参数之一。小芯更习惯用较大的Batch size(批大小)进行模型训练,因为这样可以允许图形处理器并行的同时加快计算速度。
但是,众所周知,Batch size(批尺寸)太大会导致泛化功能低下。
图源:Unsplash
一方面,使用规模相当于整个数据集的批量数据可以保证收敛达到目标函数全局最优。但是如此会导致最优收敛速度降低。
另一方面,已证明使用较小的Batch size(批尺寸)可以更快地向良好结果收敛。事实可以直观说明这一点,即较小的Batch size(批尺寸)允许模型在获取所有数据前就开始学习。
但是,它的缺点是无法保证全局最优。因此,一般建议大家首先利用小规模批量处理从更快速的训练动态中获益,而后通过训练逐步增加批量规模。
history = classifier.fit_generator(training_set,
samples_per_epoch=128,
nb_epoch=50,
validation_data= test_set,
nb_val_samples=59)
viewrawtrain4.py hostedwith ❤ by GitHub
将损耗可视化并精准绘图。
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot(history.history['val_loss'])
plt.legend(['validation'], loc='upper left')
plt.title('validation loss vs epoch')
plt.ylabel('validation loss')
plt.xlabel('Epoch')
viewrawval_loss.py hostedwith ❤ by GitHub
验证损耗VS epoch
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot(history.history['val_acc'])
plt.legend(['validation'], loc='upper left')
plt.title('validation accuracy vs epoch')
plt.ylabel('validation accuracy')
plt.xlabel('Epoch')
viewrawval_acc.py hostedwith ❤ by GitHub
该模型跑完50次 epoch可达到100%的验证精度。
结论
因此,数据不足时也能进行深度学习。
本模型仅凭各类别的100个图像就可以在50次epoch实现100%验证精度。
此模型还可以延伸到解决其他二进制或多级别图像分类问题。
有人可能认为这一模型相当简单,因为凭借肉眼也可以轻松看出汽车和巴士区别甚大。那么是否可以借助这一模型开发出识别良性/恶性肿瘤的分类器呢?
答案是肯定的。
我们可以开发出这样的分类器,但是关键在于出现任何数据集规模小的情况都要使用数据增强的方法。另一种解决办法则是采用预训练权重实现迁移学习。
现在,你明白了吗?
留言点赞关注
我们一起分享AI学习与发展的干货
如转载,请后台留言,遵守转载规范