日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

机器学习入门学习笔记:(1)BP神经网络原理推导及程序实现

發(fā)布時間:2025/3/21 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习入门学习笔记:(1)BP神经网络原理推导及程序实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
機器學(xué)習(xí)中,神經(jīng)網(wǎng)絡(luò)算法可以說是當(dāng)下使用的最廣泛的算法。神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)模仿自生物神經(jīng)網(wǎng)絡(luò),生物神經(jīng)網(wǎng)絡(luò)中的每個神經(jīng)元與其他神經(jīng)元相連,當(dāng)它“興奮”時,想下一級相連的神經(jīng)元發(fā)送化學(xué)物質(zhì),改變這些神經(jīng)元的電位;如果某神經(jīng)元的電位超過一個閾值,則被激活,否則不被激活。誤差逆?zhèn)鞑ニ惴?#xff08;error back propagation)是神經(jīng)網(wǎng)絡(luò)中最有代表性的算法,也是使用最多的算法之一。

誤差逆?zhèn)鞑ニ惴ɡ碚撏茖?dǎo)

  誤差逆?zhèn)鞑ニ惴?#xff08;error back propagation)簡稱BP網(wǎng)絡(luò)算法。而一般在說BP網(wǎng)絡(luò)算法時,默認指用BP算法訓(xùn)練的多層前饋神經(jīng)網(wǎng)絡(luò)。

  下面是一個簡單的BP神經(jīng)網(wǎng)絡(luò)示意圖。其擁有一個輸入層,一個隱含層,一個輸出層。推導(dǎo)中采用這種簡單的三層的神經(jīng)網(wǎng)絡(luò)。

?

  定義相關(guān)的一些變量如下:

  • 假設(shè)有 d 個輸入神經(jīng)元,有 l 個輸出神經(jīng)元,q 個隱含層神經(jīng)元;
  • 設(shè)輸出層第 j 個神經(jīng)元的閾值為?θj
  • 設(shè)隱含層第 h 個神經(jīng)元的閾值為?γh
  • 輸入層第 i 個神經(jīng)元與隱含層第 h 個神經(jīng)元之間的連接權(quán)為 Vih?
  • 隱含層第 h 個神經(jīng)元與輸出層第 j 個神經(jīng)元之間的連接權(quán)為 Whj?
  • 記隱含層第 h 個神經(jīng)元接收到來自于輸入層的輸入為?αh:

    ? ? ? ? ? ? ? ? ? ? ? ? ? 

  • ?記輸出層第 j 個神經(jīng)元接收到來自于隱含層的輸入為?βj: ??

  • ?             ,其中 bh?為隱含層第 h 個神經(jīng)元的輸出

      理論推導(dǎo):

      在神經(jīng)網(wǎng)絡(luò)中,神經(jīng)元接收到來自來自其他神經(jīng)元的輸入信號,這些信號乘以權(quán)重累加到神經(jīng)元接收的總輸入值上,隨后與當(dāng)前神經(jīng)元的閾值進行比較,然后通過激活函數(shù)處理,產(chǎn)生神經(jīng)元的輸出。

    ?

      激活函數(shù):

      理想的激活函數(shù)是階躍函數(shù),“0”對應(yīng)神經(jīng)元抑制,“1”對應(yīng)神經(jīng)元興奮。然而階躍函數(shù)的缺點是不連續(xù),不可導(dǎo),且不光滑,所以常用sigmoid函數(shù)作為激活函數(shù)代替階躍函數(shù)。如下圖分別是階躍函數(shù)和sigmoid函數(shù)。

      階躍函數(shù)

    ? ? ?

    ?

      sigmoid函數(shù):

    ?

      對于一個訓(xùn)練例(xk, yk),假設(shè)神經(jīng)網(wǎng)絡(luò)的輸出為 Yk ,則輸出可表示為:

        

    f(***)表示激活函數(shù),默認全部的激活函數(shù)都為sigmoid函數(shù)。

      則可以計算網(wǎng)絡(luò)上,(xk, yk)的均方差誤差為:

        

      乘以1/2是為了求導(dǎo)時能正好抵消掉常數(shù)系數(shù)。

      現(xiàn)在,從隱含層的第h個神經(jīng)元看,輸入層總共有 d 個權(quán)重傳遞參數(shù)傳給他,它又總共有 l 個權(quán)重傳遞參數(shù)傳給輸出層, 自身還有 1 個閾值。所以在我們這個神經(jīng)網(wǎng)絡(luò)中,一個隱含層神經(jīng)元有(d+l+1)個參數(shù)待確定。輸出層每個神經(jīng)元還有一個閾值,所以總共有 l 個閾值。最后,總共有(d+l+1)*q+l 個待定參數(shù)。

    首先,隨機給出這些待定的參數(shù),后面通過BP算法的迭代,這些參數(shù)的值會逐漸收斂于合適的值,那時,神經(jīng)網(wǎng)絡(luò)也就訓(xùn)練完成了。

      任意權(quán)重參數(shù)的更新公式為:

        

      下面以隱含層到輸出層的權(quán)重參數(shù) whj 為例說明:

      我們可以按照前面給出的公式求出均方差誤差 Ek ,期望其為0,或者為最小值。而BP算法基于梯度下降法(gradient descent)來求解最優(yōu)解,以目標的負梯度方向?qū)?shù)進行調(diào)整,通過多次迭代,新的權(quán)重參數(shù)會逐漸趨近于最優(yōu)解。對于誤差?Ek?,給定學(xué)習(xí)率(learning rate)即步長 η ,有:

        

      再看一下參數(shù)的傳遞方向,首先 whj 影響到了輸出層神經(jīng)元的輸入值?βj?,然后影響到輸出值 Yjk?,然后再影響到誤差 Ek ,所以可以列出如下關(guān)系式:

        

      根據(jù)輸出層神經(jīng)元的輸入值?βj?的定義:

        

      得到:

        

      對于激活函數(shù)(sigmoid函數(shù)):

        

      很容易通過求導(dǎo)證得下面的性質(zhì):

        

      使用這個性質(zhì)進行如下推導(dǎo):

      令:

        

      又由于:

        

      所以:

        ?

      由前面的定義有:

        

      所以:

        

      把這個結(jié)果結(jié)合前面的幾個式子代入:

        , ?, ?

      得到:

        

      所以:

        

    ?  OK,上面這個式子就是梯度了。通過不停地更新即梯度下降法就可實現(xiàn)權(quán)重更新了。

        

      推導(dǎo)到這里就結(jié)束了,再來解釋一下式子中各個元素的意義。

    ?    

      η 為學(xué)習(xí)率,即梯度下降的補償;為神經(jīng)網(wǎng)絡(luò)輸出層第 j 個神經(jīng)元的輸出值;為給出的訓(xùn)練例(xk, yk)的標志(label),即訓(xùn)練集給出的正確輸出;為隱含層第 h 個神經(jīng)元的輸出。

      

      類似可得:

        

      其中,

        

      這部分的解法與前面的推導(dǎo)方法類似,不做贅述。

    ?

    ?  接下來是代碼部分:

      這段代碼網(wǎng)上也有不少地方可以看到,后面會簡單介紹一下程序。

      完整程序:文件名“NN_Test.py”

    # _*_ coding: utf-8 _*_import numpy as npdef tanh(x):return np.tanh(x)def tanh_derivative(x):return 1 - np.tanh(x) * np.tanh(x)# sigmod函數(shù) def logistic(x):return 1 / (1 + np.exp(-x))# sigmod函數(shù)的導(dǎo)數(shù) def logistic_derivative(x):return logistic(x) * (1 - logistic(x))class NeuralNetwork:def __init__ (self, layers, activation = 'tanh'):if activation == 'logistic':self.activation = logisticself.activation_deriv = logistic_derivativeelif activation == 'tanh':self.activation = tanhself.activation_deriv = tanh_derivative# 隨機產(chǎn)生權(quán)重值self.weights = []for i in range(1, len(layers) - 1): # 不算輸入層,循環(huán)self.weights.append((2 * np.random.random( (layers[i-1] + 1, layers[i] + 1)) - 1) * 0.25 ) self.weights.append((2 * np.random.random( (layers[i] + 1, layers[i+1])) - 1) * 0.25 )#print self.weightsdef fit(self, x, y, learning_rate=0.2, epochs=10000):x = np.atleast_2d(x) temp = np.ones([x.shape[0], x.shape[1]+1])temp[:, 0:-1] = xx = tempy = np.array(y)for k in range(epochs): # 循環(huán)epochs次i = np.random.randint(x.shape[0]) # 隨機產(chǎn)生一個數(shù),對應(yīng)行號,即數(shù)據(jù)集編號 a = [x[i]] # 抽出這行的數(shù)據(jù)集# 迭代將輸出數(shù)據(jù)更新在a的最后一行for l in range(len(self.weights)):a.append(self.activation(np.dot(a[l], self.weights[l])))# 減去最后更新的數(shù)據(jù),得到誤差error = y[i] - a[-1]deltas = [error * self.activation_deriv(a[-1])]# 求梯度for l in range(len(a) - 2, 0, -1):deltas.append(deltas[-1].dot(self.weights[l].T) * self.activation_deriv(a[l]) )#反向排序 deltas.reverse() # 梯度下降法更新權(quán)值for i in range(len(self.weights)):layer = np.atleast_2d(a[i])delta = np.atleast_2d(deltas[i])self.weights[i] += learning_rate * layer.T.dot(delta)def predict(self, x):x = np.array(x)temp = np.ones(x.shape[0] + 1)temp[0:-1] = x a = tempfor l in range(0, len(self.weights)):a = self.activation(np.dot(a, self.weights[l]))return a

    簡要說明:

    def tanh(x):return np.tanh(x)def tanh_derivative(x):return 1 - np.tanh(x) * np.tanh(x)# sigmod函數(shù) def logistic(x):return 1 / (1 + np.exp(-x))# sigmod函數(shù)的導(dǎo)數(shù) def logistic_derivative(x):return logistic(x) * (1 - logistic(x))

    分別表示兩種激活函數(shù),tanh函數(shù)和sigmoid函數(shù)以及其的導(dǎo)數(shù),有關(guān)激活函數(shù)前文有提及。

    ?

    if activation == 'logistic':self.activation = logisticself.activation_deriv = logistic_derivativeelif activation == 'tanh':self.activation = tanhself.activation_deriv = tanh_derivative

    ?“activation”參數(shù)決定了激活函數(shù)的種類,是tanh函數(shù)還是sigmoid函數(shù)。

    ?

         self.weights = []for i in range(1, len(layers) - 1): # 不算輸入層,循環(huán)self.weights.append((2 * np.random.random( (layers[i-1] + 1, layers[i] + 1)) - 1) * 0.25 ) self.weights.append((2 * np.random.random( (layers[i] + 1, layers[i+1])) - 1) * 0.25 )#print self.weights

    以隱含層前后層計算產(chǎn)生權(quán)重參數(shù),參數(shù)初始時隨機,取值范圍是[-0.25, 0.25]

    ?

    x = np.atleast_2d(x) temp = np.ones([x.shape[0], x.shape[1]+1])temp[:, 0:-1] = xx = tempy = np.array(y)

    創(chuàng)建并初始化要使用的變量。

    ?

    for k in range(epochs): # 循環(huán)epochs次i = np.random.randint(x.shape[0]) # 隨機產(chǎn)生一個數(shù),對應(yīng)行號,即數(shù)據(jù)集編號 a = [x[i]] # 抽出這行的數(shù)據(jù)集# 迭代將輸出數(shù)據(jù)更新在a的最后一行for l in range(len(self.weights)):a.append(self.activation(np.dot(a[l], self.weights[l])))# 減去最后更新的數(shù)據(jù),得到誤差error = y[i] - a[-1]deltas = [error * self.activation_deriv(a[-1])]# 求梯度for l in range(len(a) - 2, 0, -1):deltas.append(deltas[-1].dot(self.weights[l].T) * self.activation_deriv(a[l]) )#反向排序 deltas.reverse() # 梯度下降法更新權(quán)值for i in range(len(self.weights)):layer = np.atleast_2d(a[i])delta = np.atleast_2d(deltas[i])self.weights[i] += learning_rate * layer.T.dot(delta)

    進行BP神經(jīng)網(wǎng)絡(luò)的訓(xùn)練的核心部分,在代碼中有相應(yīng)注釋。

    ?

    def predict(self, x):x = np.array(x)temp = np.ones(x.shape[0] + 1)temp[0:-1] = x a = tempfor l in range(0, len(self.weights)):a = self.activation(np.dot(a, self.weights[l]))return a

    這段是預(yù)測函數(shù),其實就是將測試集的數(shù)據(jù)輸入,然后正向走一遍訓(xùn)練好的網(wǎng)絡(luò)最后再返回預(yù)測結(jié)果。

    ?

    ?測試驗證函數(shù):

    # _*_ coding: utf-8 _*_from NN_Test import NeuralNetwork import numpy as npnn = NeuralNetwork([2, 2, 1], 'tanh') x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([0, 1, 1, 0]) nn.fit(x, y) for i in [[0, 0], [0, 1], [1, 0], [1, 1]]:print(i, nn.predict(i))

    程序中測試的是異或關(guān)系,下面是運行結(jié)果:

    ([0, 0], array([-0.01628435])) ([0, 1], array([ 0.99808061])) ([1, 0], array([ 0.99808725])) ([1, 1], array([-0.03867579]))

    顯然與標準異或關(guān)系近似。

    ?

      

    ?

    總結(jié)

    以上是生活随笔為你收集整理的机器学习入门学习笔记:(1)BP神经网络原理推导及程序实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。