機器學習:Python實現最小均方算法(lms)


      

     lms算法跟Rosenblatt感知器相比,主要區別就是權值修正方法不一樣。lms采用的是批量修正算法,Rosenblatt感知器使用的

是單樣本修正算法。兩種算法都是單層感知器,也只適用於線性可分的情況。

      詳細代碼及說明如下:

'''
   算法:最小均方算法(lms)
   均方誤差:樣本預測輸出值與實際輸出值之差平方的期望值,記為MES
   設:observed 為樣本真值,predicted為樣本預測值,則計算公式:
   (轉換為容易書寫的方式,非數學標准寫法,因為數學符號在這里不好寫)
   MES=[(observed[0]-pridicted[0])*(observed[0]-pridicted[0])+....
         (observed[n]-pridicted[n])*(observed[n]-pridicted[n])]/n
'''

'''
   變量約定:大寫表示矩陣或數組,小寫表示數字
   X:表示數組或者矩陣
   x:表示對應數組或矩陣的某個值
'''

'''
     關於學習效率(也叫步長:控制着第n次迭代中作用於權值向量的調節)。(下面的參數a):
     學習效率過大:收斂速度提高,穩定性降低,即出結果快,但是結果准確性較差
     學習效率過小:穩定性提高,收斂速度降低,即出結果慢,准確性高,耗費資源
     對於學習效率的確定,有專門的算法,這里不做研究。僅僅按照大多數情況下的選擇:折中值
'''
import numpy as np
a=0.1  ##學習率 0<a<1
X=np.array([[1,1],[1,0],[0,1],[0,0]]) ##輸入矩陣
D=np.array([1,1,1,0])  ##期望輸出結果矩陣
W=np.array([0,0])   ##權重向量
expect_e=0.005 ##期望誤差
maxtrycount=20 ##最大嘗試次數

##硬限幅函數(即標准,這個比較簡單:輸入v大於0,返回1.小於等於0返回-1)
'''
    最后的權重為W([0.1,0.1]),則:0.1x+0.1y=0 ==>y=-x
    即:分類線方程為:y=-x
'''
def sgn(v):
    if v>0:
        return 1
    else:
        return 0 ##跟上篇感知器單樣本訓練的-1比調整成了0,為了測試需要。-1訓練不出結果
    
##讀取實際輸出   
'''
    這里是兩個向量相乘,對應的數學公式:
    a(m,n)*b(p,q)=m*p+n*q
    在下面的函數中,當循環中xn=1時(此時W=([0.1,0.1])):
    np.dot(W.T,x)=(1,1)*(0.1,0.1)=1*0.1+1*0.1=0.2>0 ==>sgn 返回1
'''
def get_v(W,x):
    return sgn(np.dot(W.T,x))##dot表示兩個矩陣相乘


##讀取誤差值
def get_e(W,x,d):
    return d-get_v(W,x)

##權重計算函數(批量修正)
'''
  對應數學公式: w(n+1)=w(n)+a*x(n)*e
  對應下列變量的解釋:
  w(n+1) <= neww 的返回值
  w(n)   <=oldw(舊的權重向量)
  a      <= a(學習率,范圍:0<a<1)
  x(n)   <= x(輸入值)
  e      <= 誤差值或者誤差信號
'''
def neww(oldW,d,x,a):
    e=get_e(oldW,x,d)
    return (oldW+a*x*e,e)


##修正權值
'''
    此循環的原理:
    權值修正原理(批量修正)==>神經網絡每次讀入一個樣本,進行修正,
        達到預期誤差值或者最大嘗試次數結束,修正過程結束   
'''
cnt=0
while True:
    err=0
    i=0
    for xn in X:        
        W,e=neww(W,D[i],xn,a)
        i+=1
        err+=pow(e,2)  ##lms算法的核心步驟,即:MES
    err/=float(i)
    cnt+=1
    print(u"第 %d 次調整后的權值:"%cnt)
    print(W)
    print(u"誤差:%f"%err)
    if err<expect_e or cnt>=maxtrycount:
        break

print("最后的權值:",W.T)

##輸出結果
print("開始驗證結果...")
for xn in X:
    print("D%s and W%s =>%d"%(xn,W.T,get_v(W,xn)))


##測試准確性:
'''
   由上面的說明可知:分類線方程為y=-x,從坐標軸上可以看出:
   (2,3)屬於+1分類,(-2,-1)屬於0分類
'''

print("開始測試...")
test=np.array([2,3])
print("D%s and W%s =>%d"%(test,W.T,get_v(W,test)))
test=np.array([-2,-1])
print("D%s and W%s =>%d"%(test,W.T,get_v(W,test)))

    輸出結果:

第 1 次調整后的權值:
[ 0.1  0.1]
誤差:0.2500002 次調整后的權值:
[ 0.1  0.1]
誤差:0.000000
最后的權值: [ 0.1  0.1]
開始驗證結果...
D[1 1] and W[ 0.1  0.1] =>1
D[1 0] and W[ 0.1  0.1] =>1
D[0 1] and W[ 0.1  0.1] =>1
D[0 0] and W[ 0.1  0.1] =>0
開始測試...
D[2 3] and W[ 0.1  0.1] =>1
D[-2 -1] and W[ 0.1  0.1] =>0

     從結果看出,經過2次訓練,就得出了最優結果。

    補充說明:經過多次調整樣本或者權重,在20次循環中有時候出結果,有時候找不到最優解。所以在實驗過程中,沒有達到

預期結果,除了循環次數不夠之外,最大的可能就是樣本或者權值設置的問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM