首页 > 编程 > Python > 正文

python机器学习之神经网络(二)

2019-11-25 15:30:55
字体:
来源:转载
供稿:网友

由于Rosenblatt感知器的局限性,对于非线性分类的效果不理想。为了对线性分类无法区分的数据进行分类,需要构建多层感知器结构对数据进行分类,多层感知器结构如下:


该网络由输入层,隐藏层,和输出层构成,能表示种类繁多的非线性曲面,每一个隐藏层都有一个激活函数,将该单元的输入数据与权值相乘后得到的值(即诱导局部域)经过激活函数,激活函数的输出值作为该单元的输出,激活函数类似与硬限幅函数,但硬限幅函数在阈值处是不可导的,而激活函数处处可导。本次程序中使用的激活函数是tanh函数,公式如下:


tanh函数的图像如下:


程序中具体的tanh函数形式如下:


就是神经元j的诱导局部域

它的局部梯度分两种情况:

(1)神经元j没有位于隐藏层:


(2)神经元j位于隐藏层:


其中k是单元j后面相连的所有的单元。

局部梯度得到之后,根据增量梯度下降法的权值更新法则

即可得到下一次的权值w,经过若干次迭代,设定误差条件,即可找到权值空间的最小值。

python程序如下,为了能够可视化,训练数据采用二维数据,每一个隐藏层有8个节点,设置了7个隐藏层,一个输出层,输出层有2个单元:

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  #基本参数初始化 oldmse=10**100 fh=1 maxtrycount=500 mycount=0.0 if maxtrycount>=20:     r=maxtrycount/5 else:     r=maxtrycount/2 #sigmoid函数 ann_sigfun=None ann_delta_sigfun=None #总层数初始化,比非线性导数多一层线性层 alllevel_count=warray_txn*4 # 非线性层数初始化 hidelevel_count=alllevel_count-1  #学习率参数  learn_r0=0.002  learn_r=learn_r0    #动量参数 train_a0=learn_r0*1.2 train_a=train_a0 expect_e=0.05 #对输入数据进行预处理 ann_max=[] for m_ani in xrange(0,warray_txn):       #找出训练数据中每一项的最大值   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):     '''''生成本次的扩维输入数据 '''     '''''mysx==>输入数据,in_w==>权值矩阵,每一列为一个神经元的权值向量'''     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):     '''''找出权值矩阵均值接近0,输出结果方差接近1的权值矩阵'''     #对随机生成的多个权值进行优化选择,选择最优的权值     global warray_txn     global warray_n     mylw=[]     y_in=[]     #生成测试权值     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      #计算输出     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]))     #计算均方差     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     #返回数据整理的权值矩阵     return mylw[mychoice] mylnww=get_inlw(ann_max,300,train_x)  def get_inputx(mytrain_x,myin_w):     '''''将训练数据经过权值矩阵,形成扩维数据'''     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)#用于输入的扩维数据 #对测试数据进行扩维 def get_siminx(sim_x):     global mylnww     myxx=np.array(sim_x)     return get_inputx(myxx,mylnww) #计算一层的初始化权值矩阵 def getlevelw(myin_x,wo_n,wi_n,w_count):     mylw=[]     y_in=[]     #生成测试权值     mylw=np.random.rand(w_count,wi_n,wo_n)     mylw=mylw*2.-1      #计算输出     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)     #计算均方差     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     #返回数据整理的权值矩阵     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):             #层数     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"产生权值初始矩阵",          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"权值矩阵平均:%f"%(np.mean(np.array(ann_w)))   print u"权值矩阵方差:%f"%(np.var(np.array(ann_w)))    generate_lw(15)  #前次训练的权值矩阵 ann_oldw=copy.deepcopy(ann_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):     #第一维是层数,从0开始     ann_yi.append([])     for j in xrange(0,warray_n):         #第二维是神经元         ann_yi[i].append(0.0) ann_yi=np.array(ann_yi)          #输出层函数     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):     '''''一个样本的前向和后向计算'''     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输出信号数组         hidelevel=hidelevel_count     alllevel=alllevel_count     for i in xrange(0,alllevel):         #第一维是层数,从0开始         for j in xrange(0,n):             #第二维是神经元             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     #前向计算      #对输入变量进行预处理            myo=np.array([])     for nowlevel in xrange(0,alllevel):         #一层层向前计算         #计算诱导局部域         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          #计算误差与均方误差     myo=yi[hidelevel-1][:len(myd)]     myo_end=yi[alllevel-1][:len(myd)]     mymse=get_e(myd,myo_end)       #反向计算     #输入层不需要计算delta,输出层不需要计算W       #计算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:             #输出隐藏层的前一层,因为输出结果和前一层隐藏层的神经元数目可能存在不一致             #所以单独处理,传相当于输出隐藏层的神经元数目的数据             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     #计算与更新权值W      for nowlevel in xrange(level-1,0,-1):         #每个层的权值不一样         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]          #第二个调整参数         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         #总调整参数         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):     '''''一次读取所有样本,然后迭代一次进行训练'''     #打乱样本顺序     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的每个样本,进行训练         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"训练成功,正在进行检验"         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():     '''''训练样本,多次迭代'''     global hidelevel_count     nowtraincount=[]     nowtraincount.append(0)     #sigmoid函数指定     delta_sigfun=ann_delta_atanh     sigmoid_func=ann_atanh          tryerr=0         while True:         print u"-------开始第%d次训练---------"%(nowtraincount[0]+1),         iscontinue,iscountout,mymse=train_update(hidelevel_count,nowtraincount,sigmoid_func,delta_sigfun)         if not iscontinue:             if iscountout :                 print u"训练次数已到,误差为:%f"%mymse                  tryerr+=1                  if tryerr>3:                   break                 else:                   print u"训练失败,重新尝试第%d次"%tryerr                   nowtraincount[0]=0                   generate_lw(15+tryerr*2)                                                                   else:                 print u"训练成功,误差为:%f"%mymse                                break         def simulate(myx,sigmoid_func,delta_sigfun):     '''''一个样本的仿真计算'''     print u"仿真计算中"         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输出信号数组         hidelevel=hidelevel_count     alllevel=alllevel_count     for i in xrange(0,alllevel):         #第一维是层数,从0开始         for j in xrange(0,n):             #第二维是神经元             ann_yi[i][j]=0.0     ann_yi=np.array(ann_yi)     yi=ann_yi      #前向计算     myo=np.array([])     myy=np.array([])     for nowlevel in xrange(0,alllevel):         #一层层向前计算         #计算诱导局部域         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() 

图中蓝色是训练数据,红色是测试数据,圈圈代表类型[1,0],星星代表类型[0,1]。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表