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

Приложение Celebrate — это облачное приложение, и вся наша инфраструктура находится в AWS. Мы выбрали бессерверный путь для развертывания решения ML, что имеет значительные последствия для стоимости и масштабируемости. Также было важно сделать это решение малой задержкой, а это значит, что нам нужно кластеризовать 1000–2000 изображений за миллисекунды.

Задача, которую мы хотели решить, — найти относительное сходство между изображениями. Поиск относительного сходства с оценкой от 0 до 1 поможет нам найти те кластеры изображений, которые имеют низкое, среднее и высокое сходство. Косинусное сходство — хороший показатель для нахождения такого попарного сходства между изображениями. Для этого нам сначала нужно найти представление изображения, иногда также называемое встраиванием, которое представляет собой одномерные векторы трехмерных (RGB) изображений. Мы получаем эти представления, применяя модель машинного обучения на основе искусственных нейронных сетей. Наше окончательное решение вычисляет представления изображений и сохраняет их в постоянном хранилище — AWS EFS. Таким образом, мы не только устранили пересчет представлений, но и значительно сократили время ожидания и стоимость. Мы вычисляем косинусное сходство только по запросу на основе доступных вложений, где пользователь указывает пороговые значения для фильтрации определенных изображений.

На высоком уровне наше решение можно разделить на три части:

  1. Пользователи приложения загружают изображение в S3, а S3 Notification добавляет новый ключ изображения в SQS. AWS Lambda опрашивает эту очередь SQS и вызывает конечную точку SageMaker, которая выводит представления изображений (встраивания).
  2. Выходные данные SageMaker отправляются в другую Lambda, которая сохраняет их в EFS.
  3. Lambda, которая вызывается через шлюз API, вычисляет похожие кластеры изображений в режиме реального времени и возвращает результат конечному пользователю.

Ниже вы можете увидеть упрощенную версию нашей архитектуры:

Детали каждой части нашего решения описаны ниже:

Часть 1 — вхождение данных. Изображения хранятся в S3, учитывая огромное количество вновь загруженных и существующих изображений, и использовать наш конвейер вычислений для всех этих изображений нецелесообразно. Таким образом, ключи изображения помещаются в SQS (через конечную точку API Gateway Rest Endpoint), которая позже опрашивается Lambda. Lambda загружает изображения, предварительно обрабатывает их, вызывает часть 2 компонента машинного обучения и отправляет результат в часть 3.

Часть 2. Машинное обучение. Наш конвейер машинного обучения в основном представляет собой нейронную сеть кодировщика, которая преобразует трехмерный массив (изображение RGB) в одномерный векторный массив. Мы экспериментировали с различными архитектурами нейронных сетей, такими как VGG, Resnet и даже кодировщиками на основе Transformer. По нашему опыту, эти предварительно обученные нейронные сети уже работали очень хорошо, но в будущем мы также планируем обучать автокодировщик CNN на наших собственных данных вместо того, чтобы полагаться на предварительно обученный кодировщик Imagenet. После некоторых внутренних экспериментов мы выбрали наиболее эффективную модель и развернули ее без использования сервера с помощью Sagemaker Serverless Endpoint в нашем регионе.

Часть 3. Кластеризация. Здесь мы используем три основных ресурса AWS. Функция Lambda выполняет запись в файловую систему EFS. EFS содержит одну папку изображений для каждого пользователя. У нас есть один файл для каждого пользователя, куда записываются все вложения ML. Несмотря на то, что это значительно повысило производительность чтения/записи, нам пришлось позаботиться о блокировке файлов, чтобы предотвратить одновременную запись. Мы группируем изображения по степени сходства, используя функцию косинусного сходства от scikit-learn.

Наше обучение и оптимизация:

1. Есть несколько вещей, которые мы сделали, чтобы уменьшить задержку нашего вызова Lambda (лямбда, которая вычисляет косинусное сходство):

1.1 Использование EFS в качестве файловой системы для Lambda значительно улучшило операции чтения/записи постоянных данных (представления изображений). EFS также включается в высокопроизводительном режиме (MaxIO), что еще больше повышает производительность чтения/записи этой Lambda. Мы выбираем EFS в качестве постоянного хранилища, а не S3, потому что они принципиально отличаются, а EFS имеет то преимущество, которого нет у S3, как указано в документах AWS: «Служба Lambda монтирует файловые системы EFS, когда среда выполнения подготовлена. Это добавляет минимальную задержку при первом вызове функции, часто в течение сотен миллисекунд. Когда среда выполнения уже разогрета после предыдущих вызовов, монтирование EFS уже доступно».

1.2 Холодный запуск в Lambda является основным фактором, вызывающим секундную задержку при импорте тяжелого кода, такого как наш. Холодный запуск, вызванный временем, необходимым для подготовки среды выполнения. Устранение холодного запуска Lambda с помощью Provisioned Concurrency позади Auto Scaling Group (ASG) значительно уменьшило задержку до миллисекунд. Мы также переместили статический код, такой как тяжелый импорт машинного обучения, в верхнюю часть обработчика Lambda. Эти изменения привели к 10-кратному уменьшению задержки.

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

1.4 Для любых матричных вычислений в массиве numpy мы устранили циклы везде, где это возможно, и сильно полагались на AVX2, расширение векторизации для набора инструкций Intel x86, которое может выполнять одну инструкцию с несколькими данными (SIMD). Опять же, мы наблюдали значительное уменьшение задержки, когда нам приходилось обрабатывать большие объемы представлений изображений в памяти.

1.5 Согласно некоторым общедоступным блогам, существует корреляция между памятью Lambda и временем выполнения функции. Мы попытались поэкспериментировать с разными объемами памяти и задержкой. Улучшение было постепенным.

2. Мы запускаем конвейер SageMaker Inference, который генерирует представления изображений (экокондеры) без сервера за ASG. Несмотря на то, что это должно было работать надежно, мы заметили некоторые ошибки регулирования с помощью AWS X-Ray. Мы считаем, что эта ошибка регулирования возникла из-за времени, необходимого ASG для масштабирования конечных точек SageMaker Inference. Добавление задержки доставки между сообщениями, так что SQS «ждет» миллисекунды перед вызовом Lambda (который также вызывает Sagemaker), устранило эту проблему.

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

Соответствующие ссылки:

Лямбда — ЭФС

https://aws.amazon.com/blogs/compute/using-amazon-efs-for-aws-lambda-in-your-serverless-applications/

Лямбда — AVX2 — SIMD

https://docs.aws.amazon.com/lambda/latest/dg/runtimes-avx2.html

Питон — fcntl

https://www.oreilly.com/library/view/python-standard-library/0596000960/ch12s02.html

Sagemaker Serverless Inference

https://docs.aws.amazon.com/sagemaker/latest/dg/serverless-endpoints.html

Архитектуры нейронных сетей компьютерного зрения

https://medium.com/analytics-vidhya/cnns-architectures-lenet-alexnet-vgg-googlenet-resnet-and-more-666091488df5

Лямбда-память и продолжительность

https://medium.com/geekculture/pick-the-right-memory-size-for-your-aws-lambda-functions-682394aa4b21