編程過程中經常需要對數組進行處理,而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)),因此軸越大,操作粒度越小