บทช่วยสอนนี้แสดงให้คุณเห็นถึงวิธีใช้ส่วนประกอบ TensorFlow Serving เพื่อสร้าง TensorFlow ModelServer มาตรฐานที่ค้นพบและให้บริการเวอร์ชันใหม่ของโมเดล TensorFlow ที่ผ่านการฝึกอบรมแบบไดนามิก หากคุณเพียงต้องการใช้เซิร์ฟเวอร์มาตรฐานเพื่อรองรับโมเดลของคุณ โปรดดู บทช่วยสอนพื้นฐานเกี่ยวกับการให้บริการ TensorFlow
บทช่วยสอนนี้ใช้โมเดล Softmax Regression แบบง่ายที่แนะนำในบทช่วยสอน TensorFlow สำหรับการจำแนกประเภทรูปภาพที่เขียนด้วยลายมือ (ข้อมูล MNIST) หากคุณไม่ทราบว่า TensorFlow หรือ MNIST คืออะไร โปรดดูบทช่วยสอน MNIST สำหรับผู้เริ่มต้น ML
รหัสสำหรับบทช่วยสอนนี้ประกอบด้วยสองส่วน:
ไฟล์ Python 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
ฝึกฝน (ด้วยการวนซ้ำ 2,000 ครั้ง) และส่งออกโมเดลเวอร์ชันที่สอง:
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
เซิร์ฟเวอร์คอร์
ทีนี้ลองจินตนาการว่าโมเดล v1 และ v2 ถูกสร้างขึ้นแบบไดนามิก ณ รันไทม์ ขณะที่อัลกอริธึมใหม่กำลังถูกทดลองอยู่ หรือในขณะที่โมเดลได้รับการฝึกฝนด้วยชุดข้อมูลใหม่ ในสภาพแวดล้อมการใช้งานจริง คุณอาจต้องการสร้างเซิร์ฟเวอร์ที่สามารถรองรับการเปิดตัวแบบค่อยเป็นค่อยไป ซึ่งสามารถค้นพบ โหลด ทดลอง ตรวจสอบ หรือเปลี่ยนกลับในขณะที่ให้บริการเวอร์ชัน 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
(เส้นทางที่ค้นพบเวอร์ชันของโมเดล) ให้เป็น ModelLoader
(โหลดเวอร์ชันของโมเดลจากเส้นทางการจัดเก็บข้อมูลและจัดเตรียมอินเทอร์เฟซการเปลี่ยนสถานะให้กับ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 หัวข้อเหล่านี้อยู่นอกขอบเขตสำหรับบทช่วยสอนนี้ อย่างไรก็ตาม คุณสามารถอ้างอิง แหล่งที่มาที่กำหนดเอง และบทช่วยสอน ที่ให้บริการแบบกำหนดเองได้ สำหรับข้อมูลเพิ่มเติม
การผสม
คุณสมบัติเซิร์ฟเวอร์ทั่วไปอีกประการหนึ่งที่เราต้องการในสภาพแวดล้อมการใช้งานจริงคือการแบทช์ ตัวเร่งฮาร์ดแวร์สมัยใหม่ (GPU ฯลฯ) ที่ใช้ทำการอนุมานของแมชชีนเลิร์นนิงมักจะได้รับประสิทธิภาพในการคำนวณที่ดีที่สุดเมื่อมีการเรียกใช้คำขอการอนุมานเป็นกลุ่มจำนวนมาก
สามารถเปิดใช้งานการแบตช์ได้โดยระบุ 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()
(ซึ่งเป็นที่มาของประสิทธิภาพจริงที่ได้รับจาก GPU)
เสิร์ฟพร้อมกับผู้จัดการ
ตามที่กล่าวไว้ข้างต้น TensorFlow Serving Manager
ได้รับการออกแบบให้เป็นส่วนประกอบทั่วไปที่สามารถจัดการการโหลด การให้บริการ การยกเลิกการโหลด และการเปลี่ยนเวอร์ชันของโมเดลที่สร้างโดยระบบการเรียนรู้ของเครื่องจักรตามอำเภอใจ API สร้างขึ้นตามแนวคิดหลักต่อไปนี้:
เสิร์ฟได้ : เสิร์ฟได้เป็นวัตถุทึบแสงใด ๆ ที่สามารถใช้เพื่อให้บริการตามคำขอของไคลเอ็นต์ ขนาดและรายละเอียดของการให้บริการนั้นมีความยืดหยุ่น โดยที่การให้บริการเดี่ยวอาจรวมทุกอย่างตั้งแต่ส่วนเดียวของตารางการค้นหาไปจนถึงโมเดลที่เรียนรู้ด้วยเครื่องเดียวไปจนถึงโมเดลทูเพิล การให้บริการสามารถเป็นประเภทและอินเทอร์เฟซใดก็ได้
เวอร์ชันที่ให้บริการได้ : เวอร์ชันที่ให้บริการได้ถูกกำหนดเวอร์ชันไว้แล้ว และ TensorFlow Serving
Manager
สามารถจัดการเวอร์ชันที่ให้บริการได้ตั้งแต่หนึ่งเวอร์ชันขึ้นไป การกำหนดเวอร์ชันทำให้สามารถโหลดการให้บริการได้มากกว่าหนึ่งเวอร์ชันพร้อมกัน โดยรองรับการเปิดตัวและการทดลองแบบค่อยเป็นค่อยไปสตรีมที่ให้บริการได้ : สตรีมที่ให้บริการได้คือลำดับของเวอร์ชันของสตรีมที่ให้บริการได้ โดยมีหมายเลขเวอร์ชันเพิ่มขึ้น
โมเดล : โมเดลที่เรียนรู้ด้วยเครื่องแสดงด้วยบริการหนึ่งรายการขึ้นไป ตัวอย่างของการให้บริการได้แก่:
- เซสชัน TensorFlow หรือสิ่งล้อมรอบ เช่น
SavedModelBundle
- โมเดลการเรียนรู้ของเครื่องประเภทอื่นๆ
- ตารางค้นหาคำศัพท์
- การฝังตารางการค้นหา
โมเดลคอมโพสิตสามารถแสดงเป็นบริการอิสระหลายรายการ หรือเป็นบริการแบบคอมโพสิตเดียว การให้บริการยังอาจสอดคล้องกับเศษส่วนของโมเดลด้วย เช่น ตารางการค้นหาขนาดใหญ่ที่แบ่งส่วนในอินสแตนซ์
Manager
จำนวนมาก- เซสชัน TensorFlow หรือสิ่งล้อมรอบ เช่น
หากต้องการนำสิ่งเหล่านี้ไปไว้ในบริบทของบทช่วยสอนนี้:
โมเดล TensorFlow จะแสดงด้วย servable ประเภทหนึ่ง นั่นคือ
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 &
เซิร์ฟเวอร์จะส่งข้อความบันทึกทุกๆ หนึ่งวินาทีที่ระบุว่า "เวอร์ชัน Aspiring for servable ..." ซึ่งหมายความว่าพบการส่งออกแล้ว และกำลังติดตามการมีอยู่อย่างต่อเนื่อง
มารันไคลเอนต์ด้วย --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%
นี่เป็นการยืนยันว่าเซิร์ฟเวอร์ของคุณจะค้นพบเวอร์ชันใหม่โดยอัตโนมัติและใช้สำหรับการให้บริการ!