TensorFlow核心概念之Tensor(4):張量運算

??TensorFlow中關于張量的運算主要有:數學運算,矢量運算及矩陣運算,另外在實際的張量運算過程中,支也支持與numpy的廣播特性,不同維度的張量之間往往存在這低維張量向高維張量進行廣播的現象,這也稱之為張量的廣播機制。本文主要從數學運算、矢量運算、矩陣運算三個方面介紹張量運算相關的內容,最后我們在大致了解以下張量的廣播機制。

一、數學運算

??加減乘除、乘方開方、三角函數,指數對數以及邏輯運算等都是TensorFlow中比較常見的數學運算函數,TensorFlow提供了tf.math包來實現這些數學運算,另外大部分數學運算還可以通過運算符重載的方式來實現 。這里我們簡單示例幾種常見的數學運算操作,同樣的,在正式進入代碼演示之前,先引入我們依賴的包,代碼如下:

import numpy as np
import tensorflow as tf

print("numpy.version:", np.__version__)
print("tensorflow.version:", tf.__version__)

結果如下:

numpy.version: 1.23.5
tensorflow.version: 2.11.0

??下面我們正式展示TensorFlow中的數學運算操作,代碼如下

# 定義兩個二維張量
a = tf.constant([[1.0, 2], [3, 4]])
b = tf.constant([[1.0, 0], [-1, 0]])
print("a:")
tf.print(a)
print("----------------------------------")
print("b:")
tf.print(b)
print("----------------------------------")

# 加法運算
print("a + b:")
tf.print(a + b)
print("----------------------------------")

# 減法運算
print("a - b:")
tf.print(a - b)
print("----------------------------------")

# 乘法運算
print("a * b:")
tf.print(a * b)
print("----------------------------------")

# 除法運算
print("a / b:")
tf.print(a / b)
print("----------------------------------")

# 乘方
print("b ** 2:")
tf.print(b ** 2)
print("----------------------------------")

# 開方
print("sqrt(a):")
tf.print(tf.sqrt(a))
print("----------------------------------")

# add運算符重載,a + 1等價于tf.math.add
print("a + 1:")
tf.print(a + 1)
print("tf.math.add(a, 1):")
tf.print(tf.math.add(a, 1))
print("----------------------------------")

# 邏輯運算
print("b > 0:")
tf.print(b > 0)
print("b == 0:")
tf.print(b == 0)
print("----------------------------------")

# 最大值
print("tf.maximum(a, b)")
tf.print(tf.maximum(a, b))
print("----------------------------------")

# 最小值
print("tf.minimum(a,b)")
tf.print(tf.minimum(a,b))
print("----------------------------------")

結果如下:

a:
[[1 2]
 [3 4]]
----------------------------------
b:
[[1 0]
 [-1 0]]
----------------------------------
a + b:
[[2 2]
 [2 4]]
----------------------------------
a - b:
[[0 2]
 [4 4]]
----------------------------------
a * b:
[[1 0]
 [-3 0]]
----------------------------------
a / b:
[[1 inf]
 [-3 inf]]
----------------------------------
b ** 2:
[[1 0]
 [1 0]]
----------------------------------
sqrt(a):
[[1 1.41421354]
 [1.73205078 2]]
----------------------------------
a + 1:
[[2 3]
 [4 5]]
tf.math.add(a, 1):
[[2 3]
 [4 5]]
----------------------------------
b > 0:
[[1 0]
 [0 0]]
b == 0:
[[0 1]
 [0 1]]
----------------------------------
tf.maximum(a, b)
[[1 2]
 [3 4]]
----------------------------------
tf.minimum(a,b)
[[1 0]
 [-1 0]]
----------------------------------

二、矢量運算

??矢量運算是指在一個特定軸上進行運算,將一個張量映射到一個標量或者另外一個低維張量。
許多矢量運算都以reduce開頭。下面分別從一維張量和多維張量的角度展示矢量運算的用法,代碼如下:

#一維張量的矢量運算
a = tf.range(1,6)
print("a:")
tf.print(a)
print("----------------------------------")
#求和
tf.print("reduce_sum:", tf.reduce_sum(a, axis = 0))
#如果只是一維張量,默認可以不指定axis
#求最大值
tf.print("reduce_max:", tf.reduce_max(a)) 
#求最小值
tf.print("reduce_min:", tf.reduce_min(a))
#求最均值
tf.print("reduce_mean:", tf.reduce_mean(a)) 
#求積
tf.print("reduce_prod:", tf.reduce_prod(a))
#按順序求每個位置累加和,類似于mysql中的窗口函數
tf.print("cumsum:", tf.math.cumsum(a))
#按順序求每個位置累積
tf.print("cumprod:", tf.math.cumprod(a))
print("----------------------------------")

c = tf.constant([True,True,True])
d = tf.constant([False,False,True])
print("c:")
tf.print(c)
print("----------------------------------")
print("d:")
tf.print(d)
print("----------------------------------")
tf.print("reduce_all(c):", tf.reduce_all(c))
tf.print("reduce_all(d):", tf.reduce_all(d))
tf.print("reduce_any(d):", tf.reduce_any(d))
print("----------------------------------")

#tf.math.top_k可以用于對張量取top k
a = tf.constant([1,3,6,6,4,6])
tf.print("a:",a)
values,indices = tf.math.top_k(a, 3, sorted=True)
print("top 3:")
tf.print("indices", indices, "values", values)
print("----------------------------------")

#多維張量的矢量運算
b = tf.random.uniform(shape=[3, 3, 3], minval=0, maxval=2, dtype=tf.int32)
print("b:")
tf.print(b)
print("----------------------------------")

tf.print("axis=0, reduce_sum:\n", tf.reduce_sum(b, axis=0, keepdims=True))
tf.print("axis=1, reduce_sum:\n", tf.reduce_sum(b, axis=1, keepdims=False))
tf.print("axis=2, reduce_sum:\n", tf.reduce_sum(b, axis=2, keepdims=False))
tf.print("no axis, reduce_sum:", tf.reduce_sum(b))
print("----------------------------------")

結果如下:

a:
[1 2 3 4 5]
----------------------------------
reduce_sum: 15
reduce_max: 5
reduce_min: 1
reduce_mean: 3
reduce_prod: 120
cumsum: [1 3 6 10 15]
cumprod: [1 2 6 24 120]
----------------------------------
c:
[1 1 1]
----------------------------------
d:
[0 0 1]
----------------------------------
reduce_all(c): 1
reduce_all(d): 0
reduce_any(d): 1
----------------------------------
a: [1 3 6 6 4 6]
top 3:
indices [2 3 5] values [6 6 6]
----------------------------------
b:
[[[0 0 1]
  [1 1 0]
  [0 0 0]]

 [[0 1 1]
  [0 0 1]
  [1 1 0]]

 [[1 1 0]
  [0 0 1]
  [0 0 0]]]
----------------------------------
axis=0, reduce_sum:
 [[[1 2 2]
  [1 1 2]
  [1 1 0]]]
axis=1, reduce_sum:
 [[1 1 1]
 [1 2 2]
 [1 1 1]]
axis=2, reduce_sum:
 [[1 2 0]
 [2 1 2]
 [2 1 0]]
no axis, reduce_sum: 11
----------------------------------

三、矩陣運算

??矩陣運算主要是支持一些常規的線性代數中矩陣的計算,TensorFlow提供了tf.linalg包來實現大部分和矩陣有關的運算,包括轉置、矩陣乘法、求逆、求跡、范數、行列式、求特征值以及矩陣分解等。下面通過代碼來展示常用的矩陣運算,代碼如下:

# 定義兩個二維張量來表示矩陣 
a = tf.constant([[1, 2], [3, 4]], dtype=tf.float32)
b = tf.constant([[1, 0], [-1, 0]], dtype=tf.float32)
print("a:")
tf.print(a)
print("----------------------------------")
print("b:")
tf.print(b)
print("----------------------------------")

#矩陣轉置
tf.print("矩陣轉置:\n", tf.transpose(a))
print("----------------------------------")

#矩陣乘法
tf.print("矩陣乘法1:\n", tf.matmul(a, b))
tf.print("矩陣乘法2:\n", a @ b )
print("----------------------------------")

#矩陣求逆
tf.print("矩陣求逆:\n", tf.linalg.inv(a))
print("----------------------------------")

#矩陣求跡
tf.print("矩陣求跡:\n", tf.linalg.trace(a))
print("----------------------------------")

#矩陣特征值
tf.print("矩陣特征值:\n")
print( tf.linalg.eigvals(a))
print("----------------------------------")

#矩陣分解
s,u,v = tf.linalg.svd(a)
print("矩陣分解:\n")
tf.print(u,"\n")
tf.print(s,"\n")
tf.print(v,"\n")
tf.print(u @ tf.linalg.diag(s) @ tf.transpose(v))
print("----------------------------------")

結果如下


a:
[[1 2]
 [3 4]]
----------------------------------
b:
[[1 0]
 [-1 0]]
----------------------------------
矩陣轉置:
 [[1 3]
 [2 4]]
----------------------------------
矩陣乘法1:
 [[-1 0]
 [-1 0]]
矩陣乘法2:
 [[-1 0]
 [-1 0]]
----------------------------------
矩陣求逆:
 [[-2.00000024 1.00000012]
 [1.50000012 -0.50000006]]
----------------------------------
矩陣求跡:
 5
----------------------------------
矩陣特征值:

tf.Tensor([-0.37228122+0.j  5.372281  +0.j], shape=(2,), dtype=complex64)
----------------------------------
矩陣分解:

[[0.404553503 -0.914514303]
 [0.914514303 0.404553503]] 

[5.46498537 0.365966141] 

[[0.576048374 0.817415595]
 [0.817415595 -0.576048374]] 

[[0.999999583 1.99999964]
 [2.99999976 4]]
----------------------------------

四、廣播機制

??在Numpy中,廣播機制(broad casting)指的是通過擴展低維度ndarray的維度來實現不同維度間ndarray的加減乘除等操作的機制。TensorFlow的廣播機制來源于Numpy,其針對張量運算的廣播規則和Numpy基本是一樣的,廣播規則如下:

  1. 如果張量的維度不同,對維度小的張量進行升維,直到兩個張量的維度一樣。
  2. 如果兩個張量在某個維度上的長度是相同的,或者其中一個張量在該維度上的長度為1,那么就認為這兩個張量在該維度上是相容的。
  3. 如果兩個張量在所有維度上均相容,它們之間就能應用廣播。
  4. 廣播后,每個維度的長度將取兩個張量在該維度長度的較大值。
  5. 在任何一個維度上,如果一個張量的長度為1,另一個張量長度大于1,那么在該維度上的廣播就是對第一個張量進行復制。
    ??TensorFlow中實現廣播有兩種方式,一種是使用tf.broadcast_to顯式地講張量廣播至指定維度,還有一種就是在運算過程系統進行隱式的廣播。下面進行簡單的示例,代碼如下:
#定義兩個維度不同的張量
a = tf.constant([1, 1, 1])
b = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("a:")
tf.print(a)
print("----------------------------------")
print("b:")
tf.print(b)
print("----------------------------------")

#顯式廣播
tf.print("顯式廣播:\n", tf.broadcast_to(a, b.shape))
print("----------------------------------")

#隱式廣播
tf.print("隱式廣播:\na + b:\n", a + b) #等價于 tf.broadcast_to(a, b.shape) + b
tf.print("隱式廣播:\na + 1:\n", a + 1)#等價于 a + tf.broadcast_to(1, a.shape)
print("----------------------------------")

#計算廣播后的shape
tf.print("廣播后的shape:", tf.broadcast_static_shape(a.shape, b.shape))
tf.print("廣播后的shape:", tf.broadcast_dynamic_shape(a.shape, b.shape))
print("----------------------------------")

結果如下:

a:
[1 1 1]
----------------------------------
b:
[[1 2 3]
 [4 5 6]
 [7 8 9]]
----------------------------------
顯式廣播:
 [[1 1 1]
 [1 1 1]
 [1 1 1]]
----------------------------------
隱式廣播:
a + b:
 [[2 3 4]
 [5 6 7]
 [8 9 10]]
隱式廣播:
a + 1:
 [2 2 2]
----------------------------------
廣播后的shape: TensorShape([3, 3])
廣播后的shape: [3 3]
----------------------------------

??關于張量的運算,就簡單介紹到這里。

TensorFlow系列文章:
  1. TensorFlow核心概念之Tensor(1):張量創建
  2. TensorFlow核心概念之Tensor(2):索引切片
  3. TensorFlow核心概念之Tensor(3):變換拆合
  4. TensorFlow核心概念之Tensor(4):張量運算
  5. TensorFlow核心概念之計算圖
  6. TensorFlow核心概念之Autograph
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容