Tensorflow學習:搭建神經網絡

原文鏈接:https://www.cnblogs.com/wanyu416/p/9009985.html

一、神經網絡的實現過程

  1、準備數據集,提取特徵,作爲輸入餵給神經網絡
       2、搭建神經網絡結構,從輸入到輸出
       3、大量特徵數據餵給 NN,迭代優化 NN 參數
       4、使用訓練好的模型預測和分類 

二、前向傳播  

     前向傳播就是搭建模型的計算過程,可以針對一組輸入給出相應的輸出。

  舉例:假如生產一批零件, 體積爲 x1, 重量爲 x2, 體積和重量就是我們選擇的特徵,把它們喂入神經網絡, 當體積和重量這組數據走過神經網絡後會得到一個輸出。

  假如輸入的特徵值是:體積 0.7 ,重量 0.5 ,下圖是搭建的神經網絡框架圖

  

由搭建的神經網絡可得, 隱藏層節點 a11=x1* w11+x2*w21=0.14+0.15=0.29, 同理算得節點 a12=0.32, a13=0.38,最終計算得到輸出層 Y=-0.015, 這便實現了前向傳播過程。

 

  再來推導圖中的代碼實現過程。

  第一層:

  (1)x是輸入爲1*2的矩陣:用x表示輸入,是一個1行2列的矩陣,表示一次輸入一組特徵,這組特徵包含了體積和重量兩個元素。

  (2)W前節點編號,後節點編號(層數)爲待優化的參數:前面兩個節點,後面三個節點。所以w應該是個兩行三列的矩陣。表示爲

    

    注意:神經網絡共有幾層是指計算層, 輸入不算作計算層,所以 上圖中a 爲第一層網絡,a 是一個一行三列矩陣。

  第二層:

  (1)參數要滿足前面三個節點,後面一個節點,所以W(2)是三行一列矩陣。表示爲 

  

  我們把每層輸入乘以線上的權重w,這樣就可以用矩陣乘法輸出y了。

       下面討論這其中的細節問題。

1、神經網絡的參數

       顯然權重w是很重要的參數,我們剛開始設置w變量的時候,一般會先隨機生成這些參數,當然肯定是變量形式。

       所以這裏介紹一下 tf 常用的生成隨機數/數組的函數:

(1)tf.random_normal()     生成正態分佈隨機數

w=tf.Variable(tf.random_normal([2,3],stddev=2, mean=0, seed=1))
# 表示生成正態分佈隨機數,形狀兩行三列,標準差是2,均值是0,隨機種子是1

(2)tf.truncated_normal()  生成去掉過大偏離點的正態分佈隨機數,也就是如果隨機生成的數據偏離平均值超過兩個標準差,這個數據將重新生成

w=tf.Variable(tf.Truncated_normal([2,3],stddev=2, mean=0, seed=1))

3)tf.random_uniform()    生成均勻分佈隨機數

w=tf.Variable(tf.random_uniform([2,3],minval=0,maxval=1,dtype=tf.float32,seed=1))
# 表示從一個均勻分佈[minval maxval)中隨機採樣,產生的數是均勻分佈的,注意定義域是左閉右開,即包含 minval,不包含 maxval。

以上這些函數,如果沒有特殊要求標準差、 均值、 隨機種子是可以不寫的。看具體使用情況。

(4)其它函數:tf.zeros             表示生成全 0 數組
         tf.ones              表示生成全 1 數組
         tf.fill                  表示生成全定值數組
         tf.constant        表示生成直接給定值的數組

tf.zeros([3,2],int32)  # 表示生成[[0,0],[0,0],[0,0]]
tf.ones([3,2],int32)   # 表示生成[[1,1],[1,1],[1,1]
tf.fill([3,2],6)       # 表示生成[[6,6],[6,6],[6,6]]
tf.constant([3,2,1])   # 表示生成[3,2,1]

2、placeholder佔位,輸入多組數據

      不做贅述,直接在代碼裏面註釋這樣的操作

 

    細節討論完,下面就是用代碼實現前向傳播

# (1) 用placeholder 實現輸入定義(sess.run 中喂入一組數據)的情況,特徵有體積和重量,數據爲體積 0.7、重量 0.5

import tensorflow as tf

x = tf.placeholder(tf.float32,shape=(1,2))  # placeholder佔位,首先要指定數據類型,然後可以指定形狀,因爲我們現在只需要佔一組數據,且有兩個特徵值,所以shape爲(1,2)
w1 = tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))  # 生成權重
w2 = tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

a = tf.matmul(x,w1)   # 矩陣乘法op
y = tf.matmul(a,w2)

with tf.Session() as sess:
    init = tf.global_variables_initializer()   # 初始化以後就放在這裏,不容易忘記
    sess.run(init)
    print("y is",sess.run(y,feed_dict={x:[[0.7,0.5]]}))  # 以字典形式給feed_dict賦值,賦的是一個一行兩列的矩陣,注意張量的階數。這裏只執行了y的op,因爲執行了y也就執行了a這個op

運行顯示結果爲:

y is: [[ 3.0904665]]
# (2) 用 placeholder 實現輸入定義(sess.run 中喂入多組數據)的情況
import tensorflow as tf


#定義輸入和參數
x=tf.placeholder(tf.float32,shape=(None,2))   # 這裏佔位因爲不知道要輸入多少組數據,但還是兩個特徵,所以shape=(None,2),注意大小寫
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

#定義前向傳播過程
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

#用會話計算結果
with tf.Session() as sess:
    init_op=tf.global_variables_initializer()
    sess.run(init_op)
    print("y is:",sess.run(y,feed_dict={x:[[0.7,0.5],
                                           [0.2,0.3],
                                           [0.3,0.4],
                                           [0.4,0.5]]}))  # 輸入數據,4行2列的矩陣

運行顯示結果爲:

y is: [[ 3.0904665 ]
 [ 1.2236414 ]
 [ 1.72707319]
 [ 2.23050475]]

以上就是最簡單的神經網絡前向傳播過程。

 

三、後向傳播

  反向傳播:訓練模型參數,以減小loss值爲目的,使用優化方法,使得 NN 模型在訓練數據上的損失函數最小。

 

  損失函數(loss): 計算得到的預測值 y 與已知答案 y_ 的差距。損失函數的計算有很多方法,均方誤差( MSE) 是比較常用的方法之一。

 

  均方誤差 MSE: 求前向傳播計算結果與已知答案之差的平方再求平均。 
 

  數學公式爲:

  用tensorflow函數表示爲:loss_mse = tf.reduce_mean(tf.square(y_ - y))

 

  反向傳播訓練方法: 以減小 loss 值爲優化目標。

  一般有梯度下降、 momentum 優化器、 adam 優化器等優化方法。這三種優化方法用 tensorflow 的函數可以表示爲:

  train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

  train_step=tf.train.MomentumOptimizer(learning_rate, momentum).minimize(loss)

  train_step=tf.train.AdamOptimizer(learning_rate).minimize(loss)

 

三種優化方法的區別

        學習率:決定每次參數更新的幅度。

  優化器中都需要一個叫做學習率的參數,使用時,如果學習率選擇過大會出現震盪不收斂的情況(步子跨的太大),如果學習率選擇過小,會出現收斂速度慢的情況。我們可以選個比較小的值填入,比如 0.01、0.001。 

 

  Python代碼實現加上反向傳播的NN

  隨機產生 32 組生產出的零件的體積和重量,訓練 3000 輪,每 500 輪輸出一次損失函數。

import tensorflow as tf
import numpy as np

BATCH_SIZE = 8  # 一次輸入網絡的數據,稱爲batch。一次不能喂太多數據
SEED = 23455    # 產生統一的隨機數

# 基於seed產生隨機數,這是根據隨機種子產生隨機數的一種常用方法,要熟練運用
rdm = np.random.RandomState(SEED)
# 隨機數返回32行2列的矩陣 表示32組 體積和重量 作爲輸入數據集。因爲這裏沒用真實的數據集,所以這樣操作。
X = rdm.rand(32, 2)
# 從X這個32行2列的矩陣中 取出一行 判斷如果和小於1 給Y賦值1 如果和不小於1 給Y賦值0 (這裏只是人爲的定義),作爲輸入數據集的標籤(正確答案)
Y_ = [[int(x0 + x1 < 1)] for (x0, x1) in X]
print("X:\n", X)
print("Y_:\n",Y_)


# 1定義神經網絡的輸入、參數和輸出,定義前向傳播過程。
x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))

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

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

# 2定義損失函數及反向傳播方法。
loss = tf.reduce_mean(tf.square(y - y_))
train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss)  # 三種優化方法選擇一個就可以
# train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_mse)
# train_step = tf.train.AdamOptimizer(0.001).minimize(loss_mse)

# 3生成會話,訓練STEPS輪
with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run(init)
    # 輸出目前(未經訓練)的參數取值。
    print("w1:\n", sess.run(w1))
    print("w2:\n", sess.run(w2))
    print("\n")

    # 訓練模型。
    STEPS = 3000
    for i in range(STEPS):               #0-2999
        start = (i * BATCH_SIZE) % 32    #i=0,start=0,end=8;i=1,start=8,end=16;i=2,start=16,end=24;i=3,start=24,end=32;i=4,start=0,end=8。也就是說每次訓練8組數據,一共訓練3000次。
        end = start + BATCH_SIZE
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]})
        if i % 500 == 0:
            total_loss = sess.run(loss, feed_dict={x: X, y_: Y_})
            print("After %d training step(s), loss on all data is %g"%(i,total_loss))

    # 輸出訓練後的參數取值。
    print("\n")
    print("w1:\n", sess.run(w1))
    print("w2:\n", sess.run(w2))

運行顯示結果爲

X:
[[ 0.83494319  0.11482951]
 [ 0.66899751  0.46594987]
 [ 0.60181666  0.58838408]
 [ 0.31836656  0.20502072]
 [ 0.87043944  0.02679395]
 [ 0.41539811  0.43938369]
 [ 0.68635684  0.24833404]
 [ 0.97315228  0.68541849]
 [ 0.03081617  0.89479913]
 [ 0.24665715  0.28584862]
 [ 0.31375667  0.47718349]
 [ 0.56689254  0.77079148]
 [ 0.7321604   0.35828963]
 [ 0.15724842  0.94294584]
 [ 0.34933722  0.84634483]
 [ 0.50304053  0.81299619]
 [ 0.23869886  0.9895604 ]
 [ 0.4636501   0.32531094]
 [ 0.36510487  0.97365522]
 [ 0.73350238  0.83833013]
 [ 0.61810158  0.12580353]
 [ 0.59274817  0.18779828]
 [ 0.87150299  0.34679501]
 [ 0.25883219  0.50002932]
 [ 0.75690948  0.83429824]
 [ 0.29316649  0.05646578]
 [ 0.10409134  0.88235166]
 [ 0.06727785  0.57784761]
 [ 0.38492705  0.48384792]
 [ 0.69234428  0.19687348]
 [ 0.42783492  0.73416985]
 [ 0.09696069  0.04883936]]
Y_:
[[1], [0], [0], [1], [1], [1], [1], [0], [1], [1], [1], [0], [0], [0], [0], [0], [0], [1], [0], [0], [1], [1], [0], [1], [0], [1], [1], [1], [1], [1], [0], [1]]
w1:
[[-0.81131822  1.48459876  0.06532937]
 [-2.4427042   0.0992484   0.59122431]]
w2:
[[-0.81131822]
 [ 1.48459876]
 [ 0.06532937]]


After 0 training step(s), loss_mse on all data is 5.13118
After 500 training step(s), loss_mse on all data is 0.429111
After 1000 training step(s), loss_mse on all data is 0.409789
After 1500 training step(s), loss_mse on all data is 0.399923
After 2000 training step(s), loss_mse on all data is 0.394146
After 2500 training step(s), loss_mse on all data is 0.390597


w1:
[[-0.70006633  0.9136318   0.08953571]
 [-2.3402493  -0.14641267  0.58823055]]
w2:
[[-0.06024267]
 [ 0.91956186]
 [-0.0682071 ]]

由神經網絡的實現結果,我們可以看出,總共訓練3000輪,每輪從X的數據集和Y的標籤中抽取相對應的從start開始到end結束個特徵值和標籤,喂入神經網絡,用sess.run求出loss,每500輪打印一次loss值。經過3000輪後,我們打印出最終訓練好的參數w1、w2。

 針對上面的代碼,做出如下思考。首先最終的目的是使得loss值減小,那麼:

1、如果增大訓練次數,loss會不會繼續減小?如果減小,會不會一直在減小?

2、如果增大學習率,loss會不會繼續減小?如果減小,會不會一直在減小?

3、如果不用隨機梯度下降算法,換用其他的優化器,會產生什麼樣的變化?

 4、更改batch的值,會不會對結果有影響?

 

四、搭建神經網絡的過程

  通過以上的內容,我們可以梳理一下搭建簡單神經網絡的步驟:

  (1)導入模塊,生成模擬數據集

          import

          常量定義

          生成數據集

  (2)前向傳播:定義輸入、參數和輸出

          x=              y_=

          w1=            w2=

          a=              y=

  (3)後向傳播:定義損失函數、反向傳播方法

          loss=

          train_step=

  (4)生成會話,訓練STEPS輪

        with tf.Session as sess:

          init_op = tf.global_variables_initializer()

          sess.run(init_op)

          STEPS = 

            for i in range(STEPS):

            start = 

            end = 

            sess.run(train_step, feed_dict={ })

 

 

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