一、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()
預測結果如圖:

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