1

我需要varImp在由 nnet 方法通过插入符号创建的神经网络模型上使用函数。

编码:

#Load Packages
require(quantmod)
require(nnet)
require(caret)

#Creating data
T <- seq(0,20,length=200)                                   
y <- 1 + 3*cos(4*T+2) +.2*T^2 + rnorm(200)                  
dat <- data.frame( y, x1=Lag(y,1), x2=Lag(y,2),x3=Lag(y,3)) 
dat <- dat[4:length(dat[,1]),]
names(dat) <- c('y','x1','x2','x3')

set.seed(100) 
podzial <- createDataPartition(y, p = 3/4, list = FALSE)
zucz<-dat[podzial,]
ztest<-dat[-podzial,]

# Train control
ctrl <- trainControl(method = "LGOCV",p=0.7)

#Training
model <- train(y ~ x1+x2 , zucz, method='nnet', linout=TRUE, trace=F,maxit=100,skip=T,
           tuneGrid=expand.grid(.size=c(10),.decay=c(0,0.1,0.001,0.0001)),
           trControl = ctrl,
           preProcess = c("range"))

varImp(model,scale=F)

当我尝试使用varImp时出现错误:

Error in i2h[hidden, input] <- abeta[grep(label, nms, fixed = TRUE)] : 
number of items to replace is not a multiple of replacement length

我用不同数量的神经元做了几次测试。当神经元数量(大小参数)大于 9 时,似乎会发生错误。如何解决?

4

1 回答 1

1

我认为这很明显是caret包中的一个错误,特别是在caret:::GarsonWeights函数中。此函数尝试从最终模型中解码系数名称。他们是

names(coef(model$finalModel))
#  [1] "b->h1"   "i1->h1"  "i2->h1"  "b->h2"   "i1->h2"  "i2->h2"  "b->h3"  
#  [8] "i1->h3"  "i2->h3"  "b->h4"   "i1->h4"  "i2->h4"  "b->h5"   "i1->h5" 
# [15] "i2->h5"  "b->h6"   "i1->h6"  "i2->h6"  "b->h7"   "i1->h7"  "i2->h7" 
# [22] "b->h8"   "i1->h8"  "i2->h8"  "b->h9"   "i1->h9"  "i2->h9"  "b->h10" 
# [29] "i1->h10" "i2->h10" "b->o"    "h1->o"   "h2->o"   "h3->o"   "h4->o"  
# [36] "h5->o"   "h6->o"   "h7->o"   "h8->o"   "h9->o"   "h10->o" 

这里有 2 个输入和 10 个隐藏节点。该函数尝试通过 grepping for "i1->h1" 来查找输入 1 和隐藏注释 1 的系数

grep("i1->h1",names(coef(model$finalModel)),fixed=T)
# [1]  2 29

但如您所见,返回了两列,“i1->h1”和“i1->h10”。这就是为什么只有当您超过 9 个节点时才会出现问题。所以很明显grep这里不是正确的功能。这就是导致您看到的错误的原因。

现在,如何解决它。首先,我们需要一个更正版本的GarsonWeights. 所以我要做的是复制版本caret并尝试grep替换match

gw <- caret:::GarsonWeights
body(gw)[[c(7,4,2,4,3,3,3)]] <- quote(match(label,nms))
body(gw)[[c(8,4,2,4,3,3,3)]] <- quote(match(label,nms))

在这里,我实际上是在深入研究函数的主体并只更改一个部分。现在这种修复功能的方法非常脆弱,可能会随着不同的版本而改变。我使用caret_6.0-21.

第二个挑战是varImp使用这个更新版本的权重函数。不幸的是,我们不能直接更新caret命名空间中的那个,默认代码明确地使用那个。所以我们需要做的,实际上是改变model告诉varImp()哪个对象如何运行的对象。如果你看看model$modelInfo$varImp你可以看到它在哪里打电话caret:::GarsonWeights。我们只需要将其更改为我们的gw函数。我们可以做到这一点

body(model$modelInfo$varImp)[[c(2,3)]]<-quote(gw(object,...))

我认为这应该有效。当您train()使用method="nnet".

我建议您联系caret维护人员并报告此错误。随时提供此答案的链接以获取完整说明。

于 2014-05-26T18:05:56.023 回答