TensorFlow零基礎入門教程(一)
TensorFlow入門(一)
1.計算圖
首先解釋什麼是計算圖,瞭解TensorFlow的計算模型.
和我們常見的程式計算框架不同,並不是賦值,或者計算後,TensorFlow立馬完成這些操作,而是將這些操作,賦予在一個圖中,這個圖可以簡單地認為是我們常見的流程圖,只不過更加的詳細,包括每一步操作(op)和變數的名字.
因為神經網路的執行,需要很大的計算量,如果迴圈往復的賦值計算,將會帶來很大的麻煩,所以TensorFlow採用計算圖模型,包括其他很多框架都是採用同樣的模型.
比如說,我們建立一個神經網路,那我們首先,定義好變數(引數),然後每一步計算,包括輸出.當定以好之後,我們建立一個會話(Session),在這個會話中執行圖模型.
# tf.get_default_graph()獲取預設的計算圖
# a.graph可以檢視張量所屬的計算圖
print(a.graph is tf.get_default_graph())
# 建立兩個不同的計算圖,然後分別輸出兩個變數
g1 = tf.Graph()
with g1.as_default():
v = tf.get_variable(
'v', initializer=tf.zeros([2,3],tf.float32)
)
g2 = tf.Graph()
with g2.as_default():
v = tf.get_variable(
'v' ,initializer=tf.ones([2,3],tf.float32)
)
2. TensorFlow中的資料型別
2.1 tf.constant():常量
TensorFlow中的張量模型,也就是我們所說的Tensor的意思.
在TensorFlow中完成的是一步賦值過程,將定義的一個張量儲存在變數a或b中.a和b儲存的不是張量的值,而是這些數字的運算過程.
注意:
- 1.張量三屬性:名字,維度,型別(一般為tf.float32);
- 2.運算時,維度和型別要保持一直;
- 3.名字給出了張量的唯一識別符號,同事給出變數是如何計算的;
- 4.張量的計算和普通計算是不同的,儲存的不是數值,而是計算過程!!!!
張量的作用:
- 1.對中間計算結果的引用,增加程式碼的可讀性
- 2.計算圖構造完成後,用來獲得計算結果
import tensorflow as tf
a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([2.0, 3.0], name='b')
# 不管是張量直接相加,還是tf.add二者的作用是一致的
result1 = a + b
result2 = tf.add(a,b,name='add')
print(result1)
print(result2)
2.2 tf.Variable()
專門用來,儲存和更新神經網路中的引數,所以我們在建立神經網路模型引數的時候,使用tf.Variable()型別.
常用的常數生成函式:
- tf.zeros()
- tf.ones()
- tf.fill()
常用的隨機數生成函式:
- tf.random_normal(維度,標準差,型別)
- tf.truncated_normal()
- tf.random_uniform()
w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1))
# 與上類似,維度([3,1])
w2 = tf.Variable(tf.random_normal([3,1], stddev=1, seed=1))
2.3 tf.placeholder()
在前面定義張量時,我們使用的是tf.constant().我們都知道神經網路的訓練需要上千上萬,甚至幾百萬的迴圈迭代,而每次迴圈迭代,每次生成一個常量,TensorFlow就會在計算圖中增加一個節點,最後就會使得,圖異常複雜.所以TensorFlow引入tf.placeholder機制.
tf.placeholder相當於提前為變數,定義,開拓了一個位置,這個位置的資料在程式執行時被指定.也就是在計算圖中,我們只有一個位置,這個位置的值會不斷改變,這樣就避免了重複生成.
三個屬性:
- 型別
- 維度
- 名字
執行時,使用feed_dict來定義輸入.
x = tf.placeholder(tf.float32, shape=(None, 2), name='x-input')
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input')
3.會話(Session)
前面我們已經提到了計算圖模型,在TensorFlow中,我們使用會話(Session)來執行定義好的計算.會話擁有並管理TensorFlow中的所有資源,執行結束後,需要及時回收資源.
3.1 模式一:
呼叫會話生成函式,然後關閉會話函式.
sess = tf.Session()
with sess.as_default():
print(result2.eval())
print('\n')
# 這兩個有同樣的功能
print(sess.run(result2))
print('\n')
print(result2.eval(session=sess))
print('\n')
3.2 模式二:
利用上下文管理器,來使用會話,自動釋放資源.
with tf.Session(graph=g1) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope('',reuse=True):
print(sess.run(tf.get_variable('v')))
with tf.Session(graph=g2) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope('', reuse=True):
print(sess.run(tf.get_variable('v')))
print('\n')
3.3 模式三:
互動式會話模式,尤其是在Ipython(Jupyter Notebook),這種互動式的環境中,使用非常方便.
# 使用互動式會話模式
sess1 = tf.InteractiveSession()
print(sess1.run(result2))
sess1.close()
4.TensorFlow實現神經網路
# 匯入tensorflow庫
import tensorflow as tf
# 匯入Numpy工具包,生成一個模擬資料集
from numpy.random import RandomState
# 採用Mini-batch訓練方法,速度快,準確率高
batch_size = 8
# 首先定義兩個權重(變數),滿足正太隨機分佈,維度([2,3]),標準差是1, seed使用隨機種子,保證每次執行的結果一樣
w1 = tf.Variable(tf.random_normal([2,3], stddev=1, seed=1))
# 與上類似,維度([3,1])
w2 = tf.Variable(tf.random_normal([3,1], stddev=1, seed=1))
# 設定x變數,使用placeholder,為變數提供一個位置.若使用variable等格式,每次賦值,都會在計算圖中
# 增加一個結點,訓練幾百萬輪,會使得計算圖非常複雜,所以引入placeholder機制.
# 維度([None,2]),
x = tf.placeholder(tf.float32, shape=(None, 2), name='x-input')
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input')
# matmul實現矩陣相乘,這裡tensorflow使用計算圖方式,與numpy的矩陣相乘是不一樣的.
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
# 通過極力函式sigmoid(),實現非線性化
y = tf.sigmoid(y)
# 定義損失函式,此處使用交叉熵,以後討論,用來表徵預測資料和真實資料的誤差
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
+ (1 - y) * tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
# 定義反向傳播演算法,來優化NN中的引數,此處使用AdamOptimizer
# 學習率:0.001,優化目標:cross_entropy
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
# 通過隨機數生成模擬資料集
rdm = RandomState(1)
# 訓練資料X:資料集大小[128,2]
# 128個樣例,2個屬性
dataSet_size = 128
X = rdm.rand(dataSet_size, 2)
# 標籤資料Y:使用布林變數,如果x1 + x2 < 1則認為是正樣本,也就是為1
# 否則認為是負樣本,也就是0.
Y = [[int(x1 + x2 < 1)] for (x1,x2) in X]
# 建立一個回話,來執行計算圖
with tf.Session() as sess:
# 對所有變數進行初始化
init_op = tf.global_variables_initializer()
sess.run(init_op)
# 輸出w1和w2值,在訓練之前
print(sess.run(w1))
print(sess.run(w2))
# 設定迭代次數為5000次
Steps = 5000
# 迴圈
for i in range(Steps):
# 選取batch_size個樣本,取餘
start = (i*batch_size)%dataSet_size
# 避免超出訓練集的範圍
end = min(start + batch_size, dataSet_size)
# 對選取的樣本進行訓練,因為是placeholder,使用字典對其賦值,並迭代更新引數
sess.run(train_step, feed_dict={x : X[start:end], y_ : Y[start:end]})
# 當迭代次數為100的倍數的時候,輸出所有資料上的交叉熵
if i%100 == 0:
total_cross_entropy = sess.run(cross_entropy, feed_dict={x:X, y_ : Y})
print("After %d training step(s), cross entropy on all data is %g" % (i, total_cross_entropy))
# 輸出訓練過後的引數(權重)
print(sess.run(w1))
print(sess.run(w2))