1. 程式人生 > >一文理解Tensorflow中reduce_mean() reduce_sum() reduce_max()...系列

一文理解Tensorflow中reduce_mean() reduce_sum() reduce_max()...系列

原文medium部落格連結

在Tensorflow(TF)中,常常會看到“reduce_"系列的東西,比如reduce_sum,reduce_mean…,剛剛開始我覺得,求和就sum就行,為什麼加一個reduce_字首?

後來我意識到,每一次求和或者求平均值,其實都是自動的對Tensor進行了降維,例如,對向量[1,2,3,4]求和,得到一個標量10。

剛剛開始接觸reduce系列,通常需要花一些時間在腦海中視覺化哪一個維度被減掉了,但是在熟悉了tensor的 shape/dimensions/indexing之後,很多debug會節省很多時間。
其實TF的sum和mean與numpy,matlab都類似,index=0表示按列求和或者取平均,index=1表示按照行求和或者取平均,只是TF中處理的多是4維或者5維[batch_size, time_steps, width, height, channels]張量,不那麼容易理解,下面以一個三維Tensor為例子來操作。

# Let's initialize the tensor.
In [3]: x = tf.constant([[[1,2,3,4,5], [4,5,6,7,8]],
                         [[2,4,6,8,10],[3,6,9,12,15]],
                         [[8,8,8,8,8], [9,9,9,9,9]]])
In [9]: sess = tf.InteractiveSession()
# Let's see how it looks.
In [10]: x.eval()
Out[10]:
array([[[ 1,  2,  3,  4,  5],
        [ 4,  5,  6,  7,  8]],
       [[ 2,  4,  6,  8, 10],
        [ 3,  6,  9, 12, 15]],
       [[ 8,  8,  8,  8,  8],
        [ 9,  9,  9,  9,  9]]], dtype=int32)

這裡順便說一下tf.InteractiveSession和tf.Session的區別,經常做大專案的同學知道,tf.Session一般都是在整個網路的計算圖構建完了之後,再來run初始化變數和feed資料。但是tf.InteractiveSession不同,它支援先開sess,然後加入計算圖,也就是說,如果是做小實驗,熟悉Tensorflow的各個函式,用tf.InteractiveSession和eval()函式是合適的。
tf.reduce_max(x,0) 輸出是什麼呢?

tf.reduce_max(x, 0) 減掉的是第0維,所以這個(3,2,5)的tensor中的3會消失。

In [11]: tf.reduce_max(x,0)
Out[11]: <tf.Tensor 'Max:0' shape=(2, 5) dtype=int32>
In [12]: tf.reduce_max(x,0).eval()
Out[12]:
array([[ 8,  8,  8,  8, 10],
       [ 9,  9,  9, 12, 15]], dtype=int32)

對於第一維是一樣的,結果的shape是(3,5)

In [14]: tf.reduce_max(x,1)
Out[14]: <tf.Tensor 'Max_3:0' shape=(3, 5) dtype=int32>
In [15]: tf.reduce_max(x,1).eval()
Out[15]:
array([[ 4,  5,  6,  7,  8],
       [ 3,  6,  9, 12, 15],
       [ 9,  9,  9,  9,  9]], dtype=int32)

在一些實際程式碼中,可能會看到reduce中不是減掉單個維度而是減掉幾個維度,比如tf.reduce_max(x,(1,2))意味著我們想要每個batch中的最大值(batch_size通常是dimension 0),這種情況下坍縮的就是維度1和2.

In [16]: tf.reduce_max(x,(1,2)).eval()
Out[16]: array([ 8, 15,  9], dtype=int32)
In [17]: tf.reduce_max(x,(1,2))
Out[17]: <tf.Tensor 'Max_11:0' shape=(3,) dtype=int32>

你會發現這改變了最初tensor的shape,怎麼辦?
加上那句keepdims=True.

In [22]: tf.reduce_max(x,(1,2), keepdims=True).eval()
Out[22]:
array([[[ 8]],
       [[15]],
       [[ 9]]], dtype=int32)
In [23]: tf.reduce_max(x,(1,2), keepdims=True)
Out[23]: <tf.Tensor 'Max_10:0' shape=(3, 1, 1) dtype=int32>