написано Кристианом Дегером и Арифом Видером

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

Работая вместе, AutoScout24 и ThoughtWorks смогли разработать постоянно обновляемый инструмент оценки цен, который обеспечивает превосходную производительность и масштабируемость, используя подход Continuous Delivery к прогнозной аналитике. Мы внедрили автоматическую проверку с использованием наборов данных для тестирования в реальном времени в конвейере непрерывной доставки, чтобы мы могли с уверенностью выпускать улучшения модели в любой момент времени.

Постоянная оценка цен

AutoScout24 предлагает более 2,4 млн автомобилей по всей Европе. Это дало ему огромный клад текущих и исторических данных. Но как он может использовать это, чтобы помочь продавцам определить справедливую цену, а покупателям принять правильное решение?

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

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

Наука о данных и непрерывная доставка

До программы оценки цен AutoScout24 использовал прогнозную аналитику в основном для внутреннего принятия решений и поиска ответов на вопросы на основе исторических данных.

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

Чтобы достичь этого результата, мы поняли, что есть возможность использовать подход Continuous Delivery к предиктивной аналитике. Как правило, в разработке программного обеспечения все чаще используются такие концепции, как непрерывная поставка, разработка через тестирование и контракты, управляемые потребителем. Они почти не встречаются в практике Data Science.

Ускорение доставки с помощью сервисных команд

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

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

Было решено внедрить инструмент оценки цен в виде единого микросервиса, работающего на Amazon Web Services (AWS), с использованием Play Framework для обеспечения наибольшей гибкости.

Использование Random Forest для более точных прогнозов

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

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

Мы использовали язык статистического программирования «R», для которого доступны библиотеки случайного леса, для разработки начального сценария обучения модели. Этот сценарий обрабатывает и очищает необработанные данные о транспортных средствах за последние годы, а затем создает модель прогнозирования цен.

От модели прогнозирования цен до продукта для оценки автомобилей

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

Это означало, что ценовая модель, обучение которой мы указали в R, должна была иметь возможность автоматически переноситься в производственную систему без изменения ее поведения.

Одним из очевидных решений было предоставление ценовой модели непосредственно в среде выполнения R через соответствующий сервис, доступ к которому затем осуществлялся из клиентского приложения Play Framework через REST API. К сожалению, версия среды выполнения R с открытым исходным кодом не поддерживает многопоточность, что делает практически невозможным масштабирование для нескольких параллельных пользовательских запросов.

Поэтому мы решили использовать H2O, механизм прогнозной аналитики с открытым исходным кодом на основе Java, который можно легко интегрировать с проектами Apache Hadoop и Spark. Он также подключается к другим языкам программирования, популярным в области больших данных, таким как Python и R.

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

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

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

Время отклика в миллисекундах требует правильного подхода

В целом наш подход к экспорту обученных моделей прогнозирования в исходный код Java давал ключевое преимущество в том, что JAR-файл скомпилированной ценовой модели можно запускать вместе с веб-приложением Play (которое также можно развернуть как JAR) на одном и том же компьютере Amazon EC2 и в одна JVM. Это значительно снижает сложность обслуживания, поскольку необходимо настраивать и контролировать только использование памяти этой JVM.

Кроме того, мы могли полностью использовать уже доступные механизмы масштабирования как JVM (пулы потоков, параллелизм), так и AWS. Play Framework в значительной степени основывается на поддержке неблокирующего ввода-вывода Java. Благодаря эластичным балансировщикам нагрузки (ELB) и группам автомасштабирования (ASG) AWS предоставляет возможность автоматически и с учетом нагрузки поднимать новые машины EC2 с помощью одного и того же веб-приложения и распределять нагрузку между этими машинами.

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

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

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

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

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

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

Цена непрерывной доставки: обширное сквозное тестирование

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

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

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

Результаты этих оценок тестовых цен служат двум целям: во-первых, качество модели может быть определено путем сравнения фактических цен с ценами в наборе тестовых данных. Во-вторых, результаты можно сравнить с результатами, полученными при доступе к ценовой модели, преобразованной в байт-код Java.

Выводы

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

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

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

Вопросы или комментарии? Свяжитесь с нами в Твиттере: Кристиан и Ариф.