python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)(二)
由于Rosenblatt感知器的局限性,對(duì)于非線性分類的效果不理想。為了對(duì)線性分類無(wú)法區(qū)分的數(shù)據(jù)進(jìn)行分類,需要構(gòu)建多層感知器結(jié)構(gòu)對(duì)數(shù)據(jù)進(jìn)行分類,多層感知器結(jié)構(gòu)如下:

該網(wǎng)絡(luò)由輸入層,隱藏層,和輸出層構(gòu)成,能表示種類繁多的非線性曲面,每一個(gè)隱藏層都有一個(gè)激活函數(shù),將該單元的輸入數(shù)據(jù)與權(quán)值相乘后得到的值(即誘導(dǎo)局部域)經(jīng)過激活函數(shù),激活函數(shù)的輸出值作為該單元的輸出,激活函數(shù)類似與硬限幅函數(shù),但硬限幅函數(shù)在閾值處是不可導(dǎo)的,而激活函數(shù)處處可導(dǎo)。本次程序中使用的激活函數(shù)是tanh函數(shù),公式如下:

tanh函數(shù)的圖像如下:

程序中具體的tanh函數(shù)形式如下:

就是神經(jīng)元j的誘導(dǎo)局部域
它的局部梯度分兩種情況:
(1)神經(jīng)元j沒有位于隱藏層:

(2)神經(jīng)元j位于隱藏層:

其中k是單元j后面相連的所有的單元。
局部梯度得到之后,根據(jù)增量梯度下降法的權(quán)值更新法則

即可得到下一次的權(quán)值w,經(jīng)過若干次迭代,設(shè)定誤差條件,即可找到權(quán)值空間的最小值。
python程序如下,為了能夠可視化,訓(xùn)練數(shù)據(jù)采用二維數(shù)據(jù),每一個(gè)隱藏層有8個(gè)節(jié)點(diǎn),設(shè)置了7個(gè)隱藏層,一個(gè)輸出層,輸出層有2個(gè)單元:
import numpy as np
import random
import copy
import matplotlib.pyplot as plt
#x和d樣本初始化
train_x = [[1,6],[3,12],[3,9],[3,21],[2,16],[3,15]]
d =[[1,0],[1,0],[0,1],[0,1],[1,0],[0,1]]
warray_txn=len(train_x[0])
warray_n=warray_txn*4
#基本參數(shù)初始化
oldmse=10**100
fh=1
maxtrycount=500
mycount=0.0
if maxtrycount>=20:
r=maxtrycount/5
else:
r=maxtrycount/2
#sigmoid函數(shù)
ann_sigfun=None
ann_delta_sigfun=None
#總層數(shù)初始化,比非線性導(dǎo)數(shù)多一層線性層
alllevel_count=warray_txn*4
# 非線性層數(shù)初始化
hidelevel_count=alllevel_count-1
#學(xué)習(xí)率參數(shù)
learn_r0=0.002
learn_r=learn_r0
#動(dòng)量參數(shù)
train_a0=learn_r0*1.2
train_a=train_a0
expect_e=0.05
#對(duì)輸入數(shù)據(jù)進(jìn)行預(yù)處理
ann_max=[]
for m_ani in xrange(0,warray_txn): #找出訓(xùn)練數(shù)據(jù)中每一項(xiàng)的最大值
temp_x=np.array(train_x)
ann_max.append(np.max(temp_x[:,m_ani]))
ann_max=np.array(ann_max)
def getnowsx(mysx,in_w):
'''''生成本次的擴(kuò)維輸入數(shù)據(jù) '''
'''''mysx==>輸入數(shù)據(jù),in_w==>權(quán)值矩陣,每一列為一個(gè)神經(jīng)元的權(quán)值向量'''
global warray_n
mysx=np.array(mysx)
x_end=[]
for i in xrange(0,warray_n):
x_end.append(np.dot(mysx,in_w[:,i]))
return x_end
def get_inlw(my_train_max,w_count,myin_x):
'''''找出權(quán)值矩陣均值接近0,輸出結(jié)果方差接近1的權(quán)值矩陣'''
#對(duì)隨機(jī)生成的多個(gè)權(quán)值進(jìn)行優(yōu)化選擇,選擇最優(yōu)的權(quán)值
global warray_txn
global warray_n
mylw=[]
y_in=[]
#生成測(cè)試權(quán)值
mylw=np.random.rand(w_count,warray_txn,warray_n)
for ii in xrange (0,warray_txn):
mylw[:,ii,:]=mylw[:,ii,:]*1/float(my_train_max[ii])-1/float(my_train_max[ii])*0.5
#計(jì)算輸出
for i in xrange(0,w_count):
y_in.append([])
for xj in xrange(0,len(myin_x)):
y_in[i].append(getnowsx(myin_x[xj],mylw[i]))
#計(jì)算均方差
mymin=10**5
mychoice=0
for i in xrange(0,w_count):
myvar=np.var(y_in[i])
if abs(myvar-1)<mymin:
mymin=abs(myvar-1)
mychoice=i
#返回?cái)?shù)據(jù)整理的權(quán)值矩陣
return mylw[mychoice]
mylnww=get_inlw(ann_max,300,train_x)
def get_inputx(mytrain_x,myin_w):
'''''將訓(xùn)練數(shù)據(jù)經(jīng)過權(quán)值矩陣,形成擴(kuò)維數(shù)據(jù)'''
end_trainx=[]
for i in xrange(0,len(mytrain_x)):
end_trainx.append(getnowsx(mytrain_x[i],myin_w))
return end_trainx
x=get_inputx(train_x,mylnww)#用于輸入的擴(kuò)維數(shù)據(jù)
#對(duì)測(cè)試數(shù)據(jù)進(jìn)行擴(kuò)維
def get_siminx(sim_x):
global mylnww
myxx=np.array(sim_x)
return get_inputx(myxx,mylnww)
#計(jì)算一層的初始化權(quán)值矩陣
def getlevelw(myin_x,wo_n,wi_n,w_count):
mylw=[]
y_in=[]
#生成測(cè)試權(quán)值
mylw=np.random.rand(w_count,wi_n,wo_n)
mylw=mylw*2.-1
#計(jì)算輸出
for i in xrange(0,w_count):
y_in.append([])
for xj in xrange(0,len(myin_x)):
x_end=[]
for myii in xrange(0,wo_n):
x_end.append(np.dot(myin_x[xj],mylw[i,:,myii]))
y_in[i].append(x_end)
#計(jì)算均方差
mymin=10**3
mychoice=0
for i in xrange(0,w_count):
myvar=np.var(y_in[i])
if abs(myvar-1)<mymin:
mymin=abs(myvar-1)
mychoice=i
#返回?cái)?shù)據(jù)整理的權(quán)值矩陣
csmylw=mylw[mychoice]
return csmylw,y_in[mychoice]
ann_w=[]
def init_annw():
global x
global hidelevel_count
global warray_n
global d
global ann_w
ann_w=[]
lwyii=np.array(x)
#初始化每層的w矩陣
for myn in xrange(0,hidelevel_count):
#層數(shù)
ann_w.append([])
if myn==hidelevel_count-1:
for iii in xrange(0,warray_n):
ann_w[myn].append([])
for jjj in xrange(0,warray_n):
ann_w[myn][iii].append(0.0)
elif myn==hidelevel_count-2:
templw,lwyii=getlevelw(lwyii,len(d[0]),warray_n,200)
for xii in xrange(0,warray_n):
ann_w[myn].append([])
for xjj in xrange(0,len(d[0])):
ann_w[myn][xii].append(templw[xii,xjj])
for xjj in xrange(len(d[0]),warray_n):
ann_w[myn][xii].append(0.0)
else:
templw,lwyii=getlevelw(lwyii,warray_n,warray_n,200)
for xii in xrange(0,warray_n):
ann_w[myn].append([])
for xjj in xrange(0,warray_n):
ann_w[myn][xii].append(templw[xii,xjj])
ann_w=np.array(ann_w)
def generate_lw(trycount):
global ann_w
print u"產(chǎn)生權(quán)值初始矩陣",
meanmin=1
myann_w=ann_w
alltry=30
tryc=0
while tryc<alltry:
for i_i in range(trycount):
print ".",
init_annw()
if abs(np.mean(np.array(ann_w)))<meanmin:
meanmin=abs(np.mean(np.array(ann_w)))
myann_w=ann_w
tryc+=1
if abs(np.mean(np.array(myann_w)))<0.008:break
ann_w=myann_w
print
print u"權(quán)值矩陣平均:%f"%(np.mean(np.array(ann_w)))
print u"權(quán)值矩陣方差:%f"%(np.var(np.array(ann_w)))
generate_lw(15)
#前次訓(xùn)練的權(quán)值矩陣
ann_oldw=copy.deepcopy(ann_w)
#梯度初始化
#輸入層即第一層隱藏層不需要,所以第一層的空間無(wú)用
ann_delta=[]
for i in xrange(0,hidelevel_count):
ann_delta.append([])
for j in xrange(0,warray_n):
ann_delta[i].append(0.0)
ann_delta=np.array(ann_delta)
#輸出矩陣yi初始化
ann_yi=[]
for i in xrange(0,alllevel_count):
#第一維是層數(shù),從0開始
ann_yi.append([])
for j in xrange(0,warray_n):
#第二維是神經(jīng)元
ann_yi[i].append(0.0)
ann_yi=np.array(ann_yi)
#輸出層函數(shù)
def o_func(myy):
myresult=[]
mymean=np.mean(myy)
for i in xrange(0,len(myy)):
if myy[i]>=mymean:
myresult.append(1.0)
else:
myresult.append(0.0)
return np.array(myresult)
def get_e(myd,myo):
return np.array(myd-myo)
def ann_atanh(myv):
atanh_a=1.7159#>0
atanh_b=2/float(3)#>0
temp_rs=atanh_a*np.tanh(atanh_b*myv)
return temp_rs
def ann_delta_atanh(myy,myd,nowlevel,level,n,mydelta,myw):
anndelta=[]
atanh_a=1.7159#>0
atanh_b=2/float(3)#>0
if nowlevel==level:
#輸出層
anndelta=(float(atanh_b)/atanh_a)*(myd-myy)*(atanh_a-myy)*(atanh_a+myy)
else:
#隱藏層
anndelta=(float(atanh_b)/atanh_a)*(atanh_a-myy)*(atanh_a+myy)
temp_rs=[]
for j in xrange(0,n):
temp_rs.append(sum(myw[j]*mydelta))
anndelta=anndelta*temp_rs
return anndelta
def sample_train(myx,myd,n,sigmoid_func,delta_sigfun):
'''''一個(gè)樣本的前向和后向計(jì)算'''
global ann_yi
global ann_delta
global ann_w
global ann_wj0
global ann_y0
global hidelevel_count
global alllevel_count
global learn_r
global train_a
global ann_oldw
level=hidelevel_count
allevel=alllevel_count
#清空yi輸出信號(hào)數(shù)組
hidelevel=hidelevel_count
alllevel=alllevel_count
for i in xrange(0,alllevel):
#第一維是層數(shù),從0開始
for j in xrange(0,n):
#第二維是神經(jīng)元
ann_yi[i][j]=0.0
ann_yi=np.array(ann_yi)
yi=ann_yi
#清空delta矩陣
for i in xrange(0,hidelevel-1):
for j in xrange(0,n):
ann_delta[i][j]=0.0
delta=ann_delta
#保留W的拷貝,以便下一次迭代
ann_oldw=copy.deepcopy(ann_w)
oldw=ann_oldw
#前向計(jì)算
#對(duì)輸入變量進(jìn)行預(yù)處理
myo=np.array([])
for nowlevel in xrange(0,alllevel):
#一層層向前計(jì)算
#計(jì)算誘導(dǎo)局部域
my_y=[]
myy=yi[nowlevel-1]
myw=ann_w[nowlevel-1]
if nowlevel==0:
#第一層隱藏層
my_y=myx
yi[nowlevel]=my_y
elif nowlevel==(alllevel-1):
#輸出層
my_y=o_func(yi[nowlevel-1,:len(myd)])
yi[nowlevel,:len(myd)]=my_y
elif nowlevel==(hidelevel-1):
#最后一層輸出層
for i in xrange(0,len(myd)):
temp_y=sigmoid_func(np.dot(myw[:,i],myy))
my_y.append(temp_y)
yi[nowlevel,:len(myd)]=my_y
else:
#中間隱藏層
for i in xrange(0,len(myy)):
temp_y=sigmoid_func(np.dot(myw[:,i],myy))
my_y.append(temp_y)
yi[nowlevel]=my_y
#計(jì)算誤差與均方誤差
myo=yi[hidelevel-1][:len(myd)]
myo_end=yi[alllevel-1][:len(myd)]
mymse=get_e(myd,myo_end)
#反向計(jì)算
#輸入層不需要計(jì)算delta,輸出層不需要計(jì)算W
#計(jì)算delta
for nowlevel in xrange(level-1,0,-1):
if nowlevel==level-1:
mydelta=delta[nowlevel]
my_n=len(myd)
else:
mydelta=delta[nowlevel+1]
my_n=n
myw=ann_w[nowlevel]
if nowlevel==level-1:
#輸出層
mydelta=delta_sigfun(myo,myd,None,None,None,None,None)
## mydelta=mymse*myo
elif nowlevel==level-2:
#輸出隱藏層的前一層,因?yàn)檩敵鼋Y(jié)果和前一層隱藏層的神經(jīng)元數(shù)目可能存在不一致
#所以單獨(dú)處理,傳相當(dāng)于輸出隱藏層的神經(jīng)元數(shù)目的數(shù)據(jù)
mydelta=delta_sigfun(yi[nowlevel],myd,nowlevel,level-1,my_n,mydelta[:len(myd)],myw[:,:len(myd)])
else:
mydelta=delta_sigfun(yi[nowlevel],myd,nowlevel,level-1,my_n,mydelta,myw)
delta[nowlevel][:my_n]=mydelta
#計(jì)算與更新權(quán)值W
for nowlevel in xrange(level-1,0,-1):
#每個(gè)層的權(quán)值不一樣
if nowlevel==level-1:
#輸出層
my_n=len(myd)
mylearn_r=learn_r*0.8
mytrain_a=train_a*1.6
elif nowlevel==1:
#輸入層
my_n=len(myd)
mylearn_r=learn_r*0.9
mytrain_a=train_a*0.8
else:
#其它層
my_n=n
mylearn_r=learn_r
mytrain_a=train_a
pre_level_myy=yi[nowlevel-1]
pretrain_myww=oldw[nowlevel-1]
pretrain_myw=pretrain_myww[:,:my_n]
#第二個(gè)調(diào)整參數(shù)
temp_i=[]
for i in xrange(0,n):
temp_i.append([])
for jj in xrange(0,my_n):
temp_i[i].append(mylearn_r*delta[nowlevel,jj]*pre_level_myy[i])
temp_rs2=np.array(temp_i)
temp_rs1=mytrain_a*pretrain_myw
#總調(diào)整參數(shù)
temp_change=temp_rs1+temp_rs2
my_ww=ann_w[nowlevel-1]
my_ww[:,:my_n]+=temp_change
return mymse
def train_update(level,nowtraincount,sigmoid_func,delta_sigfun):
'''''一次讀取所有樣本,然后迭代一次進(jìn)行訓(xùn)練'''
#打亂樣本順序
global learn_r
global train_a
global train_a0
global learn_r0
global r
global x
global d
global maxtrycount
global oldmse
x_n=len(x)
ids=range(0,x_n)
train_ids=[]
sample_x=[]
sample_d=[]
while len(ids)>0:
myxz=random.randint(0,len(ids)-1)
train_ids.append(ids[myxz])
del ids[myxz]
for i in xrange(0,len(train_ids)):
sample_x.append(x[train_ids[i]])
sample_d.append(d[train_ids[i]])
sample_x=np.array(sample_x)
sample_d=np.array(sample_d)
#讀入x的每個(gè)樣本,進(jìn)行訓(xùn)練
totalmse=0.0
mymse=float(10**-10)
for i in xrange(0,x_n):
mymse=sample_train(sample_x[i],sample_d[i],warray_n,sigmoid_func,delta_sigfun)
totalmse+=sum(mymse*mymse)
totalmse=np.sqrt(totalmse/float(x_n))
print u"誤差為:%f" %(totalmse)
nowtraincount[0]+=1
learn_r=learn_r0/(1+float(nowtraincount[0])/r)
train_a=train_a0/(1+float(nowtraincount[0])/r)
if nowtraincount[0]>=maxtrycount:
return False,True,totalmse
elif totalmse<expect_e:
#(totalmse-oldmse)/oldmse>0.1 and (totalmse-oldmse)/oldmse<1:
print u"訓(xùn)練成功,正在進(jìn)行檢驗(yàn)"
totalmse=0.0
for i in xrange(0,x_n):
mytemper=(sample_d[i]-simulate(sample_x[i],sigmoid_func,delta_sigfun))
totalmse+=sum(mytemper*mytemper)
totalmse=np.sqrt(totalmse/float(x_n))
if totalmse<expect_e:
return False,False,totalmse
oldmse=totalmse
return True,False,totalmse
def train():
'''''訓(xùn)練樣本,多次迭代'''
global hidelevel_count
nowtraincount=[]
nowtraincount.append(0)
#sigmoid函數(shù)指定
delta_sigfun=ann_delta_atanh
sigmoid_func=ann_atanh
tryerr=0
while True:
print u"-------開始第%d次訓(xùn)練---------"%(nowtraincount[0]+1),
iscontinue,iscountout,mymse=train_update(hidelevel_count,nowtraincount,sigmoid_func,delta_sigfun)
if not iscontinue:
if iscountout :
print u"訓(xùn)練次數(shù)已到,誤差為:%f"%mymse
tryerr+=1
if tryerr>3:
break
else:
print u"訓(xùn)練失敗,重新嘗試第%d次"%tryerr
nowtraincount[0]=0
generate_lw(15+tryerr*2)
else:
print u"訓(xùn)練成功,誤差為:%f"%mymse
break
def simulate(myx,sigmoid_func,delta_sigfun):
'''''一個(gè)樣本的仿真計(jì)算'''
print u"仿真計(jì)算中"
global ann_yi
global ann_w
global ann_wj0
global ann_y0
global hidelevel_count
global alllevel_count
global d
myd=d[0]
myx=np.array(myx)
n=len(myx)
level=hidelevel_count
allevel=alllevel_count
#清空yi輸出信號(hào)數(shù)組
hidelevel=hidelevel_count
alllevel=alllevel_count
for i in xrange(0,alllevel):
#第一維是層數(shù),從0開始
for j in xrange(0,n):
#第二維是神經(jīng)元
ann_yi[i][j]=0.0
ann_yi=np.array(ann_yi)
yi=ann_yi
#前向計(jì)算
myo=np.array([])
myy=np.array([])
for nowlevel in xrange(0,alllevel):
#一層層向前計(jì)算
#計(jì)算誘導(dǎo)局部域
my_y=[]
myy=yi[nowlevel-1]
myw=ann_w[nowlevel-1]
if nowlevel==0:
#第一層隱藏層
my_y=myx
yi[nowlevel]=my_y
elif nowlevel==(alllevel-1):
#線性輸出層,使用線性激活
my_y=o_func(yi[nowlevel-1,:len(myd)])
yi[nowlevel,:len(myd)]=my_y
elif nowlevel==(hidelevel-1):
#最后一層隱藏輸出層,使用線性激活
for i in xrange(0,len(myd)):
temp_y=sigmoid_func(np.dot(myw[:,i],myy))
my_y.append(temp_y)
yi[nowlevel,:len(myd)]=my_y
else:
#中間隱藏層
#中間隱藏層需要加上偏置
for i in xrange(0,len(myy)):
temp_y=sigmoid_func(np.dot(myw[:,i],myy))
my_y.append(temp_y)
yi[nowlevel]=my_y
return yi[alllevel-1,:len(myd)]
train()
delta_sigfun=ann_delta_atanh
sigmoid_func=ann_atanh
for xn in xrange(0,len(x)):
if simulate(x[xn],sigmoid_func,delta_sigfun)[0]>0:
plt.plot(train_x[xn][0],train_x[xn][1],"bo")
else:
plt.plot(train_x[xn][0],train_x[xn][1],"b*")
temp_x=np.random.rand(20)*10
temp_y=np.random.rand(20)*20+temp_x
myx=temp_x
myy=temp_y
plt.subplot(111)
x_max=np.max(myx)+5
x_min=np.min(myx)-5
y_max=np.max(myy)+5
y_min=np.min(myy)-5
plt.xlim(x_min,x_max)
plt.ylim(y_min,y_max)
for i in xrange(0,len(myx)):
test=get_siminx([[myx[i],myy[i]]])
if simulate(test,sigmoid_func,delta_sigfun)[0]>0:
plt.plot(myx[i],myy[i],"ro")
else:
plt.plot(myx[i],myy[i],"r*")
plt.show()

圖中藍(lán)色是訓(xùn)練數(shù)據(jù),紅色是測(cè)試數(shù)據(jù),圈圈代表類型[1,0],星星代表類型[0,1]。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- python機(jī)器學(xué)習(xí)實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)示例解析
- python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)
- python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)
- python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)(三)
- python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)(一)
- Python機(jī)器學(xué)習(xí)應(yīng)用之基于LightGBM的分類預(yù)測(cè)篇解讀
- Python機(jī)器學(xué)習(xí)應(yīng)用之基于天氣數(shù)據(jù)集的XGBoost分類篇解讀
- Python機(jī)器學(xué)習(xí)應(yīng)用之決策樹分類實(shí)例詳解
- Python機(jī)器學(xué)習(xí)應(yīng)用之基于BP神經(jīng)網(wǎng)絡(luò)的預(yù)測(cè)篇詳解
相關(guān)文章
Pycharm社區(qū)版創(chuàng)建Flask項(xiàng)目的實(shí)現(xiàn)步驟
本文主要介紹了Pycharm社區(qū)版創(chuàng)建Flask項(xiàng)目,包括設(shè)置Python環(huán)境、安裝Flask庫(kù)以及創(chuàng)建基本的項(xiàng)目結(jié)構(gòu),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06
django 鏈接多個(gè)數(shù)據(jù)庫(kù) 并使用原生sql實(shí)現(xiàn)
這篇文章主要介紹了django 鏈接多個(gè)數(shù)據(jù)庫(kù) 并使用原生sql實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-03-03
python numpy中mat和matrix的區(qū)別
這篇文章主要介紹了python numpy中mat和matrix的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2021-03-03
python中可以發(fā)生異常自動(dòng)重試庫(kù)retrying
這篇文章主要介紹了python中可以發(fā)生異常自動(dòng)重試庫(kù)retrying,retrying是一個(gè)極簡(jiǎn)的使用Python編寫的庫(kù),主題更多相關(guān)內(nèi)容需要的朋友可以參考一下2022-06-06

