一、張量
我們知道, 計算圖中的一個節點可以表示一個張量或者一個操作符
那麼張量是什麼?
張量,可了解為一個 n 維數值陣列
每個張量的次元機關用階來描述,零階張量是一個标量,一階張量是一個向量,二階張量是一個矩陣
是以标量、向量(矢量)和矩陣等都是特殊類型的張量
TensorFlow 支援以下三種類型的張量:
1、常量:常量是其值不能改變的張量。
2、變量:當一個量在會話中的值需要更新時,使用變量來表示。例如,在神經網絡中,權重需要在訓練期間更新,可以通過将權重聲明為變量來實作。變量在使用前需要被顯示初始化。
3、占位符:用于将值輸入 TensorFlow 圖中。它們可以和 feed_dict 一起使用來輸入資料。在訓練神經網絡時,它們通常用于提供新的訓練樣本。在會話中運作計算圖時,可以為占位符指派。這樣在建構一個計算圖時不需要真正地輸入資料。需要注意的是,占位符不包含任何資料,是以不需要初始化它們。
二、TF常量型張量
import tensorflow as tf
“正常操作”
1、聲明一個标量常量:
t_1 = tf.constant(4)
with tf.Session() as sess:
print(sess.run(t_1))
4
2、聲明一個向量常量:
t_2 = tf.constant([1,3])
with tf.Session() as sess:
print(sess.run(t_2))
[1 3]
t_2 = tf.constant([4,3,2])
with tf.Session() as sess:
print(sess.run(t_2))
[4 3 2]
3、建立一個所有元素為零的張量,可以使用 tf.zeros() 函數。這個語句可以建立一個形如 [M,N] 的零元素矩陣,資料類型(dtype)可以是 int32、float32 等:
tf.zeros([M,N],tf.dtype)
例如 :
zero_t = tf.zeros([2,3],tf.int32)
with tf.Session() as sess:
print(sess.run(zero_t))
[[0 0 0]
[0 0 0]]
4、建立一個所有元素都設為 1 的張量。下面的語句即建立一個形如 [M,N]、元素均為 1 的矩陣:
tf.ones([M,N],tf,dtype)
ones_t = tf.ones([2,3],tf.int32)
with tf.Session() as sess:
print(sess.run(ones_t))
[[1 1 1]
[1 1 1]]
5、還可以建立與現有 Numpy 數組或張量常量具有相同形狀的張量常量,如下所示:
<tf.Tensor 'zeros_like:0' shape=(3,) dtype=int32>
<tf.Tensor 'ones_like:0' shape=(3,) dtype=int32>
6、在一定範圍内生成一個從初值到終值等差排布的序列:
tf.linspace(start,stop,num)
相應的值為 (stop-start)/(num-1)。例如:
range_t = tf.linspace(2.0,5.0,5) #從2到5 切成5份
with tf.Session() as sess:
print(sess.run(range_t))
[2. 2.75 3.5 4.25 5. ]
7、從開始(預設值=0)生成一個數字序列,增量為 delta(預設值=1),直到終值(但不包括終值):
tf.range(start,limit,delta)
下面給出執行個體:
range_t = tf.range(10)
with tf.Session() as sess:
print(sess.run(range_t))
#Result:[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
range_t = tf.range(0,10,1)
with tf.Session() as sess:
print(sess.run(range_t))
[0 1 2 3 4 5 6 7 8 9]
“随機操作”
TensorFlow 允許建立具有不同分布的随機張量
1、使用以下語句建立一個具有一定均值(預設值=0.0)和标準差(預設值=1.0)、形狀為 [M,N] 的正态分布随機數組:
t_random = tf.random_normal([2,3], mean=2.0, stddev=4,seed=12)
with tf.Session() as sess:
print(sess.run(t_random))
[[ 0.25347447 5.37991 1.9527606 ]
[-1.5376031 1.2588985 2.8478067 ]]
2、建立一個具有一定均值(預設值=0.0)和标準差(預設值=1.0)、形狀為 [M,N] 的截尾正态分布随機數組:
t_random = tf.truncated_normal([1,5], stddev=2,seed=12)
with tf.Session() as sess:
print(sess.run(t_random))
[[-0.87326276 1.689955 -0.02361972 -1.7688016 -3.87749 ]]
3、要在種子的 [minval(default=0),maxval] 範圍内建立形狀為 [M,N] 的給定伽馬分布随機數組,請執行如下語句:
t_random = tf.random_uniform([2,3], maxval=4,seed=12)
with tf.Session() as sess:
print(sess.run(t_random))
[[2.54461 3.6963658 2.7051091]
[2.0085006 3.8445983 3.5426888]]
4、(不起作用好像)要将給定的張量随機裁剪為指定的大小,使用以下語句:
圖像分類中,在深度學習的訓練時将圖檔的随機剪裁(random crop)已經成為很普遍的資料擴充(data augmentation)方法,随機剪裁(縮寫為:IRC)不但提高了模型精度,也增強了模型穩定性
<tf.Tensor 'random_crop:0' shape=(2, 5) dtype=float32>
這裡,t_random 是一個已經定義好的張量。這将導緻随機從張量 t_random 中裁剪出一個大小為 [2,5] 的張量。
5、随機重新排序
很多時候需要以随機的順序來呈現訓練樣本,可以使用 tf.random_shuffle() 來沿着它的第一維随機排列張量。如果 t_random 是想要重新排序的張量,使用下面的代碼:
with tf.Session() as sess:
print(sess.run(t_random))
print("随機重新排序後")
t = tf.random_shuffle(t_random)
with tf.Session() as sess:
print(sess.run(t))
[[2.54461 3.6963658 2.7051091]
[2.0085006 3.8445983 3.5426888]]
随機重新排序後
[[2.0085006 3.8445983 3.5426888]
[2.54461 3.6963658 2.7051091]]
6、随機生成的張量受初始種子值的影響
要在多次運作或會話中獲得相同的随機數,應該将種子設定為一個常數值。當使用大量的随機張量時,可以使用 tf.set_random_seed() 來為所有随機産生的張量設定種子。以下指令将所有會話的随機張量的種子設定為 54:
種子隻能有整數值
三、TF變量型張量
tensorflow中的變量是承載和更新參數的對象
變量通常在神經網絡中表示權重和偏置
此外還可以儲存或恢複變量
變量是由tf.Variable()語句建立的
它必須初始化, 可以用常量來初始化變量,也可以用一個變量來初始化另一個變量
常量初始化變量
下面的代碼中建立了兩個不同的張量變量 t_a 和 t_b。兩者将被初始化為形狀為 [50,50] 的随機均勻分布,最小值=0,最大值=10:
rand_t = tf.random_uniform([50,50],0,10,seed=0)
t_a = tf.Variable(rand_t)
t_b = tf.Variable(rand_t)
注意:變量通常在神經網絡中表示權重和偏置。
下面的代碼中定義了兩個變量,分别是權重和偏置。權重變量使用正态分布随機初始化,均值為 0,标準差為 2,權重大小為 100×100。偏置由 100 個元素組成,每個元素初始化為 0。在這裡也使用了可選參數名以給計算圖中定義的變量命名:
weights = tf.Variable(tf.random_normal([100,100],stddev=2))
bias = tf.Variable(tf.zeros([100]), name = 'biases')
變量初始化變量
下面的語句将利用前面定義的權重變量來初始化 weight2:
賦予變量實際的意義
上面兩種方式的初始化, 并不代表計算圖中的變量已經被指派了
我們之前說過, 計算圖像是一張藍圖, 在此之前張量隻被抽象定義,隻有在會話時候, 才将張量賦予實際的意義
在會話時, 賦予常量實際的意義,是自動的; 而賦予變量實際的意義,還需要再加些東西
具體需要通過聲明初始化操作對象來實作:
舉個栗子, 希望程式實作從1數到10 :
import tensorflow as tf
#建立計算圖
value = tf.Variable(0, name="value")#建立一個變量,并将其初始化為标量0:
one = tf.constant(1)
new_value = tf.add(value, one)#add和assign操作符僅僅是計算圖中的節點,是以在會話運作前,它們不會執行
update_value = tf.assign(value, new_value)
#運作會話,完成計算圖中定義的操作
initialize_var = tf.global_variables_initializer() #聲明初始化操作對象, 用于計算圖中變量的指派
with tf.Session() as sess:
sess.run(initialize_var)
print(sess.run(value))
for _ in range(10):
sess.run(update_value)
print(sess.run(value))
0
1
2
3
4
5
6
7
8
9
10
程式解讀: 這個栗子的計算圖有四個節點,分别是value變量、one常量、add加法操作符以及assign指派操作符.這個計算圖要實作的功能是value和one通過add相加,得到的值流到assign操作符,讓它再指派回value. 運作會話時,由于變量需要顯式初始化,是以需要聲明初始化操作對象,然後讓它run下來完成初始化
此外, 每個變量也可以在運作圖中單獨使用 tf.Variable.initializer 來初始化
import tensorflow as tf
#建立計算圖
value = tf.Variable(0, name="value")#建立一個變量,并将其初始化為标量0:
one = tf.constant(1)
new_value = tf.add(value, one)#add和assign操作符僅僅是計算圖中的節點,是以在會話運作前,它們不會執行
update_value = tf.assign(value, new_value)
#運作會話,完成計算圖中定義的操作
#initialize_var = tf.global_variables_initializer() #聲明初始化操作對象, 用于計算圖中變量的指派
with tf.Session() as sess:
sess.run(value.initializer)#變量在運作圖中單獨初始化,常量就不用了.
print(sess.run(value))
for _ in range(10):
sess.run(update_value)
print(sess.run(value))
0
1
2
3
4
5
6
7
8
9
10
儲存變量
神經網絡訓練完後, 一般都需要儲存訓練好的參數,也就是我們所謂的權重和偏置, 其實際上就是變量, 是以我們要使用 Saver 類來儲存變量,定義一個 Saver 操作對象:
saver = tf.train.Saver()
四、TF占位符型張量
介紹完常量和變量之後,我們來講解最重要的張量——占位符
它是不需要初始化的
在會話中運作計算圖時,可以為占位符指派,通過會話對象中run裡feed_dict
它用于将值輸入計算圖中,它和feed_dict一起來輸入資料
run(fetches,feed_dict=None,options=None,run_metadata)
是以在訓練神經網絡時(會話),它們通常用于提供新的訓練樣本
如何定義一個占位符:
tf.placeholder(dtype,shape=None,name=None)
dtype 是占位符的資料類型,并且必須在聲明占位符時指定
下面示例中, 定義一個占位符型張量x, 并計算 y=2*x,會話時使用 feed_dict 輸入一個随機的 4×5 矩陣:
import tensorflow as tf
#計算圖
x = tf.placeholder("float")#占位符
y = 2*x
data = tf.random_uniform([4,5], 10)#随機常量
#run時才算進入會話
with tf.Session() as sess:
print(data) #未進入會話
x_data = sess.run(data) #會話時才能取出它的值
print(x_data)#提出來了
print("\n\n")
print(sess.run(y, feed_dict = {x:x_data}))
Tensor("random_uniform_2:0", shape=(4, 5), dtype=float32)
[[9.789586 4.122238 2.5008888 2.8134599 2.4266639]
[3.33526 3.5702267 6.666023 1.2452259 3.4237428]
[6.941977 8.032328 2.8022385 8.071983 6.399656 ]
[6.231288 2.589786 1.2040987 8.232471 1.4575834]]
[[19.579172 8.244476 5.0017776 5.6269197 4.8533278]
[ 6.67052 7.1404533 13.332046 2.4904518 6.8474855]
[13.883954 16.064655 5.604477 16.143967 12.799312 ]
[12.462576 5.179572 2.4081974 16.464943 2.9151669]]
代碼解釋:
計算圖一共有4個節點,分别是占位型張量x、常數型張量2、乘法操作符y以及單獨的常數型張量data. 會話時取出data的值指派給x_data,然後放入feed_dict再一次進入會話指派給占位符x, 提取y的運作結果
run的時候才算進入會話
是以第一次run隻是fetch data裡的資料, 第二次才開始fetch y進行乘法運算
五、拓展閱讀
拓展1
很多時候需要大規模的常量張量對象;在這種情況下,為了優化記憶體,最好将它們聲明為一個可訓練标志設定為 False 的變量:
t_large = tf.Variable(large_array,trainable=False)
with tf.Session() as sess:
sess.run(t_large.initializer)
print(sess.run(t_large))
[1 2 3]
trainable:如果為True,則會預設将變量添加到圖形集合GraphKeys.TRAINABLE_VARIABLES中。此集合用于優化器Optimizer類優化的的預設變量清單【可為optimizer指定其他的變量集合】,也就是要訓練的變量清單。
拓展2
TensorFlow 被設計成與 Numpy 配合運作,是以所有的 TensorFlow 資料類型都是基于 Numpy 的。
使用 tf.convert_to_tensor() 可以将給定的值轉換為張量類型,并将其與 TensorFlow 函數和運算符一起使用。該函數接受 Numpy 數組、Python 清單和 Python 标量,并允許與張量對象互操作。
拓展3
下表列出了 TensorFlow 支援的常見的資料類型:
拓展4
for i in range(1,10,1):
print(i)
1
2
3
4
5
6
7
8
9
import numpy as np
for i in np.arange(1,10,1):
print(i)
1
2
3
4
5
6
7
8
9
TensorFlow 序列不可疊代。試試下面的代碼:
File "<ipython-input-30-83ab65fa2626>", line 1
for i in tf.range(10)
^
SyntaxError: invalid syntax