Saturday, September 28, 2013

Выжить при крушении. Улучшаем прогноз.

В прошлый раз я использовал линейную регрессию для прогнозирования того, выжил ли пассажир при крушении или нет. Точность прогноза составила 0.77, что неплохо для начала. Самыми значимыми переменными (по значению P-Value) были Sex, Fare, Age. Их я и брал в для прогнозирования.

Смотрим чего не хватает

Что делать, если для некоторых значимых переменных отсуствуют значения? Например, для поля возраст в тренировочном наборе отсутствует значение в 177 случаях:
Один из участников соревнования предложил заполнить эти значения спрогнозированными данными. Детальнее можно ознакомиться на форуме Kaggle, я же опишу как я применил его идею.

Добавляем новую колонку

От каких переменных может зависеть возраст? Возможно, что от количества детей (Parch) или братьев-сестер (Sibsp), а может стоимости билета (Fare)? Может можно из данных вытащить дополнительную информацию, которая нам помогла бы спрогнозировать возраст? Например, имя пассажира уже содержит его титул: Mr, Mrs, Miss, Master.

Написать скрипт, который из полного имени вытащит титул из имени не составит особого труда. Я написал его на питоне, точнее на его расширенной версии Anaconda, которая содержит массу нужных пакетов, в том числе модуль для чтения/записи csv файлов. Скрипт находится здесь. После обработки в файлах с тренировочными и тестовыми данными появилась колонка Title.
Считываю полученный csv файл в R:

Определяем переменные с помощью corrgram

Дальше определим, от каких переменных зависит возраст. Для этого воспользуюсь таким графиком, который называется коррелограмма (correlogram). Его я тоже нарыл на том же форуме, ссылка внизу. Реализована эта красота в пакете corrgram.
Поскольку corrgram показывает зависимости между числовыми переменными, добавлю колонку TitleNum, в которой будет числовое значение от Title:
Строю график.
Вот что получилось:
Чем насыщеннее цвет в нижней части, тем более тесная связь между переменными. Синий цвет - связь положительная, красный - отрицательная. Интересные графики в верхней части показывают эти изменения графически (чтобы отобразились графики в верхней части нужно задать параметер upper.panel=panel.ellipse ).
Например, между Pclass и Age есть сильная отрицательная связь, т.к. соответствующий цвет квадратика в нижней части темно-красный. На графике так же видно, что с уменьшением Pclass возраст пассажира увеличивается (сейчас, как и 100 лет назад первым классом в основном путешествовали старперы, студики и прочий нищеброд ютились в эконом классах).

Заполняем недостающие данные

Переменные, наиболее связанные с возрастом определили - это Pclass, SibSp и Title. Осталось заполнить отстутствующие значения и запихнуть в общую модель. Недостающие значения в тренировочных и тестовых данных я проставляю в процедуре, которую вызываю перед тем, как построить модель и делать прогноз. Вот код функции:
```{r}
predictMissing <- function(dataSet){
  #Find missing Age
  age.model = lm(Age~as.factor(Title)  + SibSp + Pclass, data=dataSet)
  fare.model = lm(Fare~Parch+Pclass, data=dataSet)
  for (i in 1:nrow(dataSet)){
    if (is.na(dataSet[i, "Age"])){
      dataSet[i,"Age"] = predict(age.model, newdata=dataSet[i,])
    }
  }
  return(dataSet)
}
```{r}

Финальный результат

После отправки новых прогнозов на Kaggle я увеличил счет на один процент(с 0.77512 до 0.78469). Немного, но главное - это полученный опыт! :)

Ресурсы

1. Пост от Wallace Campbell. https://www.kaggle.com/c/titanic-gettingStarted/forums/t/5232/r-code-to-score-0-79426
2. Anaconda, python visualization and explaration tool. https://store.continuum.io/cshop/anaconda/
3. Скрипт добавления колонки title. https://dl.dropboxusercontent.com/u/22607711/AddTitle.py
4. Пост на Kaggle форуме про корелограммы. https://www.kaggle.com/c/titanic-gettingStarted/prospector#489

No comments:

Post a Comment