TensorFlow實戰——實現神經網絡

TensorFlow實現神經網絡

分類問題解決思路

使用神經網絡解決分類問題主要可以分爲以下四個步驟:
1. 提取問題中實體的特徵向量作爲神經網絡的輸入。
2. 定義神經網絡的結構,並定義如何從神經網絡的輸入得到輸出。即前向傳播算法。
3. 通過訓練數據來調整神經網絡中參數的取值,即訓練神經網絡。
4. 使用訓練好的神經網絡來預測未知的數據。

前向傳播算法的實現

x爲輸入數據,w1爲從輸入層到隱藏層的參數矩陣,w2爲從隱藏層到輸出層的參數矩陣,則前向傳播過程代碼爲

a = tf.matmul(x, w1)
b = tf.matmul(a, w2)

其中tf.matmul實現了矩陣乘法的功能。

TensorFlow變量

在TensorFlow中,變量(tf.Variable)的作用就是保存和更新神經網絡中的參數。
聲明一個2*3的矩陣變量的方法

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

TensorFlow中變量的初始值可以設置成隨機數、常數或者是通過其他變量的初始值計算得到。

對於變量,初始化是非常重要的。雖然在變量定義的時候給出了變量初始化的方法,但是這個方法並沒有被真正運行,需要通過variable_name.initializer來給變量賦值。

TensorFlow提供了一種更加便捷的方式來完成變量初始化過程。

init_op = tf.initialize_all_variables()
sess.run(init_op)

通過tf.initialize_all_variables函數就不需要將變量一個一個初始化了。

集合的概念
TensorFlow中有集合的概念。比如,所有的變量都會被自動的加入到GraphKeys.VARIABLES這個集合。通過tf.all_variables函數可以拿到當前計算圖上所有的變量。
在構建機器學習模型的時候,比如神經網絡,可以通過變量聲明函數中的trainable參數來區分需要優化的參數(比如神經網絡中通過反向傳播優化的參數)和其他參數(比如迭代的輪數)。如果trainable參數爲True,那麼這個變量將會加入GraphKeys.TRAINABLE_VARIABLES集合。TensorFlow中可以通過tf.trainable_variables函數得到所有需要優化的參數。TensorFlow中提供的神經網絡優化算法會將GraphKeys.TRAINABLE_VARIABLES中的變量作爲默認的優化對象。

變量的類型是不可變的,但和類型不一樣的是,維度在程序運行中是有可能改變的,但是需要通過設置參數validate_shape=False

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

tf.assign(w1, w2)#不成功,報維度不匹配錯誤
tf.assign(w1, w2, validate_shape=False)#成功執行並且改變了w1的維度

通過TensorFlow訓練神經網絡模型

反向傳播算法的第一步是使用TensorFlow表達一個batch的數據

x = tf.constant([[0.7,0.9]])

但如果每輪迭代中選取的數據都通過常量表示,那麼計算圖太大。TensorFlow提供了placeholder機制用於提供輸入數據。

placeholder相當於定義了一個位置,這個位置中的數據在程序運行時再指定。

這樣在程序中就不需要生成大量常量來提供輸入數據,而只需要將數據通過placeholder傳入TensorFlow計算圖。
placeholder的類型也不可以改變。在實踐中,placeholder可以用來保存輸入層的訓練集中的不同樣例。

import tensorflow as tf

w1 = tf.Variable(tf.random_normal([2, 3], stddev=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1))
#定義placeholder存放輸入數據,維度不一定要定義可以用None表示,也可以用確定的維度
x = tf.placeholder(tf.float32, shape=(1,2), name="input")
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

sess = tf.Session()
init_op = tf.initialize_all_variables()
sess.run(init_op)

print(sess.run(y, feed_dict={x: [[0.7, 0.9]]}))#只計算一個樣例的前向傳播結果
#feed_dict參數用字典的方式對placeholder的參數進行賦值,這樣可以在每次運行時賦予不同的值。

在新的程序中計算前向傳播的結果時,需要提供一個feed_dict來指定x的取值。feed_dict是一個字典,在字典中需要給出每個用到的placeholder的取值。

損失函數

在得到一個batch的前向傳播結果之後,需要定義一個損失函數來刻畫當前的預測值和真實答案之間的差距。然後通過反向傳播算法來調整神經網絡參數的取值使得差距可以被縮小。

#用損失函數刻畫預測值與真實值的差距
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
#定義學習率
learning_rate = 0.001
#定義反向傳播算法來優化神經網絡中的參數
train_step = tf.train.AdamOptimizer(learing_rate).minimize(cross_entropy)

cross_entropy定義了真實值與預測值之間的交叉熵,這是分類問題中一個常用的損失函數。關於該值的詳細解釋參見下一節。

完整的神經網絡樣例程序

下列程序在一個模擬數據集上訓練神經網絡,解決二分類問題。

import tensorflow as tf
from numpy.random import RandomState

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))

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 = tf.matmul(a, w2)

cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
#隨機數生成模擬數據集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
#定義規則給出樣本標籤。所有x1+x2<1的樣例都被認爲是正樣本,而其他爲負樣本。
Y = [[int(x1+x2<1)] for (x1,x2) in X]

with tf.Session() as sess:
    init_op = tf.initialize_all_variables()
    sess.run(init_op)
    print sess.run(w1)
    print sess.run(w2)#訓練之前神經網絡參數的值打印出來
    STEPS = 5000
    for i in range(STEPS):
        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_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)

總結,神經網絡訓練的過程可以分爲以下三個步驟:
1. 定義神經網絡的結構和前向傳播的輸出結果
2. 定義損失函數以及選擇反向傳播優化的算法
3. 生成會話(tf.Session)並且在訓練數據上反覆運行反向傳播優化算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章