Какая разница, если вы тестируете модель на тестовом наборе, который включает результат? - PullRequest
0 голосов
/ 25 апреля 2020

Какая разница, если вы тестируете модель на тестовом наборе, в котором уже есть результат? Теоретически это даст дополнительную информацию для модели, но когда я запускаю пример, результаты совпадают. Я буду использовать SVM в качестве примера ниже.

Скажем, вы тренируете SVM на части данных радужной оболочки.

set.seed(123)
split = sample.split(iris$Species, SplitRatio = 0.75)
training_set = subset(iris, split == TRUE)
test_set = subset(iris, split == FALSE)

создать модель

 classifier = svm(formula = Species ~ .,
                 data = training_set,
                 type = 'C-classification',
                 kernel = 'radial')

Теперь у нас будет два прогноза. На наборе тестирования без результата, доступного для модели (правильный путь), и набора тестирования с доступным результатом. Версия 1:

    #create prediction WITHOUT outcome i.e. test_set[-5]
    y_pred <- predict(classifier, newdata = test_set[-5])
    table( y_pred, test_set[, 5])
       y_pred       setosa versicolor virginica
        setosa         12          0         0
        versicolor      0         12         1
        virginica       0          0        11

Версия 2:

    #create prediction WITH outcome i.e. the entire test set
    y_pred <- predict(classifier, newdata = test_set)
    table( y_pred, test_set[, 5])
      y_pred       setosa versicolor virginica
       setosa         12          0         0
       versicolor      0         12         1
       virginica       0          0        11

Обе версии 1 и 2 показывают идентичные результаты. Это почему? Модель просто игнорирует результат сама по себе, или остальные функции достаточно хороши, чтобы в любом случае дать прогноз?

1 Ответ

1 голос
/ 25 апреля 2020

Как уже упоминалось в комментариях, ваши два фрагмента кода фактически эквивалентны; во 2-м фрагменте:

y_pred <- predict(classifier, newdata = test_set)

5-й столбец test_set[5], содержащий результаты, под колпаком, фактически удаляется из данных, подаваемых в модель, и не используется для создания реальных прогнозов.

Но это интересный пример, демонстрирующий, как языковая функция, предназначенная для удобства, потенциально может привести новых пользователей к такой путанице: фактически здесь, единственная причина, по которой ваш второй фрагмент работает вообще без ошибка возникает из-за интерфейса формулы (довольно отличительная характеристика c of R), используемого при подгонке модели.

Чтобы увидеть, как ситуация может легко отличаться, давайте сделаем некоторые (казалось бы, неважные и тривиальные) изменения; давайте отделим элементы от меток вручную и вместо этого воспользуемся альтернативным интерфейсом данных для подгонки модели:

X = training_set[,1:4]
y = training_set[5]

classifier = svm(X, y,
                 type = 'C-classification',
                 kernel = 'radial')

Это приведет к сбою 2-го фрагмента (теперь, напротив, test_set X, используемый для обучения, также содержит метки, то есть еще один столбец, просто потому, что он получает больше входных данных (5), чем он ожидает (4):

pred = predict(classifier, test_set)

Error in scale.default(newdata[, object$scaled, drop = FALSE], center = object$x.scale$"scaled:center",  : 
  length of 'center' must equal the number of columns of 'x'
Calls: predict -> predict.svm -> scale -> scale.default
Execution halted

В этом случае он Мы несем ответственность за подготовку данных таким образом, чтобы они содержали те же самые функции, которые использовались для обучения - не меньше, но и не более:

pred = predict(classifier, test_set[,1:4]) # works OK

, но это, вероятно, предотвращает также потенциальные заблуждения, подобные тем, которые вы здесь выразили ...


Если смотреть дальше, чем R, эта вторая ситуация (то есть интерфейс данных вместо формулы 1) является скорее правилом, чем исключением. Вот случай с Python и sciki-learn; без предоставления полного примера для краткости (оставьте комментарий, если вы хотите, чтобы sh увидел его полностью), с X и y функциями и метками радужной оболочки соответственно, мы подходим к классификатору как

clf = LogisticRegression()
clf.fit(X,y)

но если мы объединим X и y в одну переменную X_plus и попытаемся предсказать ее, мы получим ожидаемую ошибку для избыточных столбцов:

clf.predict(X_plus)

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-21-b7d5b72a1945> in <module>()
----> 1 clf.predict(X_plus)


/usr/local/lib/python3.6/dist-packages/sklearn/linear_model/_base.py in decision_function(self, X)
    271         if X.shape[1] != n_features:
    272             raise ValueError("X has %d features per sample; expecting %d"
--> 273                              % (X.shape[1], n_features))
    274 
    275         scores = safe_sparse_dot(X, self.coef_.T,

ValueError: X has 5 features per sample; expecting 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...