این آموزش به شما نشان می دهد که چگونه از اجزای TensorFlow Serving برای ساختن استاندارد TensorFlow ModelServer استفاده کنید که به صورت پویا نسخه های جدید یک مدل آموزش دیده TensorFlow را کشف و ارائه می کند. اگر فقط میخواهید از سرور استاندارد برای ارائه مدلهای خود استفاده کنید، به آموزش پایه TensorFlow Serving مراجعه کنید.
این آموزش از مدل رگرسیون سافت مکس ساده معرفی شده در آموزش TensorFlow برای طبقه بندی تصاویر دست نویس (MNIST data) استفاده می کند. اگر نمی دانید TensorFlow یا MNIST چیست، به آموزش MNIST For ML Beginners مراجعه کنید.
کد این آموزش شامل دو بخش است:
یک فایل پایتون mnist_saved_model.py که چندین نسخه از مدل را آموزش و صادر می کند.
یک فایل C++ main.cc که استاندارد TensorFlow ModelServer است که مدلهای جدید صادر شده را کشف میکند و یک سرویس 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 Serving انجام می شود، انجام می شود. برای اهداف نمایشی، شما عمداً تکرارهای آموزشی را برای اجرای اول شماره گیری می کنید و آن را به عنوان v1 صادر می کنید، در حالی که به طور معمول برای اجرای دوم آموزش می دهید و آن را به عنوان v2 به همان دایرکتوری والد صادر می کنید - همانطور که انتظار داریم دومی به آن برسد. دقت طبقه بندی بهتر به دلیل آموزش فشرده تر. شما باید داده های آموزشی را برای هر آموزش اجرا شده در دایرکتوری /tmp/mnist
خود مشاهده کنید:
$ ls /tmp/mnist
1 2
ServerCore
حال تصور کنید v1 و v2 مدل به صورت پویا در زمان اجرا تولید میشوند، زمانی که الگوریتمهای جدید در حال آزمایش هستند، یا زمانی که مدل با یک مجموعه داده جدید آموزش داده میشود. در یک محیط تولید، ممکن است بخواهید سروری بسازید که بتواند از عرضه تدریجی پشتیبانی کند، که در آن نسخه 2 را می توان در حین ارائه نسخه 1 کشف، بارگیری، آزمایش، نظارت یا برگرداند. از طرف دیگر، ممکن است بخواهید v1 را قبل از آوردن v2 از بین ببرید. TensorFlow Serving از هر دو گزینه پشتیبانی می کند - در حالی که یکی برای حفظ در دسترس بودن در طول انتقال خوب است، دیگری برای به حداقل رساندن استفاده از منابع خوب است (مثلا RAM).
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 است. این یک مدل 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
بهره میبرید. برای مثال، میتوانید یک افزونه منبع داده بسازید که به جای ذخیرهسازی محلی، فضای ذخیرهسازی ابری را نظارت میکند، یا میتوانید یک پلاگین خطمشی نسخه بسازید که انتقال نسخه را به روشی متفاوت انجام میدهد - در واقع، حتی میتوانید یک پلاگین مدل سفارشی بسازید که خدمت میکند. مدل های غیر تنسورفلو این موضوعات خارج از محدوده این آموزش هستند. با این حال، می توانید برای اطلاعات بیشتر به منبع سفارشی و آموزش های قابل سرویس دهی سفارشی مراجعه کنید.
دسته بندی
یکی دیگر از ویژگی های معمولی سرور که در محیط تولید می خواهیم، دسته بندی است. شتابدهندههای سختافزاری مدرن (GPU و غیره) که برای انجام استنتاج یادگیری ماشین استفاده میشوند، معمولاً زمانی که درخواستهای استنتاج در دستههای بزرگ اجرا میشوند، بهترین بازده محاسباتی را به دست میآورند.
هنگام ایجاد SavedModelBundleSourceAdapter
، میتوان با ارائه SessionBundleConfig
مناسب، دستهبندی را فعال کرد. در این مورد ما BatchingParameters
تقریباً با مقادیر پیش فرض تنظیم می کنیم. دستهبندی را میتوان با تنظیم مقادیر زمانبندی سفارشی، batch_size و غیره بهخوبی تنظیم کرد. برای جزئیات، لطفاً به 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;
پس از رسیدن به دسته کامل، درخواستهای استنتاج به صورت داخلی در یک درخواست بزرگ (tensor) ادغام میشوند و tensorflow::Session::Run()
فراخوانی میشود (که همان جایی است که افزایش بازده واقعی در GPUها از آنجا حاصل میشود).
خدمت با مدیر
همانطور که در بالا ذکر شد، TensorFlow Serving Manager
به گونهای طراحی شده است که یک مؤلفه عمومی است که میتواند بارگیری، سرویس دهی، تخلیه و انتقال نسخه مدلهای تولید شده توسط سیستمهای یادگیری ماشین دلخواه را مدیریت کند. API های آن بر اساس مفاهیم کلیدی زیر ساخته شده اند:
Servable : 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%
این تأیید می کند که سرور شما به طور خودکار نسخه جدید را پیدا کرده و از آن برای سرویس دهی استفاده می کند!