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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...