天天看點

Tensorflow2.x版本常用函數TensorFlow2.x中的常用函數

TensorFlow2.x中的常用函數

合并與分割

tf.concat()在特定的次元上進行合并

tf.concat(tensor, axis)

其中 tensors 儲存了所有需要合并的張量 List,axis 指定需要合并的次元。

a = tf.random.normal([4,35,8]) 
b = tf.random.normal([6,35,4])
tf.concat([a,b], axis = 0)

Output:
<tf.Tensor: id=13, shape=(10, 35, 8), dtype=float32, numpy = array([[[ 1.95299834e-01, 6.87859178e-01, -5.80048323e-01, ...,1.29430830e+00, 2.56610274e-01, -1.27798581e+00],[ 4.29753691e-01, 9.11329567e-01, -4.47975427e-01, ...,
           

tf.stack()

tf.stack(tensors, axis)

是一個堆疊類型的合并,在新的次元上進行合并

其中 tensors 儲存了所有需要合并的張量 List,axis >= 0時,在axis之前插入次元;axis<0時,在axis的後方插入次元。

a = tf.random.normal([35,8])
b = tf.random.normal([35,8])
tf.stack([a,b],axis=0) 
tf.stack([a,b], axis = -1)

Output:
<tf.Tensor: id=55, shape=(2, 35, 8), dtype=float32, numpy=...>
<tf.Tensor: id=55, shape=(35, 8, 2), dtype=float32, numpy=...>
           

tf.split()

合并操作的逆過程就是分割,将一個張量分拆為多個張量。

通過 tf.split(x, axis, num_or_size_splits)可以完成張量的分割操作,其中

❑ x:待分割張量

❑ axis:分割的次元索引号 ❑ num_or_size_splits:切割方案。當num_or_size_splits 為單個數值時,如 10,表示切割為 10 份;當 num_or_size_splits 為 List 時,每個元素表示每份的長度,如[2,4,2,2]表示

切割為 4 份,每份的長度分别為 2,4,2,2

x = tf.random.normal([10,35,8])
# 等長切割
result = tf.split(x,axis=0,num_or_size_splits=10)
len(result)
Output: 10

# 自定義長度的切割
result = tf.split(x,axis=0,num_or_size_splits=[4,2,2,2])
len(result)
Output: 4
           

資料計算

向量範數(Vector norm)是表征向量“長度”的一種度量方法,在神經網絡中,常用來

表示張量的權值大小,梯度大小等。常用的向量範數有:

❑ L1 範數,定義為向量𝒙的所有元素絕對值之和

‖𝒙‖1 = ∑|𝑥𝑖| 𝑖

❑ L2 範數,定義為向量𝒙的所有元素的平方和,再開根号

‖𝒙‖2 = √∑|𝑥𝑖|2 𝑖

❑ ∞ −範數,定義為向量𝒙的所有元素絕對值的最大值:

‖𝒙‖∞ = 𝑚𝑎𝑥𝑖(|𝑥𝑖|)

對于矩陣、張量,同樣可以利用向量範數的計算公式,等價于将矩陣、張量拉平成向量後計算。

tf.norm()

In [13]: x = tf.ones([2,2])
tf.norm(x,ord=1) # 計算 L1 範數
Out[13]: <tf.Tensor: id=183, shape=(), dtype=float32, numpy=4.0>
In [14]: tf.norm(x,ord=2) # 計算 L2 範數
Out[14]: <tf.Tensor: id=189, shape=(), dtype=float32, numpy=2.0>
In [15]: import numpy as np
tf.norm(x,ord=np.inf) # 計算∞範數
Out[15]: <tf.Tensor: id=194, shape=(), dtype=float32, numpy=1.0>
           

數值複制、填充與限制

對于圖檔資料的高和寬、序列信号的長度,次元長度可能各不相同。為了友善網絡的并行計算,需要将不同長度的資料擴張為相同長度,之前我們介紹了通過複制的方式可以增加資料的長度,但是重複複制資料會破壞原有的資料結構,并不适合于此處。通常的做法是,在需要補充長度的信号開始或結束處填充足夠數量的特定數值,如 0,使得填充後的長度滿足系統要求。那麼這種操作就叫做填充(Padding)。

填充操作可以通過 tf.pad(x, paddings)函數實作,paddings 是包含了多個

[𝐿𝑒𝑓𝑡 𝑃𝑎𝑑𝑑𝑖𝑛𝑔, 𝑅𝑖𝑔ℎ𝑡 𝑃𝑎𝑑𝑑𝑖𝑛𝑔]的嵌套方案 List,如[[0,0],[2,1],[1,2]]表示第一個次元不填充,第二個次元左邊(起始處)填充兩個單元,右邊(結束處)填充一個單元,第三個次元左邊填充一個單元,右邊填充兩個單元。考慮上述 2 個句子的例子,需要在第二個句子的第一個次元的右邊填充 2 個單元,則 paddings 方案為[[0,2]]:

tf.pad()

a = tf.constant([1,2,3,4,5,6])
b = tf.constant([7,8,1,6])
b = tf.pad(b, [[0,2]]) # 填充b

Output:<tf.Tensor: id=3, shape=(6,), dtype=int32, numpy=array([7, 8, 1, 6, 
0, 0])>

#填充後句子張量形狀一緻,再将這 2 句子 Stack 在一起:
tf.stack([a,b],axis=0) # 合并

Output:<tf.Tensor: id=5, shape=(2, 6), dtype=int32, numpy=
array([[1, 2, 3, 4, 5, 6], [7, 8, 1, 6, 0, 0]])>
           

tf.tile()

通過 tf.tile 函數可以在任意次元将資料重複複制多份,如 shape 為[4,32,32,3]的資料,複制方案 multiples=[2,3,3,1],即通道資料不複制,高寬方向分别複制 2 份,圖檔數再複制1 份:

x = tf.random.normal([4,32,32,3])
tf.tile(x,[2,3,3,1]) # 資料複制

<tf.Tensor: id=25, shape=(8, 96, 96, 3), dtype=float32, numpy=...>
           

tf.maximum() tf.minimum()

在 TensorFlow 中,可以通過 tf.maximum(x, a)實作資料的下限幅:𝑥 ∈ [𝑎, +∞);可以通過 tf.minimum(x, a)實作資料的上限幅:𝑥 ∈ (−∞,𝑎]:

x = tf.range(9)
tf.maximum(x,2) # 下限幅 2

<tf.Tensor: id=48, shape=(9,), dtype=int32, numpy=array([2, 2, 2, 3, 4, 5, 6, 7, 8])>

tf.minimum(x,7) # 上限幅 7

<tf.Tensor: id=41, shape=(9,), dtype=int32, numpy=array([0, 1, 2, 3, 4, 5, 6, 7, 7])>
           

tf.clip_by_value()

tf.clip_by_value(tensor, 下限,上限)

x = tf.range(9)
tf.clip_by_value(x,2,7) # 限幅為 2~7

<tf.Tensor: id=66, shape=(9,), dtype=int32, numpy=array([2, 2, 2, 3, 4, 5, 6, 7, 7])>
           

其他進階操作

tf.gather()

tf.gather(tensor, num, axis)

num為想要收集資料的索引号

axis是按照哪個次元來進行檢索

x = tf.random.uniform([4,35,8],maxval=100,dtype=tf.int32)
tf.gather(x,[0,1],axis=0) # 在班級次元收集第 1-2 号班級成績冊

<tf.Tensor: id=83, shape=(2, 35, 8), dtype=int32, numpy=array([[[43, 10, 93, 85, 75, 87, 28, 19],[52, 17, 44, 88, 82, 54, 16, 65],[98, 26, 1, 47, 59, 3, 59, 70],…
           

tf.gather_nd()用法與tf.gather()類似,用于根據多元的坐标來檢索資料

tf.boolean_mask()

tf.boolean_mask(x,mask=[True, False,False,True],axis=0)

mask是掩碼,該方法根據掩碼來進行次元的檢索

tf.boolean_mask(x,mask=[True, False,False,True],axis=0)  x = [4, 35, 8]
Out[49]:<tf.Tensor: id=288, shape=(2, 35, 8), dtype=int32, numpy=array([[[43, 10, 93, 85, 75, 87, 28, 19],…
           

tf.where()

通過 tf.where(cond, a, b)操作可以根據 cond 條件的真假從 a 或 b 中讀取資料,條件判定規則如下:

𝑜𝑖 = {𝑎𝑖 𝑐𝑜𝑛𝑑𝑖為𝑇𝑟𝑢𝑒 𝑏𝑖 𝑐𝑜𝑛𝑑𝑖為𝐹𝑎𝑙𝑠𝑒

其中 i 為張量的索引,傳回張量大小與 a,b 張量一緻,當對應位置中𝑐𝑜𝑛𝑑𝑖為 True,𝑜𝑖位置從𝑎𝑖中複制資料;當對應位置中𝑐𝑜𝑛𝑑𝑖為 False,𝑜𝑖位置從𝑏𝑖中複制資料。考慮從 2 個全 1、 全 0 的 3x3 大小的張量 a,b 中提取資料,其中cond 為 True 的位置從 a 中對應位置提取,cond 為 False 的位置從 b 對應位置提取:

In [53]:
a = tf.ones([3,3]) # 構造 a 為全 1
b = tf.zeros([3,3]) # 構造 b 為全 0
# 構造采樣條件
cond = tf.constant([[True,False,False],[False,True,False],[True,True,False]])
tf.where(cond,a,b) # 根據條件從 a,b 中采樣
Out[53]:<tf.Tensor: id=384, shape=(3, 3), dtype=float32, numpy=
array([[1., 0., 0.],
       [0., 1., 0.],
       [1., 1., 0.]], dtype=float32)>
           

通過對于cond的where操作會得到true元素所在的位置

In [55]:tf.where(cond) # 擷取 cond 中為 True 的元素索引

Out[55]:<tf.Tensor: id=387, shape=(4, 2), dtype=int64, numpy=
array([[0, 0],
       [1, 1],
       [2, 0],
       [2, 1]], dtype=int64)>
           

tf.meshgrid()

通過 tf.meshgrid 可以友善地生成二維網格采樣點坐标,友善可視化等應用場合。考慮2 個自變量 x,y 的 Sinc 函數表達式為:

𝑧 =𝑠𝑖𝑛(𝑥2 + 𝑦2) 𝑥2 + 𝑦2

如果需要繪制函數在𝑥 ∈ [−8,8],𝑦 ∈ [−8,8]區間的 Sinc 函數的 3D 曲面,如圖 所示,則首先需要生成 x,y 的網格點坐标{(𝑥, 𝑦)},這樣才能通過 Sinc 函數的表達式計算函數在每個(𝑥, 𝑦)位置的輸出值 z。可以通過如下方式生成 1 萬個坐标采樣點:

Tensorflow2.x版本常用函數TensorFlow2.x中的常用函數
points = []
for x in range(-8,8,100): # 循環生成 x 坐标
	for y in range(-8,8,100): # 循環生成 y 坐标
		z = sinc(x,y) # 計算 sinc 函數值
		points.append([x,y,z]) # 儲存采樣點
           

很明顯這種方式串行計算效率極低,那麼有沒有簡潔高效地方式生成網格坐标呢?答案是肯定的,tf.meshgrid 函數即可實作。

通過在 x 軸上進行采樣 100 個資料點,y 軸上采樣 100 個資料點,然後通過

tf.meshgrid(x, y)即可傳回這 10000 個資料點的張量資料,shape 為[100,100,2]。為了友善計算,tf.meshgrid 會傳回在 axis=2 次元切割後的 2 個張量 a,b,其中張量 a 包含了所有點的 x坐标,b 包含了所有點的 y 坐标,shape 都為[100,100]:

x = tf.linspace(-8.,8,100) # 設定 x 坐标的間隔
y = tf.linspace(-8.,8,100) # 設定 y 坐标的間隔
x,y = tf.meshgrid(x,y) # 生成網格點,并拆分後傳回
x.shape,y.shape # 列印拆分後的所有點的 x,y 坐标張量 shape

Output:(TensorShape([100, 100]), TensorShape([100, 100]))
           

Sinc 函數在 TensorFlow 中實作如下:

z = tf.sqrt(x**2+y**2) 
z = tf.sin(z)/z # sinc 函數實作
           

通過 matplotlib 即可繪制出函數在𝑥 ∈ [−8,8], 𝑦 ∈ [−8,8]區間的 3D 曲面

fig = plt.figure()
ax = Axes3D(fig)
           

根據網格點繪制 sinc 函數 3D 曲面

ax.contour3D(x.numpy(), y.numpy(), z.numpy(), 50)
plt.show()
           

注:.numpy()方法隻用在使用tf.enable_eager_execution()(指令式程式設計開啟)後才有的方法, 否則會有==AttributeError: ‘Tensor’ object has no attribute ‘numpy’==報錯

繼續閱讀