教AI做件簡單的事:從零開始構(gòu)建首個神經(jīng)網(wǎng)絡(luò)
本文轉(zhuǎn)載自公眾號“讀芯術(shù)”(ID:AI_Discovery)。
很長時間以來,我一直對構(gòu)建神經(jīng)網(wǎng)絡(luò)躍躍欲試,現(xiàn)在終于有機會來研究它了。我想我并沒有完全掌握神經(jīng)網(wǎng)絡(luò)背后的數(shù)學(xué)原理,所以先教人工智能做一些簡單的事情吧。
代碼原理
神經(jīng)網(wǎng)絡(luò)并不是一個新概念,1943年,由沃倫·麥卡洛克(WarrenMcCulloch)和沃爾特·皮茨(Walter Pitts)首次提出。
我們將構(gòu)建一個沒有隱藏層或感知器的單層神經(jīng)網(wǎng)絡(luò)。它由一個包含訓(xùn)練示例、突觸或權(quán)重以及神經(jīng)元的輸入層和一個含有正確答案的輸出層組成。神經(jīng)網(wǎng)絡(luò)圖形如下所示:
此外,需要了解一些如sigmoid和導(dǎo)數(shù)之類的數(shù)學(xué)概念,以清楚神經(jīng)元的學(xué)習(xí)方式。神經(jīng)元只需進行簡單操作,即取一個輸入值,乘以突觸權(quán)重。之后,對所有這些乘法結(jié)果求和,并使用sigmoid函數(shù)獲得0到1內(nèi)的輸出值。
神經(jīng)元表示:
Sigmoid函數(shù):
問題界定
輸入層上有數(shù)字序列。我們預(yù)期的理想結(jié)果是,在數(shù)據(jù)集樣本中,如果輸入第一個數(shù)字是1,則神經(jīng)網(wǎng)絡(luò)返回1;如果第一個數(shù)字是0,則返回0。結(jié)果在輸出層中顯示。問題集如下圖:
先決條件
開始編碼的前提——在概念上達到一定程度的理解。
NumPY安裝:
- pip install numpy
安裝成功,即可進入編碼部分。首先,將NumPy導(dǎo)入Python文件中:
- import numpy as np
訓(xùn)練神經(jīng)網(wǎng)絡(luò)
首先,創(chuàng)建一個sigmoid函數(shù):
其次,定義訓(xùn)練示例、輸入(4×5矩陣)和輸出:
接下來,通過生成隨機值來初始化突觸權(quán)重,并將結(jié)果排列在4×1的矩陣中:
最后,構(gòu)建訓(xùn)練模型。使用for循環(huán),所有的訓(xùn)練都將在此循環(huán)中進行。調(diào)用sigmoid函數(shù),并將所有輸入的總和乘以sigmoid權(quán)重。然后采用Np.dot進行矩陣乘法。過程如下圖:
輸出結(jié)果如下圖:
現(xiàn)在進行神經(jīng)網(wǎng)絡(luò)模型訓(xùn)練,方法是計算sigmoid函數(shù)的輸出和實際輸出之間的差值。之后可以根據(jù)誤差的嚴(yán)重性調(diào)整權(quán)重。多次重復(fù)這個過程,比如說一萬次。定義sigmoid導(dǎo)數(shù):
以下是計算和調(diào)整權(quán)重的方法:
開始學(xué)習(xí),觀察學(xué)習(xí)時長會如何影響結(jié)果。從100次迭代開始:
開始情況比較樂觀——我們的人工智能已經(jīng)學(xué)會了識別模式,但錯誤率仍然居高不下?,F(xiàn)在進行1000次迭代:
情況好轉(zhuǎn),繼續(xù)進行10000次迭代:
10萬次迭代:
我們可以繼續(xù)更多次的學(xué)習(xí)迭代,但永遠(yuǎn)無法達到100%的準(zhǔn)確性,因為這需要進行無限次的計算。但即使在最壞的情況下,準(zhǔn)確率也達到了99.77%,這相當(dāng)不錯。
對于最終代碼,我寫得很漂亮,并通過函數(shù)將其分開。除此之外,在文本文件中,我還添加了一種非常復(fù)雜方法以存儲權(quán)重。這樣只需進行一次學(xué)習(xí),而且需要使用AI時,只需導(dǎo)入權(quán)重并利用sigmoid函數(shù)即可。
- import numpy as np
- from tempfile import TemporaryFile
- def sigmoid(x):
- return 1 / (1 + np.exp(-x))
- def sigmoid_der(x):
- return x * (1 - x)
- def training():
- training_inputs = np.array([[0,0,1,0], [1,1,1,0], [1,0,1,0], [0,1,1,1], [0,1,0,1]])
- trainign_outputs = np.array([[0,1,1,0,0]]).T
- np.random.seed(1)
- synaptic_weights = 2 * np.random.random((4,1)) - 1
- for i in range(50000):
- inputs = training_inputs
- outputs = sigmoid(np.dot(inputs, synaptic_weights))
- error = trainign_outputs - outputs
- adjustments = error * sigmoid_der(outputs)
- synaptic_weights += np.dot(inputs.T, adjustments)
- data_file = open("data.txt", "w")
- for row in synaptic_weights:
- np.savetxt(data_file, row)
- data_file.close()
- def thinking(inputs):
- synaptic_weights = np.loadtxt("data.txt").reshape(4, 1)
- outputs = sigmoid(np.dot(inputs, synaptic_weights))
- print(outputs)
- return outputs
- training()
- thinking(np.array([1,1,0,1]))
圖源:Pixabay
我的第一個人工智能已經(jīng)準(zhǔn)備就緒,隨時可以投入生產(chǎn)。即使它只能在極小的數(shù)據(jù)集上識別非常簡單的模式,但現(xiàn)在我們可以擴展它,例如,嘗試教授人工智能識別圖片中的內(nèi)容。學(xué)無止境,精進不休!