Всем привет,

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

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

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

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

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

Для получения дополнительной информации о Reactive Systems перейдите по этой ссылке.

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

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

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

Конкретная информация, которую собрал Клейн, была:

  • Имя, просто для справки.
  • Мидихлориан, число, которое можно использовать для измерения чувствительности к Силе.
  • Виды
  • Пол
  • Родной мир, планета рождения
  • Сторона

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

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

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

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

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

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

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

Затем Кланус нанял Муканби, известного вуки с большим опытом разработки реактивных систем в соответствии с принципами DevOps:

Работая вместе, они сменили первоначальную монолитную архитектуру на другую, полностью распределенную. Итак, вторая версия приняла форму, подобную приведенной ниже:

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

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

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

В этом новом дизайне каждый раз, когда веб-приложению, транзакционной системе, требовалось запросить прогноз, единственное, что ему нужно было сделать, - это отправить сообщение JSON, подобное этому:

{
  "name": "Manuel Lara",
  "midichlorian": 13000,
  "species": "human",
  "gender": "male",
  "homeworld": "Naboo"
}

На что аналитическая система ответит сообщением, очень похожим на это другое:

{
  "side": "Sith",
  "error": "less than 17%"
}

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

Таким образом, новая аналитическая система состояла из двух компонентов:

  • Генератор модели: приложение Scala, использующее структуру Apache Spark для непрерывного изучения модели.
  • Служба прогнозирования: приложение Java, которое использовало Spring Boot для предоставления службы REST, способной делать прогнозы с использованием последней модели, созданной предыдущим компонентом.

Первый компонент был реализован с использованием Scala только потому, что Apache Spark был создан с использованием этого языка программирования.

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

Также интересно отметить, что оба компонента использовали библиотеку MLeap, которая позволяла компоненту службы REST избегать использования библиотек Spark, которые очень тяжелы и чрезвычайно зависят от сервер Spark.

MLeap - отличная библиотека, способная работать с моделями, созданными с помощью Spark, Scikit-learn или Tensorflow. Для получения дополнительной информации перейдите по этой ссылке.

Но Реактивная система не только состоит из компонентов, которые взаимодействуют друг с другом посредством сообщений, они также должны быть эластичными и устойчивыми. Для этого оба компонента, генератор моделей и служба прогнозирования были развернуты как контейнеры Docker поверх Kubernetes .

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

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

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

Для получения дополнительной информации о встроенной интеграции между Spark и Kubernetes перейдите по этой ссылке.

На следующем рисунке показано, какой была архитектура системы внутри Kubernetes во время создания модели:

Пунктирная область - генератор модели - может считаться эфемерным. Он существует только тогда, когда создается новая модель.

Как вы могли видеть, новая архитектура соответствовала манифесту Reactive System, отражающему ее принципы:

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

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

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

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

В рамках обязательства я постараюсь осветить следующие темы:

  • Непрерывная интеграция. В этой статье я намерен добавить платформу CI и репозиторий артефактов для автоматизации их состояний сборки, тестирования и развертывания.
  • Оптимизация машинного обучения. В этой статье я хотел бы показать, как повысить точность модели, а также представить Ballerina, еще один замечательный язык для создания API.
  • Нейронные сети. Эта статья будет продолжением предыдущей в рамках оптимизации модели. В этой статье я намерен добавить в аналитическую систему Tensorflow.
  • Мониторинг и оповещение. Все системы необходимо отслеживать и улучшать на основе показателей производительности. В этой статье я намерен включить в систему ELK (Elasticsearch, Logstash и Kibana).