tf.nn.conv2d与tf.layers.conv2d的区别

68

在使用it技术时,使用tf.nn.*是否比使用tf.layers.*更具优势?

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


1
性能有什么不同吗? - Ankit Bindal
6个回答

43

正如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。


3
filter参数和filters参数是有区别的! - Sergey Bushmanov
2
对于tf.nn.conv2d,需要明确指定input_channels(作为filter的一部分)是否也是一个主要区别?而tf.contrib.layers.conv2d似乎隐含地确定了这一点?另外,在任何情况下,input_channels是否可能与input.shape[-1](输入的最后一个维度)不同? - Honeybear
1
@Mircea 为什么在从头开始构建模型时要使用 tf.layers.conv2d?因为 tf.nn.conv2d 可以让您初始化过滤器,从而加快训练时间。 - Abhisek
我想这主要是个人喜好的问题。请注意,tf.layers.conv2d还有初始化过滤器的选项,如下所示:layer = tf.layers.conv2d(..., kernel_initializer=tf.contrib.layers.xavier_initializer())我之所以更喜欢tf.layers中的这种方法,是因为它使用内核维度而不是自己设置张量,然后将其作为参数传递。 - Mircea

30

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


2
它们不同,因为它们在定义卷积层的方式上有所不同(请参见下面的答案)。 - Sergey Bushmanov
朋友,你提出了一个“用于卷积”的前提条件。我想知道max_pool层是否相同,或者它们之间有什么区别?希望能收到你的消息,非常感谢。 - wolfog

13

正如其他人所提到的,参数是不同的,特别是“filter(s)”。

tf.nn.conv2d将一个张量作为过滤器,这意味着您可以像在cifar10代码中一样指定权重衰减(或其他属性)。

(是否需要在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,则必须编写额外的代码来处理这些内容。


8
所有其他的回答都谈到参数不同,但其实,tf.nn和tf.layers conv2d的主要区别在于对于tf.nn,您需要创建自己的滤波器张量并传递它。这个滤波器需要具有以下尺寸:[kernel_height,kernel_width,in_channels,num_filters] 从本质上讲,tf.nn比tf.layers更低级。不幸的是,这个答案已经不适用了,因为tf.layers已经过时了。

3

参数的差异:

在代码中使用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) - twostarxx

2
请看这里:tensorflow > tf.layers.conv2dtensorflow > 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版本的参数是:input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None。您可以根据自己的需求选择合适的版本!

5
我读了这份文档,但我想知道使用tf.nn.conv2d + 初始值设定器和所有由tf.layer提供的功能,相对于仅使用tf.nn.layers.conv2d有何优势,例如速度是否更快。 - jul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接