ChatGPT解决这个技术问题 Extra ChatGPT

我试图理解 tf.nn.avg_pool、tf.nn.max_pool、tf.nn.conv2d 中的 strides 参数。

documentation 反复说

strides:长度 >= 4 的整数列表。输入张量的每个维度的滑动窗口的步幅。

我的问题是:

4+ 个整数分别代表什么?为什么他们必须为 convnets 设置 strides[0] = strides[3] = 1?在这个例子中,我们看到 tf.reshape(_X,shape=[-1, 28, 28, 1])。为什么是-1?

遗憾的是,文档中使用 -1 进行重塑的示例并不能很好地适应这种情况。


V
Vikash Singh

池化和卷积运算在输入张量上滑动一个“窗口”。以 tf.nn.conv2d 为例:如果输入张量有 4 个维度:[batch, height, width, channels],则卷积在 height, width 维度上的 2D 窗口上运行。

strides 确定窗口在每个维度上的偏移量。典型用法将第一个(批次)和最后一个(深度)步幅设置为 1。

让我们使用一个非常具体的示例:在 32x32 灰度输入图像上运行二维卷积。我说灰度是因为输入图像的深度=1,这有助于保持简单。让该图像看起来像这样:

00 01 02 03 04 ...
10 11 12 13 14 ...
20 21 22 23 24 ...
30 31 32 33 34 ...
...

让我们在单个示例(批量大小 = 1)上运行 2x2 卷积窗口。我们将给卷积一个输出通道深度为 8。

卷积的输入有 shape=[1, 32, 32, 1]

如果您使用 padding=SAME 指定 strides=[1,1,1,1],则过滤器的输出将为 [1, 32, 32, 8]。

过滤器将首先为以下内容创建输出:

F(00 01
  10 11)

然后为:

F(01 02
  11 12)

等等。然后它将移动到第二行,计算:

F(10, 11
  20, 21)

然后

F(11, 12
  21, 22)

如果您指定 [1, 2, 2, 1] 的步幅,它将不会重叠窗口。它将计算:

F(00, 01
  10, 11)

接着

F(02, 03
  12, 13)

对于池化操作符,步幅的操作类似。

问题 2:为什么为 convnets 跨步 [1, x, y, 1]

第一个是批次:您通常不想跳过批次中的示例,或者您不应该首先包含它们。 :)

最后 1 是卷积的深度:出于同样的原因,您通常不希望跳过输入。

conv2d 运算符更通用,因此您可以创建沿其他维度滑动窗口的卷积,但这不是卷积网络中的典型用途。典型的用途是在空间上使用它们。

为什么 reshape to -1 -1 是一个占位符,上面写着“根据需要调整以匹配完整张量所需的大小”。这是一种使代码独立于输入批量大小的方法,这样您就可以更改管道,而不必在代码中的任何地方调整批量大小。


@derek 因为(来自文本)“我们将为卷积提供 8 的输出通道深度。”。这是你在设置卷积时可以选择的东西,回答者选择了 8。
a
abunickabhi

输入是 4 维的,格式为:[batch_size, image_rows, image_cols, number_of_colors]

通常,Strides 定义了应用操作之间的重叠。在 conv2d 的情况下,它指定卷积滤波器的连续应用之间的距离是多少。特定维度的值 1 表示我们在每一行/列应用运算符,值 2 表示每秒,依此类推。

Re 1) 对卷积重要的值是第 2 和第 3,它们表示沿行和列应用卷积滤波器时的重叠。 [1, 2, 2, 1] 的值表示我们希望每隔一行和一列应用过滤器。

Re 2)我不知道技术限制(可能是 CuDNN 要求),但通常人们会沿着行或列维度使用跨步。超过批量大小不一定有意义。不确定最后一个维度。

Re 3)为其中一个维度设置-1意味着“设置第一个维度的值,使张量中的元素总数不变”。在我们的例子中,-1 将等于 batch_size。


C
Community

让我们从 stride 在 1-dim 案例中的作用开始。

假设您的 input = [1, 0, 2, 3, 0, 1, 1]kernel = [2, 1, 3] 卷积的结果是 [8, 11, 7, 9, 4],这是通过在输入上滑动内核、执行元素乘法并对所有内容求和来计算的。 Like this

8 = 1 * 2 + 0 * 1 + 2 * 3

11 = 0 * 2 + 2 * 1 + 3 * 3

7 = 2 * 2 + 3 * 1 + 0 * 3

9 = 3 * 2 + 0 * 1 + 1 * 3

4 = 0 * 2 + 1 * 1 + 1 * 3

在这里,我们滑动一个元素,但使用任何其他数字都不会阻止您。这个数字就是你的步幅。您可以将其视为通过仅获取每个第 s 个结果来对 1 步长卷积的结果进行下采样。

知道输入大小 i、内核大小 k、步幅 s 和填充 p,您可以轻松计算卷积的输出大小:

https://i.stack.imgur.com/OC5Tk.png

这里 ||操作员是指天花板操作。对于池化层 s = 1。

N 尺寸外壳。

了解 1-dim 案例的数学运算后,一旦您看到每个 dim 都是独立的,n-dim 案例就很容易了。因此,您只需分别滑动每个维度。这是一个example for 2-d。请注意,您不需要在所有维度上都具有相同的步幅。因此,对于 N-dim 输入/内核,您应该提供 N 个步幅。

所以现在很容易回答你所有的问题:

4+ 整数中的每一个代表什么? conv2d, pool 告诉你这个列表代表了每个维度之间的步幅。请注意,步长列表的长度与内核张量的等级相同。为什么他们必须为 convnets 设置 strides[0] = strides3 = 1?第一个维度是批量大小,最后一个维度是通道。既不跳过批次也不跳过通道是没有意义的。因此,您将它们设为 1。对于宽度/高度,您可以跳过某些内容,这就是为什么它们可能不是 1. tf.reshape(_X,shape=[-1, 28, 28, 1])。为什么是-1? tf.reshape 已为您解决:如果 shape 的一个组成部分是特殊值 -1,则计算该维度的大小,以便总大小保持不变。特别是,[-1] 的形状变平为一维。形状的最多一个分量可以是-1。


r
rocksyne

@dga 做了出色的解释工作,我非常感谢它的帮助。同样,我想分享我对 stride 如何在 3D 卷积中工作的发现。

根据 conv3d 上的 TensorFlow documentation,输入的形状必须按以下顺序:

[batch, in_depth, in_height, in_width, in_channels]

让我们用一个例子来解释从极右到左的变量。假设输入形状为 input_shape = [1000,16,112,112,3]

input_shape[4] is the number of colour channels (RGB or whichever format it is extracted in)
input_shape[3] is the width of the image
input_shape[2] is the height of the image
input_shape[1] is the number of frames that have been lumped into 1 complete data
input_shape[0] is the number of lumped frames of images we have.

以下是有关如何使用步幅的摘要文档。

strides:长度 >= 5 的整数列表。长度为 5 的一维张量。输入的每个维度的滑动窗口的步幅。必须有 strides[0] = strides[4] = 1

正如许多作品中所指出的那样,步幅仅仅意味着一个窗口或内核从最近的元素跳开多少步,无论是数据帧还是像素(顺便解释一下)。

从上面的文档中,3D 中的步幅看起来像这样 strides = (1,X,Y,Z,1)。

该文档强调 strides[0] = strides[4] = 1

strides[0]=1 means that we do not want to skip any data in the batch 
strides[4]=1 means that we do not want to skip in the channel 

strides[X] 表示我们应该在集总帧中跳过多少次。例如,如果我们有 16 帧,X=1 表示使用每一帧。 X=2 表示每隔一帧使用一次,然后继续

strides[y] 和 strides[z] 遵循 @dga 的解释,所以我不会重做那部分。

然而,在 keras 中,您只需要指定 3 个整数的元组/列表,指定卷积沿每个空间维度的步幅,其中空间维度为 stride[x]、strides[y] 和 strides[z]。 strides[0] 和 strides[4] 已经默认为 1。

我希望有人觉得这很有帮助!


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅