上面我們說了神經網絡的基礎知識,根據上章的基礎嘗試搭建一個標准的3層神經網絡,參考https://www.cnblogs.com/bestExpert/p/9128645.html
1.框架代碼
1.>初始化函數 — 設定輸入層節點、隱藏層節點、輸出層節點的數量,設置學習率和各層的權重
2.>訓練 — 學習給定訓練集樣本后,優化權重
3.>查詢 — 給定輸入,從輸出節點給出答案
2.初始化網絡
在init函數里面增加節點、學習率的初始化
3.權重--網絡的核心
網路中最重要的部分是鏈接權重,我們使用這些權重來計算前饋信號、反向傳播誤差,並且在試圖改進網路時優化鏈接權重本身。可以使用矩陣簡明地表示權重,因為是三層結構,所以我們需要創建:
♦ 在輸入層與隱藏層之間的連接權重矩陣Winput_hidden,大小為hidden_nodes乘以input_nodes
♦ 在隱藏層與輸出層之間的連接權重矩陣Whidden_output,大小為output_nodes乘以hidden_nodes
我們使用 numpy.randon.rand(row,columns) 或者numpy.random.normal()生成權重
如下生成一個3*3大小,數值區間為±根號下hnodes的倒數
4.查詢網絡
query()函數接受神經網絡的輸入,返回網絡的輸出。需要傳遞來自輸入層節點的輸入信號,通過隱藏層,最后從輸出層輸出。當信號饋送至給定的隱藏層節點或輸出層節點時,我們使用鏈接權重調節信號,還應用S激活函數抑制來自這些節點的信號。
1.>定義輸入值為input_list,拆分成多維數組,利用python的nmpy.array(input_list,ndmin=2).T
2.>利用輸入矩陣點乘於鏈接權重計算出隱藏層輸出:Xhidden=Whidden_input * I ,在python中我們可以利用numpy.dot()來實現矩陣的點乘
3.>對輸出矩陣應用激活函數:Ohidden=sigmoid(Xhidden),在python中我們可以利用scipy.special.expit(x)
隱藏層到輸出層過程同上,整合之后代碼如下:
5.訓練網絡:目的是根據誤差優化權重
第一部分:針對給定的訓練樣本計算輸出,這與我們剛剛在query()函數上所做的沒什么區別
第二部分:將計算得到的輸出與所需輸出對比,使用差值來指導網絡權重的更新。
第一部分和上面的一樣,將不再細分,下來主要細分第二部分
1.>train()函數增加目標值列表參數,並轉換成多維數組,方式同input的轉換,在python中我們通過targets=numpy.array(target_input,ndmin=2).T
2.>計算輸出層誤差,為目標值減去輸出值,output_errors=target-final_output
3.>計算得到隱藏層誤差,errorhidden=weightThidden_output*erroroutput,在python中我們可以通過dot()方法計算矩陣點乘得到hidden_errors
4.>計算隱藏層到輸出層的權重變化量,根據公式ΔWJ,K = & * Ek * sigmoid( Ofinal_input) * (1 - sigmoid(Ofinal_input)) • OjT ,&為學習率,sigmoid為激活函數,Oj為輸出值的輸入矩陣
5.>計算輸入層到隱藏層的權重變化量,同上。
總結前面5步如下:
一個簡單的3層神經網絡就搭建完了,這些代碼可用於創建、訓練、查詢3層神經網絡,進行幾乎任何任務,下面我們將進行特定任務,學習識別手寫數字,上面的代碼合起來如下:
import numpy as np
import scipy.special as spc
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.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
self.who = np.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
self.activation_function = lambda x: spc.expit(x)
pass
def train(self, input_list, target_list):
inputs = np.array(input_list, ndmin=2).T
hidden_input = np.dot(self.wih, input)
hidden_output = self.activation_function(hidden_input)
final_input = np.dot(self.who, hidden_output)
final_output = self.activation_function(final_input)
targets = np.array(target_list, ndmin=2).T
output_error = targets - final_output
hidden_errors = np.dot(self.who.T, output_error)
self.who += self.lr * np.dot(output_error * final_output * (1.0 - final_output), np.transpose(hidden_output))
self.wih += self.lr * np.dot(hidden_errors * hidden_output * (1.0 - hidden_output), np.transpose(inputs))
pass
def query(self, input_list):
inputs = np.array(input_list, ndmin=2).T
hidden_input = np.dot(self.wih, inputs)
hidden_output = self.activation_function(hidden_input)
final_input = np.dot(self.who, hidden_output)
final_output = self.activation_function(final_input)
return final_output
也可以在github上面下載,里面有詳細的注釋:https://github.com/pythonAndAI/nerve-net/tree/master/threeLayerDome