2016-08-23 494 views
2

我运行到一个问题,即链tf.gather()索引产生以下警告:Tensorflow:链接tf.gather()产生IndexedSlices警告

/usr/local/lib/python3.5/dist-packages/tensorflow/python/ops/gradients.py:90: UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.   
    "Converting sparse IndexedSlices to a dense Tensor of unknown shape. " 

该场景出现时一个层索引到输入层,进行对相应切片进行一些操作,然后下一层索引到结果中。这里有一个代表性的例子:

import tensorflow as tf 

## 10-Dimensional data will be fed to the model 
X = tf.placeholder(tf.float32, [10, None]) 

## W works with the first 3 features of a sample 
W = tf.Variable(tf.ones([5, 3])) 
Xi = tf.gather(X, [0,1,2]) 
mm = tf.matmul(W, Xi) 

## Indexing into the result produces a warning during backprop 
h = tf.gather(mm, [0,1]) 
... 
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss) 

警告出现时的train_step定义,如果第二tf.gather()呼叫被带走消失。如果X提供了明确数量的样本(例如,[10, 1000]),警告也会消失。

想法?

回答

6

tf.gather操作的梯度function返回IndexedSlices键入的值。在你的程序中,输入第二个tf.gathertf.matmulmm)的结果。因此,矩阵乘法的梯度函数值为IndexedSlices

现在,想象一下tf.matmul需要做什么梯度函数。要计算梯度w.r.t W,它必须乘以输入梯度与转置Xi。在这种情况下,输入梯度是IndexedSlices类型,并且Xi的转置是稠密张量(Tensor)类型。 TensorFlow没有可以在IndexedSlicesTensor上运行的矩阵乘法的实现。所以它只需在致电tf.matmul之前将IndexedSlices转换为Tensor即可。

如果你看一下该转换功能here的代码,你会发现,它打印出警告时,该疏去密转换可能导致主要是一个非常大的密集张量(_LARGE_SPARSE_NUM_ELEMENTS决定如何大),或密度未知的张量。当形状为[10, None]的形状占位符X时,此转换发生在未知形状的IndexedSlices上(实际上,只有其中一个维度未知,但仍无法静态确定生成的形状),因此您会看到打印出的警告。一旦将X的形状设置为[10, 1000],则IndexedSlices的形状将变为完全指定的形状,因此得到的稠密张量大小在阈值范围内,因此您看不到打印出的警告。

为了您的计算,如果你根本无法避免在tf.matmul的结果tf.gather,那么我会担心这样的警告太多,除非列在X数量是非常大的。

+0

谢谢。这就说得通了。我实际上能够重构我的代码以使用'tf.dynamic_partition()'而不是'tf.gather()',它除了避免警告外,还提供了更清晰的实现。 –

+0

@ArtemSokolov请你分享你的解决方案与dynamic_partition? – ryuzakinho