【神經網絡基礎】BP算法原理及兩種實現

1、BP算法

以一個單隱層神經網絡作二分類爲例,如圖: python

1.先簡單介紹一個各個參數:算法

m:表示樣本數量。bash

y:各個樣本真實值,維度爲m*1網絡

n^{[l]}:表示第l層的神經元個數。app

a^{[l]}:表示第l層的輸入變量,也是第l-1層z^{[l]}通過激活函數處理後的結果。其維度通常爲a^{[l]}=n^{[l]}*mdom

w^{[l]}:表示第l層權重參數,其維度通常爲w^{[l]}=n^{[l]}*n^{[l-1]}函數

b^{[l]}:表示第l層偏置量參數,其維度通常爲b^{[l]}=n^{[l]}*m學習

z^{[l]}:表示第l層線性變換後的結果,其維度通常爲z^{[l]}=n^{[l]}*mui

2.前向傳播計算過程:spa

  • 輸入層a^{[0]}是一個n^{[0]}*m的矩陣,即爲m個樣本,每一個樣本包含n^{[0]}個特徵,本例爲3*5。
  • 隱藏層有n^{[1]}個隱藏單元。該隱層中包括兩步計算,

一是線性變換,w_{[i]}^{[1]}爲第一個隱藏層的第i個隱藏單元參數,b_{[i]}^{[1]}爲第一個隱藏層的第i個隱藏單元偏置量;z^{[1]}=w^{[1]}*a^{[0]}+b^{[1]}

第二步是激活函數,非線性變換,而且將數值變換到0-1之間,本例選擇sigmoid函數做爲激活函數。a^{[1]}=sigmoid(z^{[1]})

  • 輸出層只有一個節點,n^{[2]}=1,對於本層而言,輸入就是a^{[1]},線性變換與激活函數處理以後獲得最終預測值a^{[2]},根據均方偏差計算損失函數L(y,a)。

3.反向傳播過程,更新參數值:

反向傳播是利用鏈式法則對各個參數求偏導數的過程。咱們的訓練目標是使得損失函數最小化,神經網絡中利用梯度降低法更新參數w和b使得損失函數L值最小化。瞭解梯度降低的話,應該知道梯度降低中更新參數的辦法是使得各個參數按必定步長(學習率)沿着函數降低最快的方向(因爲梯度方向就是函數上升最快的方向,所以函數降低最快的方向就是梯度反方向)移動,直到找到全局或局部最優解爲止。

首先要清楚z^{[k]}a^{[k]}的來源:

z^{[k]}=w^{[k]}*a^{[k-1]}+b^{[k]}

a^{[k]}=f(z^{[k]}) #f爲一種激活函數

那麼接下來求第k層和第k-1層的w與b的偏導數。

\frac{{\partial L(y,a)}}{{\partial w^{[k]}}} = \frac{{\partial L(y,a)}}{{\partial z^{[k]}}}*\frac{{\partial z^{[k]}}}{{\partial w^{[k]}}}

\frac{{\partial L(y,a)}}{{\partial b^{[k]}}} = \frac{{\partial L(y,a)}}{{\partial z^{[k]}}}*\frac{{\partial z^{[k]}}}{{\partial b^{[k]}}}

一是求\delta^{[k]}=\frac{{\partial L(y,a)}}{{\partial z^{[k]}}},定義\delta^{[k]}爲第k層的偏差項,反映了該層對最終總偏差的影響。根據鏈式法則:

\delta^{[k]}=\frac{{\partial a^{[k]}}}{{\partial z^{[k]}}}*\frac{{\partial z^{[k+1]}}}{{\partial a^{[k]}}}*\frac{{\partial L(y,a)}}{{\partial z^{[k+1]}}} = f'(z^{[k]}) (w^{[k+1]})^{T}\delta^{[k+1]}

二是求\frac{{\partial z^{[k]}}}{{\partial w^{[k]}}}\frac{{\partial z^{[k]}}}{{\partial b^{[k]}}}

\frac{{\partial z^{[k]}}}{{\partial w^{[k]}}} =a^{[k-1]}

\frac{{\partial z^{[k]}}}{{\partial b^{[k]}}}=1

所以求第k層的偏導數依賴於第k+1層的偏導數的值,體現了反向傳播的意義。

\frac{{\partial L(y,a)}}{{\partial w^{[k]}}} =\delta^{[k]}*(a^{[k-1]})^{T}

\frac{{\partial L(y,a)}}{{\partial b^{[k]}}}=\delta^{[k]}

而後更新參數爲:

w^{[k]}-=lr*\frac{{\partial L(y,a)}}{{\partial w^{[k]}}}

b^{[k]}-=lr*\frac{{\partial L(y,a)}}{{\partial b^{[k]}}}

在屢次循環迭代中,不斷執行前向傳播計算損失函數值與反向傳播更新參數,最終使得損失在必定範圍內。

2、Python實現BP神經網絡

#coding:utf-8
#BP算法的python實現
import numpy as np

def sigmoid(x):
    return 1/(1+np.exp(-x))

def derivative(x):
    return (1-x)*x

class nn(object):
    def __init__(self,layer):
        np.random.seed(2)
        self.w=[]
        for i in range(1,len(layer)):
            # np.random.random((1000,20))表明生成1000行 20列的浮點數,浮點數都是從0-1中隨機。
            self.w.append(2*np.random.random((layer[i-1],layer[i]))-1)

    def train(self,x,y,lr,echo):
        a=[x]
        for ech in range(echo):
            for i in range(0,len(self.w)):
                a.append(sigmoid(np.dot(a[i],self.w[i])))
            if(ech%100==0):
                print('echo',ech,'-error %f:',np.mean((a[-1]-y)**2))
            l_error=-(y-a[-1])
            for k in range(len(self.w)-1,-1,-1):
                l_delta = l_error*derivative(np.array(a[k+1]))
                w_update=np.dot(a[k].T,l_delta)
                l_error=np.dot(l_delta,self.w[k].T)
                self.w[k]-=lr*w_update
        return self.w

    def predict(self,w,test):
        l1 = sigmoid(np.dot(test, self.w[0]))
        l2 = sigmoid(np.dot(l1, self.w[1]))
        if l2 >= 0.5:
            print(l2,"1")
        else:
            print(l2,"0")

layer=[3,4,1]
x = np.array([[0, 0, 1],[0, 1, 1],[1, 0, 1],[1, 1, 1],[0, 0, 1]])
y = np.array([[0],[1],[1],[0],[0]])
nn=nn(layer)
w=nn.train(x,y,0.1,2000)
nn.predict(w,[1,1,0])
複製代碼

3、tensorflow實現BP神經網絡

待更新
複製代碼
相關文章
相關標籤/搜索