Make your own neural network(Python神經網路編程)三

来源:https://www.cnblogs.com/powerzzjcode/archive/2018/11/10/9939781.html
-Advertisement-
Play Games

前兩篇代碼寫了初始化與查詢,知道了S函數,初始權重矩陣。以及神經網路的計算原理,總這一篇起就是最重要的神經網路的訓練了。 神經網路的訓練簡單點來講就是讓輸出的東西更加接近我們的預期。比如我們輸出的想要是1,但是輸出了-0.5,明顯不是 我們想要的。 誤差=(期望的數值)-(實際輸出),那麼我們的誤差 ...


前兩篇代碼寫了初始化與查詢,知道了S函數,初始權重矩陣。以及神經網路的計算原理,總這一篇起就是最重要的神經網路的訓練了。

神經網路的訓練簡單點來講就是讓輸出的東西更加接近我們的預期。比如我們輸出的想要是1,但是輸出了-0.5,明顯不是 我們想要的。

誤差=(期望的數值)-(實際輸出),那麼我們的誤差就是1.5。那麼我們需要縮小這個差距,就需要讓誤差的變化形成的函數的值最小。

專業點來講就是讓損失函數的導數為0。那麼首先我們需要知道我們的損失函數是一個什麼樣的函數。

第一個候選就是(目標-實際),非常簡單明瞭的,但是以此判斷網路誤差的時候,會出現誤差為零,正負誤差相抵消了。所以這個不好。

第二個候選的是  |目標-實際|,這意味著我們的可以無視符號,誤差不能相抵消,可是由於在最小值附近的時候是一個V字形,所以到不了最小的值,只能左右徘徊,也不太好

第三個候選的是 (目標-實際)^2,二次函數是平滑連續的,求導容易計算,越接近最小值斜率越小,方便調節步長。

誤差函數用來乾什麼呢?以後再講

綜上我們決定在這三個裡面選擇第三個損失函數,但是還有其他的複雜的又去的損失函數,可以自行探索。

現在我們知道我們的誤差了。那麼這個誤差來自哪裡呢?

如圖可以看到,我們的輸出誤差是由之前的數值和權重相乘導致的,那麼我們的誤差的來源應該是權重成正比的。

比如兩個節點權重分別是3.0與1.0,那麼我們輸出誤差的3/4應該分給權重大的節點,1/4分給權重小的節點。

然後我們把這個思想擴展到多個節點,如果我們隱藏層有100個節點,按照每條鏈接的權重的比例,相應分配輸出的誤差,

這個就是反向傳播,BP(back propagation)。

 

隱藏層第一個節點的誤差就是

我們假設輸出的誤差為0.8與0.5,重要的是計算過程,權重就隨機吧。

然後將這種反向傳播到更前面的層。

那麼我們就從最後的輸出一層一層,將前面所有的誤差全都算出來。

可是很明顯這種計算是十分費時費力的,這就有要用到我們的矩陣運算了。

首先是用輸出的誤差計算隱藏層的誤差

 

右邊的e1,e2就是輸出的誤差。權重比例矩陣點乘輸出的誤差,新矩陣就是隱藏層的每個節點的誤差的列矩陣了。

但是很明顯分母太礙事了。而帶上分母只是表示這一條鏈路的權重與相比於其他連在這個輸出節點的鏈路上的占比,

簡單一點的說法就是這個分母是用來標準化的。不看它,我們僅僅失去了後饋誤差的大小(這裡我沒理解,我困擾了好久,為什麼可以沒有)

我們可以用簡單容易的方法來辨認。

這和我們之前的權重矩陣與輸入矩陣相乘感覺很相似

正好就是我們正向計算時候的權重矩陣的轉置,也方便我們代碼的書寫

用簡潔的寫法寫出來就是

最後就是原代碼中train函數的一部分的撰寫。我們需要把我們的輸入以及正確的結果(用來計算誤差)來作為參數

前半部分和查詢函數一樣,就是計算給定輸入對應輸出的數值。然後反向計算各層各節點的誤差。

#訓練神經網路
    def train(self,inputs_list,targets_list): #給函數輸入列表以及正確的輸出列表
        inputs = np.array(inputs_list,ndmin=2).T   #輸入列表轉成array數組並轉置成列向量用來計算
        targets = np.array(targets_list,ndmin=2).T  #正確輸出的列表轉成array數組並轉置成列向量用來計算
         #計算隱藏層的輸入
        hidden_inputs = np.dot(self.wih,inputs)
        #計算隱藏層的輸出,代入S函數
        hidden_outputs = self.activation_function(hidden_inputs) 
        #計算輸出層的輸入
        final_inputs = np.dot(self.who,hidden_outputs)
        #計算輸出層的輸出,代入S函數
        final_outputs = self.activation_function(final_inputs)
        
        #誤差是(目標-實際)
        #(目標-實際)^2是誤差函數,用來減小誤差,而不是誤差本身
        output_errors = targets - final_outputs
        #隱藏層誤差
        hidden_errors = np.dot(self.who.T,output_errors) #權重函數轉置矩陣點乘乘以輸出誤差矩陣
        pass

可以看到我們辛辛苦苦講了這麼多的東西用,代碼倒是沒幾行。尤其是那個計算各個節點的誤差

只用了

#隱藏層誤差
        hidden_errors = numpy.dot(self.who.T,output_errors) #權重函數轉置矩陣點乘乘以輸出誤差矩陣

就完成了,這裡還是要特別說明一下,輸入層是沒有誤差的,輸入層只做輸入!

迄今為止所有的代碼

import numpy as np
import scipy.special

#神經網路類定義
class neuralNetwork:
    
    #初始化神經網路
    def __init__(self,inputnodes,hiddennodes,outputnodes,
                learningrate):
        #設置的是輸入層節點數,隱藏層節點數,輸出層節點數
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes
        
        #設置學習率
        self.lr = learningrate
        
        #初始化權重函數
        #初始化輸入層到隱藏層的權重矩陣
#       self.wih = np.random.rand(self.hnodes,self.inodes)-0.5  #-0.5為了能出現負數
#       #初始化隱藏層到輸出層的權重矩陣
#       self.who = np.random.rand(self.onodes,self.hnodes)-0.5
        
        #按照均值為0,標準方差為傳入鏈接數的根號的倒數的正態分佈的隨機取樣,獲得更好的初始化權重
        #初始化輸入層到隱藏層的權重矩陣
        self.wih = np.random.normal(0.0,pow(self.hnodes,-0.5),(self.hnodes,self.inodes))#pow就是標準方差的表示形式
        #初始化隱藏層到輸出層的權重矩陣
        self.who = np.random.normal(0.0,pow(self.onodes,-0.5),(self.onodes,self.hnodes))
        
         #設置激活函數
        self.activation_function = lambda x:scipy.special.expit(x)
        pass
    
    #訓練神經網路
    def train(self,inputs_list,targets_list): #給函數輸入列表以及正確的輸出列表
        inputs = np.array(inputs_list,ndmin=2).T   #輸入列表轉成array數組並轉置成列向量用來計算
        targets = np.array(targets_list,ndmin=2).T  #正確輸出的列表轉成array數組並轉置成列向量用來計算
         #計算隱藏層的輸入
        hidden_inputs = np.dot(self.wih,inputs)
        #計算隱藏層的輸出,代入S函數
        hidden_outputs = self.activation_function(hidden_inputs) 
        #計算輸出層的輸入
        final_inputs = np.dot(self.who,hidden_outputs)
        #計算輸出層的輸出,代入S函數
        final_outputs = self.activation_function(final_inputs)
        
        #誤差是(目標-實際)
        #(目標-實際)^2是誤差函數,用來減小誤差,而不是誤差本身
        output_errors = targets - final_outputs
        #隱藏層誤差
        hidden_errors = np.dot(self.who.T,output_errors) #權重函數轉置矩陣點乘乘以輸出誤差矩陣
        pass
    
    #查詢神經網路的結果
    def query(self,inputs_list):#需要傳入輸入列表
        inputs = np.array(inputs_list,ndmin=2).T    #將輸入列表編程numpy數組,轉置成列向量
        #計算隱藏層的輸入
        hidden_inputs = np.dot(self.wih,inputs)    #
        #計算隱藏層的輸出,代入S函數
        hidden_outputs = self.activation_function(hidden_inputs) 
        #計算輸出層的輸入
        final_inputs = np.dot(self.who,hidden_outputs)
        #計算輸出層的輸出,代入S函數
        final_outputs = self.activation_function(final_inputs)
        #返回最終結果
        return final_outputs
        pass

#輸入層節點數,隱藏層節點數,輸出層節點數
input_nodes = 3
hidden_nodes = 3
output_nodes = 3

#learning rate is 0.3
learning_rate = 0.3

#實例化神經網路
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes,
                 learning_rate)

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 之前寫過一篇閉包的使用(點擊此處進入),這次深入彙總下php中匿名函數的深入用法和理解: php中的匿名函數 也叫閉包函數 允許指定一個沒有名稱的函數。把匿名函數賦值給變數,通過變數來調用,舉個簡單的例子: 技巧1: 將匿名函數放在普通函數中,也可以將匿名函數返回,:這樣就構成了一個簡單的閉包 技巧 ...
  • 公司的項目沒那麼忙了,而且可能項目組很快要去深圳了! 自己的引擎方面去掉了一些不必要的層級,儘量輕量級,簡單架構,模擬著一個新人接觸怎樣能上手來重新整理了一下! 游戲方面增加了C++類之後寫代碼熟多了,但是整體上大部分還是在藍圖中,有一些函數什麼的還在摸索! 女朋友還是一樣的每周末都住一下,好像一下 ...
  • HashMap的put操作源碼解析 [toc] 1、官方文檔 1.1、繼承結構 1.2、類型參數: 2、put(key, value) HashMap是一種以鍵——值對的形式來存儲數據的數據結構。HashMap允許使用 null 值和 null 鍵,它並不能保證你存放數據和取出的順序是一致的。 接下 ...
  • 本文旨在用最通俗的語言講述最枯燥的基本知識 學過Java基礎的人都知道:值傳遞和引用傳遞是初次接觸Java時的一個難點,有時候記得了語法卻記不得怎麼實際運用,有時候會的了運用卻解釋不出原理,而且坊間討論的話題又是充滿爭議:有的論壇帖子說Java只有值傳遞,有的博客說兩者皆有;這讓人有點摸不著頭腦,下 ...
  • 1.Python變數 比C語言,Java語言更加簡潔,不需要加int等等類型定義,直接變數名 = 值,Python里甚至不需要分號。有些特定的不能當做變數名,變數只能由字母、數字和下劃線組成,下劃線可以放在開頭,甚至可以有很多(只是很少有人會這麼做),數字不能作為開頭。 2.Python註釋 # 代 ...
  • 一.hashMap與hashTable與ConcurrentHashMap: 1.HashMap是繼承自AbstractMap類,而HashTable是繼承自Dictionary類。不過它們都同時實現了map、Cloneable(可複製)、Serializable(可序列化)這三個介面。<Dicti ...
  • 話不多說,先乾再說..... 打開pycharm,創建一個關於flask的項目 2.創建一個App的文件包 3.把staic和templates文件包拖進App里 4.把app.py文件改為manager.py文件 5.這裡先停一下,點擊下方Terminal,把我們所需要第三方庫準備好分別是:pip ...
  • 表達式 lambda argument_list: expression argument_list 是參數列表,類似於函數中的參數列表,表現形式多種多樣: a, b a=1, b=2 *args **kwargs a, b=1, *args 空 ...... a, b a=1, b=2 *args ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...