Сквозной проект машинного обучения, а также объяснения и решения некоторых проблем, с которыми я столкнулся.

О проекте

В этом проекте я проведу вас через сквозную задачу машинного обучения, работающую с набором данных Airbnb в Лос-Анджелесе. Набор данных был получен от Inside Airbnb (Ссылка).

Цена будет моим целевым вектором, так как я буду прогнозировать посуточные тарифы Airbnb в Лос-Анджелесе, принимая во внимание несколько независимых переменных, таких как район, количество спален, залог и т. д.

Это проблема регрессии обучения с учителем, поскольку у нас есть метка, и она непрерывна.

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

Макет проекта

Этот проект работал в следующие этапы:

  1. Исследовательский анализ данных (EDA)
  2. Подготовьте данные
  3. Разделить набор данных
  4. Базовая модель
  5. Конвейеры трансформации
  6. Шорт-лист перспективных моделей
  7. Тонкая настройка потенциальных моделей
  8. Важность перестановки
  9. Использование графиков для объяснения прогнозов для окончательной модели

Исследовательский анализ данных (EDA)

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

Изучая данные, я обнаружил множество независимых переменных, которые были уникальными, и некоторые из них имели высокий процент нулевых значений. Затем я смог удалить множество переменных, которые, казалось, не добавляли никакой ценности.

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

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

Наблюдения:

  1. В наборе данных много выбросов
  2. Наша целевая переменная сильно искажена
  3. Долгота и широта — единственные переменные, которые не искажены.
  4. Ванные комнаты, спальни, размещение, guest_included, security_deposit, clean_fee сильно коррелируют с нашим целевым вектором, ценой; выбросы затрудняют просмотр.

Подготовьте данные

Я разделил подготовку данных на следующие этапы:

  1. Исправление функций с высокой кардинальностью
  2. Исправить или удалить выбросы
  3. Выбор функции
  4. Разработка функций

Исправление функций с высокой кардинальностью

Чтобы исправить атрибуты с высокой кардинальностью, которые были слишком важны для нашей модели, чтобы их можно было удалить, я поместил все значения, которые не имели большого веса, в «Другое», что значительно уменьшило количество уникальных значений.

Исправить или удалить выбросы

Трудно поверить, что кто-то потратит 25 000 долларов на аренду Airbnb на ночь. Эти выбросы могут быть вызваны множеством возможных причин. Я рассматривал только те объекты, которые стоили менее 1000 долларов за ночь. На изображении ниже показано сравнение коробчатой ​​диаграммы до и после того, как выбросы были отфильтрованы.

Это снизило асимметрию цены с 13,4 до 2,87. Это еще достаточно высоко! Об этом можно позаботиться, используя журнал, когда мы обучаем модель. Если вы берете логарифм целевой переменной, чтобы соответствовать модели, всегда не забывайте переворачивать логарифм, используя экспоненту, перед прогнозированием.

Выбор функции

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

Разработка функций

Почтовый индекс является номинальной категориальной характеристикой. Он мог быть либо закодирован как число/=, либо как частота. После некоторой очистки я считаю закодированный почтовый индекс с помощью функции карты.

Кодирование количества основано на замене категорий их количеством. Этот метод чувствителен к выбросам, но поскольку мы работаем с почтовым индексом, он нас не затронет.

У удобств есть много информации, которая могла бы помочь нам в прогнозировании нашей целевой переменной, если бы мы каким-то образом смогли извлечь информацию из текстового столбца. Обработка естественного языка (NLP) казалась единственным ответом. Я смог извлечь ценную информацию из удобств с помощью НЛП, что помогло значительно уменьшить ошибку оценки.

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

Разделить набор данных

Глядя на матрицу корреляции ранее, мы знаем, что количество спален сильно коррелирует при прогнозировании цены за ночь на Airbnb в Лос-Анджелесе. Мы хотели бы разделить данные, чтобы убедиться, что тестовый набор репрезентативен для различных категорий нескольких спален во всем наборе данных.

В большинстве случаев количество спален в объекте находится в пределах от 1 до 3, но в некоторых объектах количество спален намного превышает 3. Важно иметь достаточное количество экземпляров в наборе данных из каждого слоя или оценку страты. важность может быть предвзятой.

Я создал новый столбец, который разделил на ячейки, убедившись, что слоев не слишком много, и что каждый слой достаточно велик. После того, как у нас есть новый столбец, все готово к стратифицированной выборке с использованием класса StratifiedShuffleSplit из Scikit-Learn.

Я не стал разбивать тест поезда на поезд и проверочный набор. Вместо этого я использовал cross_val_score из scikit-learn, чтобы увидеть, как модель соответствует тренировочному набору.

Базовая модель

Базовый уровень нашей модели с использованием средней абсолютной ошибки оказался равным 93,50.

Конвейеры трансформации

список трансформаторов, которые я использовал в конвейере:

  1. Simple Imputer с median в качестве стратегии для numerical attributes
  2. Simple Imputer с most_frequent в качестве стратегии для categorical attributes
  3. Порядковый кодировщик из библиотеки категориальных кодировщиков
  4. Стандартный масштабатор, поскольку линейные модели и машины опорных векторов лучше работают с масштабированными данными

Я сделал два отдельных конвейера; один для числовых атрибутов, а другой для категориальных атрибутов. Я собрал их вместе, используя класс ColumnTransformer из scikit-learn.

Я использовал только порядковый кодировщик для кодирования всех наших категориальных атрибутов, так как в итоге выбрал одну из моделей объединенного дерева в качестве своего окончательного выбора. Один Hot Encoder и наши древовидные модели не всегда хорошо сочетаются друг с другом. Если вы хотите подробнее изучить это, я бы порекомендовал вам прочитать эту статью (Ссылка).

Я столкнулся с проблемой при передаче Simple Imputer в категориальном конвейере, поскольку он будет передавать массив NumPy в качестве входных данных для порядкового кодировщика; что не очень обрадовало порядковый кодировщик. Затем мне пришлось создать собственный преобразователь, который применял бы категориальные нулевые значения и передал кадр данных порядковым кодировщикам.

Шорт-лист перспективных моделей

Мой подход в дальнейшем заключался в обучении ряда моделей из разных категорий (например, линейных, ансамблевых, машин опорных векторов и т. д.) с использованием стандартных параметров. Затем составьте короткий список моделей на основе их производительности, используя оценку перекрестной проверки.

Я также обучил регрессор голосования с тремя различными моделями (линейный регрессор,
регрессор с усилением градиента, регрессор машины опорных векторов). Он работал хорошо, но не смог превзойти Gradient Regressor.

Gradient Boosting Regressor, без сомнения, является нашей самой эффективной обобщенной моделью. Random Forest — единственная модель из списка, которая сильно переобучает.

Тонкая настройка потенциальных моделей

Gradient Boosting — это обобщенная модель, сбалансированная по дисперсии и смещению и не требующая гипернастройки. Хотя Random Forest переоснащает и имеет высокую дисперсию, возможно, гипернастройка модели поможет нам с переоснащением.

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

Вместо того, чтобы просто смотреть на среднюю точность по 10 перекрестным проверкам, давайте нанесем на график все 10 оценок для каждой модели вместе с блочной диаграммой, выделяющей нижний и верхний квартили, и «усами», показывающими размер оценок.

Это сложный выбор между Random Forest Regressor и Gradient Boosting Regressor. На этот раз я выберу случайный лесной регрессор, так как он лучше по средней абсолютной ошибке на 2 доллара. Мы могли бы использовать регрессор повышения градиента в зависимости от того, к чему мы стремились; меньше ошибок или меньше дисперсии.

Оценка набора тестов

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

Я мог бы также использовать НЛП в колонке описания, что могло бы еще больше снизить MAE.

Важность перестановки

Я столкнулся с несколькими проблемами при извлечении важности перестановки. Значение важности функции означает или стандартное отклонение важности функции, которое мы генерируем с использованием класса перестановки, имеет формат массива NumPy. Эти числа имели бы какой-то смысл только в том случае, если бы мы могли сгенерировать список столбцов и заархивировать его до важности функций (тип: numpy.array) или, возможно, сделать из него фрейм данных.

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

ЗАМЕТКА:

Библиотека предварительной обработки scikit-learn с кодировщиками категорий генерирует массив NumPy; что не решило бы нашу проблему.

Использование графиков для объяснения прогнозов для окончательной модели

Графики SHAP и графики частичной зависимости пригодятся, когда мы не используем модели линейного машинного обучения, поэтому для нас становится практически невозможно построить прогнозы нашей модели.

SHAP (аддитивные объяснения Шепли)

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

SHAP строит объяснения модели, задавая один и тот же вопрос для каждого прогноза и функции: «Как меняется прогноз I, когда функция j удаляется из модели?» Ответом на этот вопрос являются так называемые значения SHAP. Они количественно определяют величину и направление (положительное или отрицательное) влияния функции на прогноз.

Почтовый индекс, район и суперхозяин — три самые важные переменные, влияющие на цену Airbnb.

Графики частичной зависимости

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

Этот график говорит нам о важности гарантийного депозита как функции прогнозирования цены за ночь на Airbnb. По мере увеличения залога цена за ночь увеличивается до тех пор, пока залог не достигнет 100. Увеличение залога до более чем 100 больше не влияет на стоимость за ночь на Airbnb.

Спасибо за чтение и не стесняйтесь проверить код и веб-приложение.

Код: https://github.com/navroz-lamba/Prediciting-Airbnb-prices-in-LA

Веб-приложение: https://airbnb-la.herokuapp.com/