傳送門(所有的實驗都使用python實作)
實驗1 BP神經網絡實驗
實驗2 som網實驗
實驗3 hopfield實作八皇後問題
實驗4 模糊搜尋算法預測薄冰厚度
實驗5 遺傳算法求解tsp問題
實驗6 蟻群算法求解tsp問題
實驗7 粒子群優化算法求解tsp問題
實驗8 分布估計算法求解背包問題
實驗9 模拟退火算法求解背包問題
實驗10 禁忌搜尋算法求解tsp問題
- 實驗目的
- 程式設計實作BP神經網絡算法;
- 探究BP算法中學習因子算法收斂趨勢、收斂速度之間的關系;
- 修改訓練後BP神經網絡部分連接配接權值,分析連接配接權值修改前和修改後對相同測試樣本測試結果,了解神經網絡分布存儲等特點。
- 實驗要求
按照下面的要求操作,然後分析不同操作後網絡輸出結果。
- 可修改學習因子
- 可任意指定隐單元層數
- 可任意指定輸入層、隐含層、輸出層的單元數
- 可指定最大允許誤差ε
- 可輸入學習樣本(增加樣本)
- 可存儲訓練後的網絡各神經元之間的連接配接權值矩陣;
- 修改訓練後的BP神經網絡部分連接配接權值,分析連接配接權值修改前和修改後對相同測試樣本測試結果 。
- 實驗原理
- 明确BP神經網絡算法的基本思想如下:
- 明确BP神經網絡算法步驟和流程如下:
四、實驗内容和分析
- 實驗時建立三層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。
- 訓練結果:

- 輸入測試樣本為
0.05 0.1
0.2 0.9
0.86 0.95
輸出測試結果為
成功通過了測試,說明訓練過程正确
1.改變學習因子
設定學習因子為0.6,學習因子越小結果越準确,但是也更耗時
2.改變輸入層、隐含層、輸出層的單元數
當隐含層節點個數為3時,相同訓練樣本和測試樣本,得到測試結果為
隐含層變多之後,網絡變複雜了,訓練次數增多,但是結果更加準确。
最大允許誤差ε控制網絡識别精度。
精度取的越小,最後結果更精确,代價是付出更多的時間進行疊代。
以上實驗誤差均為0.001,本次取誤差為0.0001,發現疊代次數上升,但是精度提高。
- 增加學習樣本
在基本實驗的基礎上,增加一個學習樣本0.1 1.0 1.0後
增加一個樣本以後,雖然速度變慢,但是結果精度大大提高。
2.改變部分連接配接權值
為了保證算法能迅速收斂,是以采用的是随機梯度下降法,而非梯度下降法,是以算法是無監督型的,故不推薦修改連接配接權值。
1.實驗過程:
由于BP算法的初始權重和門檻值的随機性(為了保證梯度下降法的随機性,這裡不使用固定的權重和門檻值,可以使實驗效果更好),是以實驗的收斂次數是分散的,我們采用多次實驗,取最小收斂次數作為依據。如圖1所示。
圖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])