深度学习为什么需要那么多的数据?

前言

深度学习近两年来发展极为迅速,在计算能力大大提高的情况下,很多深度学习方向的思想都得以实现。但是,深度学习有一个令人头疼的缺点,那就是需要大量样本来进行训练才能达到较好的泛化

虽然我们有迁移学习可以适当减少我们需要的数据量,亦或者,我们可以通过数据增强的方式来翻倍我们的数据:

imgua,强大的图像增强工具

图像增强方法最直接了当,但是为什么需要那么多的数据呢,从直观上理解很简单,和人相似,学习到足够多的东西才能举一反三。当然这里指的足够多的东西是一个数据集中包含多种多样的数据,包含不同情况不同形态的尽可能丰富的数据。

数据集的分布曲线应该平滑

如果你只学习到一个场景,这个场景的数据很多,很容易造成神经网络“过度学习”,也就是所谓的学的太过了,举一反三的本领太强。举个例子,在目标检测的一个简单的任务中,我们要识别一个木板(board)和参照物(reference),下图就是一个正确的识别结果:

但假如我们的数据集是这样的(冰山一角):

发现什么了?在数据集中我们的参照物往往都放置在木板的上面,只是换了摆放的位置和拍摄的角度,也就是所有的参照物下面都有一个木板。

那么,如果我们的数据集都是这样的,然后我们进行了训练,随后,取一张没有木板的光有参照物的图像(这种图像在数据集中没有或者很少)做测试:

由于过拟合,神经网络认为参照物下方“一定是木板”

看看发生了什么?我们训练的这个神经网络太会举一反三了,认为只要有这个参照物,参照物下面的总是木板,于是就出现了这样的情况。想要消除这种情况,数据集中木板和参照物的数据必须多元化,足够多,不能光满足一种情况下的数据量,需要多种情况多种条件下的数据。

深度学习圣经有句话:常用的隐示”先验”是平滑先验局部不变性,这个先验表明我们学习的函数不应该在小区域内发生很大的变化。也就是说学习的函数应该是平滑的,不应该“偏科”。另外,只要学习的真实函数的峰值和谷值处有足够多的样本,那么平滑性假设和相关的无参数学习算法的效果都非常好,这也就是数据量丰富的优势。

但对于人工智能领域这些比较复杂的算法任务来说,我们想要获得更好的结果的直接途径,除了改进算法,那就是扩充你的数据集了。

关于神经网络的旋转不变形

这里有一个简单的手写数据识别网络的例子,LaNet5数字识别网络,一个拥有七层的简单的神经网络,但却包含了一整套神经网络的雏形。

LeNet手写数字识别网络中有一个对图像变化的简单测试,利用普通的数字图像训练好数据后,拿经过变换后的数据尝试进行识别,

以下分别是数字图经过平移、缩放、旋转后的识别情况,我们可以看到,在经过简单的平移(数字简单移动15px左右)、缩放和旋转(左右各40度)神经网络仍然可以进行识别,但是如果变形的太过分,识别就失效了。

为什么会出现这种情况,我们看下LaNet5的基本结构:

我们可以看到整个神经网络一共有7层(不包括输入层),其中有两个是池化层(pooling layer),LaNet-5使用的是平均池化方法,在网络中起到了降维的作用。

其实,为什么神经网络也可以识别数据集中微小的变形呢?说白了是因为pooling操作在降维的同时起到了一定的(很微小)旋转不变性的作用。

比如在我们检测一个物体的时候,神经网络的activation层在这个物体的边缘处发生了比较明显的变化,当这个物体稍微旋转一下,物体的边缘稍稍移动时,由于max-pooling的缘故,这个物体的边缘依然会刺激到我们的activation层,当然,max-pooling的核大小是很有限的,对于一般的图像旋转,平移,max-pooling就无法发挥作用了。

quora上也有说法,大致意思是过滤层(卷积层)有不变性,但是全连接层只会对特定的激活层产生反应,也就是如果激活层地点发生了变化,那么全连接层就检测不到了。

底下的评论中也有人进行了测试(训练第一象限位置的数字图像,然后用第二象限的图像进行测试):

设计的网络层也很简单(Keras):

class Model(object):
  
  def __init__(self, num_classes, *input_shape):
    self.model = None
    self.input_shape = input_shape[0]
    self.num_classes = num_classes
  
  def create_model(self, use_fully_connected=True):
    self.model = Sequential()
    self.model.add(Conv2D(64, (3, 3), activation='relu', input_shape=self.input_shape))
    self.model.add(Conv2D(32, (3, 3), activation='relu'))
    self.model.add(MaxPooling2D((2, 2)))
    if use_fully_connected:
      self.model.add(Flatten())
      self.model.add(Dense(128, activation='relu'))
      self.model.add(Dense(self.num_classes, activation='softmax'))
    else:
      self.model.add(Conv2D(16, (3, 3), activation='relu'))
      self.model.add(Flatten())
      self.model.add(Dense(self.num_classes, activation='softmax'))
    
  def compile(self):
    self.model.compile(loss=keras.losses.categorical_crossentropy,
                        optimizer=keras.optimizers.Adadelta(),
                        metrics=['accuracy'])
  
  def train(self, train_x, train_y, num_epochs, batch_size):
    self.model.fit(train_x, train_y, verbose=1, epochs=num_epochs, batch_size=batch_size)
    
  def test(self, test_x, test_y):
    return self.model.evaluate(test_x, test_y)

设计的模型中有max-pooling层,最后的连接层是设置为全连接层或者直接去掉。就这样训练某个位置的数字图像然后用另一个位置的数字图像去测试,不论构建的神经网络有没有全连接层,测试出来的结果都很“烂”:

准确率不足10%。

也就是说,max-pooling的作用其实是有限的,我们不应该光靠这个“特性”来偷懒,然后减少数据的收集。

其他相关的研究与看法

类似的研究还是有很多的,在Multi-scale Orderless Pooling of Deep Convolutional Activation Features作者对图像分别进行旋转、缩放、平移等各种变换操作,记录多种变换程度下测试的准确性。

可以看到,大部分的曲线都是成”拱形”的或者下降趋势,显然还是original的情况下效果最好。

还有很多另外的研究结果,大家可以自行搜索阅读。

关于Uber最新出现的论文CoordConv

Uber最新出了一片论文,在神经网络层的卷积操作上加了一层坐标层,为的就是改进神经网络对目标位置不敏感的问题(平移不变性)。

呃,评价呢,褒贬不一,有兴趣可以看看一下的连接:

卷积神经网络「失陷」,CoordConv 来填坑 要拯救CNN的CoordConv受嘲讽,翻译个坐标还用训练?

结合大家观点总结下这个论文:实现起来很简单,几十行代码就可以。但是实际上可能并不适合用于大型的任务,因为在论文中作者只是在小型任务上进行了尝试,其他的任务还没有人尝试过,我也没有,所以不好评价。

结论

说了这么多,最简单的提升神经网络不变性的方法就是拓展我们的数据集,也就是所谓的data augmentation,在kaggle上很多的trick都是通过在数据集上下功夫就可以提高算法的分数了,这个方面还是很有学问的。

当然也有很多的在神经网络上直接实现对数据的增强,达到提高测试精度的效果,有兴趣的可以阅读下:

spatial transform network AutoAugment: Learning Augmentation Policies from Data

此文由腾讯云爬虫爬取,文章来源于Oldpan博客

欢迎关注Oldpan博客公众号,持续酝酿深度学习质量文:

参考

https://medium.com/nanonets/how-to-use-deep-learning-when-you-have-limited-data-part-2-data-augmentation-c26971dc8ced https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html https://www.zhihu.com/question/30817011 Exploiting Cyclic Symmetry in Convolutional Neural Networks http://yann.lecun.com/exdb/lenet/index.html

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CVer

[计算机视觉论文速递] 2018-03-16

通知:这篇推文有14篇论文速递信息,涉及目标检测、图像分割、显著性目标检测、人脸识别和GAN等方向 最近有些忙,论文速递频率快下降至两天一更了,希望大家可以体谅...

526150
来自专栏机器之心

ECCV 2018 | 旷视科技提出统一感知解析网络UPerNet,优化场景理解

论文名称:《Unified Perceptual Parsing for Scene Understanding》

26320
来自专栏人工智能

深度学习CNN眼中的图片是什么样的

2017年最后一天,无心学习。本来想休息下的,结果看到了一篇Paper叫《Visualizing and Understanding Convolutional...

35480
来自专栏机器之心

修改一个像素,就能让神经网络识别图像出错

31970
来自专栏大数据文摘

选择困难症?一文通解如何选择最合适的机器学习算法

19140
来自专栏机器之心

嘿嘿,想变成会跳舞的小哥哥或小姐姐吗?超简单!

作者:Caroline Chan、Shiry Ginosar、Tinghui Zhou、Alexei A. Efros

10110
来自专栏新智元

【史上最有趣论文】物体检测经典模型YOLO新升级,就看一眼,速度提升 3 倍!

【新智元导读】你肯定很少见到这样的论文,全文像闲聊一样,不愧是YOLO的发明者。物体检测领域的经典论文YOLO(You Only Look Once)的两位作者...

43780
来自专栏Tencentcloud

几何与学习的交汇点

通常来说,只给出一个2D图像,人类就能够毫不费力地推断出底层场景的丰富3D结构。由于从2D推断3D本身是一个模糊的任务。

1.2K130
来自专栏机器之心

专栏 | 机器学习实战:Python信用卡欺诈检测

机器之心专栏 公众号:数据先锋(data_pioneer) 作者:唐宇迪 对信用卡交易数据建立检测模型,使用Python库进行预处理与机器学习建模工作,代码通俗...

48380
来自专栏深度学习入门与实践

【深度学习系列】迁移学习Transfer Learning

  在前面的文章中,我们通常是拿到一个任务,譬如图像分类、识别等,搜集好数据后就开始直接用模型进行训练,但是现实情况中,由于设备的局限性、时间的紧迫性等导致我们...

36750

扫码关注云+社区

领取腾讯云代金券