2016-08-23 522 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