1. 程式人生 > >[轉載]Tensorflow 的reduce_sum()函數的axis,keep_dim這些參數到底是什麽意思?

[轉載]Tensorflow 的reduce_sum()函數的axis,keep_dim這些參數到底是什麽意思?

https 二維 應該 知乎 數量 轉載 sum 元素 歸約

轉載鏈接:https://www.zhihu.com/question/51325408/answer/125426642
來源:知乎

這個問題無外乎有三個難點:

  1. 什麽是sum
  2. 什麽是reduce
  3. 什麽是維度(indices, 現在均改為了axis和numpy等包一致)

sum很簡單,就是求和,那麽問題就是2和3,讓我們慢慢來講。其實徹底講清楚了這個問題,很多關於reduce,維度的問題都會恍然大悟。

0. 到底操作哪個維度??

sum這個操作完全可以泛化為任意函數,我們就以sum為例,來看看各種情況。

首先是1維(按照tensorflow的說法其實是0維,後面會說)就是這樣:

a = 1
sum(a) => 1

那麽看看2維的情況,為了看的更清楚,特意寫成了矩陣的形式:

a = [[1,2],
     [3,4]]
sum(a) => ???

仔細觀察,那麽問題來了,sum(a)到底應該是多少?有人說,當然是[3, 7](“橫著加”[[1+2],[3+4]]),有人說 不應該是[4, 6](“豎著加”[[1+3],[2+4]]) 嗎?還有人或說,不應該是10(全加在一起)嗎?

誰是對的?

都是對的。

所以,對於多維數組元素的相加,如果不指定“如何加”,結果是未定義的,之所以有些時候沒有指定也可以得到結果,是因為不同的軟件或框架有默認的行為。對於tensorflow,默認行為是最後一種,也就是全加在一起。

1. 什麽是維度?什麽是軸(axis)?如何索引軸(axis)?

註:對Axis比較熟悉的讀者可跳過這部分解釋,只看加粗字體。

這是一個很大的問題,到底什麽是維度呢?維基百科說:

維度,又稱維數,是數學中獨立參數的數目。在物理學和哲學的領域內,指獨立的時空坐標的數目。
0維是一點,沒有長度。1維是線,只有長度。2維是一個平面,是由長度和寬度(或曲線)形成面積。3維是2維加上高度形成“體積面”。雖然在一般人中習慣了整數維,但在分形中維度不一定是整數,可能會是一個非整的有理數或者無理數。

媽呀,好復雜,我只是想寫個tensorflow代碼呀。

那麽,編程時,你就可以簡單的認為:

維度是用來索引一個多維數組中某個具體數所需要最少的坐標數量。

把這句話多讀幾遍,我想你肯定會有所頓悟。這裏之所以說第一個1維的例子時0維,是因為,一個數字根本不需要索引,因為就只有一個呀。所有不同維度的形式如下:

0維,又稱0維張量,數字,標量:1

1維,又稱1維張量,數組,vector:[1, 2, 3]

2維,又稱2維張量,矩陣,二維數組:[[1,2], [3,4]]

3維,又稱3維張量,立方(cube),三維數組:[ [[1,2], [3,4]], [[5,6], [7,8]] ]

n維:你應該get到點了吧~

再多的維只不過是是把上一個維度當作自己的元素

1維的元素是標量,2維的元素是數組,3維的元素是矩陣。

從0維到3維,邊看邊念咒語“維度是用來索引一個多維數組中某個具體數所需要最少的坐標。”

在紙上寫寫看,想要精確定位一個數字,需要幾個數字呢?比如上面例子中的3維數組,我們想要3這個數字,至少要3個數字定位,它的坐標是(0為索引起點):[0, 1, 0]

好了,現在就能說了,什麽是軸(axis),如何索引axis(代碼中常用的變量名,後文就用axis代表軸)。

什麽是axis,編程時,你就可以簡單的認為:

axis是多維數組每個維度的坐標。

同樣,把這句話多讀幾遍,我想你一定有體悟。

還拿3維來說,數字3的坐標是[0, 1, 0],那麽第一個數字0的axis是0,第二個數字1的axis是1,第三個數字0的axis是2。

讓我們再看看我們是如何得到3這個數字的:

  1. 找到3所在的2維矩陣在這個3維立方的索引:0
  2. 找到3所在的1維數組在這個2維矩陣的索引:1
  3. 找到3這個數這個1維數組的索引:0

(這裏最好寫在紙上看一看,括號比較多。)

也就是說,對於[ [[1,2], [3,4]], [[5,6], [7,8]] ]這個3維情況,[[1,2],[[5,6]], [[3,4], [7,8]]這兩個矩陣(還記得嗎,高維的元素低一個維度,因此三維立方的元素是二維矩陣)的axis是0,[1,2],[3,4],[5,6],[7,8]這4個數組(二維矩陣的元素是一維數組)的axis是1,而1,2,3,4,5,6,7,8這8個數的axis是2。

越往裏axis就越大,依次加1。

那麽,對於3維的情況,令a = [ [[1,2], [3,4]], [[5,6], [7,8]] ],tf.reduce_sum(a, axis=1)應該輸出[[ 4, 6], [12, 14]],這就是處在axis=1的4個數組相加的結果,並reduce掉了一個維度。

這裏需要註意的是,axis可以為負數,此時表示倒數第axis個維度,這和Python中列表切片的用法類似。

那麽什麽是reduce呢?

2. 什麽是reduce

reduce這個詞字面上來講,大多稱作“歸約”,但這個詞太專業了,以至於第一眼看不出來意思。我更傾向於解釋為“塌縮”,這樣就形象多了。對一個n維的情況進行reduce,就是將執行操作的這個維度“塌縮”。還是上面tf.reduce_sum(a, axis=1)的例子,輸出[[ 4, 6], [12, 14]]是二維,顯然是被“塌縮”了,塌縮的哪個維度呢?就是被操作的維度,第2個維度,也就是axis=1(0開始索引)。tf.reduce_sum(a, axis=1)具體執行步驟如下:

  1. 找到a中axis=1的元素,也就是[1,2],[3,4],[5,6],[7,8]這4個數組(兩兩一組,因為前兩個和後兩個的地位相同)
  2. 在axis=1的維度進行相加也就是[1,2]+[3,4]=[4,6],[5,6]+[7,8]=[12, 14]
  3. “塌縮”這一維度,也就是說“掉一層方括號”,得出[[ 4, 6], [12, 14]]

接下來是一個附加問題:

3. 什麽是keepdims

上面的reduce已經解釋了,“塌縮”的是被操作的維度,那麽keepdims也就是保持維度,直觀來看就是“不掉一層方括號”,不掉哪層方括號呢?就是本來應該被塌縮的那一層(詳細解釋見評論)。tf.reduce_sum(a, axis=1, keepdims=True)得出[[[ 4, 6]], [[12, 14]]],可以看到還是3維。這種尤其適合reduce完了要和別的同維元素相加的情況。

[轉載]Tensorflow 的reduce_sum()函數的axis,keep_dim這些參數到底是什麽意思?