一、常用函數
1、轉換tensor數據類型
import tensorflow as tf a=tf.constant(1.0) b=tf.cast(a,dtype='int32') print(a) print(b)
輸出:
tf.Tensor(1.0, shape=(), dtype=float32)
tf.Tensor(1, shape=(), dtype=int32)
2、tensor元素的最大值、最小值、求和與均值
import tensorflow as tf a=tf.constant([[1,1],[2,2]]) a_min=tf.reduce_min(a) # 張量元素的最小值 a_max=tf.reduce_max(a) # 張量元素的最大值 a_mean=tf.reduce_mean(a) # 張量元素的均值 a_sum=tf.reduce_sum(a) # 張量元素的和 a_row_sum=tf.reduce_sum(a,axis=0) # 張量列(第1維度)元素的和 a_col_sum=tf.reduce_sum(a,axis=1) # 張量行(第2維度)元素的和 print('張量a:\n',a) print('行求和:\n',a_row_sum) print('列求和:\n',a_col_sum)
輸出:
張量a: tf.Tensor( [[1 1] [2 2]], shape=(2, 2), dtype=int32) 行求和: tf.Tensor([3 3], shape=(2,), dtype=int32) 列求和: tf.Tensor([2 4], shape=(2,), dtype=int32)
參數說明:axis可以定義操作的方向。在矩陣中axis=0表示跨行,對各個列進行求和操作。通常axis=0對應的是tensor.shape的第一個維度。示例圖如下:
3、變量的定義與創建
TensorFlow中,如果要對一個參數進行訓練,那么這個參數必須是一個變量類tf.Variable,tf.Variable類會在反向傳播的時候進行梯度計算並保存梯度信息。
import tensorflow as tf bias = tf.Variable(initial_value=tf.constant(1.0)) # 定義一個邏輯回歸的偏倚
4、tensor的數學運算
import tensorflow as tf a = tf.constant([[1.0, 2.0], [3.0, 4.0]]) b = tf.ones([2, 2]) a_add_b = tf.add(a, b) # 張量對應元素相加 # a_add_b = a + b # 張量對應元素相加 a_subtract_b = tf.subtract(a, b) # 張量對應元素相減 # a_subtract_b = a-b # 張量對應元素相減 a_multiply_b = tf.multiply(a, b) # 張量對應元素相乘 # a_subtract_b = a*b # 張量對應元素相減 a_divide_b = tf.divide(a, b) # 張量對應元素相除 # a_divide_b = a/b # 張量對應元素相除 a_square = tf.square(a) # 張量元素平方 a_pow = tf.pow(a, y=3) # 張量元素求3次方 # a_pow = a**3 # 張量元素求3次方 a_sqrt = tf.sqrt(a) # 張量元素開方 a_sqrt = tf.sqrt(a) # 張量元素開方 a_matmul_b = tf.matmul(a, b) # 矩陣乘法 print('a:\n',a) print('b:\n',b) print('對應元素乘:\n',a_multiply_b) print('矩陣乘法:\n',a_matmul_b)
輸出結果:
a: tf.Tensor( [[1. 2.] [3. 4.]], shape=(2, 2), dtype=float32) b: tf.Tensor( [[1. 1.] [1. 1.]], shape=(2, 2), dtype=float32) 對應元素乘: tf.Tensor( [[1. 2.] [3. 4.]], shape=(2, 2), dtype=float32) 矩陣乘法: tf.Tensor( [[3. 3.] [7. 7.]], shape=(2, 2), dtype=float32)
tips:只有當張量shape相同時才能做四則運算。
5、數據集的加載與處理
import tensorflow as tf import numpy as np # 構建數據集 x = np.array(np.arange(1, 7)).reshape(3, 2) y = np.array(list('ABC')).reshape([3, 1]) data = np.concatenate([x, y], axis=1) print('生成的數據集為:\n', data) dataset = tf.data.Dataset.from_tensor_slices((x, y)) # 對數據(x,y)進行切片,將每一個變量特征與標簽組成一組 # 切片中的每個元素都是一組(特征,標簽)對 print('切片的每一組的內容:') for element in dataset: print(element) # 定義一個對x、y進行操作的函數,用於dataset.map函數 def process(x, y): ''' :param x: dataset中的x :param y: dataset中的y :return: 返回值是x,y元祖 ''' print('process傳入的x:', x) print('process傳入的y:', y) return x, y dataset.shuffle(3) # 打亂數據 dataset.map(process) # 數據進行操作preprocess dataset.batch(3) # 定義數據集每批次大小
輸出結果為:
生成的數據集為: [['1' '2' 'A'] ['3' '4' 'B'] ['5' '6' 'C']] 切片的每一組的內容: (<tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2])>, <tf.Tensor: shape=(1,), dtype=string, numpy=array([b'A'], dtype=object)>) (<tf.Tensor: shape=(2,), dtype=int32, numpy=array([3, 4])>, <tf.Tensor: shape=(1,), dtype=string, numpy=array([b'B'], dtype=object)>) (<tf.Tensor: shape=(2,), dtype=int32, numpy=array([5, 6])>, <tf.Tensor: shape=(1,), dtype=string, numpy=array([b'C'], dtype=object)>) process傳入的x: Tensor("args_0:0", shape=(2,), dtype=int32) process傳入的y: Tensor("args_1:0", shape=(1,), dtype=string)
總結:
-
tf.data.Dataset.from_tensor_slices((x, y)),用來對數據進行切片,形成x-y的特征標簽對。
-
Dataset.shuffle(),用來打亂數據
-
dataset.map(func),用來處理dataset加載的數據,map里面的函數func必須要有參數個數必須要和dataset的組成個數相同(這里組成是x、y所以參數為2),因為map傳入func的參數個數等於組成個數。
-
dataset.batch(3),用來確定每個批次的大小,訓練神經網絡時,數據經常是分批次訓練的。
6、梯度(導數)的計算
import tensorflow as tf x1 = tf.constant(1.0) x2 = tf.Variable(1.0) # 只使用一次tape計算梯度,計算y1在x1=1.0的一階導數 with tf.GradientTape(persistent=False) as tape: tape.watch(x1) # 對非tf.Variable類的數據需要加入監控才能夠訓練 y1 = x1 ** 2 # y需要在梯度帶上下文管理器上才可以被計算,如果不在梯度帶內無法被監控,計算結果為None dy1_dx1 = tape.gradient(target=y1, sources=x1) print('dy1_dx1一階導數:', dy1_dx1) # 使用多次tape計算梯度,計算兩個一階導數 with tf.GradientTape(persistent=True) as tape2: tape2.watch(x1) # 對非tf.Variable類的數據需要加入監控才能夠訓練 y1 = x1 ** 2 y2 = x2 ** 3 dy1_dx1 = tape2.gradient(target=y1, sources=x1) dy2_dx2 = tape2.gradient(target=y2, sources=x2) print('dy1_dx1一階導數:', dy1_dx1) print('dy2_dx2一階導數:', dy2_dx2) # 二階導數 with tf.GradientTape() as tape4: tape4.watch(x1) # 由於是二階導數,二階梯度帶需要先監控x1,不然二階求導tape4得不到一階求導tape3的結果,輸出為None with tf.GradientTape() as tape3: tape3.watch(x1) # 對非tf.Variable類的數據需要加入監控才能夠訓練 y1 = x1 ** 2 dy1_dx1_1 = tape3.gradient(y1, x1) dy1_dx1_2 = tape4.gradient(dy1_dx1_1, x1) print('dy3_dx1_2的二階導數為:',dy1_dx1_2)
輸出結果:
dy1_dx1一階導數: tf.Tensor(2.0, shape=(), dtype=float32) dy1_dx1一階導數: tf.Tensor(2.0, shape=(), dtype=float32) dy2_dx2一階導數: tf.Tensor(3.0, shape=(), dtype=float32) dy3_dx1_2的二階導數為: tf.Tensor(2.0, shape=(), dtype=float32)
注意事項:
-
with tf.GradientTape() as tape構建的是一個梯度帶上下文處理器,其中tf.GradientTape(persistent,watch_accessed_variables)的參數persistent表示是否可多次計算梯度,參數watch_accessed_variables表示自動監控tf.Variable類可訓練的變量。
- 對於非tf.Variable類張量計算梯度時,需要進行監控,如上述代碼在梯度帶上下文處理器中添加tape.watch( x1)。
- 對於y變量,只有y變量的聲明在上下文管理器中才能進行梯度計算,否則無法計算。
7、One-hot編碼(獨熱編碼)
import tensorflow as tf y=tf.constant([1,2,3,1]) # y有三個類別 y_trans=tf.one_hot(y,depth=3) # 定義獨熱編碼的深度為3,即用3個位數表示類別 print(y_trans)
輸出結果:
tf.Tensor( [[0. 1. 0.] [0. 0. 1.] [0. 0. 0.] [0. 1. 0.]], shape=(4, 3), dtype=float32)
函數:
tf.one_hot(indices, depth, on_value=None, off_value=None, axis=None, dtype=None, name=None)
參數說明:
-
indices:表示輸入的多個數值,通常是矩陣形式。
-
depth:編碼的深度,即獨熱編碼的位數。
-
on_value:當y歸屬為這一類時,獨熱編碼在這個位置的表示值,默認為1。
-
off_value:當y不屬於這一類時,獨熱編碼在這個位置的表示值,默認為0。
8、最大元素、最小元素的索引
當我們對y進行One-hot編碼后,我們一般是認為最大值1所在的位置即為y的類別。同理,神經網絡輸出層用sofmax函數作為激活函數后,也取預測值y最大值的位置對應的類別作為預測的分類。這時候我們就需要知道最大值是對應的哪一個位置。
import tensorflow as tf a=tf.constant([1,1,2,3,1]) a_trans=tf.one_hot(a,3) # 轉換為獨熱編碼 a_pre=tf.argmax(a_trans,axis=1) # 最大值所在的位置 print(a) print(a_trans) print(a_pre)
輸出結果:
tf.Tensor([1 1 2 3 1], shape=(5,), dtype=int32) tf.Tensor( [[0. 1. 0.] [0. 1. 0.] [0. 0. 1.] [0. 0. 0.] [0. 1. 0.]], shape=(5, 3), dtype=float32) tf.Tensor([1 1 2 0 1], shape=(5,), dtype=int64)
9、變量的自減
在訓練模型時,權重w更新公式為w=w-grad*lr,grad為梯度,lr為學習率,如果我們是手動更新權重,那么這個時候用變量的自減就很方便。
import tensorflow as tf x=tf.constant([[1],[2],[3],[4],[5]],dtype=tf.float32) w=tf.Variable([[2]],dtype=tf.float32) # 訓練的參數 with tf.GradientTape() as tape: tape.watch(x) y=tf.matmul(x,w)+0.5 w_grad=tape.gradient(y,w) # 計算梯度 w.assign_sub(0.1*w_grad) # 權重更新 print(w.value())
輸出結果:
tf.Tensor([[0.5]], shape=(1, 1), dtype=float32)