Tensorflow學習筆記day02+張量(常量+變量+佔位符)

一、張量

我們知道, 計算圖中的一個節點可以表示一個張量或者一個操作符

那麼張量是什麼?

張量,可理解爲一個 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章