Tensorflow - 为什么在tf.nn和tf.layers / tf.losses / tf.contrib.layers等中有这么多类似甚至重复的函数?

时间:2017-07-18 16:45:54

标签: tensorflow

在Tensorflow中(从v1.2.1开始),似乎有(至少)两个并行API来构建计算图。 tf.nn中有函数,如conv2d,avg_pool,relu,dropout,然后在tf.layers,tf.losses和其他地方有类似的函数,如tf.layers.conv2d,tf.layers.dense,tf.layers。差。

从表面上看,这种情况似乎只会让人感到困惑:例如,tf.nn.dropout使用了“保持率”和“保持率”。而tf.layers.dropout使用'丢弃率'作为一个论点。

这种区别是否对最终用户/开发人员有任何实际意义? 如果没有,是否有任何清理API的计划?

1 个答案:

答案 0 :(得分:21)

Tensorflow一方面提出低级API(tf.tf.nn. ...),另一方面提出更高级别的API(tf.layers.,{{1 }},...)。

更高级API的目标是提供大大简化最常见神经网络设计的功能。较低级别的API适用于有特殊需求的人,或希望更好地控制正在发生的事情的人。

虽然情况有点混乱,因为有些函数具有相同或相似的名称,而且,没有明确的方法可以区分哪个命名空间对应于API的哪个级别。

现在,让我们看一下tf.losses.conv2dtf.nn.conv2d之间的显着差异在于,后者会处理权重和偏差所需的所有变量。一行代码和voilà,你刚刚创建了一个卷积层。使用tf.layers.conv2d,您必须在将权重变量传递给函数之前自己声明权重变量。至于偏见,实际上它们甚至都没有处理过:你需要稍后自己添加它们。

除此之外,tf.nn.conv2d还建议在同一个函数调用中添加正则化和激活,您可以想象当更高级别的API覆盖了需要时,这可以减少代码大小。

更高级别也会默认做出一些可被视为最佳做法的决策。例如,tf.layers.conv2d中的损失默认添加到tf.losses集合中,这使得各个组件的恢复和求和变得容易且有些标准化。如果您使用较低级别的API,则需要自己完成所有这些操作。显然,当你开始在那里混合低级和高级API函数时,你需要小心。

更高级别的API也可以满足那些在其他框架中习惯使用类似高级功能的人们的巨大需求。当考虑在张量流之上构建的替代更高级API的数量时,这是相当明显的,例如keras 2(现在part of the official tensorflow API),slim(在tf.GraphKeys.LOSSES中),tflearn,tensorlayer等等

最后,如果我可以添加建议:如果您开始使用tensorflow并且没有对特定API的偏好,我个人会鼓励您坚持使用tf.contrib.slim API:

  • 它的API非常友好,至少与基于低级tensorflow API构建的其他高级API一样好
  • 它在tensorflow中有一个清晰的命名空间(尽管它可以 - 有时应该 - 与其他命名空间中的部分一起使用,例如tf.keras.*
  • 它现在是张量流的一等公民(过去曾在tf.data中),并且需要注意使新的张量流特征(例如tf.contrib.keras)与keras兼容。
  • 它的通用实现可以使用其他工具包,例如CNTK,因此不会锁定你的张量流。