<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 如何在Python中從頭開始實現反向傳播算法 > 原文: [https://machinelearningmastery.com/implement-backpropagation-algorithm-scratch-python/](https://machinelearningmastery.com/implement-backpropagation-algorithm-scratch-python/) 反向傳播算法是經典的前饋人工神經網絡。 這種技術仍然用于訓練大型[深度學習](http://machinelearningmastery.com/what-is-deep-learning/)網絡。 在本教程中,您將了解如何使用Python從頭開始實現反向傳播算法。 完成本教程后,您將了解: * 如何向前傳播輸入以計算輸出。 * 如何反向傳播錯誤并訓練網絡。 * 如何將反向傳播算法應用于實際預測建模問題。 讓我們開始吧。 * **2016年11月更新**:修復了activate()函數中的錯誤。謝謝Alex! * **2017年1月更新**:將cross_validation_split()中的fold_size計算更改為始終為整數。修復了Python 3的問題。 * **2017年1月更新**:更新了update_weights()中的小錯誤。謝謝Tomasz! * **Update Apr / 2018** :添加了直接鏈接到CSV數據集。 * **更新Aug / 2018** :經過測試和更新,可與Python 3.6配合使用。 ![How to Implement the Backpropagation Algorithm From Scratch In Python](img/d97e39d3b77378dff36499a1877a9015.jpg) 如何在Python中從頭開始實現反向傳播算法 照片由 [NICHD](https://www.flickr.com/photos/nichd/21086425615/) ,保留一些權利。 ## 描述 本節簡要介紹了我們將在本教程中使用的反向傳播算法和小麥種子數據集。 ### 反向傳播算法 反向傳播算法是一種來自人工神經網絡領域的多層前饋網絡的監督學習方法。 前饋神經網絡受到一個或多個神經細胞(稱為神經元)的信息處理的啟發。神經元通過其樹突接受輸入信號,樹突將電信號傳遞到細胞體。軸突將信號傳遞給突觸,突觸是細胞軸突與其他細胞樹突的連接。 反向傳播方法的原理是通過修改輸入信號的內部權重來模擬給定函數,以產生預期的輸出信號。使用監督學習方法訓練系統,其中系統輸出和已知預期輸出之間的誤差被呈現給系統并用于修改其內部狀態。 從技術上講,反向傳播算法是一種在多層前饋神經網絡中訓練權重的方法。因此,它要求網絡結構由一個或多個層定義,其中一個層完全連接到下一層。標準網絡結構是一個輸入層,一個隱藏層和一個輸出層。 反向傳播可用于分類和回歸問題,但我們將重點關注本教程中的分類。 在分類問題中,當網絡在每個類值的輸出層中具有一個神經元時,實現最佳結果。例如,具有A和B類值的2類或二元分類問題。這些預期輸出必須轉換為二進制向量,每個類值具有一列。例如分別為A和B的[1,0]和[0,1]。這稱為一個熱編碼。 ### 小麥種子數據集 種子數據集涉及從不同品種的小麥給出測量種子的物種的預測。 有201條記錄和7個數字輸入變量。這是一個有3個輸出類的分類問題。每個數字輸入值的比例變化,因此可能需要一些數據標準化以用于加權輸入的算法,如反向傳播算法。 下面是數據集的前5行的示例。 ```py 15.26,14.84,0.871,5.763,3.312,2.221,5.22,1 14.88,14.57,0.8811,5.554,3.333,1.018,4.956,1 14.29,14.09,0.905,5.291,3.337,2.699,4.825,1 13.84,13.94,0.8955,5.324,3.379,2.259,4.805,1 16.14,14.99,0.9034,5.658,3.562,1.355,5.175,1 ``` 使用預測最常見類值的零規則算法,問題的基線準確度為28.095%。 您可以從 [UCI機器學習庫](http://archive.ics.uci.edu/ml/datasets/seeds)了解更多信息并下載種子數據集。 下載種子數據集并將其放入當前工作目錄,文件名為 **seeds_dataset.csv** 。 數據集采用制表符分隔格式,因此您必須使用文本編輯器或電子表格程序將其轉換為CSV。 更新,直接下載CSV格式的數據集: * [下載小麥種子數據集](https://raw.githubusercontent.com/jbrownlee/Datasets/master/wheat-seeds.csv) ## 教程 本教程分為6個部分: 1. 初始化網絡。 2. 向前傳播。 3. 返回傳播錯誤。 4. 訓練網絡。 5. 預測。 6. 種子數據集案例研究。 這些步驟將為您提供從頭開始實現反向傳播算法所需的基礎,并將其應用于您自己的預測建模問題。 ### 1.初始化網絡 讓我們從簡單的事情開始,創建一個可供訓練的新網絡。 每個神經元都有一組需要維持的權重。每個輸入連接一個重量和偏置的額外重量。我們需要在訓練期間為神經元存儲其他屬性,因此我們將使用字典來表示每個神經元并通過名稱存儲屬性,例如權重的'**權重**'。 網絡按層組織。輸入層實際上只是我們訓練數據集的一行。第一個真實層是隱藏層。接下來是輸出層,每個類值都有一個神經元。 我們將層組織為字典數組,并將整個網絡視為一個層數組。 最好將網絡權重初始化為小的隨機數。在這種情況下,我們將使用0到1范圍內的隨機數。 下面是一個名為 **initialize_network()**的函數,它創建了一個可供訓練的新神經網絡。它接受三個參數,輸入數量,隱藏層中的神經元數量和輸出數量。 您可以看到,對于隱藏層,我們創建 **n_hidden** 神經元,隱藏層中的每個神經元都有 **n_inputs + 1** 權重,一個用于數據集中的每個輸入列,另一個用于偏見。 您還可以看到連接到隱藏層的輸出層具有 **n_outputs** 神經元,每個神經元具有 **n_hidden + 1** 權重。這意味著輸出層中的每個神經元都連接到隱藏層中每個神經元(具有權重)。 ```py # Initialize a network def initialize_network(n_inputs, n_hidden, n_outputs): network = list() hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)] network.append(hidden_layer) output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)] network.append(output_layer) return network ``` 讓我們測試一下這個功能。下面是一個創建小型網絡的完整示例。 ```py from random import seed from random import random # Initialize a network def initialize_network(n_inputs, n_hidden, n_outputs): network = list() hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)] network.append(hidden_layer) output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)] network.append(output_layer) return network seed(1) network = initialize_network(2, 1, 2) for layer in network: print(layer) ``` 運行該示例,您可以看到代碼逐個打印出每個層。您可以看到隱藏層有一個具有2個輸入權重和偏差的神經元。輸出層有2個神經元,每個神經元有1個權重加上偏差。 ```py [{'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614]}] [{'weights': [0.2550690257394217, 0.49543508709194095]}, {'weights': [0.4494910647887381, 0.651592972722763]}] ``` 現在我們知道了如何創建和初始化網絡,讓我們看看如何使用它來計算輸出。 ### 2.前向傳播 我們可以通過在每層傳播輸入信號直到輸出層輸出其值來計算神經網絡的輸出。 我們將此稱為前向傳播。 我們需要在訓練期間生成需要糾正的預測技術,這是我們在訓練網絡以對新數據進行預測后需要的方法。 我們可以將傳播分解為三個部分: 1. 神經元激活。 2. 神經元轉移。 3. 前向傳播。 #### 2.1。神經元激活 第一步是計算給定輸入的一個神經元的激活。 輸入可以是我們的訓練數據集中的一行,如隱藏層的情況。在輸出層的情況下,它也可以是隱藏層中每個神經元的輸出。 神經元激活計算為輸入的加權和。很像線性回歸。 ```py activation = sum(weight_i * input_i) + bias ``` **權重**是網絡權重,**輸入**是輸入, **i** 是權重或輸入的指標,**偏差**是沒有輸入的特殊權重(或者你可以認為輸入總是為1.0)。 下面是一個名為 **activate()**的函數的實現。您可以看到該函數假定偏差是權重列表中的最后一個權重。這有助于此處以及稍后使代碼更易于閱讀。 ```py # Calculate neuron activation for an input def activate(weights, inputs): activation = weights[-1] for i in range(len(weights)-1): activation += weights[i] * inputs[i] return activation ``` 現在,讓我們看看如何使用神經元激活。 #### 2.2。神經元轉移 一旦神經元被激活,我們需要轉移激活以查看神經元輸出實際是什么。 可以使用不同的傳遞函數。傳統上使用 [sigmoid激活函數](https://en.wikipedia.org/wiki/Sigmoid_function),但您也可以使用tanh([雙曲正切](https://en.wikipedia.org/wiki/Hyperbolic_function))函數來傳輸輸出。最近,[整流器傳遞函數](https://en.wikipedia.org/wiki/Rectifier_(neural_networks))已經在大型深度學習網絡中流行。 S形激活函數看起來像S形,它也稱為邏輯函數。它可以取任何輸入值并在S曲線上產生0到1之間的數字。它也是一個函數,我們可以很容易地計算出反向傳播誤差后我們將需要的導數(斜率)。 我們可以使用sigmoid函數傳遞激活函數,如下所示: ```py output = 1 / (1 + e^(-activation)) ``` 其中 **e** 是自然對數的基數([歐拉數](https://en.wikipedia.org/wiki/E_(mathematical_constant)))。 下面是一個名為 **transfer()**的函數,它實現了sigmoid方程。 ```py # Transfer neuron activation def transfer(activation): return 1.0 / (1.0 + exp(-activation)) ``` 現在我們已經有了它們,讓我們看看它們是如何被使用的。 #### 2.3。前向傳播 向前傳播輸入很簡單。 我們通過網絡的每一層計算每個神經元的輸出。來自一層的所有輸出都成為下一層神經元的輸入。 下面是一個名為 **forward_propagate()**的函數,它使用我們的神經網絡實現數據集中一行數據的前向傳播。 您可以看到神經元的輸出值存儲在神經元中,名稱為“**輸出**”。您還可以看到我們收集名為 **new_inputs** 的數組中的層的輸出,該數組成為數組**輸入**,并用作后續層的輸入。 該函數返回最后一層的輸出,也稱為輸出層。 ```py # Forward propagate input to a network output def forward_propagate(network, row): inputs = row for layer in network: new_inputs = [] for neuron in layer: activation = activate(neuron['weights'], inputs) neuron['output'] = transfer(activation) new_inputs.append(neuron['output']) inputs = new_inputs return inputs ``` 讓我們將所有這些部分放在一起,測試我們網絡的前向傳播。 我們定義我們的網絡內聯一個隱藏的神經元,需要2個輸入值和一個帶有兩個神經元的輸出層。 ```py from math import exp # Calculate neuron activation for an input def activate(weights, inputs): activation = weights[-1] for i in range(len(weights)-1): activation += weights[i] * inputs[i] return activation # Transfer neuron activation def transfer(activation): return 1.0 / (1.0 + exp(-activation)) # Forward propagate input to a network output def forward_propagate(network, row): inputs = row for layer in network: new_inputs = [] for neuron in layer: activation = activate(neuron['weights'], inputs) neuron['output'] = transfer(activation) new_inputs.append(neuron['output']) inputs = new_inputs return inputs # test forward propagation network = [[{'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614]}], [{'weights': [0.2550690257394217, 0.49543508709194095]}, {'weights': [0.4494910647887381, 0.651592972722763]}]] row = [1, 0, None] output = forward_propagate(network, row) print(output) ``` 運行該示例會傳播輸入模式[1,0]并生成打印的輸出值。因為輸出層有兩個神經元,所以我們得到兩個數字的列表作為輸出。 實際輸出值現在只是無意義,但接下來,我們將開始學習如何使神經元中的權重更有用。 ```py [0.6629970129852887, 0.7253160725279748] ``` ### 3.返回傳播錯誤 反向傳播算法以訓練權重的方式命名。 在預期輸出和從網絡傳播的輸出之間計算誤差。然后,這些錯誤通過網絡從輸出層向后傳播到隱藏層,為錯誤分配責任并隨時更新權重。 反向傳播誤差的數學基礎是微積分,但我們將在本節中保持高水平,并關注計算的內容以及計算采用這種特定形式的方式而不是為什么。 這部分分為兩部分。 1. 轉移衍生品。 2. 錯誤反向傳播。 #### 3.1。轉移衍生品 給定神經元的輸出值,我們需要計算它的斜率。 我們使用sigmoid傳遞函數,其導數可以計算如下: ```py derivative = output * (1.0 - output) ``` 下面是一個名為 **transfer_derivative()**的函數,它實現了這個等式。 ```py # Calculate the derivative of an neuron output def transfer_derivative(output): return output * (1.0 - output) ``` 現在,讓我們看看如何使用它。 #### 3.2。錯誤反向傳播 第一步是計算每個輸出神經元的誤差,這將使我們的誤差信號(輸入)向后傳播通過網絡。 給定神經元的誤差可以如下計算: ```py error = (expected - output) * transfer_derivative(output) ``` **預期**是神經元的預期輸出值,**輸出**是神經元的輸出值, **transfer_derivative()**計算神經元輸出值的斜率,如上所示。 此錯誤計算用于輸出層中的神經元。期望值是類值本身。在隱藏層中,事情有點復雜。 隱藏層中神經元的誤差信號被計算為輸出層中每個神經元的加權誤差。想象一下錯誤沿輸出層的權重返回到隱藏層中的神經元。 累積反向傳播的誤差信號,然后用于確定隱藏層中神經元的誤差,如下所示: ```py error = (weight_k * error_j) * transfer_derivative(output) ``` **error_j** 是輸出層中 **j** 神經元的誤差信號, **weight_k** 是連接 **k** 神經元的權重到當前的神經元和輸出是當前神經元的輸出。 下面是一個名為 **backward_propagate_error()**的函數,它實現了這個過程。 您可以看到為每個神經元計算的誤差信號以名稱“delta”存儲。您可以看到網絡層以相反的順序迭代,從輸出開始并向后工作。這確保了輸出層中的神經元具有首先計算的“delta”值,隱藏層中的神經元可以在隨后的迭代中使用。我選擇名稱“delta”來反映錯誤對神經元的改變(例如,權重增量)。 您可以看到隱藏層中神經元的誤差信號是從輸出層中的神經元累積的,其中隱藏的神經元數 **j** 也是輸出層**神經元中神經元重量的指數[ '權重'] [j]** 。 ```py # Backpropagate error and store in neurons def backward_propagate_error(network, expected): for i in reversed(range(len(network))): layer = network[i] errors = list() if i != len(network)-1: for j in range(len(layer)): error = 0.0 for neuron in network[i + 1]: error += (neuron['weights'][j] * neuron['delta']) errors.append(error) else: for j in range(len(layer)): neuron = layer[j] errors.append(expected[j] - neuron['output']) for j in range(len(layer)): neuron = layer[j] neuron['delta'] = errors[j] * transfer_derivative(neuron['output']) ``` 讓我們將所有部分放在一起,看看它是如何工作的。 我們定義一個具有輸出值的固定神經網絡,并反向傳播預期的輸出模式。下面列出了完整的示例。 ```py # Calculate the derivative of an neuron output def transfer_derivative(output): return output * (1.0 - output) # Backpropagate error and store in neurons def backward_propagate_error(network, expected): for i in reversed(range(len(network))): layer = network[i] errors = list() if i != len(network)-1: for j in range(len(layer)): error = 0.0 for neuron in network[i + 1]: error += (neuron['weights'][j] * neuron['delta']) errors.append(error) else: for j in range(len(layer)): neuron = layer[j] errors.append(expected[j] - neuron['output']) for j in range(len(layer)): neuron = layer[j] neuron['delta'] = errors[j] * transfer_derivative(neuron['output']) # test backpropagation of error network = [[{'output': 0.7105668883115941, 'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614]}], [{'output': 0.6213859615555266, 'weights': [0.2550690257394217, 0.49543508709194095]}, {'output': 0.6573693455986976, 'weights': [0.4494910647887381, 0.651592972722763]}]] expected = [0, 1] backward_propagate_error(network, expected) for layer in network: print(layer) ``` 運行該示例在錯誤的反向傳播完成后打印網絡。您可以看到計算錯誤值并將其存儲在輸出層和隱藏層的神經元中。 ```py [{'output': 0.7105668883115941, 'weights': [0.13436424411240122, 0.8474337369372327, 0.763774618976614], 'delta': -0.0005348048046610517}] [{'output': 0.6213859615555266, 'weights': [0.2550690257394217, 0.49543508709194095], 'delta': -0.14619064683582808}, {'output': 0.6573693455986976, 'weights': [0.4494910647887381, 0.651592972722763], 'delta': 0.0771723774346327}] ``` 現在讓我們使用錯誤的反向傳播來訓練網絡。 ### 4.訓練網絡 使用隨機梯度下降訓練網絡。 這涉及將訓練數據集暴露給網絡以及向前傳播輸入的每行數據的多次迭代,反向傳播錯誤并更新網絡權重。 這部分分為兩部分: 1. 更新權重。 2. 訓練網絡。 #### 4.1。更新權重 一旦通過上述反向傳播方法計算網絡中每個神經元的誤差,就可以使用它們來更新權重。 網絡權重更新如下: ```py weight = weight + learning_rate * error * input ``` 當**權重**是給定權重時, **learning_rate** 是您必須指定的參數,**錯誤**是由神經元和**的反向傳播程序計算的誤差input** 是導致錯誤的輸入值。 除了沒有輸入項,或者輸入是1.0的固定值之外,可以使用相同的程序來更新偏差權重。 學習率控制改變重量以校正錯誤的程度。例如,值為0.1將更新可能更新量的10%的權重。較小的學習率是優選的,導致在大量訓練迭代中學習較慢。這增加了網絡在所有層上找到一組良好權重的可能性,而不是最小化誤差的最快權重集(稱為早熟收斂)。 下面是一個名為 **update_weights()**的函數,它在給定輸入數據行,學習率的情況下更新網絡的權重,并假設已經執行了前向和后向傳播。 請記住,輸出層的輸入是隱藏層的輸出集合。 ```py # Update network weights with error def update_weights(network, row, l_rate): for i in range(len(network)): inputs = row[:-1] if i != 0: inputs = [neuron['output'] for neuron in network[i - 1]] for neuron in network[i]: for j in range(len(inputs)): neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j] neuron['weights'][-1] += l_rate * neuron['delta'] ``` 現在我們知道如何更新網絡權重,讓我們看看我們如何重復這樣做。 #### 4.2。訓練網絡 如上所述,使用隨機梯度下降來更新網絡。 這涉及首先循環固定數量的時期并且在每個時期內更新訓練數據集中的每一行的網絡。 由于針對每種訓練模式進行了更新,因此這種類型的學習稱為在線學習。如果在更新權重之前在迭代中累積了錯誤,則稱為批量學習或批量梯度下降。 下面是一個函數,它利用給定的訓練數據集,學習率,固定的迭代數和預期的輸出值數來實現已經初始化的神經網絡的訓練。 預期的輸出值數量用于將訓練數據中的類值轉換為一個熱編碼。這是一個二進制向量,每個類值有一列,以匹配網絡的輸出。這是計算輸出層的誤差所必需的。 您還可以看到預期輸出和網絡輸出之間的總和平方誤差在每個時期累積并打印。這有助于創建網絡學習和改進每個時代的痕跡。 ```py # Train a network for a fixed number of epochs def train_network(network, train, l_rate, n_epoch, n_outputs): for epoch in range(n_epoch): sum_error = 0 for row in train: outputs = forward_propagate(network, row) expected = [0 for i in range(n_outputs)] expected[row[-1]] = 1 sum_error += sum([(expected[i]-outputs[i])**2 for i in range(len(expected))]) backward_propagate_error(network, expected) update_weights(network, row, l_rate) print('>epoch=%d, lrate=%.3f, error=%.3f' % (epoch, l_rate, sum_error)) ``` 我們現在擁有訓練網絡的所有部分。我們可以匯總一個示例,其中包括我們目前所見的所有內容,包括網絡初始化和在小型數據集上訓練網絡。 下面是一個小型人為的數據集,我們可以用它來測試我們的神經網絡的訓練。 ```py X1 X2 Y 2.7810836 2.550537003 0 1.465489372 2.362125076 0 3.396561688 4.400293529 0 1.38807019 1.850220317 0 3.06407232 3.005305973 0 7.627531214 2.759262235 1 5.332441248 2.088626775 1 6.922596716 1.77106367 1 8.675418651 -0.242068655 1 7.673756466 3.508563011 1 ``` 以下是完整的示例。我們將在隱藏層中使用2個神經元。這是一個二元分類問題(2個類),因此輸出層中將有兩個神經元。該網絡將被訓練20個時代,學習率為0.5,這很高,因為我們正在訓練如此少的迭代。 ```py from math import exp from random import seed from random import random # Initialize a network def initialize_network(n_inputs, n_hidden, n_outputs): network = list() hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)] network.append(hidden_layer) output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)] network.append(output_layer) return network # Calculate neuron activation for an input def activate(weights, inputs): activation = weights[-1] for i in range(len(weights)-1): activation += weights[i] * inputs[i] return activation # Transfer neuron activation def transfer(activation): return 1.0 / (1.0 + exp(-activation)) # Forward propagate input to a network output def forward_propagate(network, row): inputs = row for layer in network: new_inputs = [] for neuron in layer: activation = activate(neuron['weights'], inputs) neuron['output'] = transfer(activation) new_inputs.append(neuron['output']) inputs = new_inputs return inputs # Calculate the derivative of an neuron output def transfer_derivative(output): return output * (1.0 - output) # Backpropagate error and store in neurons def backward_propagate_error(network, expected): for i in reversed(range(len(network))): layer = network[i] errors = list() if i != len(network)-1: for j in range(len(layer)): error = 0.0 for neuron in network[i + 1]: error += (neuron['weights'][j] * neuron['delta']) errors.append(error) else: for j in range(len(layer)): neuron = layer[j] errors.append(expected[j] - neuron['output']) for j in range(len(layer)): neuron = layer[j] neuron['delta'] = errors[j] * transfer_derivative(neuron['output']) # Update network weights with error def update_weights(network, row, l_rate): for i in range(len(network)): inputs = row[:-1] if i != 0: inputs = [neuron['output'] for neuron in network[i - 1]] for neuron in network[i]: for j in range(len(inputs)): neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j] neuron['weights'][-1] += l_rate * neuron['delta'] # Train a network for a fixed number of epochs def train_network(network, train, l_rate, n_epoch, n_outputs): for epoch in range(n_epoch): sum_error = 0 for row in train: outputs = forward_propagate(network, row) expected = [0 for i in range(n_outputs)] expected[row[-1]] = 1 sum_error += sum([(expected[i]-outputs[i])**2 for i in range(len(expected))]) backward_propagate_error(network, expected) update_weights(network, row, l_rate) print('>epoch=%d, lrate=%.3f, error=%.3f' % (epoch, l_rate, sum_error)) # Test training backprop algorithm seed(1) dataset = [[2.7810836,2.550537003,0], [1.465489372,2.362125076,0], [3.396561688,4.400293529,0], [1.38807019,1.850220317,0], [3.06407232,3.005305973,0], [7.627531214,2.759262235,1], [5.332441248,2.088626775,1], [6.922596716,1.77106367,1], [8.675418651,-0.242068655,1], [7.673756466,3.508563011,1]] n_inputs = len(dataset[0]) - 1 n_outputs = len(set([row[-1] for row in dataset])) network = initialize_network(n_inputs, 2, n_outputs) train_network(network, dataset, 0.5, 20, n_outputs) for layer in network: print(layer) ``` 運行該示例首先打印每個訓練時期的總和平方誤差。我們可以看到這個錯誤的趨勢隨著每個時期而減少。 一旦經過訓練,就會打印網絡,顯示學習的重量。網絡中還有輸出和delta值,可以忽略。如果需要,我們可以更新我們的訓練功能以刪除這些數據。 ```py >epoch=0, lrate=0.500, error=6.350 >epoch=1, lrate=0.500, error=5.531 >epoch=2, lrate=0.500, error=5.221 >epoch=3, lrate=0.500, error=4.951 >epoch=4, lrate=0.500, error=4.519 >epoch=5, lrate=0.500, error=4.173 >epoch=6, lrate=0.500, error=3.835 >epoch=7, lrate=0.500, error=3.506 >epoch=8, lrate=0.500, error=3.192 >epoch=9, lrate=0.500, error=2.898 >epoch=10, lrate=0.500, error=2.626 >epoch=11, lrate=0.500, error=2.377 >epoch=12, lrate=0.500, error=2.153 >epoch=13, lrate=0.500, error=1.953 >epoch=14, lrate=0.500, error=1.774 >epoch=15, lrate=0.500, error=1.614 >epoch=16, lrate=0.500, error=1.472 >epoch=17, lrate=0.500, error=1.346 >epoch=18, lrate=0.500, error=1.233 >epoch=19, lrate=0.500, error=1.132 [{'weights': [-1.4688375095432327, 1.850887325439514, 1.0858178629550297], 'output': 0.029980305604426185, 'delta': -0.0059546604162323625}, {'weights': [0.37711098142462157, -0.0625909894552989, 0.2765123702642716], 'output': 0.9456229000211323, 'delta': 0.0026279652850863837}] [{'weights': [2.515394649397849, -0.3391927502445985, -0.9671565426390275], 'output': 0.23648794202357587, 'delta': -0.04270059278364587}, {'weights': [-2.5584149848484263, 1.0036422106209202, 0.42383086467582715], 'output': 0.7790535202438367, 'delta': 0.03803132596437354}] ``` 一旦網絡被訓練,我們需要使用它來進行預測。 ### 5.預測 使用訓練有素的神經網絡進行預測很容易。 我們已經看到了如何向前傳播輸入模式以獲得輸出。這就是我們做出預測所需要做的。我們可以直接使用輸出值本身作為屬于每個輸出類的模式的概率。 將此輸出轉換為清晰的類預測可能更有用。我們可以通過選擇具有更大概率的類值來做到這一點。這也稱為 [arg max函數](https://en.wikipedia.org/wiki/Arg_max)。 下面是一個名為 **predict()**的函數,它實現了這個過程。它返回網絡輸出中具有最大概率的索引。它假定類值已從0開始轉換為整數。 ```py # Make a prediction with a network def predict(network, row): outputs = forward_propagate(network, row) return outputs.index(max(outputs)) ``` 我們可以將它與上面的代碼一起用于前向傳播輸入,并使用我們的小型設計數據集來測試使用已經訓練過的網絡進行預測。該示例對從上一步驟訓練的網絡進行硬編碼。 下面列出了完整的示例。 ```py from math import exp # Calculate neuron activation for an input def activate(weights, inputs): activation = weights[-1] for i in range(len(weights)-1): activation += weights[i] * inputs[i] return activation # Transfer neuron activation def transfer(activation): return 1.0 / (1.0 + exp(-activation)) # Forward propagate input to a network output def forward_propagate(network, row): inputs = row for layer in network: new_inputs = [] for neuron in layer: activation = activate(neuron['weights'], inputs) neuron['output'] = transfer(activation) new_inputs.append(neuron['output']) inputs = new_inputs return inputs # Make a prediction with a network def predict(network, row): outputs = forward_propagate(network, row) return outputs.index(max(outputs)) # Test making predictions with the network dataset = [[2.7810836,2.550537003,0], [1.465489372,2.362125076,0], [3.396561688,4.400293529,0], [1.38807019,1.850220317,0], [3.06407232,3.005305973,0], [7.627531214,2.759262235,1], [5.332441248,2.088626775,1], [6.922596716,1.77106367,1], [8.675418651,-0.242068655,1], [7.673756466,3.508563011,1]] network = [[{'weights': [-1.482313569067226, 1.8308790073202204, 1.078381922048799]}, {'weights': [0.23244990332399884, 0.3621998343835864, 0.40289821191094327]}], [{'weights': [2.5001872433501404, 0.7887233511355132, -1.1026649757805829]}, {'weights': [-2.429350576245497, 0.8357651039198697, 1.0699217181280656]}]] for row in dataset: prediction = predict(network, row) print('Expected=%d, Got=%d' % (row[-1], prediction)) ``` 運行該示例將打印訓練數據集中每條記錄的預期輸出,然后是網絡進行的清晰預測。 它表明網絡在這個小數據集上達到了100%的準確率。 ```py Expected=0, Got=0 Expected=0, Got=0 Expected=0, Got=0 Expected=0, Got=0 Expected=0, Got=0 Expected=1, Got=1 Expected=1, Got=1 Expected=1, Got=1 Expected=1, Got=1 Expected=1, Got=1 ``` 現在我們準備將反向傳播算法應用于現實世界數據集。 ### 6.小麥種子數據集 本節將Backpropagation算法應用于小麥種子數據集。 第一步是加載數據集并將加載的數據轉換為我們可以在神經網絡中使用的數字。為此我們將使用輔助函數 **load_csv()**來加載文件, **str_column_to_float()**將字符串數轉換為浮點數, **str_column_to_int()**轉換??為class列到整數值。 輸入值的比例不同,需要歸一化到0和1的范圍。通常的做法是將輸入值標準化為所選傳遞函數的范圍,在這種情況下,輸出0到1之間的值的sigmoid函數。 **dataset_minmax()**和 **normalize_dataset()**輔助函數用于標準化輸入值。 我們將使用5倍折疊交叉驗證來評估算法。這意味著每個折疊中將有201/5 = 40.2或40個記錄。我們將使用輔助函數 **evaluate_algorithm()**來評估具有交叉驗證的算法和 **accuracy_metric()**來計算預測的準確性。 開發了一個名為 **back_propagation()**的新功能來管理反向傳播算法的應用,首先初始化網絡,在訓練數據集上訓練它,然后使用訓練好的網絡對測試數據集進行預測。 The complete example is listed below. ```py # Backprop on the Seeds Dataset from random import seed from random import randrange from random import random from csv import reader from math import exp # Load a CSV file def load_csv(filename): dataset = list() with open(filename, 'r') as file: csv_reader = reader(file) for row in csv_reader: if not row: continue dataset.append(row) return dataset # Convert string column to float def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) # Convert string column to integer def str_column_to_int(dataset, column): class_values = [row[column] for row in dataset] unique = set(class_values) lookup = dict() for i, value in enumerate(unique): lookup[value] = i for row in dataset: row[column] = lookup[row[column]] return lookup # Find the min and max values for each column def dataset_minmax(dataset): minmax = list() stats = [[min(column), max(column)] for column in zip(*dataset)] return stats # Rescale dataset columns to the range 0-1 def normalize_dataset(dataset, minmax): for row in dataset: for i in range(len(row)-1): row[i] = (row[i] - minmax[i][0]) / (minmax[i][1] - minmax[i][0]) # Split a dataset into k folds def cross_validation_split(dataset, n_folds): dataset_split = list() dataset_copy = list(dataset) fold_size = int(len(dataset) / n_folds) for i in range(n_folds): fold = list() while len(fold) < fold_size: index = randrange(len(dataset_copy)) fold.append(dataset_copy.pop(index)) dataset_split.append(fold) return dataset_split # Calculate accuracy percentage def accuracy_metric(actual, predicted): correct = 0 for i in range(len(actual)): if actual[i] == predicted[i]: correct += 1 return correct / float(len(actual)) * 100.0 # Evaluate an algorithm using a cross validation split def evaluate_algorithm(dataset, algorithm, n_folds, *args): folds = cross_validation_split(dataset, n_folds) scores = list() for fold in folds: train_set = list(folds) train_set.remove(fold) train_set = sum(train_set, []) test_set = list() for row in fold: row_copy = list(row) test_set.append(row_copy) row_copy[-1] = None predicted = algorithm(train_set, test_set, *args) actual = [row[-1] for row in fold] accuracy = accuracy_metric(actual, predicted) scores.append(accuracy) return scores # Calculate neuron activation for an input def activate(weights, inputs): activation = weights[-1] for i in range(len(weights)-1): activation += weights[i] * inputs[i] return activation # Transfer neuron activation def transfer(activation): return 1.0 / (1.0 + exp(-activation)) # Forward propagate input to a network output def forward_propagate(network, row): inputs = row for layer in network: new_inputs = [] for neuron in layer: activation = activate(neuron['weights'], inputs) neuron['output'] = transfer(activation) new_inputs.append(neuron['output']) inputs = new_inputs return inputs # Calculate the derivative of an neuron output def transfer_derivative(output): return output * (1.0 - output) # Backpropagate error and store in neurons def backward_propagate_error(network, expected): for i in reversed(range(len(network))): layer = network[i] errors = list() if i != len(network)-1: for j in range(len(layer)): error = 0.0 for neuron in network[i + 1]: error += (neuron['weights'][j] * neuron['delta']) errors.append(error) else: for j in range(len(layer)): neuron = layer[j] errors.append(expected[j] - neuron['output']) for j in range(len(layer)): neuron = layer[j] neuron['delta'] = errors[j] * transfer_derivative(neuron['output']) # Update network weights with error def update_weights(network, row, l_rate): for i in range(len(network)): inputs = row[:-1] if i != 0: inputs = [neuron['output'] for neuron in network[i - 1]] for neuron in network[i]: for j in range(len(inputs)): neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j] neuron['weights'][-1] += l_rate * neuron['delta'] # Train a network for a fixed number of epochs def train_network(network, train, l_rate, n_epoch, n_outputs): for epoch in range(n_epoch): for row in train: outputs = forward_propagate(network, row) expected = [0 for i in range(n_outputs)] expected[row[-1]] = 1 backward_propagate_error(network, expected) update_weights(network, row, l_rate) # Initialize a network def initialize_network(n_inputs, n_hidden, n_outputs): network = list() hidden_layer = [{'weights':[random() for i in range(n_inputs + 1)]} for i in range(n_hidden)] network.append(hidden_layer) output_layer = [{'weights':[random() for i in range(n_hidden + 1)]} for i in range(n_outputs)] network.append(output_layer) return network # Make a prediction with a network def predict(network, row): outputs = forward_propagate(network, row) return outputs.index(max(outputs)) # Backpropagation Algorithm With Stochastic Gradient Descent def back_propagation(train, test, l_rate, n_epoch, n_hidden): n_inputs = len(train[0]) - 1 n_outputs = len(set([row[-1] for row in train])) network = initialize_network(n_inputs, n_hidden, n_outputs) train_network(network, train, l_rate, n_epoch, n_outputs) predictions = list() for row in test: prediction = predict(network, row) predictions.append(prediction) return(predictions) # Test Backprop on Seeds dataset seed(1) # load and prepare data filename = 'seeds_dataset.csv' dataset = load_csv(filename) for i in range(len(dataset[0])-1): str_column_to_float(dataset, i) # convert class column to integers str_column_to_int(dataset, len(dataset[0])-1) # normalize input variables minmax = dataset_minmax(dataset) normalize_dataset(dataset, minmax) # evaluate algorithm n_folds = 5 l_rate = 0.3 n_epoch = 500 n_hidden = 5 scores = evaluate_algorithm(dataset, back_propagation, n_folds, l_rate, n_epoch, n_hidden) print('Scores: %s' % scores) print('Mean Accuracy: %.3f%%' % (sum(scores)/float(len(scores)))) ``` 構建了隱藏層中有5個神經元,輸出層中有3個神經元的網絡。該網絡訓練了500個時代,學習率為0.3。通過一些試驗和錯誤發現了這些參數,但您可以做得更好。 運行該示例打印每個折疊的平均分類準確度以及所有折疊的平均表現。 您可以看到反向傳播和所選配置實現了大約93%的平均分類精度,這明顯優于零精度算法,其精確度略高于28%。 ```py Scores: [92.85714285714286, 92.85714285714286, 97.61904761904762, 92.85714285714286, 90.47619047619048] Mean Accuracy: 93.333% ``` ## 擴展 本節列出了您可能希望探索的教程的擴展。 * **調諧算法參數**。嘗試更長或更短的訓練更大或更小的網絡。看看你是否可以在種子數據集上獲得更好的表現。 * **其他方法**。嘗試不同的權重初始化技術(如小隨機數)和不同的傳遞函數(如tanh)。 * **更多層**。添加對更多隱藏層的支持,其訓練方式與本教程中使用的一個隱藏層相同。 * **回歸**。更改網絡,使輸出層中只有一個神經元,并預測實際值。選擇回歸數據集進行練習。線性傳遞函數可以用于輸出層中的神經元,或者所選數據集的輸出值可以縮放到0和1之間的值。 * **批量梯度下降**。將訓練程序從在線更改為批量梯度下降,并僅在每個時期結束時更新權重。 **你有沒有試過這些擴展?** 在下面的評論中分享您的經驗。 ## 評論 在本教程中,您了解了如何從頭開始實現Backpropagation算法。 具體來說,你學到了: * 如何轉發傳播輸入以計算網絡輸出。 * 如何反向傳播錯誤并更新網絡權重。 * 如何將反向傳播算法應用于現實世界數據集。 **你有什么問題嗎?** 在下面的評論中提出您的問題,我會盡力回答。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看