Почему эти модели, произведенные в Caret, не идентичны?

Я действительно пытаюсь понять, почему два фрагмента кода не создают одинаковые модели. Чтобы создать первую нейронную сеть (NN1), я использовал (код ниже) перекрестную проверку в функции train пакета Caret, чтобы найти лучшие параметры. На странице 2 виньетки пакета говорится, что он будет «Подгоните окончательную модель ко всем обучающим данным, используя оптимальный набор параметров».

Итак, в приведенном ниже коде я ожидаю, что NN1 отразит полный обучающий набор с лучшими параметрами, которые составляют размер = 5 и затухание = 0,1.

Я планировал использовать параметры этого шага для создания модели, которая будет запущена в производство, с использованием объединенных данных обучения и тестирования. Прежде чем создать эту производственную модель, я хотел убедиться, что правильно использую выходные данные функции train.

Итак, я создал вторую модель (NN2) с функцией поезда, но без тюнинга. Вместо этого я указал параметры 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 

person rmacey    schedule 21.02.2017    source источник


Ответы (1)


Я считаю, что это связано со случайным семенем. Когда вы выполняете перекрестную проверку, вы подбираете множество моделей из этого начального числа (set.seed(2)). Окончательная модель соответствует тем же параметрам, но исходное значение, которое окончательная модель поместила в рамках перекрестной проверки, отличается от того, когда вы пытаетесь просто подогнать эту окончательную модель с этими параметрами самостоятельно. Вы видите это здесь, потому что веса в каждом вызове нейронной сети (nnet) генерируются каждый раз случайным образом.

person cdeterman    schedule 21.02.2017
comment
в этом есть смысл. Отмечу, что параметр Wts в пакете nnet является начальным вектором параметров. Если он отсутствует, он выбирается случайным образом. Есть ли способ установить начальное значение функции nnet из Caret. Я не специалист по нейронным сетям и плохо понимаю, как указать начальные веса (сколько, какой диапазон значений). Этот пост, кажется, предлагает идею. Возможно, я смогу передать некоторые начальные веса в nnet через Caret. - person rmacey; 21.02.2017
comment
Я считаю, что вы можете просто передать параметр Wts непосредственно функции train. Однако я бы посоветовал не всегда использовать одни и те же веса. Я бы сделал это только для того, чтобы доказать себе, что происходит. - person cdeterman; 21.02.2017