tf.nn.conv2d 与 tf.layers.conv2d

Posted

技术标签:

【中文标题】tf.nn.conv2d 与 tf.layers.conv2d【英文标题】:tf.nn.conv2d vs tf.layers.conv2d 【发布时间】:2017-08-04 17:34:00 【问题描述】:

使用tf.nn.* 比使用tf.layers.* 有什么优势吗?

例如,文档中的大多数示例都使用tf.nn.conv2d,但不清楚他们为什么这样做。

【问题讨论】:

性能有什么不同吗? 【参考方案1】:

所有这些其他回复都在谈论参数如何不同,但实际上,tf.nn 和 tf.layers conv2d 的主要区别在于,对于 tf.nn,您需要创建自己的过滤器张量并将其传入. 此过滤器的大小必须为:[kernel_height, kernel_width, in_channels, num_filters]

本质上,tf.nn 的级别低于 tf.layers。不幸的是,这个答案不再适用,因为 tf.layers 已过时

【讨论】:

【参考方案2】:

参数差异:

在代码中使用 tf.layer*:

# Convolution Layer with 32 filters and a kernel size of 5
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu) 
# Max Pooling (down-sampling) with strides of 2 and kernel size of 2
conv1 = tf.layers.max_pooling2d(conv1, 2, 2)

在代码中使用 tf.nn*: (请注意,我们需要另外将权重和偏差作为参数传递)

strides = 1
# Weights matrix looks like: [kernel_size(=5), kernel_size(=5), input_channels (=3), filters (= 32)]
# Similarly bias = looks like [filters (=32)]
out = tf.nn.conv2d(input, weights, padding="SAME", strides = [1, strides, strides, 1])
out = tf.nn.bias_add(out, bias)
out = tf.nn.relu(out)

【讨论】:

您可以使用tf.nn.conv2d(input, weights, activation=tf.nn.relu) 之类的激活来代替out = tf.nn.relu(out)【参考方案3】:

看这里:tensorflow > tf.layers.conv2d

这里:tensorflow > conv2d

如你所见,图层版本的参数是:

tf.layers.conv2d(inputs, filters, kernel_size, strides=(1, 1), padding='valid', data_format='channels_last', dilation_rate=(1, 1), activation=None, use_bias=True , kernel_initializer=None,bias_initializer=tf.zeros_initializer(), kernel_regularizer=None,bias_regularizer=None, activity_regularizer=None, trainable=True, name=None, reuse=None)

和nn版本:

tf.nn.conv2d(输入、过滤器、步幅、填充、use_cudnn_on_gpu=None、data_format=None、name=None)

我认为您可以选择具有您想要/需要/喜欢的选项的那个!

【讨论】:

我阅读了文档,但我只是想知道使用 tf.nn.conv2d + 初始化程序和 tf.layer 提供的所有功能是否比 tf.nn.layers.conv2d 有优势,例如如果它更快。【参考方案4】:

对于卷积,它们是相同的。更准确地说,tf.layers.conv2d(实际上是_Conv)使用tf.nn.convolution 作为后端。可以关注以下调用链:tf.layers.conv2d>Conv2D>Conv2D.apply()>_Conv>_Conv.apply()>_Layer.apply()>_Layer.\__call__()>_Conv.call()>nn.convolution()...

【讨论】:

它们并不相同,因为它们定义卷积层的方式不同(请参阅下面的答案)。 朋友,你做了一个前提条件是“用于卷积”。我想知道 max_pool 层是相同的还是它们之间有什么区别?希望能收到您的留言,非常感谢。【参考方案5】:

正如其他人提到的,参数是不同的,尤其是“过滤器”。 tf.nn.conv2d 将张量作为过滤器,这意味着您可以在cifar10 code 中指定权重衰减(或其他属性),如下所示。 (您是否想要/需要在 conv 层中进行权重衰减是另一个问题。)

kernel = _variable_with_weight_decay('weights',
                                     shape=[5, 5, 3, 64],
                                     stddev=5e-2,
                                     wd=0.0)
conv = tf.nn.conv2d(images, kernel, [1, 1, 1, 1], padding='SAME')

我不太确定如何在 tf.layers.conv2d 中设置权重衰减,因为它只需要一个整数作为过滤器。也许使用kernel_constraint

另一方面,tf.layers.conv2d 会自动处理激活和偏差,而如果您使用 tf.nn.conv2d,则必须为此编写额外的代码。

【讨论】:

【参考方案6】:

正如 GBY 提到的,它们使用相同的实现。

参数略有不同。

对于 tf.nn.conv2d:

filter: A Tensor. Must have the same type as input. A 4-D tensor of shape [filter_height, filter_width, in_channels, out_channels]

对于 tf.layers.conv2d:

filters: Integer, the dimensionality of the output space (i.e. the number of filters in the convolution).

我会在加载预训练模型时使用 tf.nn.conv2d(示例代码:https://github.com/ry/tensorflow-vgg16),而对于从头训练的模型,我会使用 tf.layers.conv2d。

【讨论】:

参数filterfilters 完全不同! 对于tf.nn.conv2d,您明确需要指定input_channels(作为filter 的一部分),而tf.contrib.layers.conv2d 显然隐含地确定了这一点,这难道不是一个主要区别吗?还有任何情况下input_channels 不是input.shape[-1](输入的最后一个暗淡)? @Mircea 为什么在从头开始构建模型时使用tf.layers.conv2d?因为tf.nn.conv2d 会让你初始化过滤器,这将加快训练时间。 我想这主要是一个偏好问题。请注意,tf.layers.conv2d 还具有初始化过滤器的选项,如下所示:layer = tf.layers.conv2d(..., kernel_initializer=tf.contrib.layers.xavier_initializer()) 我更喜欢 tf.layers 的原因是使用内核尺寸而不是自己设置张量,然后将其作为参数。

以上是关于tf.nn.conv2d 与 tf.layers.conv2d的主要内容,如果未能解决你的问题,请参考以下文章

tf.nn.conv2d 参数介绍

tf.nn的conv2d卷积与max_pool池化

tf.nn.conv2d是怎样实现卷积的

TF-卷积函数 tf.nn.conv2d 介绍

TF-卷积函数 tf.nn.conv2d 介绍

tf.nn.conv2d 在 tensorflow 中做了啥?