【问题标题】:Why aren't these models produced in Caret identical?为什么在 Caret 中生产的这些模型不完全相同?
【发布时间】:2017-07-11 08:43:17
【问题描述】:

我真的很想了解为什么两段代码不会产生相同的模型。为了创建第一个神经网络 (NN1),我在 Caret 包的 train 函数中使用(下面的代码)交叉验证来找到最佳参数。 package's vignette 的第 2 页建议它将“使用最佳参数集将最终模型拟合到所有训练数据”。

因此,在下面的代码中,我希望 NN1 反映完整的训练集,其中最好的参数恰好是 size=5 和 decay=0.1。

我的计划是使用此步骤中的参数创建一个模型,并使用组合的训练和测试数据投入生产。在创建此生产模型之前,我想确保正确使用 train 函数的输出。

所以我创建了第二个模型 (NN2),它具有训练功能,但 without tuning。相反,我指定了参数 size=5 和 decay=0.1。使用相同的数据、相同的参数(和相同的种子),我期望相同的模型,但事实并非如此。为什么这些型号不一样?

# Create some data
library(caret)
set.seed(2)
xy<-data.frame(Response=factor(sample(c("Y","N"),534,replace = TRUE,prob=c(0.5,0.5))),
               GradeGroup=factor(sample(c("G1","G2","G3"),534,replace=TRUE,prob=c(0.4,0.3,0.3))),
               Sibling=sample(c(TRUE,FALSE),534,replace=TRUE,prob=c(0.3,0.7)),
               Dist=rnorm(534))

xyTrain <- xy[1:360,]
xyTest <- xy[361:534,]

# Create NN1 using cross-validation
tc <- trainControl(method="cv", number = 10, savePredictions = TRUE, classProbs = TRUE)
set.seed(2)
NN1 <- train(Response~.,data=xyTrain,
             method="nnet",
             trControl=tc,
             verbose=FALSE,
             metric="Accuracy")

# Create NN2 using parameters from NN1
fitControl <- trainControl(method="none", classProbs = TRUE)
set.seed(2)
NN2 <- train(Response~.,data=xyTrain,
             method="nnet",
             trControl=fitControl,
             verbose=FALSE,
             tuneGrid=data.frame(size=NN1$bestTune[[1]],decay=NN1$bestTune[[2]]),
             metric="Accuracy")

这是结果

> # Parameters of NN1
> NN1$bestTune
  size decay
1    1     0
> 
> # Code to show results of NN1 and NN2 differ
> testFitted <- data.frame(fitNN1=NN1$finalModel$fitted.values,
+                          fitNN2=NN2$finalModel$fitted.values)
> 
> testPred<-data.frame(predNN1=predict(NN1,xyTest,type="prob")$Y,
+                      predNN2=predict(NN2,xyTest,type="prob")$Y)
> # Fitted values are different
> head(testFitted)
      fitNN1    fitNN2
X1 0.4824096 0.4834579
X2 0.4673498 0.4705441
X3 0.4509407 0.4498603
X4 0.4510129 0.4498710
X5 0.4690963 0.4753655
X6 0.4509160 0.4498539
> # Predictions on test set are different
> head(testPred)
    predNN1   predNN2
1 0.4763952 0.4784981
2 0.4509160 0.4498539
3 0.5281298 0.5276355
4 0.4512930 0.4498993
5 0.4741959 0.4804776
6 0.4509335 0.4498589
> 
> # Accuracy of predictions are different
> sum(predict(NN1,xyTest,type="raw")==xyTest$Response)/nrow(xyTest)
[1] 0.4655172
> sum(predict(NN2,xyTest,type="raw")==xyTest$Response)/nrow(xyTest)
[1] 0.4597701
> 
> # Summary of models
> summary(NN1)
a 4-1-1 network with 7 weights
options were - entropy fitting 
 b->h1 i1->h1 i2->h1 i3->h1 i4->h1 
 -8.38   6.58   5.51  -9.50   1.06 
 b->o h1->o 
-0.20  1.39 
> summary(NN2)
a 4-1-1 network with 7 weights
options were - entropy fitting 
 b->h1 i1->h1 i2->h1 i3->h1 i4->h1 
 10.94  -8.27  -7.36   8.50  -0.76 
 b->o h1->o 
 3.15 -3.35 

【问题讨论】:

    标签: r r-caret nnet


    【解决方案1】:

    我相信这与随机种子有关。当您进行交叉验证时,您将从该起始种子 (set.seed(2)) 拟合许多模型。最终模型拟合相同的参数,但最终模型在交叉验证中拟合的种子与您尝试仅使用这些参数拟合最终模型时的种子不同。您在这里看到这一点是因为每次神经网络调用 (nnet) 中的权重都是随机生成的。

    【讨论】:

    • 这是有道理的。我注意到 nnet 包中的Wts 参数是初始参数向量。如果它丢失它是随机选择的。有没有办法将种子设置为 Caret 的 nnet 函数。我不是神经网络专家,也不知道如何指定初始权重(多少,值的范围)。这个post 似乎提供了一个想法。也许我可以通过 Caret 将一些初始权重传递给 nnet。
    • 我相信你可以直接将Wts参数传递给train函数。但是,我会告诫不要总是使用相同的权重。我这样做只是为了向自己证明正在发生的事情。
    猜你喜欢
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    • 2020-10-21
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    相关资源
    最近更新 更多