В сентябре хотел обслужить модель от tfhub.dev онлайн.

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

Было бы замечательно иметь кнопку "Отправить в производство" на TensorFlow Hub?

Я предположил, что платформа ИИ (GCP) должна идеально подойти. Так что я попробовал. А сейчас я пишу о своем опыте, чтобы уделить время другим людям, а в будущем и себе.

Информация предоставляется как есть, отзывы приветствуются.

Модель

Возьмем в качестве примера LaBSE: универсальный кодировщик предложений. Учитывая предложение на входе, он выводит вектор (т.е. много чисел с плавающей запятой). Этот вектор представляет смысл предложения. Более того: он не зависит от языка. Это означает, что "Oui" и "Да" дадут очень похожие векторы, в то время как вектор, представляющий "Nein!", будет сильно отличаться.

В любом случае, что делает LaBSE интересным примером, так это то, что он требует, чтобы входное предложение было задано в виде токенов (а не в виде текста) (подробнее об этом здесь). Поэтому нам нужно предварительно обработать входное предложение с помощью следующего препроцессора: https://tfhub.dev/google/universal-sentence-encoder-cmlm/multilingual-preprocess/2.

Мы могли бы развернуть две разные модели: препроцессор, с одной стороны, и LaBSE, с другой. Но в нашем случае гораздо эффективнее будет запускать оба вместе. Кроме того, будет показано, как объединить две модели, а затем развернуть их как одну. Итак, давайте посмотрим на код (Python 3 в Jupyter Notebook) и прокомментируем его шаг за шагом:

L20: Зачем использовать @tf.function?

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

Вот сообщение об ошибке, которое вы можете получить от AI Platform, если вы не использовали @tf.function:

Serving signature name: "serving_default" not found in signature def

L22: Зачем выбирать выход «по умолчанию»?

LaBSE возвращает выходные данные нескольких слоев. Это отлично подходит для некоторых случаев использования, но требует очень больших выходных данных. Настолько большой, что он больше 2 МБ. И 2 МБ — это ограничение, установленное AI Platform. Таким образом, мы выбираем только тот вывод «по умолчанию», который соответствует нашим потребностям. И это уже около 15 КБ на каждое предложение! Это означает, что при запросе векторов для пакета размером более 130 предложений (~ 2 МБ/15 КБ) этот предел составит 2 МБ. То есть… если сервер способен обработать такой большой пакет до истечения времени ожидания.

L50: Зачем указывать РЕГИОН?

Потому что наша модель больше 500 МБ. Это означает, что его можно развернуть только на машинах типа Compute Engine (N1) (см. doc). Отсюда и другие ограничения. Например:

Использование региональной конечной точки подразумевает другие дополнительные ограничения:

  • Для создания модели и версии необходимо запросить REGION-ml.googleapis.com вместо ml.googleapis.com (cf doc). Вот почему мы должны указать РЕГИОН. В противном случае вы, вероятно, получите ошибку HTTP, например Модель не найдена. Или, если вы попытаетесь развернуть новую версию модели для консоли: вы можете увидеть неотвечающую кнопку для ее сохранения. В этом случае убедитесь, что ваша модель развернута на региональной модели. Вот скриншот Google Cloud Console, который показывает разницу конечных точек:

  • в настоящее время вы не можете включить ведение журнала потока (консоли).
  • Модели, развернутые на региональных конечных точках, не поддерживают пакетное предсказание.

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

L56: Зачем указывать runtime-version=2.6

В некоторых более старых версиях среды выполнения я получал следующую ошибку: Тип операции не зарегистрирован ‘RegexSplitWithOffsets . Указание последней версии выше 2.5.0 решило проблему.

Подробнее об этом здесь.

Давайте использовать модель

Некоторые соображения

Развертывание новой версии модели занимает более 6 мин.

Использование автоматического масштабирования: подготовка нового узла занимает около 6 минут после того, как алгоритм автоматического масштабирования решит запросить создание нового узла.

Ориентир

Я протестировал машины N1 с/без ускорения графического процессора (Nvidia K80), чтобы векторизовать все предложения книги. Я взял книгу из 30 тысяч слов и 1533 предложений (около 2 часов чтения).

  • n1-standard-2, пакет из 1 предложения: 2200 с (~36 мин)
  • n1-standard-2, пакет из 64 предложений: HttpError 503 при запросе https://... ошибка: Время ожидания уведомления истекло: 64 предложения за раз слишком много для этого типа экземпляра
  • n1-standard-2 + GPU, пакет из 1 предложения: 500 с
  • n1-standard-2 + GPU, пакет из 32 предложений: 56 с
  • n1-standard-2 + GPU, пакет из 64 предложений: 57 с
  • n1-standard-2 + GPU, пакет из 128 предложений: 79 с.
  • Чтобы закончить, я попытался выполнить запросы одновременно с 6 воркерами, на n1-standard-2 + GPU, пакет из 1 предложения: 34 с.

Заключение

Я должен узнавать что-то новое, и это всегда приятно.

Однако платформа искусственного интеллекта от GCP не соответствует моим ожиданиям от сервиса, масштабируемого до нуля. Более того, пытаясь решить вопросы, я заметил, что сообщество пользователей AI Platform все еще находится на этапе, когда поиск ответов затруднен (что напоминает мне мой прошлый опыт использования Amazon Sagemaker)

Так что теперь мне очень жаль, что на Tensorflow Hub не было кнопки "Отправить в производство". Если это тоже ваш случай, вас может заинтересовать следующее: https://mailchi.mp/26059db71a9b/maas-model-as-a-service-deploy-tensorflowhub-serving

Надеюсь, вам понравился этот пост. Заранее благодарим за отзыв.

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