Пакет Kickstarter для новичков!

Вспышка пандемии COVID-19 вынудила весь мир внести серьезные изменения в свой образ жизни, постоянно находясь в помещении. Имея все дополнительное время, сэкономленное от поездок на работу и прогулок, я решил заняться вещами, которые иначе никогда бы не смог. Одним из них был Kaggle.

Во всех своих предыдущих проектах я работал с наборами визуальных данных, поэтому хотел попробовать свои силы в чем-то другом. Я хотел развить понимание всего конвейера, начиная от очистки данных и заканчивая различными преобразованиями, выбором функций и, наконец, моделированием машинного обучения. Для этого я выбрал задачу для начинающих с обширным набором данных: Цены на жилье: продвинутые методы регрессии. Я поставил цель получить менее 1 тыс. (~ 20% лучших).

Как и ожидалось, 90% моего времени ушло на очистку данных и разработку функций, а оставшиеся 10% - на применение к ним моделей машинного обучения. Я понял, насколько важно знать свои данные. Слепая передача его модели SOTA без какой-либо инженерии данных приведет вас только к этому. Мне пришлось читать много блогов и блокнотов Kaggle, но я неукоснительно следил за этим. В этой статье я опишу процесс, которому я следовал, очень простыми словами и с примерами, чтобы такие новички, как я, могли понять, с чего начать.

Для справки, вот мои записные книжки с полным кодом, чтобы вы могли следить за объяснениями -

Очистка данных и разработка функций: https://github.com/Shikhargupta/kaggle_house_pricing/blob/master/Feat_Engg.ipynb

Важность функций и моделирование: https://github.com/Shikhargupta/kaggle_house_pricing/blob/master/Ensemble.ipynb

Набор данных Ames Housing

Прежде чем приступить к процессу, давайте кратко рассмотрим рассматриваемый набор данных. Он имеет 80 столбцов (характеристик), каждый из которых описывает конкретный аспект дома (например, район, коммунальные услуги, тип крыши и т. Д.), Которые могут или не могут играть роль при определении его цены (целевая переменная). Он состоит в общей сложности из 2920 наблюдений, 1460 из которых будут использоваться для подгонки (обучающие данные), а остальные - для определения того, насколько хорошо работает ваша модель (тестовые данные). . Наша цель - максимально точно спрогнозировать SalePrice для дома, принимая во внимание характеристики (возможно, не все). Я предлагаю вам просмотреть описание данных, чтобы понять, что означает каждое поле. Критерием оценки является среднеквадратичная ошибка (RMSE) между логарифмом прогнозируемого значения и логарифмом наблюдаемой продажной цены. Чем меньше балл, тем лучше предсказуемость вашей модели!

Очистка данных (выбросы и NAN)

Прежде всего, мы очистим наш набор данных, чтобы избежать каких-либо ошибок или неточностей, когда мы введем его в нашу модель.

Всегда помните, что конечная цель - обучить нашу модель машинного обучения, и данные должны быть подготовлены таким же образом. Помните, как любое действие, которое мы выполняем, может в конечном итоге улучшить или снизить эффективность регрессора / классификатора.

Например, наличие поля NAN может отправить программу обучения на бросок и выдать ошибку. Еще одним убийцей нашего прогноза может быть выброс. Имеющиеся у нас данные о жилье были собраны и сохранены вручную и подвержены человеческим ошибкам. Очевидно, большое (20 спален) или маленькое (10 кв. Футов LotArea) наблюдение может повернуть нашу модель в неверном направлении и повлиять на нашу оценку. Нам нужно либо избавиться от этих точек данных, либо соответствующим образом присвоить значения.

Что касается набора данных Ames Housing, мы хорошо справляемся с выбросами. Автор уже указал на предполагаемые выбросы в бумаге, которые я визуализировал здесь, на этом графике.

Точки данных с GrLivArea ›4000 являются выбросами из-за аномально высоких цен SalePrices и LivArea и должны быть удалены. Хотя больше ничего не упоминается, я обнаружил одно несоответствие в функции «GarageYr», которая показывает год постройки гаража в доме. Значение было 2027, что указывает на будущее. Вместо того, чтобы избавиться от наблюдения, я приписал его моде. Перед этим я убедился, что в доме есть гараж, проверив атрибут «GarageType». Перед внесением каких-либо изменений важно «знать свои данные», поэтому помните об этих небольших, но важных аспектах.

Для NAN я построил график для всех функций, имеющих хотя бы одну из них. Затем я проанализировал их один за другим и решил, как поступить с отсутствующим значением. Большинство из них были заменены режимом этой функции, но были некоторые особые случаи, подобные этому -

Функциональная инженерия

Это, несомненно, самая важная и трудоемкая часть процесса. Мой подход заключался в том, чтобы брать их по одному (80 из них!) и применять преобразования. Это может показаться громоздким, но поверьте мне, это поможет. Моя методология заключалась в том, чтобы визуализировать их с помощью разных графиков (seaborn дает вам красивые графики!) И основывать свое решение (либо оставить их с любыми изменениями, либо оставить их). Это хорошее время, чтобы использовать свои аналитические способности. Здесь нет ракетостроения, а набор данных очень интуитивно понятен (больше спален, выше цена) и логичен. Я объясню, что я сделал, на нескольких примерах в широких категориях.

Полиномы

Если вы планируете регрессировать на огромном наборе данных, линейный метод не должен быть единственным способом сделать это. Некоторые функции могут иметь связь с целевой переменной, которая не может быть выражена в единственной степени. Поэтому я вручную отобрал 10 переменных с наибольшей корреляцией (из корреляционной матрицы), создал их версии с квадратным, кубическим и квадратным корнем и добавил их в набор данных.

Непрерывные функции

Это те, которые имеют непрерывные значения, такие как LotArea, GarageArea, 1stFlrSF и т. Д. Моя тактика для такого рода функций заключалась в построении их графиков распределения и их диаграммы рассеяния с помощью SalePrice (наша целевая переменная). Вот фрагмент "LotFrontage"

Диаграмма разброса показывает, что влияние LotFrontage может быть не очень значительным на SalePrice, но это что-то, и мы его сохраним. Левый график показывает, насколько сильно искажено это распределение признаков. Всегда помните: чем ближе распределение к нормальному, тем лучше будет работать ваша модель прогнозирования. Итак, всегда старайтесь преобразовать свои данные, чтобы сделать их более нормальными. Обычно для этого используются следующие методы - преобразование журналов и биннинг. Я веду журнал здесь.

Некоторые функции могут показаться непрерывными, но лучше подойдут при преобразовании в категориальные. Например, характеристики, относящиеся к году (год постройки дома, год ремонта и т. Д.). Также есть другие неотъемлемые характеристики, такие как - количество спален, количество бассейнов, автомобили, которые могут поместиться в гараже. Все они будут иметь больше смысла, если преобразовать их в категориальные, и я сделал то же самое.

Категориальные функции

Все прерывистые переменные категоричны. Практика, которой я здесь придерживаюсь, заключается в том, чтобы визуализировать функцию, используя полосовой график и среднюю цену SalePrice для каждой категории. Возьмем для примера HeatingQC (качество нагрева):

Первый позволяет мне визуализировать количество домов в каждой категории и указывать на любые расхождения (как мы увидим позже). Второй помогает мне решить, рассматривать ли его как упорядоченную функцию (заменять каждую категорию целым числом) или создавать фиктивные переменные. Этот пример явно порядковый (например, самый высокий рейтинг, самая высокая средняя цена и т. Д.), Поэтому мы заменим их упорядоченными целыми числами. Коробчатые диаграммы также могут быть эффективным способом визуализации данных.

Отбросьте (бесполезные) функции

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

Полосная диаграмма показывает, что в большинстве домов тип улицы «Pave», а количество улиц для «Grvl» незначительно. Эта функция имеет почти постоянное поведение для всех цен на жилье и, следовательно, не способствует достижению цели. Мы можем отказаться от этой функции.

Точно так же для PoolArea значение равно 0 для большинства наблюдений (почти все дома не имеют бассейна) и, следовательно, не будет нам полезен при прогнозировании. Мы можем бросить это.

Важность функции

Даже после тщательного анализа всех функций некоторые избыточные функции могут ускользнуть от невооруженного глаза. Мы будем использовать встроенную функцию важности функции XGBoost, чтобы в дальнейшем идентифицировать незначительные столбцы и избавляться от них, прежде чем мы подойдем к нашей модели. Давайте сначала получим индекс для всех 324 функций, которые у нас есть после преобразований.

Мы видим, что многие из наших функций не влияют на определение SalePrice, и поэтому мы избавимся от них. После отказа от функций с оценкой 0 наш набор данных уменьшился с 324 столбцов до 218!

Моделирование машинного обучения

Наконец, та часть, для которой мы все это начали. Честно говоря, 90% нашей работы уже выполнено. Если у вас есть хорошо структурированный и плотный набор данных, моделирование будет легкой прогулкой. Я подготовил список самых известных регрессионных моделей, на которых я хотел подогнать свои данные (перечисленные далее в этом разделе). Затем я разделил свои тестовые данные на наборы для тестирования и проверки. Я обучил модель на тестовом наборе и оценил при валидации. Это помогло мне представить, какая модель работает лучше. Вот пример регрессора XGBoost.

Если вы заметили, я сделал преобразование журнала SalePrice, так как оно дает лучшее распределение. Получая результаты, я преобразовал цены обратно в исходную шкалу, взяв экспоненту от значения.

Настройка параметров

Каждая регрессионная модель имеет собственный набор параметров, которые очень чувствительны к набору данных, на котором она обучается. Если вы хотите получить высокооптимизированные результаты (а вы это делаете!), То обязательно иметь наиболее эффективный набор параметров. Обычный способ - запустить поиск по сетке с помощью GridSearchCV, но это требует значительных вычислительных мощностей. Если у вас нет доступа к графическому процессору, лучше избегайте его (моему MacBookPro потребовалось более 7 часов для XGBoost, и он все равно мог завершить поиск). Альтернативный способ - выполнить анализ параметров, в котором мы оцениваем нашу тренировку, изменяя один параметр и оставляя остальные неизменными. Для этого нужно иметь четкое представление о диапазоне значений, которые могут подходить для параметра, который мы проверяем. Вот пример поиска альфы для RidgeRegressor.

Ансамбль

Итак, до сих пор у нас есть оценки отдельных регрессионных моделей. Но не лучше ли было бы взвесить прогнозы всех моделей и получить общий результат? У каждой модели есть своя изюминка. Некоторые лучше извлекают определенную информацию из данных, а некоторые более восприимчивы к другим. Было бы лучше, если бы мы проконсультировались с различными моделями, а затем составили окончательный прогноз. Это называется ансамбль. При этом мы обучаем все наши модели на обучающих данных, а при прогнозировании объединяем результаты. Эта комбинация может быть чем угодно - среднее всех значений, средневзвешенное значение и т. Д. Я использовал вариант взвешенного среднего и выбрал веса в соответствии с тем, как отдельные модели работали на проверочном наборе. Вот код.

Заключение

Хотя эксперименты с различными моделями на поверхности могут дать вам хорошие результаты, но важно понимать математику, лежащую в основе этого, чтобы в будущем вы могли выбрать регрессор, рассуждая. Кроме того, мой способ, безусловно, не лучший подход к этой проблеме ценообразования на жилье, и вы можете придумать свой собственный, так что продолжайте пытаться!