3.3 创建新的训练数据:旋转图像
如果思考一下MNIST训练数据,你就会意识到,这是关于人们所书写数字的一个相当丰富的样本集。这里有各种各样、各种风格的书写,有的写得很好,有的写得很糟。
神经网络必须尽可能多地学习这些变化类型。在这里,有多种形式的数字“4”,有些被压扁了,有些比较宽,有些进行了旋转,有些顶部是开放的,有些顶部是闭合的,这对神经网络的学习都是有帮助的。
如果我们能够创造更多的变化类型作为样本,会不会有用处呢?如何做到这一点呢?再多收集几千个人类手写数字样本,对我们来说有点不太容易。我们可以这样做,但是工作量有点大。
一个很酷的想法就是利用已有的样本,通过顺时针或逆时针旋转它们,比如说旋转10度,创建新的样本。对于每一个训练样本而言,我们能够生成两个额外的样本。我们可以使用不同的旋转角度创建更多的样本,但是,目前,让我们只尝试+10和-10两个角度,看看这种想法能不能成功。
同样,Python的许多扩展包和程序库都很有用。ndimage.interpolation.rotate()可以将数组转过一个给定的角度,这正是我们所需要的。请记住,由于我们将神经网络设计成为接收一长串输入信号,因此输入的是784长的一串一维数字。我们需要将这一长串数字重新变成28×28的数组,这样就可以旋转这个数组,然后在将这个数组馈送到神经网络之前,将数组解开,重新变成一长串的784个信号。
假设得到了先前的scaled_input数组,下列代码演示了如何使用ndimage.interpolation.rotate()函数:
# create rotated variations # rotated anticlockwise by 10 degrees inputs_plus10_img = scipy.ndimage.interpolation.rotate( scaled_input.reshape(28,28) , 10 , cval=0.01 , reshape=False) # rotated clockwise by 10 degrees inputs_minus10_img = scipy.ndimage.interpolation.rotate( scaled_input.reshape(28,28) , -10 , cval=0.01 , reshape=False)
可以看到,原先的scaled_input数组被重新转变为28乘以 28的数组,然后进行了调整。reshape=False,这个参数防止程序库过分“热心”,将图像压扁,使得数组旋转后可以完全适合,而没有剪掉任何部分。在原始图像中,一些数组元素不存在,但是现在这些数组元素进入了视野,cval就是用来填充数组元素的值。由于我们要移动输入值范围,避免0作为神经网络的输入值,因此不使用0.0作为默认值,而是使用0.01作为默认值。
小型MNIST训练集的记录6(第7条记录)是一个手写数字“1”。在下图中可以看到,原先的数字图片和使用代码生成的两个额外的变化形式。
可以清楚地看到这种方式的好处。原始图像的版本旋转+10度,提供了一个样本,就像某些人的书写风格是将1向后倾斜。将原来图片的版本顺时针旋转10度更有趣。和原始的版本相比,这个版本在某种意义上是更具代表性的学习图片。
让我们创建新的Python Notebook,使用原来的神经网络代码,不过,现在我们将原始图片朝顺时针和逆时针两个方向旋转10度,作为额外的训练样本,来训练神经网络。这段代码在GitHub上可以得到,请访问以下链接:
设定学习率为0.1,并且只使用一个训练世代,初始运行神经网络,所得的性能是0.9669。这对于没有使用额外旋转图像进行训练的神经网络的性能0.954而言,是一个长足的进步。这样的表现,和列在Yann LeCeun网站中的记录相比也已经是名列前茅了。
让我们进行一系列的实验,改变世代的数目看看是否能够让已经不错的表现更上一层楼。现在,我们创建了更多的训练数据,可以采用更小、更谨慎的学习步长,因此将学习率减少到0.01,这样就总体上延长了学习时间。
请记住,由于特定的神经网络架构或训练数据的完整性,事情很可能存在内在的限制,因此我们不会期待得到98%或以上的准确度,或者甚至是100%的准确度。我们说“特定的神经网络架构”,意思是在每一层节点数目的选择、隐藏层的选择和激活函数的选择等。
我们旋转训练图像的角度,将其作为额外的训练样本,下图显示了在这种情况下的神经网络的性能。同时,下图也显示了没有使用额外旋转的训练样本时神经网络的性能,以便进行简单的比较。
可以看到,在5个世代的情况下,最好的结果是0.9745或97.5%的准确度。这再一次打破了我们先前的纪录。
值得注意的是,如果旋转的角度过大,神经网络的性能会出现下降。由于旋转较大的角度意味着创建了实际上不能代表数字的图像,因此神经网络的性能出现了下降,这是可以理解的。想象一下,将“3”向一个方向旋转90度,这就不再是3了。因此,将过度旋转的图像添加到训练样本中,增加了错误样本,降低了训练的质量。对于最大化附加数据的价值,10度看起来是最佳角度。
在10个世代的情况下,神经网络的性能出现了峰值,打破了记录,达到了0.9787,几乎到达98%!对于这种简单的神经网络而言,这是一个惊人的结果,也是最佳的一种状态。请记住,有些人会对神经网络或数据进行一些巧妙的处理,我们还未这样做,我们只是保持简单的神经网络,但是却依然取得了令人骄傲的结果。
做得好!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论