【Python 初学者】从零开始构建自己的神经网络
此圖為使用神經網絡預測貓狗案例。
原創:CSDN/知乎:川川菜鳥
文章目錄
- 什么是神經網絡?
- 訓練神經網絡
- 前向傳播
- 損失函數
- 反向傳播
- 完整應用
- 提問
- 結束語
什么是神經網絡?
大多數神經網絡的介紹性文本在描述它們時都會提出大腦類比。在不深入研究大腦類比的情況下,我發現將神經網絡簡單地描述為將給定輸入映射到所需輸出的數學函數會更容易。
神經網絡由以下組件組成
- 輸入層x
- 任意數量的隱藏層
- 一個輸出層,?
- 每層W 和 b之間的一組權重和偏差
- 每個隱藏層的激活函數選擇 σ。在本教程中,我們將使用 Sigmoid 激活函數。
下圖顯示了 2 層神經網絡的架構(請注意,在計算神經網絡中的層數時,輸入層通常被排除在外)
在 Python 中創建神經網絡類很容易
class NeuralNetwork:def __init__(self, x, y):self.input = xself.weights1 = np.random.rand(self.input.shape[1],4) self.weights2 = np.random.rand(4,1) self.y = yself.output = np.zeros(y.shape)訓練神經網絡
一個簡單的 2 層神經網絡的輸出?是:
可能會注意到,在上面的等式中,權重W和偏差b是影響輸出? 的唯一變量。自然地,權重和偏差的正確值決定了預測的強度。從輸入數據微調權重和偏差的過程稱為訓練神經網絡。
訓練過程的每次迭代包括以下步驟:
- 計算預測輸出?,稱為前饋
- 更新權重和偏差,稱為反向傳播
下面的時序圖說明了這個過程
前向傳播
正如我們在上面的時序圖中看到的,前饋只是簡單的微積分,對于一個基本的 2 層神經網絡,神經網絡的輸出是:
讓我們在我們的 python 代碼中添加一個前饋函數來做到這一點。請注意,為簡單起見,我們假設偏差為 0。
然而,我們仍然需要一種方法來評估我們預測的“優度”,損失函數使我們能夠做到這一點。
損失函數
有許多可用的損失函數,我們問題的性質應該決定我們選擇的損失函數。在本教程中,我們將使用一個簡單的平方和誤差作為我們的損失函數。
也就是說,平方和誤差只是每個預測值與實際值之間的差值之和。差異被平方,以便我們測量差異的絕對值。
我們在訓練中的目標是找到最小化損失函數的最佳權重和偏差集。
反向傳播
現在我們已經測量了預測的誤差(損失),我們需要找到一種方法將誤差傳播回去,并更新我們的權重和偏差。
為了知道調整權重和偏差的適當數量,我們需要知道損失函數相對于權重和偏差的導數。 回想一下微積分,函數的導數就是函數的斜率。
如果我們有導數,我們可以簡單地通過增加/減少它來更新權重和偏差(參見上圖)。這被稱為梯度下降。
但是,我們不能直接計算損失函數對權重和偏差的導數,因為損失函數的方程不包含權重和偏差。因此,我們需要鏈式法則來幫助我們計算它。(計算損失函數相對于權重的導數的鏈式法則。請注意,為簡單起見,我們僅顯示了假定 1 層神經網絡的偏導數。)
可以看出損失函數相對于權重的導數(斜率),這樣我們就可以相應地調整權重。現在我們已經有了,讓我們將反向傳播函數添加到我們的 python 代碼中。
完整應用
完整代碼:
# coding=gbk """ 作者:川川 @時間 : 2022/11/23 15:36 """ import numpy as np import matplotlib.pyplot as plt# 激活函數 def sigmoid(x):return 1.0 / (1 + np.exp(-x))# def sigmoid_derivative(x):return x * (1.0 - x)# 計算損失函數 def compute_loss(y_hat, y):return ((y_hat - y)**2).sum()class NeuralNetwork:def __init__(self, x, y):self.input = x# 它為每個輸入創建 4 個介于 0 和 1 之間的隨機數self.weights1 = np.random.rand(self.input.shape[1], 4)self.weights2 = np.random.rand(4, 1)self.y = yself.output = np.zeros(self.y.shape)def feedforward(self):self.layer1 = sigmoid(np.dot(self.input, self.weights1))self.output = sigmoid(np.dot(self.layer1, self.weights2))def backprop(self):# application of the chain rule to find derivative of the loss function with respect to weights2 and weights1d_weights2 = np.dot(self.layer1.T, (2 * (self.y - self.output) * sigmoid_derivative(self.output)))d_weights1 = np.dot(self.input.T, (np.dot(2 * (self.y - self.output) * sigmoid_derivative(self.output),self.weights2.T) * sigmoid_derivative(self.layer1)))# update the weights with the derivative (slope) of the loss functionself.weights1 += d_weights1self.weights2 += d_weights2if __name__ == "__main__":X = np.array([[0, 0, 1],[0, 1, 1],[1, 0, 1],[1, 1, 1]])y = np.array([[0], [1], [1], [0]])nn = NeuralNetwork(X, y)loss_values = [] # 記錄loss列表for i in range(1500):nn.feedforward()nn.backprop()loss = compute_loss(nn.output, y) # 計算lossloss_values.append(loss)print(nn.output) # 輸出 print(f" final loss : {loss}") # 最終loss plt.plot(loss_values) # 可視化loss變化 plt.show()現在我們已經有了用于執行前饋和反向傳播的完整 python 代碼,讓我們將我們的神經網絡應用到一個示例中,看看它的效果如何。(對應上面代碼)
讓我們對神經網絡進行 1500 次迭代訓練,看看會發生什么。查看下面的每次迭代損失圖,我們可以清楚地看到損失單調遞減到最小值。這與我們之前討論的梯度下降算法是一致的。
讓我們看看 1500 次迭代后神經網絡的最終預測(輸出)
我們的前饋和反向傳播算法成功地訓練了神經網絡,并且預測收斂于真實值。請注意,預測值與實際值之間存在細微差異。這是可取的,因為它可以防止過度擬合并允許神經網絡更好地泛化到看不見的數據。
提問
- 除了 Sigmoid 函數,我們還可以使用什么激活函數?
- 如何訓練神經網絡時使用學習率?
- 如何使用卷積進行圖像分類任務?
結束語
從頭開始編寫自己的神經網絡學到了很多東西。 盡管 TensorFlow 和 Keras 等深度學習庫可以在不完全了解神經網絡內部工作原理的情況下輕松構建深度網絡,但我發現更深入地了解神經網絡是很有用的。
總結
以上是生活随笔為你收集整理的【Python 初学者】从零开始构建自己的神经网络的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Scheme语言学习---求解三个数中其
- 下一篇: python人脸识别代码_Python不