предсказать.glm() на данных слепого теста

Я использую регуляризованную логистическую регрессию для задачи классификации с использованием пакета glmnet. В процессе разработки все работает нормально, но у меня возникла проблема с предсказаниями на данных слепого тестирования.

Поскольку я не знаю метку класса, мой фрейм данных для тестирования имеет столбец меньше, чем тот, который я использовал для обучения. Это кажется проблемой для predict.glm(), потому что он ожидает совпадения размеров - я могу «исправить» это, добавив столбец с некоторыми произвольными метками в тестовых данных, но это кажется плохой идеей. Я надеюсь, что этот пример проиллюстрирует проблему:

library(glmnet)
example = data.frame(rnorm(20))
colnames(example) = "A"
example$B = rnorm(20)
example$class = ((example$A + example$B) > 0)*1

testframe = data.frame(rnorm(20))
colnames(testframe) = "A"
testframe$B = rnorm(20)

x = model.matrix(class ~ ., data = example)
y = data.matrix(example$class)

# this is similar to the situation I have with my data
# the class labels are ommited on the blind test set

Поэтому, если я просто продолжу так, я получаю сообщение об ошибке:

x.test = as.matrix(testframe)
ridge = glmnet(x,y, alpha = 0, family = "binomial", lambda = 0.01789997)
ridge.pred = predict(ridge, newx = x.test, s = 0.01789997, type = "class")

Ошибка в cbind2(1, newx) %*% nbeta: ошибка Cholmod «X и/или Y имеют неправильные размеры» в файле ../MatrixOps/cholmod_sdmult.c, строка 90

Я могу «исправить» проблему, добавив столбец класса в мои тестовые данные:

testframe$class = 0
x.test = model.matrix(class ~ ., data = testframe)
ridge.pred2 = predict(ridge, newx = x.test, s = 0.01789997, type = "class")

Итак, у меня есть пара вопросов по этому поводу:
а) Безопасен ли этот обходной путь с добавлением столбца? Делать это кажется очень неправильным/опасным, потому что я не знаю, будет ли его использовать метод прогнозирования (зачем в противном случае требуется наличие этого столбца?
б) Какой лучший/"правильный" способ сделай это?

Заранее спасибо!


person ahanf    schedule 06.01.2018    source источник
comment
Удалите столбец перехвата из x, и ваш исходный код будет работать. то есть сделать это, x = model.matrix(class ~ ., data = example)[,-1] . Полный ответ опубликую позже сегодня, когда у меня будет время, чтобы объяснить более подробно.   -  person jmuhlenkamp    schedule 08.01.2018


Ответы (1)


Ответить

При создании матрицы x удалите столбец (Intercept) (который всегда является первым столбцом). Тогда ваша функция predict будет работать без обходного пути. В частности, используйте эту строку для создания x.

x = model.matrix(class ~ ., data = example)[,-1]

Пояснение

Вы получаете сообщение об ошибке, потому что model.matrix создает столбец для перехвата в модели, которого нет в вашей матрице x.test.

colnames(x)
# [1] "(Intercept)" "A"           "B"          
colnames(x.test)
# [1] "A" "B"

Если вы не установите intercept=FALSE, glmnet добавит для вас точку пересечения в модель. Таким образом, проще всего исключить столбец перехвата как из матриц x, так и из матриц x.test.

person jmuhlenkamp    schedule 07.01.2018