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

Это имеет смысл в часы пик, но это сообщение также появляется в некоторые нечетные часы (15:00). Итак, на Kaggle был задан интересный вопрос: влияет ли погода каким-либо образом на множитель всплеска? В частности, какую роль внешние погодные условия играют в воздействии на баланс между спросом и предложением, который, в свою очередь, повышает мультипликатор всплеска?

Это была постановка проблемы, которую я и моя команда в программе MSBA в Вашингтонском университете решили исследовать.

Набор данных:

Ссылка на набор данных: https://www.kaggle.com/datasets/ravi72munde/uber-lyft-cab-prices

Описание набора данных:

В наборе данных есть 2 файла.

  1. Набор данных о ценах на другие такси Убер/Лифт, собранный за 18 нояб. — 18 дек. 2018 г.
# of records = 693,071
# of columns = 10

This data was collected by querying the Uber API every 5 mins to get the 
price details, surge multiplier for trips between each possible pair of 
districts in the Boston area.

Columns:
1) distance
2) cab_type
3) time_stamp
4) destination
5) source
6) price
7) surge_multiplier
8) id
9) product_id
10) name

2. Набор данных о погодных условиях для всех районов Бостона.

# of records = 6,276
# of columns = 7

This data was collected by querying a popular weather app 
(app source not mentioned) every 1 hour.

Columns: 
1) temp
2) clouds
3) pressure
4) rain
5) time_stamp
6) humidity
7) wind

Обработка и очистка данных

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

Сначала мы извлекли месяц, год, день из метки времени. Фрагмент кода показан ниже.

weather['hour'] = weather.apply(lambda x : dt.datetime.fromtimestamp(x['time_stamp']).hour, axis = 1)
weather['day'] = weather.apply(lambda x : dt.datetime.fromtimestamp(x['time_stamp']).day, axis = 1)
weather['year'] = weather.apply(lambda x : dt.datetime.fromtimestamp(x['time_stamp']).year, axis = 1)
weather['month'] = weather.apply(lambda x : dt.datetime.fromtimestamp(x['time_stamp']).month, axis = 1)
weather['minute'] = weather.apply(lambda x : dt.datetime.fromtimestamp(x['time_stamp']).minute, axis = 1)
weather['day_of_the_week'] = weather.apply(lambda x : dt.datetime.fromtimestamp(x['time_stamp']).weekday(), axis = 1)

После извлечения отдельных полей было выполнено окончательное слияние двух наборов данных с использованием панд, показанных ниже:

merged_df = pd.merge(merged_df, weather, on = ['hour', 'day', 'location', 'year', 'month'])

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

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

Кроме того, измерение дождя отсутствовало для 86% собранных данных о погоде. Мы считали это отсутствием дождя. (сделано предположение, поскольку процесс сбора данных был не очень ясен).

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

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

Добавил пару визуализаций, которые оказались наиболее актуальными.

Множитель всплеска 1,25 наиболее распространен во все дни недели. И поскольку мы предполагаем, что всплеск увеличивается линейно, мы можем сказать, что множитель всплеска обычно увеличивается до 1,5 довольно часто и лишь изредка доходит до 2.

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

Постановка задачи

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

Принимая во внимание приведенную выше постановку проблемы, мы создали новый столбец с именем всплеск_индикатор, который является категориальным столбцом, который равен 0, если множитель всплеска равен 1, и 1, если множитель всплеска больше 1.

Теперь наша постановка задачи состоит в том, чтобы предсказать эту переменную всплеска_индикатора на основе внешних погодных условий.

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

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

Логистическая регрессия

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

Следующим шагом была попытка найти осмысленные группы погодных переменных, и, основываясь на некоторых данных из этого https://www.noaa.gov/education, мы пришли к следующим группам:

Wind speed ·············: [0-3.5 mph], [3.5-7 mph], [7-10 mph], [10-18 mph]​

is_raining·················1 for “raining”, 0 for “not raining”​

rush_hour················1 for [Weekday 6-10am & 3-7pm],  0 for others​

Freezing_pt··············1 for “below 32F”, 0 for “above 32F”​

Cloudy ·····················1 for “above 50% cloud coverage”, 0 for “lower”​

Night life··················1 for “Friday and Saturday from 10pm-3am”, 0 for others

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

Кроме того, поскольку у нас большой дисбаланс классов в нашем наборе данных (около 94 % поездок без всплеска, 6 % поездок с всплеском), нам пришлось снизить порог вероятности ниже 0,075, чтобы предсказать индикатор всплеска.

Это была точность для этой модели:

Точность ~ 21%, при очень высокой скорости FP ~ 82%

Значимые переменные: час_пик (уровень значимости 1%), скорость ветра (уровень значимости 10%).

Измененная постановка задачи, PCA и деревья решений

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

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

Для группировки наших погодных переменных мы решили использовать PCA, чтобы сгруппировать наши погодные переменные вместе. Это помогло бы нам лучше объяснить изменчивость всех различных параметров погоды с точки зрения меньшего количества признаков.

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

Это 5 основных компонентов, которые мы получили после применения преобразования PCA к нашим погодным переменным. Мы решили использовать первые 4 из этих основных компонентов, которые объясняют 80% изменчивости между переменными. Мы переименовали наши основные компоненты следующим образом:

PC1 = pressure_imp (due to a positive coefficient on pressure)
PC2 = wind_imp (due to a positive coefficient on wind)
PC3 = temp_imp (due to a positive coefficient on temperature)
PC4 = humidity_imp (due to a positive coefficient on humidity)

На приведенном выше графике представлены районы, упорядоченные по количеству поездок, для которых показатель всплеска = 1. Для нашего анализа мы использовали первые 3 района с максимальным количеством поездок в случае всплеска.

Окончательное дерево решений для поездок из Бикон-Хилл (регион с наибольшим количеством поездок в случае всплеска). Поскольку интерпретация основных компонентов немного сложна, в этом случае обычно легко интерпретировать деревья также сложно. Но наша точность с использованием этого нового подхода увеличилась до ~ 43%, а скорость FP снизилась до ~ 58%.

Таким образом, это дало нам хороший показатель того, что мы делаем что-то правильно. Следующим шагом в этом процессе будет использование повышения и итеративное построение дерева с использованием XGBoost и использование совокупности прогнозов для разных деревьев с использованием случайного леса.

Для всего кода, используемого в этом проекте до сих пор, вот ссылка github на репозиторий: https://github.com/creed123/Lyft-surge-prediction