Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Вступ

Привіт!

У цій статті я поділюся досвідом побудови мікросервісної архітектури для проекту, що використовує нейронні мережі.

Поговоримо про вимоги до архітектури, подивимося різні структурні діаграми, розберемо кожен із компонентів готової архітектури, і навіть оцінимо технічні метрики рішення.

Приємного читання!

Пару слів про завдання та її вирішення

Основна ідея – на основі фото дати оцінку привабливості людини за десятибальною шкалою.

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

Зараз ми верхньорівнево пройдемося по пайплайну оцінки, а наголос зробимо на взаємодію мікросервісів у контексті загальної архітектури проекту. 

При роботі над пайплайном оцінки привабливості, завдання було декомпозовано на наступні складові:

  1. Виділення осіб на фото
  2. Оцінка кожної з осіб
  3. Рендер результату

Перше вирішується силами передбаченої MTCNN. Для другого була навчена згорткова нейромережа на PyTorch, як backbone був використаний ResNet34 - з балансу "якість / швидкість інференсу на CPU"

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Функціональна діаграма пайплайну оцінки

Аналіз вимог до архітектури проекту

У життєвому циклі ML Проекти етапи роботи над архітектурою та автоматизацією розгортання моделі, найчастіше, одні з найвитратніших за часом та ресурсами.

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Життєвий цикл ML проекту

Даний проект не виняток - було прийнято рішення обернути пайплайн оцінки в онлайн-сервіс, для цього потрібно поринути в архітектуру. Були окреслені такі базові вимоги:

  1. Єдине сховище логів – усі послуги повинні писати логи в одне місце, їх має бути зручно аналізувати
  2. Можливість горизонтального масштабування сервісу оцінки як найбільш ймовірного Bottleneck
  3. На оцінку кожного зображення має бути виділена однакова кількість ресурсів процесора — щоб уникнути викидів у розподілі часу на інференс
  4. Швидке (пере)розгортання як конкретних сервісів, так і стека загалом
  5. Можливість, за необхідності, використовувати у різних сервісах спільні об'єкти

Архітектура

Після аналізу вимог стало очевидним, що мікросервісна архітектура вписується практично ідеально.

Для того, щоб позбутися зайвого головного болю, як фронтенд був обраний Telegram API.

Для початку розглянемо структурну діаграму готової архітектури, далі перейдемо до опису кожного компонента, а також формалізуємо процес успішної обробки зображення.

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Структурна діаграма готової архітектури

Поговоримо докладніше про кожен із компонентів діаграми, позначимо їх Single Responsibility у процесі оцінки зображення.

Мікросервіс «attrai-telegram-bot»

Цей мікросервіс інкапсулює всі взаємодії з Telegram API. Можна виділити 2 основних сценарії - робота з зображенням користувача і робота з результатом пайплайна оцінки. Розберемо обидва сценарії у загальному вигляді.

При отриманні повідомлення користувача із зображенням:

  1. Проводиться фільтрація, що складається з наступних перевірок:
    • Наявність оптимального розміру зображення
    • Кількості зображень користувача, що вже перебувають у черзі
  2. Під час проходження первинної фільтрації зображення зберігається у docker volume
  3. У чергу “to_estimate” прод'юситься тяга, в якій, у тому числі, фігурує шлях до зображення, що лежить у нашому volume
  4. Якщо перераховані вище етапи пройдені успішно – користувач отримає повідомлення з приблизним часом обробки зображення, яке розраховується на основі кількості тяган у черзі. У разі помилки користувач буде явним чином про це сповіщено шляхом надсилання повідомлення з інформацією про те, що могло піти не так.

Також, цей мікросервіс, як celery worker, слухає чергу "after_estimate", яка призначається для тяган, що пройшли через пайплайн оцінки.

При отриманні нової таски з “after_estimate”:

  1. Якщо зображення оброблено успішно – надсилаємо результат користувачеві, якщо ні – сповіщаємо про помилку
  2. Видаляємо зображення, що є результатом пайплайну оцінки

Мікросервіс оцінки «attrai-estimator»

Даний мікросервіс є celery worker та інкапсулює в собі все, що пов'язано з пайплайною оцінкою зображення. Алгоритм роботи тут один – розберемо його.

При отриманні нової таски з “to_estimate”:

  1. Проганяємо зображення через пайплайн оцінки:
    1. Завантажуємо зображення на згадку
    2. Наводимо зображення до потрібного розміру
    3. Знаходимо всі особи (MTCNN)
    4. Оцінюємо всі особи (повертаємо знайдені в минулому пункті особи в батч та інференсим ResNet34)
    5. Рендерим підсумкове зображення
      1. Малюємо bounding boxes
      2. Малюємо оцінки
  2. Видаляємо користувача (вихідне) зображення
  3. Зберігаємо вихід з пайплайну оцінки
  4. Кладемо таску в чергу "after_estimate", яку слухає розібраний вище мікросервіс "attrai-telegram-bot"

Graylog (+ mongoDB + Elasticsearch)

Сірий - Це рішення для централізованого управління логами. У цьому проекті він використовувався за своїм прямим призначенням.

Вибір упав саме на нього, а не на звичний для всіх ELK стек, через зручність роботи з ним з-під Python. Все, що потрібно зробити для логування в Graylog, це додати GELFTCPHandler з пакета graypy до решти root logger handlers нашого python-мікросервісу.

Я, як людина, яка до цього працювала тільки з ELK стеком, загалом отримала позитивний досвід під час роботи з Graylog. Єдине, що пригнічує - перевага за фіч Kibana над веб-інтерфейсом Graylog.

RabbitMQ

RabbitMQ – це брокер повідомлень на основі протоколу AMQP.

У цьому проекті він використовувався як найбільш стабільний та перевірений часом брокер для Celery і працював у тривалому режимі.

Redis

Redis - це NoSQL СУБД, що працює зі структурами даних типу "ключ - значення"

Іноді виникає потреба використовувати в різних python-мікросервісах спільні об'єкти, що реалізують будь-які структури даних.

Наприклад, у Redis зберігається hashmap виду «telegram_user_id => кількість активних тасок у черзі», що дозволяє обмежити кількість запитів від одного користувача певним значенням і тим самим запобігти DoS-атакам.

Формалізуємо процес успішної обробки зображення

  1. Користувач надсилає зображення в Telegram бота
  2. attrai-telegram-bot отримує повідомлення від Telegram API і розбирає його
  3. Таск із зображенням додається до асинхронної черги «to_estimate»
  4. Користувач отримує повідомлення з запланованим часом оцінки
  5. «attrai-estimator» бере таск із черги «to_estimate», проганяє через пайплайн оцінки та прод'юсить таск у чергу «after_estimate»
  6. «attrai-telegram-bot», який слухає чергу «after_estimate», надсилає результат користувачеві

DevOps

Нарешті після огляду архітектури можна перейти до не менш цікавої частини — DevOps

Докер-рій

 

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Докер-рій  — система кластеризації, функціонал якої реалізований усередині Docker Engine та доступний із коробки.

За допомогою «рою» всі ноди нашого кластера можна розділити на 2 типи – worker і manager. На машинах першого типу розгортаються групи контейнерів (стеки), машини другого типу відповідають за скалювання, балансування та інші класні фічі. Менеджери за замовчуванням є воркерами.

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Кластер з одним leader manager та трьома worker

Мінімально можливий розмір кластера – 1 нода, єдина машина одночасно виступатиме як leader manager та worker. Виходячи з розміру проекту та мінімальних вимог до відмовостійкості, було прийнято рішення використати саме цей підхід.

Забігаючи вперед, скажу, що з моменту першої production-поставки, яка була в середині червня, проблем, пов'язаних з даною організацією кластера, не було (але це не означає, що подібна організація хоч скільки-небудь допустима у будь-яких середньо-великих проектах, на які накладаються вимоги щодо відмовостійкості).

Docker Stack

У режимі "рою" за розгортання стеків (наборів docker services) відповідає docker stack

Він підтримує docker-compose конфіги, дозволяючи додатково використовувати параметри deploy.  

Наприклад, за допомогою даних параметрів були обмежені ресурси на кожен з інстансів мікросервісу оцінки (виділяємо на N інстансів N ядер, в самому мікросервісі обмежуємо кількість ядер, використовуване PyTorch`єм, одним)

attrai_estimator:
  image: 'erqups/attrai_estimator:1.2'
  deploy:
    replicas: 4
    resources:
      limits:
        cpus: '4'
    restart_policy:
      condition: on-failure
      …

Redis, RabbitMQ і Graylog — stateful сервіси і масштабувати їх так само просто, як «attrai-estimator», не вийде

Передбачаючи питання, чому не Kubernetes?

Здається, що використання Kubernetes у проектах маленького та середнього розміру – оверхід, весь необхідний функціонал можна отримати від Docker Swarm, який досить user friendly для оркестратора контейнерів, а також має низький поріг входження.

Інфраструктура

Розгорталося це все на VDS з наступними характеристиками:

  • CPU: 4 ядра Intel Xeon Gold 5120 CPU @ 2.20GHz
  • Оперативна пам'ять: 8 GB
  • SSD: 160 ГБ

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

Але, одразу після деплою, я запостив посилання на одну з найпопулярніших у СНД іміджборд (ага, ту саму), після чого люди зацікавилися і за кілька годин сервіс успішно обробив десятки тисяч зображень. При цьому в пікові моменти ресурси CPU та RAM не були використані навіть наполовину.

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж
Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Ще трохи графіки

Кількість унікальних користувачів та запитів на оцінку, з моменту деплою, залежно від дня

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Розподіл часу інференсу пайплайну оцінки

Загальний огляд архітектури сервісу для оцінки зовнішності на основі нейронних мереж

Висновки

Резюмуючи, можу сказати, що архітектура та підхід до оркестрації контейнерів повністю себе виправдали — навіть у пікові моменти не було падінь та просідань за часом обробки. 

Думаю, проекти маленького та середнього розмірів, що використовують у своєму процесі реалтайм інференс нейронних мереж на CPU, успішно можуть запозичити практики, описані в цій статті.

Додам, що спочатку стаття була більшою, але щоб не постити лонгрід, вирішив деякі моменти в цій статті опустити — повернемося до них у наступних публікаціях.

Потикати бота можна в Telegram - @ AttraiBot, працюватиме, як мінімум, до кінця осені 2020 року. Нагадаю - ніякі дані користувача не зберігаються - ні вихідні зображення, ні результати пайплайна оцінки - все зноситься після обробки.

Джерело: habr.com

Додати коментар або відгук