این آموزش به شما نشان می دهد که چگونه از اجزای 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استفاده می شود، نگاشت می شود.SourceAdapterStoragePath(مسیری که در آن نسخه مدل کشف میشود) را با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%
این تایید می کند که سرور شما به طور خودکار نسخه جدید را پیدا کرده و از آن برای سرویس دهی استفاده می کند!