极限学习机(Extreme Learning Machine) 具有学习效率高和泛化能力强的优点,被广泛应用于分类、回归、聚类、特征学习等问题中。本文利用elmNNRcpp包实现极限学习机的回归和分类算法。
极限学习机(Extreme Learning Machine) 是一种单隐含层前馈神经网络(Single-hidden Layer Feedforward Neural Network)。
特点是输入层和隐含层的连接权值、隐含层的阈值可以随机设定,且设定完后不用再调整;隐含层和输出层之间的连接权值不需要迭代调整,通过解方程组方式一次性确定。
环境&软件
- win10 64bit
- R 3.6.1
安装包
if(!requireNamespace("elmNNRcpp")) install.packages("elmNNRcpp")
ELM回归
加载Boston数据,将数据转为矩阵,分为90%的训练数据和10%的测试数据,数据格式要转换成特征矩阵x和目标矩阵y,满足模型训练的数据格式要求。最后返回预测误差和结果图。
# 1.加载数据
library(elmNNRcpp)
data(Boston, package = 'KernelKnn')
# 查看数据结构
str(Boston)
## 'data.frame': 506 obs. of 14 variables:
## $ crim : num 0.00632 0.02731 0.02729 0.03237 0.06905 ...
## $ zn : num 18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
## $ indus : num 2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
## $ chas : int 0 0 0 0 0 0 0 0 0 0 ...
## $ nox : num 0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
## $ rm : num 6.58 6.42 7.18 7 7.15 ...
## $ age : num 65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
## $ dis : num 4.09 4.97 4.97 6.06 6.06 ...
## $ rad : int 1 2 2 3 3 3 5 5 5 5 ...
## $ tax : num 296 242 242 222 222 222 311 311 311 311 ...
## $ ptratio: num 15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
## $ black : num 397 397 393 395 397 ...
## $ lstat : num 4.98 9.14 4.03 2.94 5.33 ...
## $ medv : num 24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...
# 转为矩阵
Boston = as.matrix(Boston)
# 2.数据分割
# 90%训练数据
train <- Boston[sample(1:nrow(Boston),round(0.9*nrow(Boston))),]
# 10%测试数据
test <- Boston[(nrow(train)+1):nrow(Boston),]
# 3.格式转换
train_x <- train[,-ncol(train)]
train_y <- train[,ncol(train),drop=FALSE]
test_x <- test[,-ncol(test)]
test_y <- test[,ncol(test),drop=FALSE]
# 3.模型训练
model = elm_train(train_x, train_y, nhid = 20, actfun = 'purelin', init_weights = 'uniform_negative')
# 4.模型预测
predict_y = elm_predict(model, test_x)
# 5.误差表
data.frame(rmse=sqrt(mean((predict_y- test_y)^2)),
mape=mean(abs(predict_y-test_y)/test_y))
## rmse mape
## 1 3.263716 0.1553263
# 图
plot(predict_y,type='b',xlab = 'samples',
ylab = "value",main = 'ELM regression for Boston')
lines(test_y,type = 'b',col="red")
legend("topleft",c("predict","actual"),col = c("red","black"),lty=2)
elm.png
ELM分类
加载ionosphere数据,由于elm_train函数对于分类算法中目标矩阵的格式特殊要求,需要将目标矩阵转为ont-hot格式。由于正负样本不均衡,数据分割中采用了分层抽样,目的是测试数据和训练数据中正负样本比例大致相同。elm_predict函数输出的是概率值,需要用max.col函数转为为类别值。
# 1.加载数据
data(ionosphere, package = 'KernelKnn')
# 查看数据结构
str(ionosphere)
## 'data.frame': 351 obs. of 35 variables:
## $ V1 : int 1 1 1 1 1 1 1 0 1 1 ...
## $ V2 : int 0 0 0 0 0 0 0 0 0 0 ...
## $ V3 : num 0.995 1 1 1 1 ...
## $ V4 : num -0.0589 -0.1883 -0.0336 -0.4516 -0.024 ...
## $ V5 : num 0.852 0.93 1 1 0.941 ...
## $ V6 : num 0.02306 -0.36156 0.00485 1 0.06531 ...
## $ V7 : num 0.834 -0.109 1 0.712 0.921 ...
## $ V8 : num -0.377 -0.936 -0.121 -1 -0.233 ...
## $ V9 : num 1 1 0.89 0 0.772 ...
## $ V10 : num 0.0376 -0.0455 0.012 0 -0.164 ...
## $ V11 : num 0.852 0.509 0.731 0 0.528 ...
## $ V12 : num -0.1776 -0.6774 0.0535 0 -0.2028 ...
## $ V13 : num 0.598 0.344 0.854 0 0.564 ...
## $ V14 : num -0.44945 -0.69707 0.00827 0 -0.00712 ...
## $ V15 : num 0.605 -0.517 0.546 -1 0.344 ...
## $ V16 : num -0.38223 -0.97515 0.00299 0.14516 -0.27457 ...
## $ V17 : num 0.844 0.055 0.838 0.541 0.529 ...
## $ V18 : num -0.385 -0.622 -0.136 -0.393 -0.218 ...
## $ V19 : num 0.582 0.331 0.755 -1 0.451 ...
## $ V20 : num -0.3219 -1 -0.0854 -0.5447 -0.1781 ...
## $ V21 : num 0.5697 -0.1315 0.7089 -0.6997 0.0598 ...
## $ V22 : num -0.297 -0.453 -0.275 1 -0.356 ...
## $ V23 : num 0.3695 -0.1806 0.4339 0 0.0231 ...
## $ V24 : num -0.474 -0.357 -0.121 0 -0.529 ...
## $ V25 : num 0.5681 -0.2033 0.5753 1 0.0329 ...
## $ V26 : num -0.512 -0.266 -0.402 0.907 -0.652 ...
## $ V27 : num 0.411 -0.205 0.59 0.516 0.133 ...
## $ V28 : num -0.462 -0.184 -0.221 1 -0.532 ...
## $ V29 : num 0.2127 -0.1904 0.431 1 0.0243 ...
## $ V30 : num -0.341 -0.116 -0.174 -0.201 -0.622 ...
## $ V31 : num 0.4227 -0.1663 0.6044 0.2568 -0.0571 ...
## $ V32 : num -0.5449 -0.0629 -0.2418 1 -0.5957 ...
## $ V33 : num 0.1864 -0.1374 0.5605 -0.3238 -0.0461 ...
## $ V34 : num -0.453 -0.0245 -0.3824 1 -0.657 ...
## $ class: Factor w/ 2 levels "b","g": 2 1 2 1 2 1 2 1 2 1 ...
# 2.数据清洗
data = ionosphere[,-2] # 删除第二列不变量
data$class <- as.numeric(data$class) # 标签列转为数字
data <- data[order(data$class),] # 按标签列排序
data <- as.matrix(data) # 转为矩阵
# 3.数据分割(分层抽样)
# 训练数据行号
library(sampling)
train_index <- strata(data,stratanames = "class",size = round(table(data[,ncol(data)])*0.9))$ID_unit
# 70%训练数据
train <- data[train_index,]
# 30%测试数据
test <- data[-train_index,]
# 4.格式转换
train_x <- train[,-ncol(train)]
train_y <- onehot_encode(train[,ncol(train)]-1) # 训练数据目标变量one-hot编码(0,1)
test_x <- test[,-ncol(test)]
test_y <- test[,ncol(test)]
# 5.模型训练
model = elm_train(train_x, train_y, nhid = 20, actfun = 'relu')
# 6.模型预测
predict_y = elm_predict(model, test_x,normalize = TRUE)
# 概率转类型
predict_y = max.col(predict_y, ties.method = "random")
# 7.误差
mean(predict_y==test_y) # 准确率
## [1] 0.8333333
table(predict=predict_y,actual=test_y) # 混淆矩阵
## actual
## predict 1 2
## 1 7 0
## 2 6 23