這是第一篇關於 ML 演化演算法課程的文章。
當你知道神經網路的參數,但不知道輸出應該是什麼時,就需要遺傳演算法,例如,這個演算法可以用來玩Google Dinosaur 或Flappy Bird,因為你不知道輸出應該是什麼,但您有能力對最可行的選項進行排序,例如按時間,稱為適應度函數。
我一直沒能找到這樣一個有效、簡單且可用的演算法,所以我開始創建自己的輕量級、簡單、完美運行的遺傳演算法。
我的目的不是拖拖拉拉地寫這篇文章,也不是用它的篇幅來折磨讀者,所以我們直接上程式碼吧。正如已經提到的,程式碼很簡單,所以大部分內容不需要在整篇文章中描述。
首先我們要導入模組:
import numpy as np import random
然後我們加入Dataset及其答案,但不使用反向傳播演算法,而只是簡單地統計正確答案的數量。然後你可以在其他變體上進行測試,這些變體現在已被註解掉
x = np.array([[1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 1, 1], [1, 1, 1]]) y = np.array([[0],[1],[1], [0], [0], [0], [0], [1], [1]]) #x = np.array([[0, 1, 1], [0, 0, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 0], [0, 0, 0], [1, 1, 0], [1, 1, 1]]) #y = np.array([[1],[0], [0], [1], [0], [1], [0], [1], [1]]) #x = np.array([[1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, 0], [1, 1, 0], [0, 1, 1], [1, 1, 1]]) #y = np.array([[1],[0],[1], [0], [1], [0], [1], [0], [1]])
新增列表和激活函數。這些清單的含義稍後將會變得清晰。第一個激活函數是 sigmoid,第二個是閾值。
listNet = [] NewNet = [] goodNET = [] GoodNet0 = [] GoodNet1 = [] GoodNet2 = [] GoodNet3 = [] GoodNet4 = [] GoodNet5 = [] GoodNet6 = [] good = 0 epoch = 0 good = 0 epoch = 0 def sigmoid(x): return 1/(1 + np.exp(-x)) def finfunc(x): if x[0] >= 0.5: x[0] = 1 return x[0] else: x[0] = 0 return x[0]
接下來,我們需要創建兩個類,第一個類用於創建初始群體,第二個類用於所有後續群體,因為第一次我們需要隨機創建權重,然後僅交叉和使它們變異。 init() 函數用於創建或添加權重,predict() 是演算法本身和計算最佳選項所必需的,Fredict() 函數的不同之處在於它返回答案和適應度函數來顯示數字在螢幕上查看訓練階段。在輸出層,首先使用 sigmoid 函數使答案更接近其中一個選項,然後才使用閾值函數。
class Network(): def __init__(self): self.H1 = np.random.randn(3, 6) self.O1 = np.random.randn(6, 1) def predict(self, x, y): t1 = x @ self.H1 t1 = sigmoid(t1) t2 = t1 @ self.O1 t2 = sigmoid(t2) t2 = finfunc(t2) if t2 == y[0]: global good good += 1 def Fpredict(self, x, y): t1 = x @ self.H1 t1 = sigmoid(t1) t2 = t1 @ self.O1 t2 = sigmoid(t2) t2 = finfunc(t2) if t2 == y[0]: global good good += 1 return t2, good class Network1(): def __init__(self, H1, O1): self.H1 = H1 self.O1 = O1 def predict(self, x, y): t1 = x @ self.H1 t1 = sigmoid(t1) t2 = t1 @ self.O1 t2 = sigmoid(t2) t2 = finfunc(t2) if t2 == y[0]: global good good += 1 def Fpredict(self, x, y): t1 = x @ self.H1 t1 = sigmoid(t1) t2 = t1 @ self.O1 t2 = sigmoid(t2) t2 = finfunc(t2) if t2 == y[0]: global good good += 1 return t2, good
我們輸出第一個答案和變數good,這是這裡的適應度函數,然後我們為下一個神經網路重置它,列印「wait0」(你可以在這裡寫任何你想要的東西)是必要的,以免對不同神經網路的答案從哪裡開始感到困惑。
import numpy as np import random
第一個週期過去了,在這裡以及隨後的所有周期中,我們只給了六個問題來檢查它如何處理任務,而它還沒有滿足,也就是說,我們檢查它是否臨時抱佛腳,這種情況有時會發生。現在讓我們更詳細地討論一下:根據它正確回答了多少個答案,我們將其分配給其中一個類,如果大量答案是正確的,那麼我們必須支持這樣的神經網絡並增加其數量,以便隨著隨後的變異將會出現更多更聰明的人,要理解這一點,你可以想像100個人中有一個天才,但這對每個人來說是不夠的,這意味著他的天才將在下一代中消失,這意味著神經網路要么學習速度非常慢,要么根本不存在,為了避免這種情況,我們增加了循環中具有大量正確答案的神經網路的數量。最後,我們清空主 listNet 列表,按照從最好到最差的順序為其分配 GoodNet 列表的新值,篩選出 100 個最佳個體,用於後續突變。
x = np.array([[1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 1, 1], [1, 1, 1]]) y = np.array([[0],[1],[1], [0], [0], [0], [0], [1], [1]]) #x = np.array([[0, 1, 1], [0, 0, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 0], [0, 0, 0], [1, 1, 0], [1, 1, 1]]) #y = np.array([[1],[0], [0], [1], [0], [1], [0], [1], [1]]) #x = np.array([[1, 1, 0], [0, 0, 1], [1, 0, 1], [0, 1, 0], [1, 0, 0], [0, 0, 0], [1, 1, 0], [0, 1, 1], [1, 1, 1]]) #y = np.array([[1],[0],[1], [0], [1], [0], [1], [0], [1]])
交叉和變異本身:我們從第一個親本中取出一部分,從第二個中取出第二部分,進行變異,然後我們在 NewNet 列表中得到一個孩子,所以 1000 次。
listNet = [] NewNet = [] goodNET = [] GoodNet0 = [] GoodNet1 = [] GoodNet2 = [] GoodNet3 = [] GoodNet4 = [] GoodNet5 = [] GoodNet6 = [] good = 0 epoch = 0 good = 0 epoch = 0 def sigmoid(x): return 1/(1 + np.exp(-x)) def finfunc(x): if x[0] >= 0.5: x[0] = 1 return x[0] else: x[0] = 0 return x[0]
從程式碼的前一部分開始,我們使用 Network1(),因為我們現在是交叉和變異,而不是隨機創建。所以我們需要重複1000 次(這是一個超參數,所以你可以自己選擇epoch 的數量,15 對我來說就足夠了),我們在第一個epoch 上顯示答案,第1000 個是最終版本(如果你有,例如,20,然後指定20)。這裡程式碼是重複的,所以我就不描述了,一切都很清楚了。
import numpy as np import random
這就是神經網路應該找到的模式,這就是最終版本所依賴的數字(第一,第二,第三)並忽略其餘的。例如,您可以執行邏輯運算(XOR、NOT、AND ...),僅在這種情況下,在網路類別中將輸入資料變更為2,我還遵循隱藏層中的神經元等於輸入的規則數據乘以二,它起作用了,但你可以嘗試你的選擇,向神經網路提供相同數量的一些答案和其他答案也很重要,以便正確答案的數量,例如“a”,將等於“b”,否則神經網路將回答所有答案同樣的方式,也就是說,如果有更多的a,那麼它會回答所有問題,但不會有任何結果,也在訓練樣本中給它完全不同的選項,以便它理解模式,例如,如果你一個XOR塊,那麼你必須添加一個帶有兩個1的選項,但是在邏輯運算的情況下,你必須給出所有選項,因為它們太少了,它不會理解任何東西。
就是這樣! ! !下一篇文章(必讀!):很快…
程式碼:https://github.com/LanskoyKirill/GenNumPy.git
我的網站(可能正在重新設計):selfrobotics.space
以上是使用 Python 和 NumPy 為神經網路創建簡單高效的遺傳演算法的詳細內容。更多資訊請關注PHP中文網其他相關文章!