天天看點

實驗1 BP神經網絡實驗

傳送門(所有的實驗都使用python實作)

​​實驗1 BP神經網絡實驗​​

​​實驗2 som網實驗​​

​​實驗3 hopfield實作八皇後問題​​

​​實驗4 模糊搜尋算法預測薄冰厚度​​

​​實驗5 遺傳算法求解tsp問題​​

​​實驗6 蟻群算法求解tsp問題​​

​​實驗7 粒子群優化算法求解tsp問題​​

​​實驗8 分布估計算法求解背包問題​​

​​實驗9 模拟退火算法求解背包問題​​

​​實驗10 禁忌搜尋算法求解tsp問題​​

  • 實驗目的
  1. 程式設計實作BP神經網絡算法;
  2. 探究BP算法中學習因子算法收斂趨勢、收斂速度之間的關系;
  3. 修改訓練後BP神經網絡部分連接配接權值,分析連接配接權值修改前和修改後對相同測試樣本測試結果,了解神經網絡分布存儲等特點。
  • 實驗要求

   按照下面的要求操作,然後分析不同操作後網絡輸出結果。

  1. 可修改學習因子
  2. 可任意指定隐單元層數
  3. 可任意指定輸入層、隐含層、輸出層的單元數
  4. 可指定最大允許誤差ε
  5. 可輸入學習樣本(增加樣本)
  6. 可存儲訓練後的網絡各神經元之間的連接配接權值矩陣;
  7. 修改訓練後的BP神經網絡部分連接配接權值,分析連接配接權值修改前和修改後對相同測試樣本測試結果 。
  • 實驗原理
  1. 明确BP神經網絡算法的基本思想如下:
  2. 明确BP神經網絡算法步驟和流程如下:

四、實驗内容和分析

  1. 實驗時建立三層BP神經網絡,輸入節點2個,隐含層節點2個,輸出節點1個,輸入訓練樣本如下表:

表1 輸入訓練樣本

輸入值 輸出
0.0 0.0 0.0
0.0 1.0 1.0
1.0 0.0 1.0
1.0 1.0 0.0
0.1 1.0 1.0

學習因子分别為0.9, 最大允許誤差0.001。

  1. 訓練結果:
實驗1 BP神經網絡實驗
  1. 輸入測試樣本為

0.05  0.1 

0.2   0.9 

0.86  0.95 

輸出測試結果為

實驗1 BP神經網絡實驗

成功通過了測試,說明訓練過程正确

1.改變學習因子

設定學習因子為0.6,學習因子越小結果越準确,但是也更耗時

實驗1 BP神經網絡實驗

2.改變輸入層、隐含層、輸出層的單元數

當隐含層節點個數為3時,相同訓練樣本和測試樣本,得到測試結果為

實驗1 BP神經網絡實驗

隐含層變多之後,網絡變複雜了,訓練次數增多,但是結果更加準确。

最大允許誤差ε控制網絡識别精度。

精度取的越小,最後結果更精确,代價是付出更多的時間進行疊代。

以上實驗誤差均為0.001,本次取誤差為0.0001,發現疊代次數上升,但是精度提高。

實驗1 BP神經網絡實驗
  1. 增加學習樣本

在基本實驗的基礎上,增加一個學習樣本0.1 1.0 1.0後

實驗1 BP神經網絡實驗

增加一個樣本以後,雖然速度變慢,但是結果精度大大提高。

2.改變部分連接配接權值

為了保證算法能迅速收斂,是以采用的是随機梯度下降法,而非梯度下降法,是以算法是無監督型的,故不推薦修改連接配接權值。

1.實驗過程:

由于BP算法的初始權重和門檻值的随機性(為了保證梯度下降法的随機性,這裡不使用固定的權重和門檻值,可以使實驗效果更好),是以實驗的收斂次數是分散的,我們采用多次實驗,取最小收斂次數作為依據。如圖1所示。

實驗1 BP神經網絡實驗
實驗1 BP神經網絡實驗

圖1 部分實驗過程

 實驗過程如圖1所示,多次執行算法,通過觀察其收斂次數和測試結果的效果來決定是否采集本次資料。

2.實驗結果:

本實驗中,樣本資料如表一所示,預設配置:最大疊代次數為10000,最大誤差為0.001,學習因子為0.5,動量為0.9。實驗結果在實驗内容部分給出。

# -*- coding: UTF-8 -*-
import random
import math
class bp:
    def init_w(self,w,x,y):#初始化偏置值
        for i in range(x):
            for j in range(y):
                w[i][j]=random.random()
                if(w[i][j]<0.5):w[i][j]=-w[i][j];
    def init_se(self,w,x):#初始化權值
        for i in range(x):
            w[i]=random.random()
            if(w[i]<0.5):
                w[i]=-w[i]
        
    def  forward(self,   inp,  outp,w, x, y, se):#向前傳播輸入
        for j in range(y):
            outp[j]=0
            for i in range(x):
                outp[j]+=inp[i]*w[i][j]
            outp[j] = outp[j]+se[j];
            outp[j] = (1.0)/(1+math.exp(-outp[j]))
    def  reforward(self):#反向誤差更新
        self.sumse = 0;
        #計算輸出層誤差
        for i in range(self.o_size):
            self.eo[i] = self.ouput[i] * (1.0-self.ouput[i]) * (self.ouputex[i]-self.ouput[i]);
            if(self.eo[i]<0.0):
                self.sumse -= self.eo[i];
            else:
                self.sumse += self.eo[i]
        #計算輸入層誤差  
        for i in range(self.h_size):
            self. eh[i] = 0;
            for j in range(self.o_size):
                self. eh[i]+= self.hidden[i] * (1-self.hidden[i]) * self.who[i][j] * self.eo[j];
    def  updatew(self):
        #更新隐含層與輸出層權值
        for i in range(self.h_size):
            for j in range(self.o_size):
                self.upwho[i][j]=(self.L*self.hidden[i]*self.eo[j])+(self.Mom*self.upwho[i][j])
                self.who[i][j]+=self.upwho[i][j]
        #更新輸入與隐含層權值
        for i in range(self.i_size):
            for j in range(self.h_size):
                self.upwih[i][j]=(self.L*self.input[i]*self.eh[j])+(self.Mom*self.upwih[i][j])
                self.wih[i][j]+=self.upwih[i][j]   
        #更新門檻值
    def  updatefa(self):
        for i in range(self.i_size):
            self.seh[i]+=self.L*self.eh[i]
        for i in range(self.o_size):
            self.seo[i]+=self.L*self.eo[i]
        #訓練函數
    def  train(self ,in1,out1):
        self.input=in1
        self.ouputex=out1
        self.forward(self.input, self.hidden, self.wih, self.i_size, self.h_size, self.seh)#向前傳播輸入
        self.forward(self.hidden, self.ouput, self.who, self.h_size, self.o_size, self.seo)
        self.reforward()#反向誤差傳播
        self.updatew()#更新網絡權重
        self.updatefa()#更新門檻值
    #測試函數
    def test(self,init1):
        self.input=init1
        self.forward(self.input, self.hidden, self.wih, self.i_size, self.h_size, self.seh)
        self.forward(self.hidden, self.ouput, self.who, self.h_size, self.o_size, self.seo)
        for i in range(self.o_size):
            print(self.ouput[i])
    #傳回門檻值
    def get_e(self,w,x):
        self.f=0
        for i in range(self.o_size):
            print(w[i],end="")
            self.f+=1
            if(self.f%2==0):
                print("")    
        print("")
    #傳回權值          
    def get_w(self,w,x,y):
        self.f=0;
        for i in range(x):
            for j in range(y):
                print(w[i][j],end="")
                print("     ",end="")
                self.f+=1
                if(self.f%2==0):
                    print("")         
    #類初始化                  
    def __init__(self,size,l,mom):

        self.L=l                        #學習因子                                                                                    
        self.Mom=mom;        #動量
        self.i_size=size[0];          #輸入層數量
        self.h_size=size[1];        #隐含層數量
        self.o_size=size[2];          #輸出層數量
        self.wih=[[0 for i in range(self.h_size)] for j in range(self.i_size)]    #輸入層與隐含層權值
        self.who=[[0 for i in range(self.o_size)] for j in range(self.h_size)]     #隐含層與輸出層權值
        self.upwih=[[0 for i in range(self.h_size)] for j in range(self.i_size)]    
        self.upwho=[[0 for i in range(self.o_size)] for j in range(self.h_size)]     # 動量更新
        self.input=[0 for i in range(self.i_size)]                      #輸入層  
        self.hidden=[0 for i in range(self.h_size)]                #隐含層
        self.ouput=[0 for i in range(self.o_size)]                   #輸出層
        self.ouputex=[0 for i in range(self.o_size)]                #期待輸出
        self.seh= [0 for i in range(self.h_size)]                       #隐含層偏置
        self.seo= [0 for i in range(self.o_size)]                       #輸出層偏置
        self.eh= [0 for i in range(self.h_size)]                       #隐含層誤差
        self.eo= [0 for i in range(self.o_size)]                       #輸出層誤差
        
        self. init_w(self.wih,self.i_size,self.h_size)          #初始化 輸入層到隐含層
        self. init_w(self.who,self.h_size,self.o_size)         #初始化 隐含層到輸出層.
         
        self.init_se(self.seh, self.h_size)#初始化隐含層的偏置
        self.init_se(self.seo, self.o_size)#初始化輸出層的偏置
    
           
         
size =[2,2,1]
inputData = [[0.0,0.0],[0.0,1.0],[1.0,0.0],[1.0,1.0],[0.1,1.0],[0.1,1.0]]
outputData = [[0.0],[1.0],[1.0],[0.0],[1.0],[1.0]]
testData = [[0.05,0.1],[0.2,0.9],[0.86,0.95]]


t=bp(size,0.5,0.9)

for i in range(10000):
    for j in range(6):
        t.train(inputData[j],outputData[j])
    if(t.sumse<0.001): 
        print("疊代次數:",i)
        break
    
print("誤差為:",t.sumse)  
print("輸入層與隐含層連接配接權值為:",end="")
t.get_w(t.wih,t.i_size,t.h_size)
print("隐含層與輸出層連接配接權值為:",end="")
t.get_w(t.who,t.h_size,t.o_size)
print("隐含層神經元門檻值為:",end="")
t.get_e(t.seh, t.h_size)
print("輸出層神經元門檻值為:",end="")
t.get_e(t.seo, t.o_size)
    
for i in range(3):
    print("訓練樣本為:",testData[i],"        結果為:",end="")
    t.test(testData[i])