所以我有一些代码
tensors = [] //its filled with 3D float tensors
total = sum(tensors)
Run Code Online (Sandbox Code Playgroud)
如果我将最后一行更改为
total = tf.add_n(tensors)
Run Code Online (Sandbox Code Playgroud)
那么代码会产生相同的输出,但运行速度要慢得多,并且很快会导致内存不足异常。这里发生了什么?有人可以解释一下 python 内置的 sum 函数和 tf.add_n 如何分别与张量数组交互,以及为什么 python sum 似乎是一个更好的版本?
当您使用 时sum,您调用一个标准的 python 算法,该算法递归__add__地调用数组的元素。由于__add__(或+) 确实在张量流的张量上重载,因此它按预期工作:它创建一个可以在会话期间执行的图。然而,这并不是最优的,因为您添加的操作与列表中的元素一样多;此外,您还强制执行操作的顺序(将前两个元素相加,然后将第三个元素添加到结果中,依此类推),这也不是最佳的。
相比之下,add_n是专门执行此操作的操作。看看这张图,我认为确实很能说明问题:
import tensorflow as tf\n\nwith tf.variable_scope(\'sum\'):\n xs = [tf.zeros(()) for _ in range(10)]\n sum(xs)\n\nwith tf.variable_scope(\'add_n\'):\n xs = [tf.zeros(()) for _ in range(10)]\n tf.add_n(xs)\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n然而 \xe2\x80\x93 与我之前的想法相反 \xe2\x80\x93add_n占用更多内存,因为它等待 \xe2\x80\x93 并在存储所有传入输入之前存储 \xe2\x80\x93 。如果输入数量很大,那么差异可能很大。
我所期望的行为add_n,即可用输入的求和,实际上是通过 实现的tf.accumulate_n。这应该是更好的选择,因为它比 占用更少的内存,add_n但不强制执行求和顺序sum。
为什么tensorflow-wavenet的作者使用sum而不是tf.accumulate_n?当然是因为之前这个函数在 TF < 1.7 上是不可微分的。因此,如果您必须支持 TF < 1.7并且具有内存效率,那么 Good oldsum实际上是一个不错的选择。
| 归档时间: |
|
| 查看次数: |
2163 次 |
| 最近记录: |