Python 實現 BP 神經網絡

2021-02-21 Python那些事

(點擊上方公眾號,可快速關注一起學Python)

來源:溫夢月 

www.jianshu.com/p/4824a45fc87d#

一、多層前向神經網絡

多層前向神經網絡由三部分組成:輸出層、隱藏層、輸出層,每層由單元組成;

輸入層由訓練集的實例特徵向量傳入,經過連接結點的權重傳入下一層,前一層的輸出是下一層的輸入;隱藏層的個數是任意的,輸入層只有一層,輸出層也只有一層;

除去輸入層之外,隱藏層和輸出層的層數和為n,則該神經網絡稱為n層神經網絡,如下圖為2層的神經網絡;

一層中加權求和,根據非線性方程進行轉化輸出;理論上,如果有足夠多的隱藏層和足夠大的訓練集,可以模擬出任何方程;

二、設計神經網絡結構

使用神經網絡之前,必須要確定神經網絡的層數,以及每層單元的個數;

為了加速學習過程,特徵向量在傳入輸入層前,通常需要標準化到0和1之間;

離散型變量可以被編碼成每一個輸入單元對應一個特徵值可能賦的值;

比如:特徵值A可能取三個值(a0,a1,a2),那麼可以使用3個輸入單元來代表A:

如果A=a0,則代表a0的單元值取1,其餘取0;

如果A=a1,則代表a1的單元值取1,其餘取0;

如果A=a2,則代表a2的單元值取1,其餘取0;

神經網絡既解決分類(classification)問題,也可以解決回歸(regression)問題。對於分類問題,如果是兩類,則可以用一個輸出單元(0和1)分別表示兩類;如果多餘兩類,則每一個類別用一個輸出單元表示,所以輸出層的單元數量通常等一類別的數量。

沒有明確的規則來設計最佳個數的隱藏層,一般根據實驗測試誤差和準確率來改進實驗。

三、交叉驗證方法

如何計算準確率?最簡單的方法是通過一組訓練集和測試集,訓練集通過訓練得到模型,將測試集輸入模型得到測試結果,將測試結果和測試集的真實標籤進行比較,得到準確率。

在機器學習領域一個常用的方法是交叉驗證方法。一組數據不分成2份,可能分為10份,

第1次:第1份作為測試集,剩餘9份作為訓練集;

第2次:第2份作為測試集,剩餘9份作為訓練集;

……

這樣經過10次訓練,得到10組準確率,將這10組數據求平均值得到平均準確率的結果。這裡10是特例。一般意義上將數據分為k份,稱該算法為K-fold cross validation,即每一次選擇k份中的一份作為測試集,剩餘k-1份作為訓練集,重複k次,最終得到平均準確率,是一種比較科學準確的方法。

四、BP算法

通過迭代來處理訓練集中的實例;

對比經過神經網絡後預測值與真實值之間的差;

反方向(從輸出層=>隱藏層=>輸入層)來最小化誤差,來更新每個連接的權重;

4.1、算法詳細介紹

輸入:數據集、學習率、一個多層神經網絡構架;

輸出:一個訓練好的神經網絡;

初始化權重和偏向:隨機初始化在-1到1之間(或者其它),每個單元有一個偏向;對於每一個訓練實例X,執行以下步驟:

1、由輸入層向前傳送:

結合神經網絡示意圖進行分析:

由輸入層到隱藏層:

由隱藏層到輸出層:

兩個公式進行總結,可以得到:

Ij為當前層單元值,Oi為上一層的單元值,wij為兩層之間,連接兩個單元值的權重值,sitaj為每一層的偏向值。我們要對每一層的輸出進行非線性的轉換,示意圖如下:

當前層輸出為Ij,f為非線性轉化函數,又稱為激活函數,定義如下:

即每一層的輸出為:

這樣就可以通過輸入值正向得到每一層的輸出值。

2、根據誤差反向傳送 對於輸出層:其中Tk是真實值,Ok是預測值

對於隱藏層:

權重更新:其中l為學習率

偏向更新:

3、終止條件

偏重的更新低於某個閾值;

預測的錯誤率低於某個閾值;

達到預設一定的循環次數;

4、非線性轉化函數

上面提到的非線性轉化函數f,一般情況下可以用兩種函數:

(1)tanh(x)函數:

(2)邏輯函數,本文上面用的就是邏輯函數

五、BP神經網絡的python實現

需要先導入numpy模塊

import numpy as np

定義非線性轉化函數,由於還需要用到給函數的導數形式,因此一起定義

def tanh(x):
   return np.tanh(x)
def tanh_deriv(x):
   return 1.0 - np.tanh(x)*np.tanh(x)
def logistic(x):
   return 1/(1 + np.exp(-x))
def logistic_derivative(x):
   return logistic(x)*(1-logistic(x))

設計BP神經網絡的形式(幾層,每層多少單元個數),用到了面向對象,主要是選擇哪種非線性函數,以及初始化權重。layers是一個list,裡面包含每一層的單元個數。

class NeuralNetwork:
   def __init__(self, layers, activation='tanh'):
       """
       :param layers: A list containing the number of units in each layer.
       Should be at least two values
       :param activation: The activation function to be used. Can be
       "logistic" or "tanh"
       """
       if activation == 'logistic':
           self.activation = logistic
           self.activation_deriv = logistic_derivative
       elif activation == 'tanh':
           self.activation = tanh
           self.activation_deriv = tanh_deriv

       self.weights = []
       for i in range(1, len(layers) - 1):
           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)

實現算法

def 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] = X
   X = temp
   y = np.array(y)

   for k in range(epochs):
       i = np.random.randint(X.shape[0])
       a = [X[i]]

       for l in range(len(self.weights)):
           a.append(self.activation(np.dot(a[l], self.weights[l])))
       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()

       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 = temp
   for l in range(0, len(self.weights)):
       a = self.activation(np.dot(a, self.weights[l]))
   return a

我們給出一組數進行預測,我們上面的程序文件保存名稱為BP

from BP import NeuralNetwork
import numpy as np

nn = NeuralNetwork([2, 2, 2,1], 'tanh')
x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([1, 0, 0, 1])
nn.fit(x, y, 0.1, 10000)
for i in [[0, 0], [0, 1], [1, 0], [1, 1]]:
   print(i, nn.predict(i))

結果如下:

([0, 0], array([ 0.99142175]))

([0, 1], array([ 0.01544219]))

([1, 0], array([ 0.03699765]))

([1, 1], array([ 0.99547991]))

看完本文有收穫?請轉發分享給更多人

關注「Python那些事」,提升Python技能

相關焦點

  • 圖神經網絡-圖遊走算法核心代碼SkipGram、Node2Vec實現
    圖神經網絡-圖遊走算法核心代碼SkipGram、Node2Vec實現1.
  • Python項目實戰篇——常用驗證碼標註&識別(CNN神經網絡模型訓練/測試/部署)
    >Python項目實戰篇——常用驗證碼標註&識別(前端+後端實現高效率數據標註)這篇文章引入機器學習,給大家講解下基於該項目的CNN神經網絡模型訓練/測試/部署。二、背景知識    按照學習的好習慣,先搜索網上資源,再腦洞一下,先思考啥是神經網絡,啥是卷積,CNN神經網絡為啥能提取圖片特徵,這些問題筆者剛開始全部都遇到過,一臉蒙蔽有沒有。不要急,有問題有時候是好事,說明你知道自己那些不知道,等到自己了解和懂得多了,有些問題就迎刃而解。
  • 基於孿生神經網絡的人臉識別(1)——人臉檢測
    基於pytorch1.2+python3.6.
  • 用 Keras 編寫你的第一個人工神經網絡
    這便於直接用於需要數值輸入輸出的神經網絡, 適合我們第一個 Keras 神經網絡。下載數據集並且重命名為 pima-indians-diabetes.csv 放入 python 腳本所在的目錄的 data/pima-indians-diabetes.csv。你可以只直接使用 Numpy 庫的 loadtxt() 方法加載數據,一共 8 個輸出變量和 1 個輸出變量(最後一列)。
  • 收藏 | 用 Keras 實現神經網絡來解決梯度消失的問題
    在這篇文章中,我們將學習如何使用Keras創建一個自歸一化的深度前饋神經網絡。這將解決梯度不穩定的問題,加速訓練收斂,提高模型性能。背景在他們的2010年裡程碑論文中,Xavier gloriot和Yoshua Bengio提供了關於訓練深度神經網絡困難的寶貴見解。
  • 防止神經網絡模型過擬合的6種方法及keras代碼實現
    這些常見的模型比如卷積神經網絡、循環神經網絡、自編碼器等等。這種在訓練集上表現的好,在測試集上效果差,模型泛化能力弱,則是典型的過擬合問題。下面將結合實際介紹幾種解決過擬合的方法。我們就可以通過圖像平移、翻轉、縮放、切割等手段將資料庫成倍擴充;在神經網絡中,數據增強意味著增加數據規模,也就是增加數據集裡中圖像的數量。數據增強例子如下:
  • tensorflow中實現神經網絡訓練手寫數字數據集mnist
    tensorflow中實現神經網絡訓練手寫數字數據集mnist一:網絡結構基於tensorflow實現一個簡單的三層神經網絡,並使用它訓練mnist
  • 用Keras實現使用自歸一化神經網絡來解決梯度消失的問題
    在這篇文章中,我們將學習如何使用Keras創建一個自歸一化的深度前饋神經網絡。這將解決梯度不穩定的問題,加速訓練收斂,提高模型性能。背景在他們的2010年裡程碑論文中,Xavier gloriot和Yoshua Bengio提供了關於訓練深度神經網絡困難的寶貴見解。
  • 用 Keras 實現使用自歸一化神經網絡來解決梯度消失的問題
    在這篇文章中,我們將學習如何使用Keras創建一個自歸一化的深度前饋神經網絡。這將解決梯度不穩定的問題,加速訓練收斂,提高模型性能。背景在他們的2010年裡程碑論文中,Xavier gloriot和Yoshua Bengio提供了關於訓練深度神經網絡困難的寶貴見解。
  • 使用Python+OpenCV實現圖像數據採集
    conda create -n opencv python=3.6這將在Python版本3.6中創建一個名為opencv的新環境,可以用正在使用的任何版本替換它。pip install opencv-python用CV2拍照接下來,我們必須創建一個視頻捕獲實例。
  • 用 Python 實現溺水識別
    這裡整體程序的流程如下:百度姿態識別圖片並標註CNN網絡實現圖像分類根據分類結果可視化輸出結果最終輸出的程序效果如下圖:在我愛計算機視覺公眾號後臺回復"溺水識別",即可收到全部源碼和數據。一、實驗前的準備首先我們使用的python版本是3.6.5所用到的模塊如下:OpenCV:用來調用姿態識別接口繪製姿態識別結果Baidu-aip:用來加載人體分析模塊實現人體姿態識別configparser :配置文件模塊 讀寫配置文件
  • Python 必備 debug 神器:pdb
    目錄叨逼叨首先,介紹一下 pdb 調試,pdb 是 python 的一個內置模塊,用於命令行來調試 Python 代碼。
  • 運用python實現埠掃描
    前言最近在學習掃描器,web掃描器的內容,今天就分享一下python下的namp的埠掃描功能模塊的實現並在代碼中了解一下在
  • TF2.0初體驗-使用TF2.0 + Keras構建簡單的神經網絡
    今天體驗了一把,確實挺不錯的,那麼今天就手把手來教學如何通過TF2.0 + Keras構建一個簡單神經網絡。1、安裝TF2.0虛擬環境首先,我們要在電腦裡裝一個tf2.0的虛擬環境(我的電腦是mac,windows和linux類似)。這裡使用anaconda的命令:注意,後面的python版本最好帶上,否則什麼庫都不給你裝。
  • 學界 | 新型循環神經網絡IndRNN:可構建更長更深的RNN(附GitHub實現)
    同時本文還給出了 IndRNN 的 TensorFlow 實現,詳見文中 GitHub 連結。循環神經網絡 (RNN) [16] 已在動作識別 [8]、場景標註 [4] 、語言處理 [5] 等序列學習問題中獲得廣泛應用,並且成果顯著。與卷積神經網絡 ( CNN ) 等前饋網絡相比,RNN 具有循環連接,其中最後的隱藏狀態是到下一狀態的輸入。
  • 神經網絡在複雜系統建模中的應用
    基於深度神經網絡的隱馬爾可夫模型可將語音到詞語的轉換錯誤率從27.4%降低到18.5%。   在圖像處理領域中,利用深度學習的層次結構提取圖像的潛在複雜結構規則,然後利用神經網絡構建從視覺特徵到高層語義的映射模型,可實現視覺內容與高層語義之間的有效映射,獲取圖像的高層語義內容,有效解決基於視覺認知機理的圖像語義內容及圖像理解問題。
  • 神經網絡 | 在 Python中使用OpenCV檢測手勢
    帶標籤的手勢圖像VGG是Visual Geometry Group Network的縮寫,即視覺幾何群網絡。VGG-16預訓練的模型需要RGB的3通道圖像,但是上述手勢識別資料庫的圖像只有黑白兩色,這意味著 Numpy 數組只有一個通道,而不是三個通道(即每個數組的形狀是(224,224,1))。
  • 神經網絡簡介(上)
    這類機器學習的系統會自行確定需要注意哪些特徵,神經網絡就是這類系統的例子。神經網絡神經網絡是一種深度學習算法,可以說它是最常見的深度學習算法,有時候會用神經網絡來代表深度學習詞。神經網絡可以從輸入數據進行學習到哪些特徵比較重要。神經網絡模型裡最基本的構建塊就是神經元。
  • 2021年必火的圖神經網絡到底是什麼?
    )是一種基於圖結構的深度學習方法,從其定義中可以看出圖神經網絡主要由兩部分組成,即「圖」和「神經網絡」。1.2典型神經網絡典型的神經網絡結構有兩條主線,一條主線是卷積神經網絡,簡稱CNN,主要用於圖像類數據的處理。另一條主線是循環神經網絡,簡稱RNN,主要用於時序類數據的處理。由於神經網絡結構的介紹不是本篇的重點,因此在這裡不做重點介紹。
  • 深度學習中的正則化技術概述(附Python+keras實現代碼)
    注意:本文假設你具備神經網絡及其在keras中實現神經網絡結構的基本知識。如果沒有,你可以先參考下面的文章。使用Keras進行深度學習:(一)Keras 入門目錄什麼是正則化?類似地,dropout也比正常的神經網絡模型表現得更好。選擇丟棄節點的比率是dropout函數中的超參數。如上圖所示,dropout可以應用於隱藏層以及輸入層。