我在R中尝试使用Boston数据集进行神经网络分析。
data("Boston",package="MASS") data <- Boston
保留我们想要使用的变量:
keeps <- c("crim", "indus", "nox", "rm" , "age", "dis", "tax" ,"ptratio", "lstat" ,"medv" ) data <- data[keeps]
在这种情况下,公式被存储在一个名为f的R对象中。响应变量medv将被“回归”到剩余的九个属性上。我的操作如下:
f <- medv ~ crim + indus + nox + rm + age + dis + tax + ptratio + lstat
为了设置训练样本,从506行数据中不重复地抽取400行,使用sample方法:
set.seed(2016) n = nrow(data) train <- sample(1:n, 400, FALSE)
使用R的neuralnet函数进行拟合。
library(neuralnet)fit<- neuralnet(f, data = data[train ,], hidden=c(10 ,12 ,20), algorithm = "rprop+", err.fct = "sse", act.fct = "logistic", threshold =0.1, linear.output=TRUE)
但是显示了算法未收敛的警告消息。
警告消息:算法在1次重复中未在stepmax内收敛
尝试使用compute进行预测,
pred <- compute(fit,data[-train, 1:9])
显示了以下错误消息
Error in nrow[w] * ncol[w] : non-numeric argument to binary operatorIn addition: Warning message:In is.na(weights) : is.na() applied to non-(list or vector) of type 'NULL'
为什么会出现这个错误,以及如何恢复以进行预测?我想在该数据集上使用neuralnet函数。
回答:
当neuralnet
未收敛时,结果神经网络是不完整的。你可以通过调用attributes(fit)$names
来判断。当训练收敛时,它会看起来像这样:
[1] "call" "response" "covariate" "model.list" "err.fct" [6] "act.fct" "linear.output" "data" "net.result" "weights" [11] "startweights" "generalized.weights" "result.matrix"
当未收敛时,一些属性将不会被定义:
[1] "call" "response" "covariate" "model.list" "err.fct" "act.fct" "linear.output"[8] "data"
这解释了为什么compute
不起作用。
当训练未收敛时,第一个可能的解决方案是增加stepmax
(默认值为100000)。你还可以添加lifesign = "full"
,以更好地了解训练过程。
此外,看你的代码,我认为三个层分别有10、12和20个神经元太多了。我建议从一个层开始,神经元数量与输入数量相同,在你的情况下是9个。
编辑:
通过缩放(记得缩放训练和测试数据,并对compute
结果进行“反缩放”),它会更快地收敛。还要注意,我减少了层数和神经元数量,并且仍然降低了错误阈值。
data("Boston",package="MASS") data <- Bostonkeeps <- c("crim", "indus", "nox", "rm" , "age", "dis", "tax" ,"ptratio", "lstat" ,"medv" ) data <- data[keeps]f <- medv ~ crim + indus + nox + rm + age + dis + tax + ptratio + lstatset.seed(2016) n = nrow(data) train <- sample(1:n, 400, FALSE)# 缩放数据。缩放参数存储在这个矩阵中以便后续使用。scaledData <- scale(data)fit<- neuralnet::neuralnet(f, data = scaledData[train ,], hidden=9, algorithm = "rprop+", err.fct = "sse", act.fct = "logistic", threshold = 0.01, linear.output=TRUE, lifesign = "full")pred <- neuralnet::compute(fit,scaledData[-train, 1:9])scaledResults <- pred$net.result * attr(scaledData, "scaled:scale")["medv"] + attr(scaledData, "scaled:center")["medv"]cleanOutput <- data.frame(Actual = data$medv[-train], Prediction = scaledResults, diff = abs(scaledResults - data$medv[-train]))# 显示一些结果summary(cleanOutput)