python實現單隱層神經網絡基本模型

應朋友之請寫了一份python實現單隱層BP Ann model的code,很久沒寫博客,就順便發上來。這篇代碼比較乾淨利落,比較純粹的描述了Ann的基本原理,初學機器學習的同窗能夠參考。
python


模型中幾個比較重要的參數:數組

1.學習率網絡

學習率是影響模型收斂的重要因素,通常來講要根據具體場景靈活調整,太高的學習率會使得函數快速發散。app

2.隱元數量dom

通常來講,增長隱層中神經元的數量比直接增長隱層更加有效,這也是單隱層神經網絡的特色。對於複雜程度不算過高的問題而言,單隱層的效果優於多隱層。機器學習

3.隨機種子位數ide

代碼中增長了這一參數,來控制初始化鏈接權與閾值的精度。因爲神經網絡中初始權重與閾值是隨機生成的,那麼其隨機精度會對結果產生必定的影響。在輸入元、隱元的數量較多時,調整隨機精度會起到減少偏差的做用。函數


代碼中舉了一個很是簡單的訓練示例,筆者自擬了一個規則:學習

    輸入兩個變量,當變量A = 變量B時,返回類型1,矩陣化爲[1,0]。當變量A != 變量B時,返回類型2,矩陣化爲[0,1]。測試


讓神經網絡去學習這個simple的規則,並給出20條測試數據去驗證。最終使用了5000條訓練數據,就得到了100%的正確分類能力。


#---Author:伍思磊---
#---Mail:wusilei@1006.tv---
#---2015/7/27---

import random
import math

#---神經網絡Model---
class Ann:
    #構造函數 初始化模型參數
    def __init__(self, i_num, h_num, o_num):
        #可調參數
        self.learn_rate = 0.1    #學習率
        self.num_long = 2        #輸出結果位數
        self.random_long = 10    #隨機種子位數

        #輸入參數
        self.input_num = i_num   #輸入層 數量
        self.hidden_num = h_num  #隱層 數量
        self.output_num = o_num  #輸出層 數量

        #模型參數
        self.input = []          #輸入層
        self.hidden = []         #隱層
        self.output = []         #輸出層
        self.error = []          #偏差
        self.expectation = []    #指望
        self.weight_ih = self.__ini_weight(self.input_num, self.hidden_num)   #輸入層->隱層 鏈接權
        self.weight_ho = self.__ini_weight(self.hidden_num, self.output_num)  #隱層->輸出層 鏈接權
        self.threshold_h = self.__ini_threshold(self.hidden_num)              #隱層 閾值
        self.threshold_o = self.__ini_threshold(self.output_num)              #輸出層 閾值
        

    #初始鏈接權生成器
    def __ini_weight(self, x, y):
        result = []
        long = math.pow(10, self.random_long)
        for i in range(0, x, 1):
            res = []
            for j in range(0, y, 1):
                num = round(random.randint(-1*long,long)/long, self.random_long)
                res.insert(j, num)
            result.insert(i, res)
        return result

    #初始閾值生成器
    def __ini_threshold(self, n):
        result = []
        long = pow(10, self.random_long)
        for i in range(0, n, 1):
            num = round(random.randint(-1*long,long)/long, self.random_long)
            result.insert(i, num)
        return result

    #激勵函數 sigma
    def excitation(self, value):
        sigma = 1/(1+(math.exp(-1*value)))
        return sigma

    #輸入數據
    def input_param(self, data, expectation = []):
        self.input = []
        for value in data:
            self.input.append(value)
        if(expectation):
            self.expectation = []
            for value in expectation:
                self.expectation.append(value)

    #隱層計算
    def count_hidden(self):
        self.hidden = []
        for h in range(0, self.hidden_num, 1):
            Hval = 0
            for i in range(len(self.input)):
                Hval += self.input[i] * self.weight_ih[i][h]
            Hval = self.excitation(Hval+self.threshold_h[h])
            self.hidden.insert(h, Hval)

    #輸出層計算
    def count_output(self):
        self.output = []
        for o in range(0, self.output_num, 1):
            Oval = 0
            for h in range(len(self.hidden)):
                Oval += self.hidden[h] * self.weight_ho[h][o]
            Oval += self.threshold_o[o]
            Oval = round(Oval, self.num_long)
            self.output.insert(o, Oval)

    #偏差計算
    def count_error(self):
        self.error = []
        for key in range(len(self.output)):
            self.error.insert(key, self.expectation[key] - self.output[key])

    #鏈接權反饋訓練 輸入層->隱層
    def train_weight_ih(self):
        for i in range(len(self.weight_ih)):
            for h in range(len(self.weight_ih[i])):
                tmp = 0
                for o in range(0, self.output_num, 1):
                    tmp += self.weight_ho[h][o] * self.error[o]
                self.weight_ih[i][h] = self.weight_ih[i][h] + self.learn_rate * self.hidden[h] * (1 - self.hidden[h]) * self.input[i] * tmp
            

    #鏈接權反饋訓練 隱層->輸出層
    def train_weight_ho(self):
        for h in range(len(self.weight_ho)):
            for o in range(len(self.weight_ho[h])):
                self.weight_ho[h][o] = self.weight_ho[h][o] + self.learn_rate * self.hidden[h] * self.error[o]
                
    #閾值反饋訓練 隱層
    def train_threshold_h(self):
        for h in range(len(self.threshold_h)):
            tmp = 0
            for o in range(0, self.output_num, 1):
                tmp += self.weight_ho[h][o] * self.error[o]
            self.threshold_h[h] = self.threshold_h[h] + self.learn_rate * self.hidden[h] * (1 - self.hidden[h]) * tmp
            

    #閾值反饋訓練 輸出層
    def train_threshold_o(self):
        for o in range(len(self.threshold_o)):
            self.threshold_o[o] = self.threshold_o[o] + self.error[o]

    #反饋訓練
    def train(self):
        self.train_weight_ih()
        self.train_weight_ho()
        self.train_threshold_h()
        self.train_threshold_o()

    #歸一化函數
    def normal_num(self, max, min, data):
        data = (data - min)/(max - min)
        return data

    #尋找集合的最大值和最小值

#---業務部分(示例)---

#要訓練的規則,輸入兩個值,若是兩值相等返回[1,0],反之返回[0,1]
def testFunc(val):
    if(val[0] == val[1]):
        return [1,0]
    else:
        return [0,1]

#構造神經網絡模型
ann = Ann(2,3,2)

#生成訓練數據,隨機生成5000組[0,1][1,0][1,1][0,0]隨機數組
data = []
for i in range(0, 10000, 1):
    x = random.randint(0,1)
    y = random.randint(0,1)
    data.append([x,y])

#取得訓練數據中的最大值和最小值
for i in range(len(data)):
    for j in range(len(data[i])):
        if(i == 0 and j == 0):
            max = min = data[i][j]
        elif(data[i][j] > max):
            max = data[i][j]
        elif(data[i][j] < min):
            min = data[i][j]

#訓練數據歸一化
dataNormal = []
for i in range(len(data)):
    dataNormal.insert(i, [])
    for j in range(len(data[i])):
        dataNormal[i].append(ann.normal_num(max, min, data[i][j]))

#計算訓練數據指望值,並進行反饋訓練
for i in range(len(data)):
    #計算指望值
    exp = testFunc(data[i])
    #輸入訓練數據與指望
    ann.input_param(dataNormal[i], exp)
    #計算隱層
    ann.count_hidden()
    #計算輸出層
    ann.count_output()
    #計算偏差
    ann.count_error()
    #反饋訓練
    ann.train()

#生成測試數據,隨機生成20組
testdata = []
for i in range(0, 20, 1):
    x = random.randint(0,1)
    y = random.randint(0,1)
    testdata.append([x,y])

#進行測試,同時輸出神經網絡預測值與實際指望值
for i in range(len(testdata)):
    exp = testFunc(testdata[i])
    ann.input_param(testdata[i])
    ann.count_hidden()
    ann.count_output()
    print("Ann:")
    print(ann.output)
    print("Exp:")
    print(exp)
    print("\r")
相關文章
相關標籤/搜索