בניית TensorFlow ModelServer סטנדרטי

מדריך זה מראה לך כיצד להשתמש ברכיבי TensorFlow Serving כדי לבנות את TensorFlow ModelServer הסטנדרטי שמגלה באופן דינמי ומשרת גרסאות חדשות של מודל TensorFlow מאומן. אם אתה רק רוצה להשתמש בשרת הסטנדרטי לשרת המודלים שלך, לראות TensorFlow הגשת הדרכה בסיסית .

מדריך זה משתמש במודל הפשוט של Softmax Regression שהוצג במדריך TensorFlow לסיווג תמונה בכתב יד (נתוני MNIST). אם אתה לא יודע מה TensorFlow או MNIST הוא, לראות את MNIST עבור ML למתחילים הדרכה.

הקוד של הדרכה זו מורכב משני חלקים:

  • פייתון קובץ mnist_saved_model.py כי רכבות היצוא מספר גרסאות של המודל.

  • הקובץ ++ C main.cc המהווה את ModelServer TensorFlow התקן שמגלה מיוצאים חדש מודלים ומפעיל gRPC שירות עבור המשרתים אותם.

מדריך זה מוביל את המשימות הבאות:

  1. אימון ויצוא של מודל TensorFlow.
  2. ניהול מודל גרסאות עם הגשה TensorFlow ServerCore .
  3. ומינון Configure באמצעות SavedModelBundleSourceAdapterConfig .
  4. מגיש בקשה עם הגשת TensorFlow ServerCore .
  5. הפעל ובדוק את השירות.

לפני תחילת עבודה, ראשון להתקין דוקר

אימון וייצוא מודל 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

ServerCore

כעת דמיינו לעצמכם את v1 ו-v2 של המודל נוצרים באופן דינמי בזמן ריצה, כאשר אלגוריתמים חדשים מתנסים, או כאשר המודל מאומן עם מערך נתונים חדש. בסביבת ייצור, ייתכן שתרצה לבנות שרת שיכול לתמוך בהשקה הדרגתית, שבה ניתן לגלות, לטעון, להתנסות, לנטר או להחזיר את v2 בזמן הגשת v1. לחלופין, ייתכן שתרצה להרוס את v1 לפני העלאת v2. TensorFlow Serving תומך בשתי האפשרויות -- בעוד שאחת טובה לשמירה על זמינות במהלך המעבר, השנייה טובה למזעור השימוש במשאבים (למשל זיכרון RAM).

TensorFlow הגשת Manager עושה בדיוק את זה. הוא מטפל במחזור החיים המלא של דגמי TensorFlow כולל טעינה, הגשה ופריקה שלהם וכן מעברי גרסאות. במדריך זה, תוכל לבנות את השרת על גבי TensorFlow הגשת 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 :: פרמטר אפשרויות. להלן מספר אפשרויות נפוצות:

  • ModelServerConfig המציין דגמים להיות טעון. מודלים מוכרזים או באמצעות model_config_list , אשר מצהיר רשימה סטטית של דגמים, או באמצעות custom_model_config , המגדיר בצורה המנהג להכריז על רשימת הדגמים שעשויים להתעדכן בזמן ריצה.
  • PlatformConfigMap הממפה משמו של הפלטפורמה (כגון tensorflow ) אל PlatformConfig , אשר משמש ליצירת SourceAdapter . SourceAdapter מסתגל StoragePath (הנתיב בו גרסת מודל מתגלה) למדל Loader (המון גרסת מודל מנתיב אחסון ומספק ממשקי המעבר למדינה אלי Manager ). אם PlatformConfig מכיל SavedModelBundleSourceAdapterConfig , A SavedModelBundleSourceAdapter תיווצר, אשר נסביר בהמשך.

SavedModelBundle הוא מרכיב מרכזי של הצגת TensorFlow. הוא מייצג מודל TensorFlow נטען מ נתיב נתון ומספק אותו Session::Run הממשק כמו TensorFlow כדי היקש ריצה. SavedModelBundleSourceAdapter נתיב האחסון מסתגל Loader<SavedModelBundle> כך בחי מודל יכולים להיות מנוהלים על ידי Manager . שימו לב SavedModelBundle הוא ממשיכו של עוד בשימוש SessionBundle . אנו מעודדים את המשתמשים להשתמש SavedModelBundle כמו תמיכה SessionBundle יוסר בקרוב.

עם כל אלה, ServerCore פנימי מבצע את הפעולות הבאות:

  • Instantiates FileSystemStoragePathSource כי נתיבי ייצוא מודל צגים הכריז model_config_list .
  • Instantiates SourceAdapter באמצעות PlatformConfigMap עם פלטפורמת מודל הכריז model_config_list ומחבר את FileSystemStoragePathSource אליו. בדרך זו, בכל פעם שיוצאת גרסה חדשה מודל מתגלה תחת נתיב הייצוא, SavedModelBundleSourceAdapter מסתגל אותו Loader<SavedModelBundle> .
  • Instantiates יישום ספציפי של Manager שנקרא AspiredVersionsManager שמנהלת את כל כגון Loader מקרים נוצר על ידי SavedModelBundleSourceAdapter . ServerCore מייצאת את Manager הממשק ידי האצלת קריאות AspiredVersionsManager .

בכל פעם גרסה חדשה זמינה, זה AspiredVersionsManager טוען את הגרסה החדשה, ותחת מסיר התנהגות ברירת המחדל שלו לישנה. אם אתה רוצה להתחיל להתאים אישית, אתה מוזמן להבין את הרכיבים שהוא יוצר באופן פנימי, וכיצד להגדיר אותם.

ראוי להזכיר כי TensorFlow Serving תוכנן מאפס להיות מאוד גמיש וניתן להרחבה. אתה יכול לבנות תוספים שונים להתנהגות מערכת אישית, תוך ניצול רכיבי ליבה גנריות כמו ServerCore ו AspiredVersionsManager . לדוגמה, אתה יכול לבנות תוסף מקור נתונים שמנטר אחסון בענן במקום אחסון מקומי, או שאתה יכול לבנות תוסף מדיניות גרסה שעושה מעבר גרסה בצורה אחרת -- למעשה, אתה יכול אפילו לבנות תוסף דגם מותאם אישית שמשרת דגמים שאינם TensorFlow. נושאים אלה אינם בהיקף של הדרכה זו. עם זאת, אתה יכול להפנות את מקור המנהג ואת מנהג servable הדרכות לקבלת מידע נוסף.

אצווה

תכונת שרת טיפוסית נוספת שאנו רוצים בסביבת ייצור היא אצווה. מאיצי חומרה מודרניים (GPU וכו') המשמשים להסקת למידה חישובית משיגים בדרך כלל את יעילות החישוב הטובה ביותר כאשר בקשות הסקת מסקנות מופעלות באצוות גדולות.

מינון ניתן להפעיל באמצעות מתן נאה SessionBundleConfig בעת יצירת SavedModelBundleSourceAdapter . במקרה זה אנו קובעים את 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;

בהגיעו אצווה מלא, בקשות היקש ימוזגו באופן פנימי בקשה גדולה אחת (מותח), ו tensorflow::Session::Run() מופעלת (וזו בדיוק המטרה של שיפור ביעילות בפועל על GPUs מגיע).

מגישים עם מנהל

כפי שצוין לעיל, הגשת TensorFlow Manager נועד להיות מרכיב גנרי שיכול לטפל טעינה, הגשה, פריקת המעבר לגרסה של דגמים שנוצרו על ידי מערכות למידת מכונה שרירותיות. ממשקי ה-API שלו בנויים סביב מושגי המפתח הבאים:

  • Servable: servable הוא אובייקט כלשהו אטום שניתן להשתמש בהם כדי לשרת בקשות הלקוח. הגודל והפירוט של חומר הגשה גמישים, כך שניתן להגשה בודד עשוי לכלול כל דבר, החל מרסיס בודד של טבלת חיפוש, לדגם אחד שנלמד על ידי מכונה ועד למספר דגמים. ניתן להגשה יכול להיות מכל סוג וממשק.

  • Servable גרסה: Servables הם versioned ו הגשה TensorFlow Manager יכול לנהל גירסאות אחד או יותר של servable. גירסאות מאפשרות לטעון יותר מגרסה אחת של קובץ הגשה בו-זמנית, התומכת בהשקה הדרגתית ובניסויים.

  • Servable זרם: זרם servable הוא רצף של גרסאות של servable, עם הגדלת מספרי גרסאות.

  • דגם: דגם-נודע מכונית מיוצג על ידי servables אחד או יותר. דוגמאות להגשה הן:

    • הפעלה או עטיפות TensorFlow סביבם, כגון SavedModelBundle .
    • סוגים אחרים של מודלים שנלמדו על ידי מכונה.
    • טבלאות חיפוש אוצר מילים.
    • הטמעת טבלאות חיפוש.

    מודל מרוכב יכול להיות מיוצג כמספר רכיבים עצמאיים להגשה, או כרכיב מרוכב יחיד. Servable עשויה גם מתאימה שבריר דגם, למשל עם טבלת חיפוש גדולה sharded פני רבי Manager מקרים.

כדי לשים את כל אלה בהקשר של הדרכה זו:

  • מודלים TensorFlow מיוצגים על ידי סוג אחד של servable - SavedModelBundle . SavedModelBundle פנימי מורכב tensorflow:Session זיווג עם כמה מטא נתונים לגבי מה הגרף נטען לתוך הפגישה וכיצד להפעיל אותו עבור היקש.

  • ישנה ספריית מערכת קבצים המכילה זרם של יצוא TensorFlow, כל אחד בספריית המשנה שלו ששמה הוא מספר גרסה. ניתן לחשוב על הספרייה החיצונית כייצוג בסידרה של הזרם הניתן להגשה עבור מודל TensorFlow המוגש. כל ייצוא מתאים ל-servables שניתן לטעון.

  • AspiredVersionsManager מנטר את זרם הייצוא, ומנהלת מחזור החיים של כל SavedModelBundle servables דינמי.

TensorflowPredictImpl::Predict אז פשוט:

  • בקשות SavedModelBundle ממנהל (דרך ServerCore).
  • משתמש generic signatures למפות שמות מותח לוגיים PredictRequest לשמות מותחים אמיתיים וערכי נקשרי tensors.
  • מפעיל מסקנות.

בדוק והפעל את השרת

העתק את הגרסה הראשונה של הייצוא לתיקיה המנוטרת:

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%

זה מאשר שהשרת שלך מגלה אוטומטית את הגרסה החדשה ומשתמש בה להגשה!