在 CNN 的一层中的 patch 中共享权重 w ,无论猫在图片的哪个位置都可以找到。

 

当我们试图识别一个猫的图片的时候,我们并不在意猫出现在哪个位置。无论是左上角,右下角,它在你眼里都是一只猫。我们希望 CNNs 能够无差别的识别,这如何做到呢?

如我们之前所见,一个给定的 patch 的分类,是由 patch 对应的权重和偏置项决定的。

如果我们想让左上角的猫与右下角的猫以同样的方式被识别,他们的权重和偏置项需要一样,这样他们才能以同一种方法识别。

这正是我们在 CNNs 中做的。一个给定输出层学到的权重和偏置项会共享在输入层所有的 patch 里。注意,当我们增大滤波器的深度的时候,我们需要学习的权重和偏置项的数量也会增加,因为权重并没有共享在所有输出的 channel 里。

共享参数还有一个额外的好处。如果我们不在所有的 patch 里用相同的权重,我们必须对每一个 patch 和它对应的隐藏层神经元学习新的参数。这不利于规模化,特别对于高清图片。因此,共享权重不仅帮我们平移不变,还给我们一个更小,可以规模化的模型。

 

Padding

 

一个 5x5 的网格附带一个 3x3 的滤波器。来源: Andrej Karpathy。

 

假设现在有一个 5x5 网格 (如上图所示) 和一个尺寸为 3x3 stride值为 1 的滤波器(filter)。 下一层的 width 和 height 是多少呢? 如图中所示,在水平和竖直方向都可以在3个不同的位置放置 patch, 下一层的维度即为 3x3。下一层宽和高的尺寸就会按此规则缩放。

在理想状态下,我们可以在层间保持相同的宽度和高度,以便继续添加图层,保持网络的一致性,而不用担心维度的缩小。如何实现这一构想?其中一种简单的办法是,在 5x5 原始图片的外层包裹一圈 0 ,如下图所示。

 

加了 0 padding的相同网格。 来源: Andrej Karpathy。

这将会把原始图片扩展到 7x7。 现在我们知道如何让下一层图片的尺寸维持在 5x5,保持维度的一致性。

维度

综合目前所学的知识,我们应该如何计算 CNN 中每一层神经元的数量呢?

输入层(input layer)维度值为W, 滤波器(filter)的维度值为 F (height * width * depth), stride 的数值为 S, padding 的数值为 P, 下一层的维度值可用如下公式表示: (W−F+2P)/S+1

我们可以通过每一层神经元的维度信息,得知模型的规模,并了解到我们设定的 filter size 和 stride 如何影响整个神经网络的尺寸。

介绍

接下来的几个练习将检测你对 CNNs 维度的理解,理解维度可以帮你在模型大小和模型质量上,做精确的权衡。你将会了解,一些参数对模型大小的影响会远大于另外一些。

设置

H = height, W = width, D = depth

  • 我们有一个输入维度是 32x32x3 (HxWxD)
  • 20个维度为 8x8x3 (HxWxD) 的滤波器
  • 高和宽的stride(步长)都为 2。(S)
  • padding 大小为1 (P)

计算新的高度和宽度的公式是:

new_height = (input_height - filter_height + 2 * P)/S + 1
new_width = (input_width - filter_width + 2 * P)/S + 1

卷积层输出维度

输出的维度(shape)是什么?  14x14x20


代入公式可以得到下列结果:

(32 - 8 + 2 * 1)/2 + 1 = 14
(32 - 8 + 2 * 1)/2 + 1 = 14

新的深度与滤波器的数量相同,都是 20。

对应如下代码:

input = tf.placeholder(tf.float32, (None, 32, 32, 3))
filter_weights = tf.Variable(tf.truncated_normal((8, 8, 3, 20))) # (height, width, input_depth, output_depth)
filter_bias = tf.Variable(tf.zeros(20))
strides = [1, 2, 2, 1] # (batch, height, width, depth)
padding = 'VALID'
conv = tf.nn.conv2d(input, filter_weights, strides, padding) + filter_bias

注意,这里的conv 输出的是 [1, 13, 13, 20]。这是对应 batch size 的 4D 大小,重要的是它不是 [1, 14, 14, 20]。这是因为 TensorFlow 的 padding 算法与上面的并不完全相同。一个可替换方案是把 padding 从 'VALID' 改为'SAME',这样得到的结果是 [1, 16, 16, 20]。如果你想了解 TensorFlow 中的 padding 如何工作,可以看这个文档

总之,TensorFlow 使用如下等式计算 SAME 、PADDING

SAME Padding, 输出的高和宽,计算如下:

out_height = ceil(float(in_height) / float(strides1))

out_width = ceil(float(in_width) / float(strides[2]))

VALID Padding, 输出的高和宽,计算如下:

out_height = ceil(float(in_height - filter_height + 1) / float(strides1))

out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))

posted on 2018-07-04 17:31  未完代码  阅读(2996)  评论(0编辑  收藏  举报