Авторы Павлос Мицулис Нтомпос и Стефано Бонетти

Вступление

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

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

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

Чтобы сделать это более конкретным, давайте рассмотрим пример.

В HomeAway мы привлекаем партнеров (то есть владельцев недвижимости), которые хотят разместить свою недвижимость на нашем веб-сайте. В маркетинговых целях мы хотим спрогнозировать LTV нашего партнера. Вы когда-нибудь слышали о LTV? Нет, это не телеканал. Вот как это определяет Википедия:

В маркетинге […] жизненная ценность (LTV) - это прогноз чистой прибыли, относящейся ко всем будущим отношениям с покупателем. Модель прогнозирования может иметь различные уровни сложности и точности, от грубой эвристики до использования сложных методов прогнозной аналитики.

В нашем случае LTV определяется практически как «сколько денег партнер заработает нам в первый год». Из-за сезонности нашего бизнеса это хороший показатель общего LTV.

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

Итак, мы хотим создать сервис, который прогнозирует наш LTV.

Дизайн и развитие

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

ОСТОРОЖНО: это означает жертвовать с точки зрения количества раствора, а не его качества.

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

Если мы рассмотрим наш предиктор LTV в качестве примера, нам нужно задать себе следующий вопрос: что мы можем сделать, чтобы получить LTV как можно скорее? Один из вариантов - сначала использовать статические значения. Легкий. Например, мы могли бы начать с решения на основе правил, которое берет новый листинг, проверяет его местоположение и ищет его LTV в статической таблице.

Таким образом, наши требования значительно сократились, и они не требуют машинного обучения.

Такое построение системы дает два преимущества:

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

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

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

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

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

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

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

CI/CD

Непрерывная интеграция и непрерывная доставка - широко используемые практики в разработке программного обеспечения. Доступны различные инструменты и платформы для обеспечения различных возможностей CI / CD. Однако все конвейеры CI / CD разделяют одни и те же общие шаги:

  • все изменения кода привязаны к какой-либо разновидности системы контроля версий, такой как Git;
  • инструмент CI / CD обнаруживает новое изменение, запускает автоматические тесты и создает все соответствующие артефакты;
  • если тесты проходят, артефакты развертываются во всех соответствующих средах и, наконец, в ожидании проверки, в производственной среде.

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

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

Тестируя модели машинного обучения, мы задаем следующий вопрос: «Моя новая модель лучше базовой?». Наш простой подход к ответу на этот вопрос заключается в следующем:

  1. выберите набор данных удержания, который будет использоваться для испытаний модели. Этот набор данных должен быть достаточно небольшим, чтобы избежать слишком сильного замедления конвейера CI / CD;
  2. рассчитать точность как для новой, так и для базовой модели, сделав прогнозы на основе отложенного набора данных;
  3. утверждать, что новая точность выше базовой.

В HomeAway в настоящее время мы используем Средняя абсолютная ошибка (MAE) и Среднеквадратическая ошибка (RMSE) в качестве показателей точности в тестах модели нашего предиктора LTV.

def test_ml_models(hold_out_dataset):
 # Mean Absolute Error and Root Mean Square Error For Baseline Model
 baseline_mae, baseline_rmse = _error_for_baseline(hold_out_dataset)
 
 # Mean Absolute Error and Root Mean Square Error For New Model
 new_model_mae, new_model_rmse = _error_for_new(hold_out_dataset)
 
 assert new_model_mae < baseline_mae
 assert new_model_rmse < baseline_rmse

Мониторинг

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

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

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

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

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

TL;DR

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

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

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