Sum 函數 Axis 詳解

編程過程中經常需要對數組進行處理,而sum又是經常需要用到的函數,sum函數傳參時會用到axis參數,低維度還好,高維度經常容易混淆,本文基於TF,對數組sum時axis進行詳解,即對哪個位置加,加完形狀變什麼樣。

Tip: tf只是用來調用生成結果,對axis的理解適合任意語言

 

Sum

首先明確axis的作用,axis參數是加和時用來固定的軸,也可以說是數學裏的維度。常見的情形遇到的是標量,向量和矩陣,分別是1維,2維,三維,分別對應1個軸(x),2個軸(x,y),3個軸(x,y,z),本文以3維爲例解析axis參數。

 

1.首先生成三維矩陣:

import tensorflow as tf
oriFeat = tf.constant([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
print(oriFeat)
tensor = tf.nn.embedding_lookup(oriFeat,[[0,1],[1,2],[2,3]])
print(tensor)

這裏用numpy生成也行,大同小異,得到我們使用的三維矩陣:

tf.Tensor(
[[[ 1  2  3]
  [ 4  5  6]]

 [[ 4  5  6]
  [ 7  8  9]]

 [[ 7  8  9]
  [10 11 12]]], shape=(3, 2, 3), dtype=int32)

這裏維度是 3x2x3 對應三個軸 x,y,z

 

2.其次給給定元素進行軸的標記:

第一層分 3 個部分,每個部分包含一個 2x3 的矩陣,例:

A => [ 1  2  3]        B => [ 4  5  6]        C => [ 7  8  9]  
     [ 4  5  6]             [ 7  8  9]             [10 11 12]
      (0,x,x)                (1,x,x)                (2,x,x)

這一部分座標對應到三維座標軸的是 (0,x,x),後面兩個分別是(1,x,x), (2,x,x)

第二層分 2 個部分,每個部分包含一個 1x3 的向量:(以第A爲例)

A => [ 1  2  3]  ==>    A.1 => [1,2,3]   A.2 => [3,4,5] 
     [ 4  5  6] 
      (0,x,x)                  (0,0,x)          (0,1,x)

第三層分 3 個部分,每個部分包含 3 個標量:(以A.1爲例)

 A.1 => [1,2,3]      A.1.1 => 1    A.1.2 => 2     A.1.3 => 3    
        (0,0,x)     (0,0,0)       (0,0,1)        (0,0,2)

 

通過上面分解,最初的3 x 2 x 3的矩陣可以轉化爲如下對應座標:

     [ 1  2  3]                    [ 4  5  6]                   [ 7  8  9]  
     [ 4  5  6]                    [ 7  8  9]                   [10 11 12]
                        
[(0,0,0),(0,0,1),(0,0,2)]   [(1,0,0),(1,0,1),(1,0,2)]   [(2,0,0),(2,0,1),(2,0,2)]   
[(0,1,0),(0,1,1),(0,1,2)]   [(1,1,0),(1,1,1),(1,1,2)]   [(2,1,0),(2,1,1),(2,1,2)]

 

3.計算之前,首先明白兩個概念,也是對sum和axis的理解:

1).sum後維度

對哪個axis即軸進行加和,對應軸代表的維度就會消失,這裏可以理解成三維物體對某一維進行壓縮,從而維度降低,所以 3x2x3 ,如果執行sum(matrix,axis=0),則第一個維度消失,得到的新的維度是 2x3,同理, sum(matrix,axis=1) 的到的新維度爲3x3,sum(matrix,axis=2)得到的新維度是3x2

2).sum加哪裏,加對應axis軸,其餘軸固定不變,類似於固定變量法:

先對上述矩陣執行axis=0的sum操作:

     [ 1  2  3]                    [ 4  5  6]                   [ 7  8  9]  
     [ 4  5  6]                    [ 7  8  9]                   [10 11 12]
                        
[(0,0,0),(0,0,1),(0,0,2)]   [(1,0,0),(1,0,1),(1,0,2)]   [(2,0,0),(2,0,1),(2,0,2)]   
[(0,1,0),(0,1,1),(0,1,2)]   [(1,1,0),(1,1,1),(1,1,2)]   [(2,1,0),(2,1,1),(2,1,2)]

固定y,z軸,對x軸加和:
(0,0,0) + (1,0,0) + (2,0,0) => (0,0) => 1 + 4 + 7 = 12
(0,0,1) + (1,0,1) + (2,0,1) => (0,1) => 2 + 5 + 8 = 15
(0,0,2) + (1,0,2) + (2,0,2) => (0,2) => 3 + 6 + 9 = 18
 

x軸壓縮,由上可知得到的是2x3的矩陣,這裏已經示例得到了1x3,再進行3次加和即可得到另一個1x3

    changeTensor = tf.reduce_sum(tensor,axis=0)
    print(changeTensor)
tf.Tensor(
[[12 15 18]
 [21 24 27]], shape=(2, 3), dtype=int32)

 

對上述矩陣執行axis=1的sum操作,以A爲例:

     [ 1  2  3]                           axis=1 對應(x,y,z)裏的y位置
     [ 4  5  6]                           所有y位置上的點進行加和壓縮
                                          
[(0,0,0),(0,0,1),(0,0,2)]                (0,0,0) + (0,1,0) => (0,0) = 1 + 4 = 5 
[(0,1,0),(0,1,1),(0,1,2)]                (0,0,1) + (0,1,1) => (0,1) = 2 + 5 = 7 
                                         (0,0,2) + (0,1,2) => (0,2) = 3 + 6 = 9

y軸壓縮後,根據上面可以得到新的維度爲3x3,A得到一個1x3,同理B,C也各得到一個1x3,組合起來得到3x3

B得到 1x3 (11,13,15)
C得到 1x3 (17,19,21)
    changeTensor = tf.reduce_sum(tensor,axis=1)
    print(changeTensor)
tf.Tensor(
[[ 5  7  9]
 [11 13 15]
 [17 19 21]], shape=(3, 3), dtype=int32)

 

再以axis=2示例,這個相對於axis=0或axis=1比較少見,沒進行座標分解時,自己理解也比較頭大:

     [ 1  2  3]                           axis=2 對應(x,y,z)裏的z位置
     [ 4  5  6]                           所有y位置上的點進行加和壓縮
                                          
[(0,0,0),(0,0,1),(0,0,2)]        (0,0,0) + (0,0,1) + (0,0,2) => (0,0) => 1+2+3 = 6  
[(0,1,0),(0,1,1),(0,1,2)]        (0,1,0) + (0,1,1) + (0,1,2) => (0,1) => 4+5+6 = 15

z軸壓縮後,根據上面可以得到新的維度爲3x2,A得到一個1x2,同理B,C也各得到一個1x2,組合起來得到3x2

B得到 1x2 (15 24)
C得到 1x2 (24 33)
    changeTensor = tf.reduce_sum(tensor,axis=2)
    print(changeTensor)
tf.Tensor(
[[ 6 15]
 [15 24]
 [24 33]], shape=(3, 2), dtype=int32)

 

Tip:

由於需要固定axis以外的軸進行sum操作,所以我們只在axis=0時需要對所有矩陣(即3x2x3)進行操作,當axis=0或axis=1時,x維度已經被固定,所以我們可以在一個小的矩陣(2x3)中進行sum操作。

其次,可以發現,隨着軸的增加,操作的量也越來越小,axis=0時,我們sum一個需要同時操作3個2x3的矩陣((0,0,0) + (1,0,0) + (2,0,0)),但當axis=2時,我們只需要一個向量裏的元素((0,0,0) + (0,0,1) + (0,0,2)),因此軸越大,操作粒度越小

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章