1. 程式人生 > >Tensorflow框架(一)

Tensorflow框架(一)

很榮幸從我的導師那裡獲得了一次給我們院老師講解人工智慧程式碼的機會,有一種"受命以來,夙夜憂嘆,恐託付不效"的感覺,所以找了本高分評價書籍《TensorFlow 實戰Google深度學習框架》系統的回顧一下,寫下這個系列的部落格,主要提煉了書中重要知識點,同時對複雜的部分提供個人理解。使用框架前,需要對深度學習有一定的理論基礎。

 

一、計算圖

TensorFlow 程式一般可以分為兩個階段:

  • 定義計算圖中所有的計算
  • 執行計算

 

# 這裡定義了一個計算圖
a = tf.constant([1.0,2.0], name = "a")
b = tf.constant([2.0,3.0], name = "b")
result = a + b

# 查詢張量所屬的計算圖,下列因為沒有特意指定,所以是當前預設的計算圖
print(a.graph is tf.get_default_graph())

 

使用tf.Graph生成新的計算圖,不同計算圖的張量運算不會共享

# 定義g1圖並生成變數v
g1 = tf.Graph()
with g1.as_default():
    v = tf.get_variable(
        "v", shape = [1], initializer = tf.zeros_initializer())

# 定義g2圖並生成變數v
g2 = tf.Graph()
with g2.as_default():
    v = tf.get_variable(
        "v", shape = [1], initializer = tf.ones_initializer())

# 在計算圖g1中讀取變數v的取值
with tf.Session(graph = g1) as sess:
    sess.run(tf.global_variables_initializer())
    tf.global_variables_initializer()
    with tf.variable_scope("", reuse = True):
        print(sess.run(tf.get_variable("v")))

# 在計算圖g2中讀取變數v的取值   
with tf.Session(graph = g2) as sess:
    sess.run(tf.global_variables_initializer())
    tf.global_variables_initializer()
    with tf.variable_scope("", reuse = True):
        print(sess.run(tf.get_variable("v")))

 

此段程式碼會報錯,a預設型別為float32,b預設型別int32

a = tf.constant([1.0, 2.0], name = "a")
b = tf.constant([2, 3], name = "b")
result = tf.add(a, b, name = "add")
print(result)

 

二、張量

# tf.constant 生成常量
a = tf.constant([1.0, 2.0], name = "a")
b = tf.constant([2.0, 3.0], name = "b")
result = a + b

# 使用張量獲取張量維度
result.get_shape

 

三、會話

之前所說的都是定義一個計算圖,後續我們需要執行定義好的計算,這就需要使用會話

a = tf.constant([1.0, 2.0], name = "a")
b = tf.constant([2, 3], name = "b")
result = tf.add(a, b, name = "add")
print (result)

此時打印出的結果是:

Tensor("add_1:0", shape=(2,), dtype=int32)

分別表示了這個result張量名字,維度和型別,但實際未出現結果,下述程式碼通過定義會話成功的打印出了結果

 

a = tf.constant([1, 2], name = "a")
b = tf.constant([2, 3], name = "b")
result = tf.add(a, b, name = "add")

# 定義一個會話,通過python上下文管理器管理會話
with tf.Session() as sess:
    print(sess.run(result))

# 當然也可以使用.eval()函式列印result的值
with tf.Session() as sess:
    print(result.eval())

 

未特殊指定情況下,會話使用了之前預設定義的圖.

# 把定義的sess1會話設定為預設會話
sess1 = tf.Session()
with sess1.as_default():
    print(result.eval())

 

互動式會話

tf.InteractiveSession()函式會將自動生成的會話註冊成為預設會話

sess = tf.InteractiveSession()
print(result.eval())
sess.close()

通過使用tf.ConfigProto配置要生成會話

config = tf.ConfigProto(allow_soft_placement = True,
                        log_device_placement = True)

sess1 = tf.InteractiveSession(config = config)
sess2 = tf.Session(config = config)

allow_soft_placement = True時候,在某些無法使用GPU計算的時候,會轉到CPU上進行,預設值為False

log_device_placement = True受,日誌會記錄每個節點被安排在哪個裝置上以方便除錯

 

四、變數

建立變數:

weights = tf.Variable(tf.random_normal([2, 3], stddev = 2))
biases = tf.Variable(tf.zeros([3]))

# 使用其他變數初始值來初始化新的變數
w2 = tf.Variable(weights.initialized_value() * 2.0)

 Tensorflow隨機數生成函式

 

Tensorflow常數生成函式

 

需要注意的是變數是特殊的張量,所有的變數都會假如到GraphKeys.VARIABLES集合中,通過tf.global_variables函式可以拿到當前計算圖上所有的變數。當構建機器學習模型的時候,可以通過變數宣告函式中的trainable引數區分需要優化的引數和其他引數。

注意變數的型別不匹配

# 該段程式會出現報錯現象
w1 = tf.Variable(tf.random_normal([2,3], stddev = 1), name = "w1")
w2 = tf.Variable(tf.random_normal([2,3], dtype = tf.float64, stddev = 1), name = "w2")
w1.assign(w2)

 

Tensorflow還支援改變變數的維度

w1 = tf.Variable(tf.random_normal([2,3], stddev = 1), name = "w1")
w2 = tf.Variable(tf.random_normal([2,2], stddev = 1), name = "w2")

# 報錯
w1.assign(w2)

# 設定引數validate_shape = False可以修改
tf.assign(w1, w2, validate_shape = False)

 

五、搭建簡單的神經網路

Tensorflow下搭建神經網路的步驟主要是:

  • 定義神經網路的結構和前向傳播的輸出結果
  • 定義損失函式以及選擇反向傳播演算法
  • 生成會話並且在訓練資料上反覆執行反向傳播優化演算法
# 定義神經網路的引數
batch_size = 8
w1 = tf.Variable(tf.random_normal([2, 3], stddev = 1, seed = 1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev = 1, seed = 1))

# shape的一個維度上使用None,可以使用不同batch大小填充輸入資料
x = tf.placeholder(tf.float32, shape = [None, 2], name = "x-input")
y = tf.placeholder(tf.float32, shape = [None, 1], name = "y_input")

# 定義神經網路前向傳播
a = tf.matmul(x, w1)
y_hat = tf.sigmoid(tf.matmul(a, w2))

# 定義損失函式
# tf.clip_by_value在這裡表示如果y_hat小於1e-10,則就等於1e-10,如果y_hat大於1,則就等於1
loss = -tf.reduce_mean(y * tf.log(tf.clip_by_value(y_hat, 1e-10, 1.0))
                      + (1-y) * tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
# 定義反向傳播演算法
# 使用Adam演算法優化
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)

# 使用隨機數生成模擬資料集
np.random.seed(1)
dataset_size = 128
X = np.random.rand(dataset_size, 2)
Y = [[int (x1 + x2 < 1)] for (x1, x2) in X]

# 初始化變數
init = tf.global_variables_initializer()

# 建立會話執行程式
with tf.Session() as sess:
    # 執行初始化變數
    sess.run(init)
    print(sess.run(w1))
    print(sess.run(w2))
    
    steps = 5000
    for i in range(steps):
        # 選區batch_size個樣本進行訓練
        start = (i * batch_size) % dataset_size
        end = min(start + batch_size, dataset_size)
        
        # 使用選取的樣本訓練神經網路
        sess.run(train_step, feed_dict = {x:X[start:end], y:Y[start:end]})
        
        if i % 1000 == 0:
            # 每隔一段時間計算在所有資料上的交叉熵
            total_loss = sess.run(loss, feed_dict = {x: X, y: Y})
            print("After %d training step, loss:%g" %(i, total_loss))