1. 程式人生 > >使用前向傳播和反向傳播的神經網路程式碼

使用前向傳播和反向傳播的神經網路程式碼

本程式碼使用監督學習的方法來更合理的設定引數取值,設定神經網路引數的過程就是神經網路的訓練過程。使用監督學習的方式設定神經網路引數需要有一個標註好的訓練資料集batch,監督學習最重要的思想就是,在已知答案的標註資料集上,模型給出的預測結果要儘量接近真實的答案。
在神經網路優化演算法中,最常用的方法就是反向傳播演算法,基於當前神經網路模型的預測答案與正確答案之間的差距,反向傳播演算法會相應更新神經網路引數的取值,使差距越來越小。通常,在得到前向傳播結果後,會需要定義一個損失函式(例如交叉熵)來刻畫當前的預測值和真實答案之間的差距。目前Tensor支援7種反向傳播的優化器,比較常用的優化方法有3種:tf.train.GradientDescentOptimizer、tf.train.AdamOptimizer和tf.train.MomentumOptimizer。在定義了反向傳播演算法之後,通過執行sess.run(train_step)就可以對神經網路中的引數進行優化,使得在當前batch下損失函式最小。

import tensorflow as tf
#Numpy是一個科學計算的工具包,通過randomstate生成模擬資料集
from numpy.random import RandomState

batch_size = 8 #神經網路訓練集batch大小為8
#定義神經網路的結構,輸入為2個引數,隱藏層為3個引數,輸出為1個引數
#宣告w1、w2兩個變數,通過設定seed引數隨機種子,隨機種子相同,則每次使用此程式碼都生成相同的隨機數
#stddev為標準差,沒有mean設定均值,則均值預設為0
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1
, seed=1)) #w1為輸入到隱藏層的權重,2*3的矩陣 w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1)) #w2為隱藏層打輸出的權重,3*1的矩陣 #維度中使用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) #a為隱藏層的輸出,matmul為矩陣的相乘
y = tf.matmul(a, w2) #y為神經網路的輸出 #定義損失函式和反向傳播的演算法 cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))) #clip_by_value函式將y限制在1e-10和1.0的範圍內,防止出現log0的錯誤 #*為矩陣元素之間的相乘 #y_為正確結果,y為預測結果 #cross_entropy定義了真實值與預測值之間的交叉熵,是一種損失函式 train_step = tf.train.AdamOptimizer(0.001).minimize((cross_entropy)) #反向傳播演算法 #通過隨機數生成一個模擬資料集 rdm = RandomState(1) #rdm為偽隨機數發生器,種子為1,只要種子相同,該發生器每次生成的隨機數都是一樣的 dataset_size = 128 X = rdm.rand(dataset_size, 2) #生成隨機數,大小為128*2的矩陣 #Y屬於樣本的標籤,所有x1+x2<1的都被認為是正樣本,其餘為負樣本。 Y = [[int(x1+x2 <1)] for (x1, x2) in X] #列表解析格式 #若x1+x2 <1為真,則int(x1+x2 <1)為1,若假,則輸出為0 #建立會話 with tf.Session() as sess: init_op = tf.global_variables_initializer() #所有需要初始化的值 sess.run(init_op) #初始化變數 print(sess.run(w1)) print(sess.run(w2)) ''' #在訓練之前神經網路權重的值 w1 = [[-0.81131822, 1.48459876, 0.06532937], [-2.44270396, 0.0992484, 0.59122431]] w2 = [[-0.81131822, 1.48459876, 0.06532937]] ''' # 設定訓練的輪數 STEPS = 5000 for i in range(STEPS): # 每次從資料集中選8個數據進行訓練 start = (i * batch_size) % dataset_size # 訓練集在資料集中的開始位置 end = min(start + batch_size, dataset_size) # 結束位置,若超過dataset_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 steps(s), cross entropy on all data is %g" % (i, total_cross_entropy)) # 在訓練之後神經網路權重的值 print(sess.run(w1)) print(sess.run(w2)) >>[[-0.81131822 1.48459876 0.06532937] [-2.4427042 0.0992484 0.59122431]] [[-0.81131822] [ 1.48459876] [ 0.06532937]] #訓練之前神經網路引數的值 >>After 0 training steps(s), cross entropy on all data is 0.0674925 After 1000 training steps(s), cross entropy on all data is 0.0163385 After 2000 training steps(s), cross entropy on all data is 0.00907547 After 3000 training steps(s), cross entropy on all data is 0.00714436 After 4000 training steps(s), cross entropy on all data is 0.00578471 #這是每1000次訓練之後的交叉熵,可以發現隨著訓練的執行,交叉熵是逐漸變小的,交叉熵越小說明預測的結果和真實的結果差距越小 >>[[-1.96182752 2.58235407 1.68203771] [-3.46817183 1.06982315 2.11788988]] [[-1.82471502] [ 2.68546653] [ 1.41819501]] #訓練之後神經網路引數的值

可以得出訓練神經網路的過程為以下3步:

  1. 定義神經網路的結構和前向傳播的輸出結果
  2. 定義損失函式以及選擇反向傳播優化的演算法
  3. 生成會話並且在訓練資料上反覆執行反向傳播優化演算法