1. 程式人生 > >機器學習之BP神經網路 以及 tensorflow 實現

機器學習之BP神經網路 以及 tensorflow 實現

BP (Back Propagation)神經網路簡介 :

先介紹一下神經元,在生物神經網路中,每個神經元與其它神經元相連,當一個神經元“興奮”時,就會通過穿出神經向其它神經元傳送化學物質,其它神經元會通過穿人神經接受資訊然後再傳遞至神經中樞處理資訊。現在機器學習中的神經網路就是基於生物學中的神經元模型的。一個一個的神經元與其它神經元相互連線構成所謂的神經網路。

BP 神經網路分為兩個過程
1. 工作訊號正向傳遞子過程
2. 誤差訊號逆向傳遞過程

在一般的BP神經網路中,單個樣本有m個輸入和n個輸出,在輸入層和輸出層之間還有若干個隱藏層,實際上 1989年時就已經有人證明了一個萬能逼近定理 :
在任何閉區間的連續函式都可以用一個隱藏層的BP神經網路進行任意精度的逼近。
所以說一個三層的神經網路就可以實現一個任意從m維到n維的一個對映。這三層分別是
輸入層、隱藏層、輸出層 如圖所示 :

關於隱藏層的選擇 :
在BP神經網路中,輸入層和輸出層的節點數目都是固定的,關鍵的就是在於隱藏層數目的選擇,隱藏層數目的選擇決定了神經網路工作的效果

一般而言,有一個關於隱藏層數目的經驗公式

這裡寫圖片描述

其中 h 為隱藏層節點數目,m為輸入層節點數目,n為輸出層節點數目 a 為 1-10 之間的調節常數。一般而言如果資料多的話我們可以設a稍微大一點,而資料不是太多的時候就設定的小一點防止過擬合。

正向傳遞子過程 :
設節點 i 與 節點 j 之間的權值 為 wij,節點 j 的閥值為 bj,每個節點的輸出值為 xj,具體的計算方法如下
這裡寫圖片描述

其中 f 為啟用函式 ,一般選擇sigmoid函式或者 線性函式正向傳播中輸入層沒有閥值

BP神經網路的關鍵之處就在於反向誤差的傳播
假設我的第j個輸出結果為 dj 則誤差函式如下所示 :
這裡寫圖片描述

BP神經網路的墓地就是通過不斷修改 w 值 和 b 值使得誤差達到最小 (因為一旦 w b 值全部確定以後,一個輸入就對應著一個輸出,所以只要讓誤差最小就可以了)而調整誤差的方法就是使用梯度下降法不斷減小誤差。

我們選擇激勵函式為
這裡寫圖片描述

對於介於隱藏層與輸出層之間的權值wij 由偏微分公式我們可以得到

這裡寫圖片描述

對於激勵函式求導 (為了方便我們得到整體的導數)我們可以得到

這裡寫圖片描述

然後對於wij 的偏導數我們也可以求出
這裡寫圖片描述

其中 :

這裡寫圖片描述

對於bj的導數為
這裡寫圖片描述

這就是著名的學習規則,通過改變神經元之間的連線權值來減少系統實際輸出和期望輸出的誤差,這個規 則又叫做Widrow-Hoff學習規則或者糾錯學習規則。

對最後一層處理完畢之後我們開始對前一層進行處理,首先將誤差通過權值向前傳遞得到上一層的誤差,那麼同樣的對於上一層使用梯度下降法最小化誤差就可以了/

這裡寫圖片描述

這裡寫圖片描述

剩下的就是根據梯度下降法更新w與b的值,以使得誤差最小

這裡寫圖片描述
都是一樣的方法調整誤差就可以了

標準BP神經網路的缺陷:
(1)容易形成區域性極小值而得不到全域性最優值。
BP神經網路中極小值比較多,所以很容易陷入區域性極小值,這就要求對初始權值和閥值有要求,要使得初始權值和閥值隨機性足夠好,可以多次隨機來實現。
(2)訓練次數多使得學習效率低,收斂速度慢。
(3)隱含層的選取缺乏理論的指導。
(4)訓練時學習新樣本有遺忘舊樣本的趨勢。
通常BP神經網路在訓練之前會對資料歸一化處理,即將資料
對映到更小的區間內,比如[0,1]或[-1,1]。

tensorflow 在 moist 上的實現程式碼


import tensorflow as tf 
from  tensorflow.examples.tutorials.mnist  import  input_data
import numpy as np 

mnist = input_data.read_data_sets('data', one_hot = True)

num_classes = 10
input_size = 784
hidden_units_size = 30
batch_size = 100
training_iterations = 10000

X = tf.placeholder (tf.float32, shape = [None, input_size])
Y = tf.placeholder (tf.float32, shape = [None, num_classes])

W1 = tf.Variable (tf.random_normal ([input_size, hidden_units_size], stddev = 0.1))
B1 = tf.Variable (tf.constant (0.1), [hidden_units_size])
W2 = tf.Variable (tf.random_normal ([hidden_units_size, num_classes], stddev = 0.1))
B2 = tf.Variable (tf.constant (0.1), [num_classes])

hidden_opt = tf.matmul (X, W1) + B1
hidden_opt = tf.nn.relu (hidden_opt)
final_opt = tf.matmul (hidden_opt, W2) + B2
final_opt = tf.nn.relu (final_opt)

loss = tf.reduce_mean (tf.nn.softmax_cross_entropy_with_logits (labels = Y, logits = final_opt))
opt = tf.train.GradientDescentOptimizer (0.05).minimize (loss)
init = tf.global_variables_initializer ()
correct_prediction = tf.equal (tf.argmax (Y, 1), tf.argmax (final_opt, 1))
accuracy = tf.reduce_mean (tf.cast (correct_prediction, 'float'))

sess = tf.Session ()
sess.run (init)
for i in range (training_iterations) :
    batch = mnist.train.next_batch (batch_size)
    batch_input = batch[0]
    batch_labels = batch[1]
    training_loss = sess.run ([opt, loss], feed_dict = {X: batch_input, Y: batch_labels})
    if i % 1000 == 0 :
        train_accuracy = accuracy.eval (session = sess, feed_dict = {X: batch_input,Y: batch_labels})
        print ("step : %d, training accuracy = %g " % (i, train_accuracy))