1. 程式人生 > >TensorFlow零基礎入門教程(一)

TensorFlow零基礎入門教程(一)

TensorFlow入門(一)

da9d6629fbaad81c1b2bc35526990404.jpg

1.計算圖

首先解釋什麼是計算圖,瞭解TensorFlow的計算模型.

image.png

和我們常見的程式計算框架不同,並不是賦值,或者計算後,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))