用PyTorch搭建極限學習機(ELM)


一、ELM是什么

為解決前饋神經網絡中出現的問題,黃廣斌教授等提出了極限學習機(ELM) 算法。ELM 算法是在 SLFNs 算法基礎上發展的,當 ELM 算法的激活函數無限可微,ELM 的隱藏層輸出矩陣 H 可以不受迭代訓練的影響,保持不變。選取合適的輸入權重𝜔𝑖和隱含層的閾值𝑏𝑖,ELM 算法可以達到零誤差逼近實際輸出值的效果。極限學習機的數學原理是最小二乘法,在此不進行探討,感興趣的自行查詢資料。

總結極限學習機的特點:

1.三層網絡結構,只需初始化隱含層的權重和偏置,輸出層的權重計算可得;

2.輸出層矩陣 beta= 隱藏層輸出矩陣的廣義逆H+  *  訓練集標簽的轉置矩陣Y’ ;

3.訓練速度快,不需要通過迭代來不斷調整神經網絡的參數;

4.隱藏層激活函數的選擇,隱藏層激活函數對 ELM 的模型的泛化性能具有重要的影響,選擇合適的激活函數對 ELM 算法非常重要;

5.ELM 隱藏層節點數以及激活函數的參數會對 ELM 算法產生一定的影響;

6.ELM 的建立比較依賴訓練數據,因為 ELM 網絡模型訓練完成后不再調整參數,所以訓練數據集對 ELM 的參數影響較大。減少訓練數據集的隨機性以及數據中的噪聲,有助於提高 ELM 模型的性能。

如果需要ELM的其他代碼可以到黃教授的官網去找,指路 https://www3.ntu.edu.sg/home/egbhuang/elm_codes.html

 

二、重點代碼講解

1.關於數據處理,請參照我上一篇隨筆,步驟是一樣的;

2.如何求beta矩陣

  H = np.linalg.pinv(hiddenout.data.numpy().reshape(len(y_train),5))    #求廣義逆
  T = y_train.data.numpy().reshape(len(y_train))    #矩陣轉置
  beta = np.dot(H,T)    #矩陣相乘

np.linalg.pinv()是numpy模塊中的求矩陣廣義逆的方法;

numpy().reshape()是對矩陣的維度進行編輯以符合矩陣相乘的要求;

np.dot()使兩個矩陣相乘。

 

因為我們是用pytorch框架搭建的神經網絡,所以需要對NN中的參數進行自定義初始化。遍歷參數的方式有3種,module.parameters()是網絡中的參數、module.named_parameters()包含參數名和參數值、

module.state_dict()主要用於保存參數值到文件中。這三種方式都可以遍歷並修改其中的值,例如:

for param in module.parameters():
    print(param)
    param.data.fill_(update_param)
    print(param)

  對於一些參數較少的網絡這個方式可以,但是對於參數很多的網絡既不方便還可能出錯,所以我用的是另一種方式。

module.state_dict()['name'].copy_(update_value)

  因為state_dict()是以字典的方式存儲的,所以可以通過鍵值索引來修改其中的value,然后保存到文件中,再用load()函數調用即可。

 

圖為參數字典的輸出結果 

 

三、代碼及運行結果

搭建極限學習機網絡

# 神經網絡結構 
net = torch.nn.Sequential( 
    torch.nn.Linear(2, 5), 
    torch.nn.ReLU(), 
    torch.nn.Linear(5, 1),
    torch.nn.Softplus()
    )

計算β矩陣並保存參數

def save():
  ihlayer = torch.nn.Sequential( 
    torch.nn.Linear(2, 5), 
    torch.nn.ReLU()
  )
  hiddenout = ihlayer(xtrain).squeeze(-1)
  H = np.linalg.pinv(hiddenout.data.numpy().reshape(len(y_train),5))    #求廣義逆
  T = y_train.data.numpy().reshape(len(y_train))    #矩陣轉置
  beta = np.dot(H,T)    #矩陣相乘
  beta = torch.tensor(beta).float()
  #print(ihlayer.state_dict())
  
  net.state_dict()['0.weight'].copy_(ihlayer.state_dict()['0.weight'])
  net.state_dict()['0.bias'].copy_(ihlayer.state_dict()['0.bias'])
  net.state_dict()['2.weight'].copy_(beta)
  net.state_dict()['2.bias'].copy_(torch.tensor(0))
  #print(net.state_dict())
  # 保存神經網絡 
  torch.save(net.state_dict(), 'elmnet_params.pkl') # 只保存神經網絡的模型參數

調用參數並進行預測

# 只載入神經網絡的模型參數,神經網絡的結構需要與保存的神經網絡相同的結構 
def reload_params(): 
  net.load_state_dict(torch.load('elmnet_params.pkl')) 
  prediction = net(xtest)
  prediction = prediction.squeeze(-1)
  
  #plt.subplot(133) 
  plt.title('net') 
  plt.scatter(ytest.data.numpy(), prediction.data.numpy()) 
  plt.plot(ytest.data.numpy(), ytest.data.numpy(),'r--') 
  plt.show()

  

預測結果如圖:

 

預測結果欠佳,看來還需要優化。 

 


免責聲明!

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



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