Serverless tensorflow на AWS Lambda

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


    Ввведение


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


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


    Мои коллеги называют это “коммодитизацией машинного обучения” и в чем-то они правы. Самое главное — что сегодня легко найти/скачать/натренировать модель и хочется иметь возможность также легко ее деплоить.


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


    Для решения такой задачи деплоя мне понравилось работать с облачными микросервисами.


    Amazon, Google и Microsoft недавно предоставили FaaS — function as a service. Они относительно дешевые, их легко деплоить (не требуется Docker) и можно параллельно запускать практически неограниченное количество сущностей.


    Сейчас я расскажу, как можно задеплоить модели TensorFlow/Keras на AWS Lambda — FaaS от Amazon. Как итог — API для распознавания содержания на изображениях стоимостью 1$ за 20000 распознаваний. Можно дешевле? Возможно. Можно проще? Вряд ли.


    Function-as-a-service


    Рассмотрим диаграмму различных видов деплоя приложений:


    Image


    Слева мы видим on premise — когда мы владеем сервером. Далее мы видим Infrastructure-as-a-Service — здесь мы уже работаем с виртуальной машиной — сервером, расположенным в датацентре. Следующий шаг — Platform-as-a-Service, когда у нас уже нет доступа к самой машине, но мы управляем контейнером в котором будет исполняться приложение. И наконец-то Function-as-a-Service, когда мы контролируем только код, а все остальное спрятано от нас. Это хорошие новости, так как мы увидим позже, что дает нам очень крутую функциональность.


    AWS Lambda — это имплементация FAAS на платформе AWS. Кратко про имплементацию. Контейнером для него является zip архив [код + библиотеки]. Код такой же как на локальной машине. AWS разворачивает этот код на контейнерах в зависимости от количества внешних запросов (триггеров). Границы сверху по сути нет — текущее ограничения — 1000 одновременно работающих контейнеров, но его легко можно поднять до 10000 и выше через саппорт.


    Image


    Главные плюсы AWS Lambda:


    • Легко деплоить (без docker) — только код и библиотеки
    • Легко подключать к триггерам (API, S3, SNS, DynamoDB)
    • Хорошее масштабирование — в продакшене мы запускали более 40 тысяч инвокаций одновременно. Можно и больше.
    • Низкая цена вызова. Для моих коллег из BD направления также важно, что микросервисы поддерживают pay-as-you-go модель для использования сервиса. Это делает понятной юнит-экономику использования модели при масштабировании.

    Зачем портировать нейросети на serverless


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


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


    Image


    (Изображение из блога AWS)


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


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

    На AWS Lambda архитектура будет выглядеть заметно проще:


    Image


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


    Во-вторых вам не придется платить за простой сервера. В Serverless архитектуре оплата идет за один реквест. Это означает, что если у вас будет 25 тысяч реквестов, вы заплатите только за 25 тысяч реквестов, в независимости каким потоком они пришли. Таким образом не только стоимость становится более прозрачной, но и стоимость сама по себе очень низкая. Для примера на Tensorflow, который я покажу позднее стоимость составляет 20-25 тысяч запросов за 1 доллар. Кластер с аналогичным функционалом стоит гораздо больше, а выгоднее он становиться только на очень большом количестве реквестом (>1 миллиона).


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


    Как вы увидите ниже, деплой всей инфраструктуры для вышеупомянутого приложения требуется не более 4 строк кода.


    Было бы некорректно не сказать о недостатках serverless инфраструктуры и о тех случаях, когда она работать не будет. У AWS Lambda есть жесткие ограничения на время обработки и на доступную память, которые надо иметь в виду.


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


    Во-вторых, у AWS Lambda есть небольшое, но определенное время старта (100-200мс). Для приложений глубокого обучения требуется еще некоторое время на скачивание модели с S3. Для примера, который я буду показывать ниже, холодный запуск будет составлять 4.5 секунды, а теплый — 3 секунды. Для некоторых приложений это может быть не критично, но если ваше приложение сфокусировано на максимально быстрой обработке одиночного реквеста, кластер будет более хорошим вариантом.


    Приложение


    Теперь перейдем к практической части.


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


    IMAGE: panda
    Памятка: Модель и оригинальный код доступны здесь


    Мы будем использовать следующий стек:


    • API Gateway для управления запросами
    • AWS Lambda для процессинга
    • Serverless фреймворк для деплоя

    “Hello world” код


    Для начала вам нужно установиться и настроить Serverless фреймворк, который мы будет использовать для оркестрации и деплоя приложения. Ссылка на гайд.


    Сделайте пустую папку и запустить следующую команду:


    serverless install -u https://github.com/ryfeus/lambda-packs/tree/master/tensorflow/source -n tensorflow
    cd tensorflow
    serverless deploy
    serverless invoke --function main --log

    Вы получите следующих ответ:


    /tmp/imagenet/imagenet_synset_to_human_label_map.txt
    /tmp/imagenet/imagenet_2012_challenge_label_map_proto.pbtxt
    /tmp/imagenet/classify_image_graph_def.pb
    /tmp/imagenet/inputimage.jpg
    giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.89107)
    indri, indris, Indri indri, Indri brevicaudatus (score = 0.00779)
    lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens (score = 0.00296)
    custard apple (score = 0.00147)
    earthstar (score = 0.00117)

    Как вы видите, наше приложение успешно распознало картинку с пандой (0,89).


    Вуаля. Мы успешно задеплоили нейронную сеть для распознавания изображений на Tensorflow на AWS Lambda.


    Рассмотрим код поподробнее


    Начнем с конфигурационного файла. Ничего нестандартного — мы используем базовую конфигурацию AWS Lambda.


    service: tensorflow
    
    frameworkVersion: ">=1.2.0 <2.0.0"
    
    provider:
      name: aws
      runtime: python2.7
      memorySize: 1536
      timeout: 300
    
    functions:
      main:
        handler: index.handler

    Если мы посмотрим на сам файл 'index.py', то мы увидим, что сначала мы скачиваем модель ('.pb' файл) в папку '/tmp/' на AWS Lambda, а потом импортируем ее стандартным образом через Tensorflow.


    Ниже ссылки на части кода в Github, которые вы должны иметь в виду если вы хотите вставить свою собственную модель:


    Скачивание модели с S3:


        strBucket = 'ryfeuslambda'
        strKey = 'tensorflow/imagenet/classify_image_graph_def.pb'
        strFile = '/tmp/imagenet/classify_image_graph_def.pb'
        downloadFromS3(strBucket,strKey,strFile)
        print(strFile)

    Импорт модели:


    def create_graph():
        with tf.gfile.FastGFile(os.path.join('/tmp/imagenet/', 'classify_image_graph_def.pb'), 'rb') as f:
            graph_def = tf.GraphDef()
            graph_def.ParseFromString(f.read())
            _ = tf.import_graph_def(graph_def, name='')

    Скачивание изображения:


        strFile = '/tmp/imagenet/inputimage.jpg'
        if ('imagelink' in event):
            urllib.urlretrieve(event['imagelink'], strFile)
        else:
            strBucket = 'ryfeuslambda'
            strKey = 'tensorflow/imagenet/cropped_panda.jpg'
            downloadFromS3(strBucket,strKey,strFile)
            print(strFile)

    Получение предсказаний из модели:


            softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')
            predictions = sess.run(softmax_tensor,
                                   {'DecodeJpeg/contents:0': image_data})
            predictions = np.squeeze(predictions)

    Теперь давайте добавим API к лямбде.


    Пример с API


    Самый простой способ добавить API это модифицировать конфигурационный YAML файл.


    service: tensorflow
    
    frameworkVersion: ">=1.2.0 <2.0.0"
    
    provider:
      name: aws
      runtime: python2.7
      memorySize: 1536
      timeout: 300
    
    functions:
      main:
        handler: index.handler
        events:
          - http: GET handler

    Теперь давайте передеплоим стек:


    serverless deploy

    Получаем следующее.


    Service Information
    service: tensorflow
    stage: dev
    region: us-east-1
    stack: tensorflow-dev
    api keys:
      None
    endpoints:
      GET - https://<urlkey>.execute-api.us-east-1.amazonaws.com/dev/handler
    functions:
      main: tensorflow-dev-main

    Чтобы протестировать API можно просто открыть качестве ссылки:


    https://<urlkey>.execute-api.us-east-1.amazonaws.com/dev/handler

    Или использовать curl:


    curl https://<urlkey>.execute-api.us-east-1.amazonaws.com/dev/handler

    Мы получим:


    {"return": "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.89107)"}

    Заключение


    Мы создали API для модели на Tensorflow на основе AWS Lambda с помощью Serverless фреймворка. Все удалось сделать достаточно просто и такой подход сэкономил нам много времени по сравнению с традиционным подходом.


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


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


    Библиотеки включают в себя следующие примеры:


    • Машинное обучение (Scikit, LightGBM)
    • Компьютерное зрение (Skimage, OpenCV, PIL)
    • Распознавание текста (Tesseract)
    • Анализ текста (Spacy)
    • Веб скрейпинг (Selenium, PhantomJS, lxml)
    • Тестирование API (WRK, pyrestest)

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

    Open Data Science
    260,00
    Крупнейшее русскоязычное Data Science сообщество
    Поделиться публикацией

    Комментарии 12

      +1

      3 секунды на ответ — это же офигеть как много

        0
        Согласен, но если требуется обработать большой батч задач (скажем 100-200 тысяч), то лямбда справится лучше кластера, так как гораздо быстрее смасштабируется.
          0
          OpenFaas идет вместе с похожими примерами (Tesseract OCR, Text-to-Speech, Inception, Colorization и тд.), но на ответ уходит миллисекунд 100 в среднем. Возможно, дело в том, что все данные сразу находятся в образе и в контейнере и не выкачиваются каждый раз.
          0
          Думаю, стоит уточнить, что оплата взымается как за запрос, так и за время исполнения запроса: aws.amazon.com/lambda/pricing. При использовании 512 Mb оперативы нужно заплатить 0.2 * 10e-6$ за запрос + ~0.8 * 10e-6$ за каждые 100ms выполнения (с округлением в большую сторону). Что, впрочем, все равно дешево.

          Ну и раз уж разговор про deep learning, то стоит также отметить, что GPU-инстансов в AWS Lamda пока не завезли. Весь inference – на CPU.
            0
            Может проще зайти с другой стороны? K8S в том же облаке и регионе, в нем крутится под(ы) c REST/gRPC endpoints, а тонкая lambda используется лишь для принятия запросов и отправке их на инференс. И тут уже и GPU можно использовать, и проблема Cold Start снимается навсегда.
              +2

              И зачем тут лямбда?

                0
                Что бы не выставлять наружу K8S напрямую. Аутентификация, валидация и так далее — это тоже расходы.
                  0
                  Но в целом я с вами абсолютно согласен — Serverless, на мой взгляд, лишь красивый способ продать излишки вычислительных мощностей сверх-мелкой розницей. И без этого вполне можно обойтись: нечего баловать.
              0
              каталоги готовых решений

              а поделитесь ссылками на каталоги?
              для TensorFlow формат .pb родной?

                +1
                pb родной. Каталог моделей есть здесь (https://github.com/tensorflow/models) и здесь (https://github.com/tensorflow/hub)
                0

                Спасибо за статью, хотел бы заметить что вы не уточнили одно очень важное ограничение ламбд, а именно эфемерное хранилище не может превышать 512 мб, следовательно если ваша модель больше, ваша ламбда сломается во время запуска.
                Мне не совсем понятно зачем закачивать модель с s3 в эфемерное хранилище, скорость чтения с s3 штука непредсказуемая и может выстрелить вам ногу. Смотрите у нас есть след ограничение:


                Size of code/dependencies that you can zip into a deployment package (uncompressed .zip/.jar size).: 250mb

                Если ваша модель в сжатом виде не превосходит данного ограничения, то просто пакуем ее с кодом ламбды и в рантайме пользуемся из /var/task/YOUR_LAMBDA.


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


                На мой взгляд не хватает разъяснений о Serverless.com который никакого отношения к AWS не имеет ибо является фремворком среди других фреймворков FaaS таких как SAM, Zappa, Claudia JS, итд.

                  0
                  Большое спасибо за комментарий. По поводу ограничения в 500мб я согласен, в текущей имплементации оно есть. Если модель помещается вместе с кодом, то в идеале лучше ее класть туда, но проблем с S3 я на высоких нагрузках не наблюдал. По поводу Serverless.com и контейнеризации я согласен, спасибо за обратную связь.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое