tf.layers.conv2d和tf.contrib.slim.conv2d之间的区别

Dre*_*w M 6 python neural-network deep-learning conv-neural-network tensorflow

我正在尝试使用tf-slim的conv2d将我正在使用的网络转换为使用tf.layers.conv2d,因为看起来tf.layers是更受支持且面向未来的选项.函数签名非常相似,但两者之间在算法上有什么不同吗?我得到的输出张量尺寸不同于预期.

x = tf.layers.conv2d(inputs=x,
                     filters=256,
                     kernel_size=[3,3],
                     trainable=True)
Run Code Online (Sandbox Code Playgroud)

与此相反:

x = slim.conv2d(x, 256, 3)
Run Code Online (Sandbox Code Playgroud)

Oli*_*ene 12

我得到的输出张量尺寸不同于预期.

这是因为,默认情况下,slim.conv2d使用相同的填充,而tf.layers.conv2d使用有效的填充.

如果要重现完全相同的行为,这是正确的实现:

x = tf.layers.conv2d(x, 256, 3, padding='same')
Run Code Online (Sandbox Code Playgroud)


den*_*ger 6

描述tf.slim更清楚地说明了差异:具体来说,如果您在“层”下查看,可以找到以下内容:

图层

尽管 TensorFlow 操作集相当广泛,但神经网络的开发人员通常会根据“层”、“损失”、“度量”和“网络”等更高级别的概念来考虑模型。一个层,例如卷积层、全连接层或 BatchNorm 层,比单个 TensorFlow 操作更抽象,并且通常涉及多个操作。此外,与更原始的操作不同,层通常(但并非总是)具有与其关联的变量(可调参数)。例如,神经网络中的卷积层由几个低级操作组成:

  • 创建权重和偏差变量
  • 将权重与上一层的输入进行卷积
  • 将偏差添加到卷积的结果中。
  • 应用激活函数。

仅使用普通的 TensorFlow 代码,这可能相当费力:

input = ...
with tf.name_scope('conv1_1') as scope:
  kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 128], dtype=tf.float32,
                                           stddev=1e-1), name='weights')
  conv = tf.nn.conv2d(input, kernel, [1, 1, 1, 1], padding='SAME')
  biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32),
                       trainable=True, name='biases')
  bias = tf.nn.bias_add(conv, biases)
  conv1 = tf.nn.relu(bias, name=scope)
Run Code Online (Sandbox Code Playgroud)

为了减少重复复制此代码的需要,TF-Slim 提供了许多在神经网络层更抽象的层次上定义的便捷操作。例如,将上面的代码与调用相应的 TF-Slim 代码进行比较:

input = ...
net = slim.conv2d(input, 128, [3, 3], scope='conv1_1')
Run Code Online (Sandbox Code Playgroud)

简而言之,slim运算符为您做了一些简洁的抽象,这样您就不必担心 TensorFlow 的所有细节——如果你问我的话,这是一个很好的补充。不过,这似乎仍在积极开发中,所以在(面向未来的)开发中积极使用它之前,我会多读一点它。