В этом руководстве показано, как использовать компоненты обслуживания TensorFlow для создания стандартного сервера TensorFlow ModelServer, который динамически обнаруживает и обслуживает новые версии обученной модели TensorFlow. Если вы просто хотите использовать стандартный сервер для обслуживания своих моделей, см. базовое руководство по обслуживанию TensorFlow .
В этом руководстве используется простая модель регрессии Softmax, представленная в руководстве TensorFlow для классификации рукописных изображений (данные MNIST). Если вы не знаете, что такое TensorFlow или MNIST, см. учебник MNIST для начинающих ML .
Код этого руководства состоит из двух частей:
Файл Python mnist_saved_model.py , который обучает и экспортирует несколько версий модели.
Файл C++ main.cc , который является стандартным сервером моделей TensorFlow, который обнаруживает новые экспортированные модели и запускает службу gRPC для их обслуживания.
В этом руководстве рассматриваются следующие задачи:
- Обучите и экспортируйте модель TensorFlow.
- Управляйте версиями модели с помощью TensorFlow Serving
ServerCore
. - Настройте пакетную обработку с помощью
SavedModelBundleSourceAdapterConfig
. - Обслуживайте запрос с помощью TensorFlow Serving
ServerCore
. - Запустите и протестируйте службу.
Прежде чем начать, сначала установите Docker
Обучение и экспорт модели TensorFlow
Во-первых, если вы еще этого не сделали, клонируйте этот репозиторий на свой локальный компьютер:
git clone https://github.com/tensorflow/serving.git
cd serving
Очистите каталог экспорта, если он уже существует:
rm -rf /tmp/models
Обучите (со 100 итерациями) и экспортируйте первую версию модели:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=100 --model_version=1 /tmp/mnist
Обучите (с 2000 итерациями) и экспортируйте вторую версию модели:
tools/run_in_docker.sh python tensorflow_serving/example/mnist_saved_model.py \
--training_iteration=2000 --model_version=2 /tmp/mnist
Как вы можете видеть в mnist_saved_model.py
, обучение и экспорт выполняются так же, как и в базовом руководстве по обслуживанию TensorFlow . В демонстрационных целях вы намеренно сокращаете количество итераций обучения для первого запуска и экспортируете его как версию v1, в то время как обычно обучаете его для второго запуска и экспортируете как v2 в тот же родительский каталог - чего мы ожидаем от последнего. более высокая точность классификации за счет более интенсивного обучения. Вы должны увидеть данные обучения для каждого запуска обучения в вашем каталоге /tmp/mnist
:
$ ls /tmp/mnist
1 2
Серверное ядро
Теперь представьте, что версии v1 и v2 модели динамически генерируются во время выполнения, когда экспериментируются новые алгоритмы или когда модель обучается с использованием нового набора данных. В производственной среде вам может потребоваться создать сервер, поддерживающий постепенное развертывание, на котором версию 2 можно будет обнаруживать, загружать, экспериментировать, отслеживать или отменять при обслуживании версии 1. Альтернативно, вы можете захотеть удалить версию v1, прежде чем поднимать версию v2. TensorFlow Serving поддерживает оба варианта: один из них хорош для поддержания доступности во время перехода, а другой — для минимизации использования ресурсов (например, оперативной памяти).
TensorFlow Serving Manager
делает именно это. Он обрабатывает полный жизненный цикл моделей TensorFlow, включая их загрузку, обслуживание и выгрузку, а также смену версий. В этом руководстве вы создадите свой сервер на основе TensorFlow Serving ServerCore
, который внутри является оболочкой AspiredVersionsManager
.
int main(int argc, char** argv) {
...
ServerCore::Options options;
options.model_server_config = model_server_config;
options.servable_state_monitor_creator = &CreateServableStateMonitor;
options.custom_model_config_loader = &LoadCustomModelConfig;
::google::protobuf::Any source_adapter_config;
SavedModelBundleSourceAdapterConfig
saved_model_bundle_source_adapter_config;
source_adapter_config.PackFrom(saved_model_bundle_source_adapter_config);
(*(*options.platform_config_map.mutable_platform_configs())
[kTensorFlowModelPlatform].mutable_source_adapter_config()) =
source_adapter_config;
std::unique_ptr<ServerCore> core;
TF_CHECK_OK(ServerCore::Create(options, &core));
RunServer(port, std::move(core));
return 0;
}
ServerCore::Create()
принимает параметр ServerCore::Options. Вот несколько часто используемых вариантов:
-
ModelServerConfig
, определяющий модели для загрузки. Модели объявляются либо черезmodel_config_list
, который объявляет статический список моделей, либо черезcustom_model_config
, который определяет собственный способ объявления списка моделей, которые могут обновляться во время выполнения. -
PlatformConfigMap
, который сопоставляет имя платформы (например,tensorflow
) сPlatformConfig
, который используется для созданияSourceAdapter
.SourceAdapter
адаптируетStoragePath
(путь, по которому обнаруживается версия модели) дляLoader
модели (загружает версию модели из пути хранения и предоставляетManager
интерфейсы перехода состояний). ЕслиPlatformConfig
содержитSavedModelBundleSourceAdapterConfig
, будет созданSavedModelBundleSourceAdapter
, который мы объясним позже.
SavedModelBundle
— ключевой компонент TensorFlow Serving. Он представляет собой модель TensorFlow, загруженную по заданному пути, и предоставляет тот же Session::Run
, что и TensorFlow, для выполнения вывода. SavedModelBundleSourceAdapter
адаптирует путь хранения к Loader<SavedModelBundle>
, чтобы временем жизни модели можно было управлять с помощью Manager
. Обратите внимание, что SavedModelBundle
является преемником устаревшего SessionBundle
. Пользователям рекомендуется использовать SavedModelBundle
поскольку поддержка SessionBundle
скоро будет удалена.
При всем этом ServerCore
внутренне выполняет следующие действия:
- Создает экземпляр
FileSystemStoragePathSource
, который отслеживает пути экспорта модели, объявленные вmodel_config_list
. - Создает
SourceAdapter
с помощьюPlatformConfigMap
с платформой модели, объявленной вmodel_config_list
, и подключает к немуFileSystemStoragePathSource
. Таким образом, всякий раз, когда по пути экспорта обнаруживается новая версия модели,SavedModelBundleSourceAdapter
адаптирует ее кLoader<SavedModelBundle>
. - Создает конкретную реализацию
Manager
под названиемAspiredVersionsManager
, которая управляет всеми такими экземплярамиLoader
, созданнымиSavedModelBundleSourceAdapter
.ServerCore
экспортирует интерфейсManager
, делегируя вызовыAspiredVersionsManager
.
Всякий раз, когда доступна новая версия, этот AspiredVersionsManager
загружает новую версию, а в соответствии с поведением по умолчанию выгружает старую. Если вы хотите начать настройку, вам рекомендуется понять компоненты, которые он создает внутри, и способы их настройки.
Стоит отметить, что TensorFlow Serving разработан с нуля, чтобы быть очень гибким и расширяемым. Вы можете создавать различные плагины для настройки поведения системы, используя при этом преимущества общих основных компонентов, таких как ServerCore
и AspiredVersionsManager
. Например, вы можете создать подключаемый модуль источника данных, который отслеживает облачное хранилище вместо локального хранилища, или вы можете создать подключаемый модуль политики версий, который осуществляет переход версий другим способом. Фактически, вы даже можете создать подключаемый модуль собственной модели, который служит модели, не относящиеся к TensorFlow. Эти темы выходят за рамки данного руководства. Однако для получения дополнительной информации вы можете обратиться к пользовательскому исходному коду и пользовательским обслуживаемым руководствам.
Пакетирование
Еще одна типичная функция сервера, которую мы хотим использовать в производственной среде, — это пакетная обработка. Современные аппаратные ускорители (графические процессоры и т. д.), используемые для вывода машинного обучения, обычно достигают наилучшей эффективности вычислений, когда запросы вывода выполняются большими пакетами.
Пакетную обработку можно включить, указав правильный SessionBundleConfig
при создании SavedModelBundleSourceAdapter
. В этом случае мы устанавливаем BatchingParameters
практически значения по умолчанию. Пакетную обработку можно настроить, установив собственные значения тайм-аута, размера пакета и т. д. Подробную информацию см. в разделе BatchingParameters
.
SessionBundleConfig session_bundle_config;
// Batching config
if (enable_batching) {
BatchingParameters* batching_parameters =
session_bundle_config.mutable_batching_parameters();
batching_parameters->mutable_thread_pool_name()->set_value(
"model_server_batch_threads");
}
*saved_model_bundle_source_adapter_config.mutable_legacy_config() =
session_bundle_config;
При достижении полного пакета запросы на вывод внутренне объединяются в один большой запрос (тензор) и вызывается tensorflow::Session::Run()
(именно отсюда и происходит фактическое повышение эффективности графических процессоров).
Обслуживать с менеджером
Как упоминалось выше, TensorFlow Serving Manager
спроектирован как универсальный компонент, который может обрабатывать загрузку, обслуживание, выгрузку и смену версий моделей, созданных произвольными системами машинного обучения. Его API построены на основе следующих ключевых концепций:
Servable : Servable — это любой непрозрачный объект, который можно использовать для обслуживания клиентских запросов. Размер и степень детализации обслуживаемого объекта являются гибкими, так что один обслуживаемый объект может включать в себя что угодно: от одного фрагмента таблицы поиска до одной модели машинного обучения или кортежа моделей. Обслуживаемый объект может быть любого типа и интерфейса.
Версия обслуживаемого файла : сервируемые файлы имеют версии, и TensorFlow Serving
Manager
может управлять одной или несколькими версиями обслуживаемых файлов. Управление версиями позволяет одновременно загружать более одной версии обслуживаемого объекта, поддерживая постепенное развертывание и экспериментирование.Обслуживаемый поток : Обслуживаемый поток — это последовательность версий обслуживаемого объекта с возрастающими номерами версий.
Модель : модель машинного обучения представлена одним или несколькими обслуживаемыми объектами. Примеры обслуживаемых объектов:
- Сеанс TensorFlow или оболочки вокруг них, такие как
SavedModelBundle
. - Другие виды моделей машинного обучения.
- Таблицы поиска словарного запаса.
- Встраивание справочных таблиц.
Составная модель может быть представлена как несколько независимых обслуживаемых объектов или как один составной обслуживаемый объект. Обслуживаемый объект также может соответствовать части Модели, например, с большой таблицей поиска, сегментированной по множеству экземпляров
Manager
.- Сеанс TensorFlow или оболочки вокруг них, такие как
Чтобы поместить все это в контекст этого урока:
Модели TensorFlow представлены одним видом обслуживаемых объектов —
SavedModelBundle
.SavedModelBundle
внутренне состоит изtensorflow:Session
в сочетании с некоторыми метаданными о том, какой граф загружается в сеанс и как его запустить для вывода.Существует каталог файловой системы, содержащий поток экспорта TensorFlow, каждый в своем собственном подкаталоге, имя которого является номером версии. Внешний каталог можно рассматривать как сериализованное представление обслуживаемого потока для обслуживаемой модели TensorFlow. Каждый экспорт соответствует обслуживаемому объекту, который можно загрузить.
AspiredVersionsManager
отслеживает поток экспорта и динамически управляет жизненным циклом всех обслуживаемых объектовSavedModelBundle
.
TensorflowPredictImpl::Predict
тогда просто:
- Запрашивает
SavedModelBundle
у менеджера (через ServerCore). - Использует
generic signatures
для сопоставления имен логических тензоров вPredictRequest
с реальными именами тензоров и привязки значений к тензорам. - Выполняет вывод.
Протестируйте и запустите сервер
Скопируйте первую версию экспорта в отслеживаемую папку:
mkdir /tmp/monitored
cp -r /tmp/mnist/1 /tmp/monitored
Затем запустите сервер:
docker run -p 8500:8500 \
--mount type=bind,source=/tmp/monitored,target=/models/mnist \
-t --entrypoint=tensorflow_model_server tensorflow/serving --enable_batching \
--port=8500 --model_name=mnist --model_base_path=/models/mnist &
Сервер каждую секунду будет выдавать сообщения журнала с надписью «Стремящаяся версия для обслуживаемого...», что означает, что он нашел экспорт и отслеживает его дальнейшее существование.
Давайте запустим клиент с --concurrency=10
. Это отправит параллельные запросы на сервер и, таким образом, активирует вашу логику пакетной обработки.
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
--num_tests=1000 --server=127.0.0.1:8500 --concurrency=10
В результате получается результат, который выглядит так:
...
Inference error rate: 13.1%
Затем копируем вторую версию экспорта в отслеживаемую папку и повторно запускаем тест:
cp -r /tmp/mnist/2 /tmp/monitored
tools/run_in_docker.sh python tensorflow_serving/example/mnist_client.py \
--num_tests=1000 --server=127.0.0.1:8500 --concurrency=10
В результате получается результат, который выглядит так:
...
Inference error rate: 9.5%
Это подтверждает, что ваш сервер автоматически обнаруживает новую версию и использует ее для обслуживания!