大腦可與神經網絡相媲美。 這是通常用於幫助剛接觸該主題的人理解機器學習和人工神經網絡背後的想法的類比。
因為在幕後進行了幾層數學和統計計算,所以將這些網絡定義為數學函數是一種更高級的方法。
這是為那些真正對機器學習感興趣並想了解 Python 神經網絡代碼是如何編寫的人準備的。
在本文中,我們將演示如何從頭開始構建完全連接的深度神經網絡 (DNN) 蟒蛇 3.
我們的 Python 神經網絡代碼的文件結構概述
這裡將創建三個文件。 第一個是簡單的 nn.py 文件,將在“設置輔助函數”和“從頭開始構建神經網絡”中討論。
我們還將有一個名為 mnist loader.py 的文件來加載測試數據,如“加載 MNIST 數據”中所述。
最後,我們將有一個名為 test.py 的文件,它將在終端中啟動以測試我們的神經網絡。
該文件在“運行測試”中有詳細描述。
安裝過程
必須下載 NumPy Python 庫才能學習本教程。 您可以通過在終端上使用以下命令來完成此操作:
導入模塊並設置 Helper 功能
我們需要的僅有的兩個庫是 random 和 NumPy,我們將立即導入它們。 對於我們神經網絡的初始權重,我們將使用隨機庫對它們進行洗牌。
為了加快計算速度,我們將使用 NumPy 或 np(按照慣例,它通常作為 np 導入)。 我們的兩個輔助函數將在我們的導入之後生成。 兩個 sigmoid 函數:一個和 sigmoid prime。
邏輯回歸將使用 sigmoid 函數對數據進行分類,而反向傳播將使用 sigmoid 素數函數計算增量或梯度。
創建網絡類
構建一個完全鏈接的神經網絡是本節的唯一重點。 網絡類將包含後面的所有功能。 函數 Object() { [native code] } 最初將在我們的網絡類中創建。
函數 Object() { [native code] } 需要一個參數,sizes。 size 變量是一組數值,表示我們神經網絡的每一層中存在的輸入節點的數量。
我們在 __init__ 方法中初始化了四個屬性。 輸入變量sizes分別用於設置層大小列表和層數num層。
第一步是將我們網絡的初始偏差隨機分配給輸入層之後的每一層。
最後,輸入和輸出層之間的每個鏈接都有隨機生成的權重。 Np.Random.Randn() 給出從上下文的正態分佈中抽取的隨機樣本。
前饋功能
在神經網絡中,信息由前饋函數向前發送。 此函數將需要一個參數 a,表示當前激活向量。
該函數通過迭代網絡中的所有偏差和權重來估計每一層的激活。 給出的答案是預測,即最後一層的激活。
小批量梯度下降
我們網絡類的主力是梯度下降。 在這個版本中,我們使用小批量(隨機)梯度下降,梯度下降的一種修改變體。
這表明將使用一小批數據點來更新我們的模型。 四個必需參數和一個可選參數傳遞給此方法。 四個必需的變量是訓練數據集、時期數、小批量的大小和學習率 (eta)。
可根據要求提供測試數據。 當我們最終評估這個網絡時,我們將提供測試數據。 一旦訓練數據轉換為列表類型,此函數中的樣本數最初設置為列表的長度。
我們還將相同的過程應用於測試數據中給出的數據。這是因為它們不是作為列表返回給我們,而是實際上是列表的拉鍊。 當我們稍後加載 MNIST 數據樣本時,我們將了解更多相關信息。
如果我們可以確保將兩種類型的數據都作為列表提供,那麼這種類型轉換就不一定是必要的。
一旦我們有了數據,我們就會循環遍歷訓練階段。 一個訓練週期只是一輪神經網絡訓練。 在製作小批量列表之前,我們首先對每個 epoch 中的數據進行洗牌以確保隨機性。
將為每個小批量調用更新小批量函數,如下所述。 如果測試數據可用,也會返回測試準確度。
成本導數輔助函數
在我們真正創建反向傳播代碼之前,讓我們先開發一個稱為成本導數的輔助函數。 如果我們在輸出層出錯,成本導數函數會顯示出來。
它需要兩個輸入:輸出激活數組和預期輸出值的 y 坐標。
反向傳播函數
我們目前的激活向量,激活,以及任何其他激活向量,激活和 z 向量,zs,都必須牢記在心。 首先激活一個稱為輸入層的層。
在放置它們之後,我們將遍歷每個偏差和權重。 每個循環都涉及將 z 向量計算為權重和激活的點積,將其添加到 zs 列表中,重新計算激活,並將更新的激活添加到激活列表中。
最後,數學。 delta 等於前一層的誤差乘以 zs 向量的最後一個元素的 sigmoid 素數,在我們開始反向傳播之前計算。
nabla b 的最後一層設置為 delta,nabla w 的最後一層設置為 delta 和倒數第二層激活的點積(轉置以便我們可以實際進行數學運算) .
我們像以前一樣繼續,從第二層開始,到最後一層結束,並在完成最後一層之後重複該過程。 然後將 nablas 作為元組返回。
更新小批量梯度下降
我們之前的 SGD(隨機梯度下降)方法結合了小批量更新。 由於它在 SGD 中使用,但也需要反向傳播,所以我討論了將這個函數放在哪裡。
最後,我選擇把它貼在這裡。 它首先生成 0 個偏差和權重 nablas 的向量,就像我們的反向傳播函數一樣。
它需要 mini-batch 和 eta 學習率作為它的兩個輸入。 在 mini-batch 中,我們使用 backprop 函數來獲得每個 nabla 數組對於每個輸入 x 和輸出 y 的增量。 然後使用這些增量更新 nabla 列表。
最後,我們使用學習率和 nablas 來更新網絡的權重和偏差。 每個值都更新為最近的值,減去學習率,乘以 minibatch 大小,然後添加到 nabla 值。
評估功能
評估函數是我們需要編寫的最後一個函數。 測試數據是此功能的唯一輸入。 在此函數中,我們僅將網絡的輸出與預期結果 y 進行比較。 通過向前饋送輸入 x,網絡的輸出被確定。
完整的代碼
當我們組合所有代碼時,它就是這樣出現的。
測試神經網絡
加載 MNIST 數據
MNIST 數據 是 .pkl.gz 格式,我們將使用 GZIP 打開並使用 pickle 加載。 讓我們編寫一個快速方法來將此數據加載為大小為 XNUMX 的元組,分為訓練、驗證和測試數據。
為了使我們的數據更易於管理,我們將編寫另一個函數來將 y 編碼為 10 項數組。 除了與圖像的正確數字匹配的 0 之外,該數組將全為 1。
我們將使用基本加載數據和一種熱編碼方法將我們的數據加載為可讀格式。 將編寫另一個函數,將我們的 x 值轉換為大小為 784 的列表,與圖像的 784 像素匹配,並將我們的 y 值轉換為它們的單個熱編碼向量形式。
然後我們將組合 x 和 y 值,使一個索引與另一個索引匹配。 這適用於訓練、驗證和測試數據集。 然後我們返回更改後的數據。
運行測試
我們將創建一個名為“mnist loader”的新文件,它將在我們開始測試之前導入我們之前建立的神經網絡(simple nn)和 MNIST 數據集加載器。
在這個文件中,我們需要做的就是導入數據,構建一個輸入層大小為 784,輸出層大小為 10 的網絡,在訓練數據上運行網絡的 SGD 函數,然後使用測試數據對其進行測試。
請記住,對於我們的輸入層列表,784 和 10 之間的任何數字都沒有區別。我們可以隨意更改其他層; 只有輸入和輸出大小是固定的。
不需要三層; 我們可能會使用四個、五個甚至兩個。 盡情嘗試吧。
結論
在這裡,我們使用 Python 3 從頭開始創建神經網絡。 除了高級數學,我們還討論了實現的細節。
我們從實現輔助函數開始。 對於神經元的工作,sigmoid 和 sigmoid 素數函數是至關重要的。 然後我們將前饋函數付諸實踐,這是將數據輸入神經網絡的基本過程。
接下來,我們在 Python 中創建了梯度下降函數,這是驅動神經網絡的引擎。 為了找到“局部最小值”並優化其權重和偏差,我們的神經網絡使用梯度下降。 我們使用以下命令創建了反向傳播函數 梯度下降.
通過在輸出與正確標籤不匹配時提供更新,此功能使神經網絡能夠“學習”。
最後,我們把我們全新的 Python 神經網絡 使用 MNIST 數據集進行測試。 一切運行順利。
編碼愉快!
發表評論