פורמט SavedModel של TensorFlow 2 הוא הדרך המומלצת לשתף דגמים וחלקי דגמים שעברו הכשרה מראש ב- TensorFlow Hub. הוא מחליף את הפורמט הישן יותר של TF1 Hub ומגיע עם סט חדש של ממשקי API.
דף זה מסביר כיצד לעשות שימוש חוזר ב-TF2 SavedModels בתוכנית TensorFlow 2 עם ה-API ברמה נמוכה hub.load()
והעטיפה שלו hub.KerasLayer
. (בדרך כלל, hub.KerasLayer
משולב עם tf.keras.layers
אחרים כדי לבנות מודל Keras או ה- model_fn
של TF2 Estimator.) ממשקי API אלה יכולים גם לטעון את המודלים הישנים בפורמט TF1 Hub, במגבלות, עיין במדריך התאימות .
משתמשי TensorFlow 1 יכולים לעדכן ל-TF 1.15 ולאחר מכן להשתמש באותם ממשקי API. גרסאות ישנות יותר של TF1 לא עובדות.
שימוש ב- SavedModels מ- TF Hub
שימוש ב-SaveModel ב-Keras
Keras הוא ה-API ברמה גבוהה של TensorFlow לבניית מודלים של למידה עמוקה על ידי חיבור אובייקטי Keras Layer. ספריית tensorflow_hub
מספקת את ה-class hub.KerasLayer
שמאוחל עם ה-URL (או נתיב מערכת הקבצים) של SavedModel ולאחר מכן מספק את החישוב מה-SavedModel, כולל המשקולות המאומנות מראש שלו.
הנה דוגמה לשימוש בהטמעת טקסט מאומנת מראש:
import tensorflow as tf
import tensorflow_hub as hub
hub_url = "https://tfhub.dev/google/nnlm-en-dim128/2"
embed = hub.KerasLayer(hub_url)
embeddings = embed(["A long sentence.", "single-word", "http://example.com"])
print(embeddings.shape, embeddings.dtype)
מכאן, ניתן לבנות מסווג טקסט בצורה הרגילה של Keras:
model = tf.keras.Sequential([
embed,
tf.keras.layers.Dense(16, activation="relu"),
tf.keras.layers.Dense(1, activation="sigmoid"),
])
ה- Text Classification colab הוא דוגמה מלאה כיצד לאמן ולהעריך מסווג כזה.
משקלי הדגם ב- hub.KerasLayer
מוגדרים כברירת מחדל כבלתי ניתן לאימון. עיין בסעיף על כוונון עדין להלן כיצד לשנות זאת. משקולות מחולקות בין כל היישומים של אותו אובייקט שכבה, כרגיל ב-Keras.
שימוש ב-SaveModel באומד
משתמשים ב-API של Estimator של TensorFlow להדרכה מבוזרת יכולים להשתמש ב-SaveedModels מ-TF Hub על ידי כתיבת model_fn
שלהם במונחים של hub.KerasLayer
בין tf.keras.layers
אחרים.
מאחורי הקלעים: SavedModel הורדה ושמירה במטמון
שימוש ב- SavedModel מ- TensorFlow Hub (או שרתי HTTPS אחרים שמיישמים את פרוטוקול האירוח שלו) מוריד ומפרק אותו למערכת הקבצים המקומית אם עדיין לא קיים. ניתן להגדיר את משתנה הסביבה TFHUB_CACHE_DIR
לעקוף את מיקום ברירת המחדל הזמני לאחסון במטמון של SavedModels שהורדו ולא דחוסים. לפרטים, ראה שמירה במטמון .
שימוש ב- SavedModel ב-TensorFlow ברמה נמוכה
דגם ידיות
ניתן לטעון SavedModels handle
שצוינה , כאשר handle
היא נתיב של מערכת קבצים, כתובת URL חוקית של דגם TFhub.dev (למשל "https://tfhub.dev/..."). כתובות ה-URL של מודלים של Kaggle Mirror TFhub.dev מטפל בהתאם לתנאים שלנו ולרישיון המשויך לנכסי הדגם, למשל, "https://www.kaggle.com/...". ידיות מדגמי Kaggle שוות ערך לידית ה-TFhub.dev המקבילה להן.
הפונקציה hub.load(handle)
מורידה ומבטלת דחיסה של SavedModel (אלא אם handle
הוא כבר נתיב של מערכת קבצים) ולאחר מכן מחזירה את התוצאה של טעינתו עם הפונקציה המובנית של TensorFlow tf.saved_model.load()
. לכן, hub.load()
יכול להתמודד עם כל SavedModel חוקי (בניגוד ל- hub.Module
קודמו עבור TF1).
נושא מתקדם: למה לצפות מה-SavedModel לאחר הטעינה
בהתאם לתוכן של SavedModel, ניתן להפעיל את התוצאה של obj = hub.load(...)
בדרכים שונות (כפי שהוסבר בפירוט רב יותר במדריך SavedModel של TensorFlow:
חתימות ההגשה של SavedModel (אם יש כאלה) מיוצגות כמילון של פונקציות קונקרטיות וניתן לקרוא אותן כמו
tensors_out = obj.signatures["serving_default"](**tensors_in)
, עם מילוני טנסורים הממוקמים על ידי הקלט והפלט המתאימים. שמות ובכפוף לצורת החתימה ולאילוצי dtype.שיטות ה-
@tf.function
-מעוטרות של האובייקט השמור (אם יש) משוחזרות כאובייקטי tf.function שניתן לקרוא להם על ידי כל השילובים של ארגומנטים Tensor ולא-Tensor שעבורם הפונקציה tf. עוקבה לפני השמירה. בפרט, אם יש שיטתobj.__call__
עם עקבות מתאימות, ניתן לקרואobj
עצמו כמו פונקציית Python. דוגמה פשוטה יכולה להיראות כמוoutput_tensor = obj(input_tensor, training=False)
.
זה משאיר חופש עצום בממשקים ש-SavedModels יכולים ליישם. ממשק SavedModels לשימוש חוזר עבור obj
קובע מוסכמות כך שקוד לקוח, כולל מתאמים כמו hub.KerasLayer
, יודעים להשתמש ב-SaveedModel.
ייתכן שחלק מה- SavedModels לא יפעלו בהתאם למוסכמה הזו, במיוחד דגמים שלמים שלא מיועדים לשימוש חוזר בדגמים גדולים יותר, ורק מספקים חתימות הגשה.
המשתנים הניתנים לאימון ב- SavedModel נטענים מחדש כניתנים לאימון, ו- tf.GradientTape
יצפה בהם כברירת מחדל. עיין בסעיף על כוונון עדין להלן לכמה אזהרות, ושקול להימנע מכך בתור התחלה. גם אם אתה רוצה לכוונן עדין, אולי תרצה לראות אם obj.trainable_variables
מייעץ לאמן מחדש רק תת-קבוצה של המשתנים הניתנים לאימון במקור.
יצירת SavedModels עבור TF Hub
סקירה כללית
SavedModel הוא פורמט ההסדרה הסטנדרטי של TensorFlow עבור דגמים או חלקי מודל מאומנים. הוא מאחסן את המשקולות המאומנות של הדגם יחד עם פעולות TensorFlow המדויקות לביצוע החישוב שלו. ניתן להשתמש בו באופן עצמאי מהקוד שיצר אותו. בפרט, ניתן לעשות בו שימוש חוזר על פני ממשקי API שונים לבניית מודלים ברמה גבוהה כמו Keras, מכיוון שפעולות TensorFlow הן השפה הבסיסית המשותפת שלהם.
חוסך מקרס
החל מ-TensorFlow 2, tf.keras.Model.save()
ו- tf.keras.models.save_model()
כברירת מחדל לפורמט SavedModel (לא HDF5). SavedModels המתקבלים שניתן להשתמש בהם עם hub.load()
, hub.KerasLayer
ומתאמים דומים עבור ממשקי API ברמה גבוהה אחרים כאשר הם הופכים לזמינים.
כדי לשתף דגם שלם של Keras, פשוט שמור אותו עם include_optimizer=False
.
כדי לשתף חלק מדגם Keras, הפוך את היצירה לדגם בפני עצמו ואז שמור את זה. אתה יכול לפרוס את הקוד כך מההתחלה....
piece_to_share = tf.keras.Model(...)
full_model = tf.keras.Sequential([piece_to_share, ...])
full_model.fit(...)
piece_to_share.save(...)
...או גזרו את היצירה לחלוקה לאחר מעשה (אם היא תואמת את השכבות של הדגם המלא שלכם):
full_model = tf.keras.Model(...)
sharing_input = full_model.get_layer(...).get_output_at(0)
sharing_output = full_model.get_layer(...).get_output_at(0)
piece_to_share = tf.keras.Model(sharing_input, sharing_output)
piece_to_share.save(..., include_optimizer=False)
TensorFlow Models ב- GitHub משתמשת בגישה הקודמת עבור BERT (ראה nlp/tools/export_tfhub_lib.py , שים לב לפיצול בין core_model
לייצוא וה- pretrainer
לשחזור המחסום) והגישה השנייה עבור ResNet (ראה legacy/image_classification/tfhub_export.py ).
חיסכון מ-TensorFlow ברמה נמוכה
זה מצריך היכרות טובה עם SavedModel Guide של TensorFlow.
אם אתה רוצה לספק יותר מסתם חתימת הגשה, עליך ליישם את ממשק SavedModel לשימוש חוזר . מבחינה קונספטואלית, זה נראה כך
class MyMulModel(tf.train.Checkpoint):
def __init__(self, v_init):
super().__init__()
self.v = tf.Variable(v_init)
self.variables = [self.v]
self.trainable_variables = [self.v]
self.regularization_losses = [
tf.function(input_signature=[])(lambda: 0.001 * self.v**2),
]
@tf.function(input_signature=[tf.TensorSpec(shape=None, dtype=tf.float32)])
def __call__(self, inputs):
return tf.multiply(inputs, self.v)
tf.saved_model.save(MyMulModel(2.0), "/tmp/my_mul")
layer = hub.KerasLayer("/tmp/my_mul")
print(layer([10., 20.])) # [20., 40.]
layer.trainable = True
print(layer.trainable_weights) # [2.]
print(layer.losses) # 0.004
כוונון עדין
אימון המשתנים שכבר הוכשרו של SavedModel מיובא יחד עם אלה של המודל סביבו נקרא כוונון עדין של SavedModel. זה יכול להביא לאיכות טובה יותר, אבל לעתים קרובות הופך את האימון ליותר תובעני (עשוי לקחת יותר זמן, להיות תלוי יותר במייעל ובפרמטרים שלו, להגביר את הסיכון להתאמת יתר ולדרוש הגדלת מערך נתונים, במיוחד עבור CNNs). אנו ממליצים לצרכנים של SavedModel לבחון כוונון עדין רק לאחר שקבעו משטר אימונים טוב, ורק אם המוציא לאור של SavedModel ממליץ על כך.
כוונון עדין משנה את פרמטרי המודל ה"רציפים" שמאומנים. הוא אינו משנה טרנספורמציות מקודדות קשיחות, כגון יצירת אסימון של קלט טקסט ומיפוי אסימונים לערכים התואמים שלהם במטריצת הטמעה.
עבור צרכני SavedModel
יצירת hub.KerasLayer
כמו
layer = hub.KerasLayer(..., trainable=True)
מאפשר כוונון עדין של SavedModel שנטען על ידי השכבה. הוא מוסיף את המשקולות הניתנות לאימון ומסדרי המשקל המוצהרים ב- SavedModel למודל Keras, ומריץ את החישוב של SavedModel במצב אימון (חשבו על נשירה וכו').
סיווג התמונה colab מכיל דוגמה מקצה לקצה עם כוונון עדין אופציונלי.
ייצוא מחדש של תוצאת הכוונון העדין
משתמשים מתקדמים עשויים לרצות לשמור את התוצאות של כוונון עדין בחזרה לתוך SavedModel שניתן להשתמש בו במקום זה שנטען במקור. זה יכול להיעשות עם קוד כמו
loaded_obj = hub.load("https://tfhub.dev/...")
hub_layer = hub.KerasLayer(loaded_obj, trainable=True, ...)
model = keras.Sequential([..., hub_layer, ...])
model.compile(...)
model.fit(...)
export_module_dir = os.path.join(os.getcwd(), "finetuned_model_export")
tf.saved_model.save(loaded_obj, export_module_dir)
ליוצרי SavedModel
בעת יצירת SavedModel לשיתוף ב- TensorFlow Hub, חשבו מראש אם וכיצד על הצרכנים שלו לכוונן אותו, וספק הדרכה בתיעוד.
שמירה מדגם Keras אמורה לגרום לכל המכניקה של כוונון עדין לעבוד (חיסכון בירידה בהסדרת משקל, הכרזה על משתנים הניתנים לאימון, מעקב אחר __call__
גם training=True
וגם training=False
וכו')
בחר ממשק מודל שמשחק היטב עם זרימת שיפוע, למשל, לוגיטי פלט במקום הסתברויות softmax או תחזיות מובילות.
אם המודל משתמש בנשירה, נורמליזציה של אצווה או טכניקות אימון דומות הכוללות היפרפרמטרים, הגדר אותם לערכים הגיוניים על פני בעיות יעד צפויות וגדלי אצווה רבים. (נכון לכתיבת שורות אלה, חיסכון מ-Keras לא מקל על מתן אפשרות לצרכנים להתאים אותם.)
מסדרי משקל בשכבות בודדות נשמרים (עם מקדמי חוזק הסידור שלהם), אבל הסדרת משקל מתוך המייעל (כמו tf.keras.optimizers.Ftrl.l1_regularization_strength=...)
) אובדת. ייעץ לצרכנים של SavedModel שלך בהתאם.