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。
【讨论】:
参数filter
和filters
完全不同!
对于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的主要内容,如果未能解决你的问题,请参考以下文章