TensorFlow之張量


張量的概念

TensorFlow中的Tensor就是張量,張量是數學對象,是對標量、向量、矩陣的泛化。我們可以直接理解成張量就是列表,就是多維數組。

 

張量的維數用階來表示:

0階張量 標量 單個值 例:a = 1
1階張量 向量 1維數組 例:a = [1,2,3]
2階張量 矩陣 2維數組 例:a = [[1,2,3],[4,5,6]]
n階張量 張量 n維數組 例:a = [[[[[...n個括號...]]]]]

 

判斷張量有幾階  就看等號右邊的方括號有幾個  0個就是0階 2個就是2階。

多維張量在內存中也是以一維數組的方式連續存儲的。

 

創建張量

tf.constant()方法用來創建一個張量,傳入內容,可以是數字、python列表、NumPy數組,第二個參數為指定數據類型,可以省略。

如:

import tensorflow as tf
a = tf.constant([1,2,3],dtype=tf.int32)
print(a)

打印結果:

tf.Tensor([1 2 3], shape=(3,), dtype=int32)

 

shape是張量的形狀,一個張量有多少階,就看形狀中的逗號隔開了幾個數字,比如形狀為(3,)的張量 逗號隔開了3這一個數字,所以它的階數是1階,里面有3個元素, 再比如形狀為(3,3)的張量  逗號隔開了3和3兩個數字,所以它的階數是2階,並且是一個3行3列的矩陣。

當然,也可以以屬性的方式來查看張量信息

print('張量的階數:', a.ndim)
print('張量的形狀:', a.shape)
print('張量的類型:', a.dtype)

打印結果:

張量的階數: 1
張量的形狀: (3,)
張量的類型: <dtype: 'int32'>

 

張量的數據類型

在上面創建張量我加了dtype參數指定數據類型為int32,不指定數據類型也是一樣的,tensorflow會根據張量內容自動推斷類型,如果張量內容是數字,那么默認數據類型是int32,如果張量內容是浮點數,那么默認數據類型是float32,如果需要指定其他位數如int64或float64就需要傳遞參數手動指定.

張量的數據類型有:

int 有符號整數
float 有符號浮點數
uint 無符號整數
以上這三種都有位數的划分,比如int有 tf.int8、tf.int16、tf.int32、tf.int64。

string 字符串
bool 布爾型
complex 復數 由實數和虛數組成

 

tf.cast()方法可以將張量的數據類型進行轉換,比如:

import tensorflow as tf
a = tf.constant([1,2,3],dtype=tf.int32)
print(a)

b = tf.cast(a,dtype=tf.int64)
print(b)

打印結果:

tf.Tensor([1 2 3], shape=(3,), dtype=int32)
tf.Tensor([1 2 3], shape=(3,), dtype=int64)

 

NumPy數據轉換

如果數據是由numpy創建的話,需要使用tf.convert_to_tensor()函數將numpy的數據類型轉換成TensorFlow的張量數據類型。

import tensorflow as tf
import numpy as np
a = np.arange(0,10)
print(a)
b = tf.convert_to_tensor(a)
print(b)

打印結果:

[0 1 2 3 4 5 6 7 8 9]
tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32)

 

注意一點的是,numpy創建浮點數矩陣的時候默認是float64類型,轉換的時候tensorflow同樣會去接收它的數據類型,因此由numpy數據生成的張量會出現默認浮點數類型是float64位的情況,如下:

import tensorflow as tf
import numpy as np
a = np.array([1.1,2.2,3.3])
print(a)
b = tf.constant(a)
print(b)
c = tf.convert_to_tensor(a)
print(c)

打印結果:

[1.1 2.2 3.3]
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float64)
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float64)

 

大多數機器學習場景下我們用32位浮點數已經足夠滿足計算需求,32位浮點數的運算比64位浮點數的運算要快的多,因此用numpy數組生成張量時可以顯式的指定數據類型:

import tensorflow as tf
import numpy as np
a = np.array([1.1,2.2,3.3])
print(a)
b = tf.constant(a,dtype=tf.float32)
print(b)
c = tf.convert_to_tensor(a,dtype=tf.float32)
print(c)

打印結果:

[1.1 2.2 3.3]
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float32)
tf.Tensor([1.1 2.2 3.3], shape=(3,), dtype=float32)

 

固定張量

TensorFlow提供了一些創建固定張量的函數,比如創建值全是0的張量,創建值全是1的張量。

全0張量

 tf.zeros(shape,dtype=float32)

參數的寫法不止一種,記一種好記的就可以了,比如一維直接寫個數,二維寫[行數,列數],三維寫[行數,列數,高度],多維以此類推 [n,m,k,j,......]

#創建一維張量 4個元素
a = tf.zeros(4)
print(a)

#創建一維張量 4個元素
aa = tf.zeros([4])
print(aa)

#創建3行3列的二維張量
b = tf.zeros([3,3])
print(b)

#創建3行3列的二維張量
bb = tf.zeros((3,3))
print(bb)

#指定類型
c = tf.zeros([3,3],tf.int8)
print(c)

 

全1張量

 tf.ones(shape,dtype=float32)

創建值全是1的張量,除了將zeros函數替換成ones函數之外,創建用法和全0張量完全一致。

 

元素值相同的張量

tf.fill(shape,value)

fill函數沒有dtype參數,它根據value參數自動判斷類型。

#創建一維張量 4個元素
aa = tf.fill([4],10)
print(aa)

打印結果:

tf.Tensor([10 10 10 10], shape=(4,), dtype=int32)

 

#創建3行3列的二維張量
c = tf.fill([3,3],4.4)
print(c)

打印結果:

tf.Tensor(
[[4.4 4.4 4.4]
[4.4 4.4 4.4]
[4.4 4.4 4.4]], shape=(3, 3), dtype=float32)

 

隨機數張量

正態分布

函數簽名:tf.random.normal(shape,mean,stddev,dtype)

shape:張量形狀
mean:均值 默認為0
stddev:標准差 默認為1
dtype:存儲類型 默認為float32

 

示例:

#創建2行2列均值為0標准差為1的隨機數張量
a = tf.random.normal([2, 2], mean=0, stddev=1)
print(a)

打印結果:

tf.Tensor(
[[-0.849204 0.42851505]
[-2.1599882 -0.6131579 ]], shape=(2, 2), dtype=float32)

 

截斷正態分布

函數簽名:tf.random.truncated_normal(shape,mean,stddev,dtype)

本函數返回一個截斷的正態分布,截斷的標准是2倍的標准差,可以保證生成的數據更向均值集中。

 

示例:

b = tf.random.truncated_normal([2, 2], mean=0, stddev=1)
print(b)

打印結果:

tf.Tensor(
[[-0.06899758 1.8015716 ]
[-0.39744875 0.00498725]], shape=(2, 2), dtype=float32)

 

通俗的說,就是當均值為0,標准差為1時,使用本函數創建出的隨機張量中,不可能出現區間[-2,2]以外的點, 而使用tf.random.normal函數則可能出現區間[-2,2]以外的點。

 

設置隨機種子

如果想要保證多次生成的隨機數張量完全一致,可以設置相同的隨機種子。

tf.random.set_seed(10)
a = tf.random.normal([1,5])
print(a)

tf.random.set_seed(10)
b = tf.random.normal([1,5])
print(b)

打印結果:

tf.Tensor([[-0.8757808 0.3356369 -0.35219625 -0.30314562 -0.03882965]], shape=(1, 5), dtype=float32)
tf.Tensor([[-0.8757808 0.3356369 -0.35219625 -0.30314562 -0.03882965]], shape=(1, 5), dtype=float32)

 

均勻分布

函數簽名:tf.random.uniform(shape,minval,maxval,dtype)

shape:張量形狀
minval:最小值 閉區間
maxval:最大值 開區間
dtype:數據類型 默認float32

c = tf.random.uniform([2, 2], minval=0, maxval=1)
print(c)

打印結果:

tf.Tensor(
[[0.46760368 0.58308244]
[0.5945486 0.2994659 ]], shape=(2, 2), dtype=float32)

 

序列張量

函數簽名:tf.range(start,limit,delta,dtype)

start:起始數字 閉區間
limit:結束數字 開區間
delta:步長 默認1
dtype:數據類型 默認自動推斷

 

用法如下:

#創建0-9序列
a = tf.range(10)
print(a)

打印結果:

tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32)

 

#創建偶數序列
b = tf.range(10,delta=2)
print(b)

打印結果:

tf.Tensor([0 2 4 6 8], shape=(5,), dtype=int32)

 

#創建奇數序列
c = tf.range(1,10,delta=2)
print(c)

打印結果:

tf.Tensor([1 3 5 7 9], shape=(5,), dtype=int32)

 

張量的運算

四則運算

注意,只有階數相同的張量才可以做四則運算

 

加法:tf.add

a = tf.constant([1,2,3])
b = tf.constant([1,2,3])
print(tf.add(a,b))

打印結果:

tf.Tensor([2 4 6], shape=(3,), dtype=int32)

 

減法:tf.subtract

a = tf.constant([2,4,6])
b = tf.constant([0,0,3])
print(tf.subtract(a,b))

打印結果:

tf.Tensor([2 4 3], shape=(3,), dtype=int32)

 

乘法:ttf.multiply

a = tf.constant([2,4,6])
b = tf.constant([0,0,3])
print(tf.multiply(a,b))

打印結果:

tf.Tensor([ 0  0 18], shape=(3,), dtype=int32)

 

除法:tf.divide

a = tf.constant([2,4,6])
b = tf.constant([0,0,3])
print(tf.divide(b,a))

打印結果:

tf.Tensor([0.  0.  0.5], shape=(3,), dtype=float64)

 

平方、次方與開方

對張量求平方:tf.square

a = tf.constant([1,2,3,4,5])
print(tf.square(a))

打印結果:

tf.Tensor([ 1  4  9 16 25], shape=(5,), dtype=int32)

 

對張量求次方:tf.pow

a = tf.range(5) #創建一個序列張量 0 1 2 3 4
b = tf.pow(a,3) #求序列張量的3次方
print(b)

打印結果:

tf.Tensor([ 0  1  8 27 64], shape=(5,), dtype=int32)

 

如果說求a張量的b張量次方,那么就等於是將a張量的每個位置的元素求b張量中對應元素的次方。

a = tf.constant([[2,2],[2,2]])
b = tf.constant([[1,2],[3,4]])
print(tf.pow(a,b))

打印結果:

tf.Tensor(
[[ 2 4]
[ 8 16]], shape=(2, 2), dtype=int32)

 

如果指數是分數,那么就是根號運算。比如指數是0.5的話,那么就是對張量逐元素求平方根。

a = tf.constant([1,4,9,16,25],dtype=tf.float32)
print(tf.pow(a,0.5))

打印結果:

tf.Tensor([1. 2. 3. 4. 5.], shape=(5,), dtype=float32)

開根號會涉及小數點,因此張量元素類型必須是浮點數類型

 

對張量求平方根:tf.sqrt

a = tf.constant([1,4,9,16,25],dtype=tf.float64)
print(tf.sqrt(a))

打印結果:

tf.Tensor([1. 2. 3. 4. 5.], shape=(5,), dtype=float64)

 

其他運算

除了常用的運算之外,tensorflow還提供了其他更廣泛的運算。

tf.sign(x) 取符號
tf.abs(x) 求絕對值
tf.negative(x) 求相反數
tf.reciprocal(x) 求倒數
tf.ceil(x) 向上取整
tf.floor(x) 向下取整
tf.round(x) 四舍五入取整
tf.maximum(x,y)返回兩個張量中的最大值 (逐個位置比較兩張量的元素,取最大值,最終返回一個新張量)
tf.minimum(x,y)返回兩個張量中的最小值 (逐個位置比較兩張量的元素,取最小值,最終返回一個新張量)

 

重載運算符

為了使用簡便,tensorflow將常用的數學運算符號進行了重載,讓我們可以對張量進行直接運算而不用顯式調用函數進行運算。

例如加法運算,可以直接把tf.add(a,b)寫成a+b

a = tf.constant([1,2,3])
b = tf.constant([1,2,3])
print(tf.add(a,b))
print(a+b)

打印結果:

tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)

 

矩陣乘法

矩陣乘法是線性代數中很重要的內容,矩陣乘法的條件是第一個矩陣的列數要等於第二個矩陣的行數才可以進行乘法計算。

計算規則是,第一個矩陣的每行的每個數字與第二個矩陣的每列的每個數字對應相乘再相加,計算結果是第一個矩陣的行數第二個矩陣的列數所對應的值。

 

比如矩陣A:
2 3
4 5

矩陣B:
1 2
3 4

AB兩矩陣相乘,得到新矩陣C
C11:2*1 + 3*3 = 11
C12:2*2 + 3*4 = 16
C21:4*1 + 5*3 = 19
C22:4*2 + 5*4 = 28

也就是:
11 16
19 28

 

可以用tf.matmul(a,b)函數來計算矩陣乘積,也可以用@運算符來進行運算。

a = tf.constant([[2,3],[4,5]])
print(a)
b = tf.constant([[1,2],[3,4]])
print(b)
print(tf.matmul(a,b))

打印結果:

tf.Tensor(
[[2 3]
[4 5]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[1 2]
[3 4]], shape=(2, 2), dtype=int32)
tf.Tensor(
[[11 16]
[19 28]], shape=(2, 2), dtype=int32)

 

張量的統計

常用統計函數有如下四種:

tf.reduce_sum(tensor,axis) 求和
tf.reduce_mean(tensor,axis) 求平均值
tf.reduce_max(tensor,axis) 求最大值
tf.reduce_min(tensor,axis) 求最小值

參數axis為0時,代表縱向操作,沿經度方向(也就是按列、跨行),axis為1時,代表橫向操作,沿緯度方向(也就是按行、跨列),不指定axis則代表全局操作。

a = tf.constant([[5,3,1],[2,4,6]])
print(a)

print('縱向操作:{}'.format(tf.reduce_sum(a,0)))
print('橫向操作:{}'.format(tf.reduce_sum(a,1)))
print('全局操作:{}'.format(tf.reduce_sum(a)))

打印結果:

tf.Tensor(
[[5 3 1]
[2 4 6]], shape=(2, 3), dtype=int32)
縱向操作:[7 7 7]
橫向操作:[ 9 12]
全局操作:21

 

求平均值需要提一下,求出的結果數據類型與原始張量的數據類型會保持一致,也就會出現如下現象:

a = tf.constant([[5,3,1],[2,4,6]])
print(a)
print(tf.reduce_mean(a,0))

打印結果:

[[5 3 1]
[2 4 6]], shape=(2, 3), dtype=int32)
tf.Tensor([3 3 3], shape=(3,), dtype=int32)

縱向求平均值第一列5+2=7,除以2得3.5,但是受限於int數據類型,所以最后的值為3

為了解決這個問題,我們可以將張量的數據類型轉換成float再進行統計即可。

a = tf.constant([[5,3,1],[2,4,6]])
print(a)
print(tf.reduce_mean(tf.cast(a,dtype=tf.float32),0))

打印結果:

tf.Tensor(
[[5 3 1]
[2 4 6]], shape=(2, 3), dtype=int32)
tf.Tensor([3.5 3.5 3.5], shape=(3,), dtype=float32)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM