一、張量
我們知道, 計算圖中的一個節點可以表示一個張量或者一個操作符
那麼張量是什麼?
張量,可理解爲一個 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.zeros_like(t_2)
<tf.Tensor 'zeros_like:0' shape=(3,) dtype=int32>
tf.ones_like(t_2)
<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.random_crop(t_random,[2,5],seed=12)
<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.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:
weights2 = tf.Variable(weights.initial_value, name='w2')
賦予變量實際的意義
上面兩種方式的初始化, 並不代表計算圖中的變量已經被賦值了
我們之前說過, 計算圖像是一張藍圖, 在此之前張量只被抽象定義,只有在會話時候, 纔將張量賦予實際的意義
在會話時, 賦予常量實際的意義,是自動的; 而賦予變量實際的意義,還需要再加些東西
具體需要通過聲明初始化操作對象來實現:
intial_op = tf.global_variables_initializer()
舉個栗子, 希望程序實現從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 的變量:
large_array = [1,2,3] #假如時一個很大的數組
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 序列不可迭代。試試下面的代碼:
for i in tf.range(10)
File "<ipython-input-30-83ab65fa2626>", line 1
for i in tf.range(10)
^
SyntaxError: invalid syntax