העברת שימוש tf. סיכום ל- TF 2.x

הצג באתר TensorFlow.org הפעל בגוגל קולאב צפה במקור ב-GitHub הורד מחברת
import tensorflow as tf

TensorFlow 2.x כוללת שינויים משמעותיים tf.summary API המשמש נתוני סיכום כתיבה עבור להדמיה ב TensorBoard.

מה השתנה

זה שימושי לחשוב על tf.summary API כשתי-APIs משנה:

  • קבוצה של חיילים מיחידות לסיכומים הפרט הקלטה - summary.scalar() , summary.histogram() , summary.image() , summary.audio() , ולאחר summary.text() - אשר נקראים מוטבעות מקוד המודל שלך.
  • היגיון כתיבה שאוסף את הסיכומים האישיים הללו וכותב אותם לקובץ יומן בפורמט מיוחד (שאותו TensorBoard קורא לאחר מכן כדי ליצור הדמיות).

ב-TF 1.x

שני החצאים היו צריכים להיות חוטית באופן ידני יחד - על ידי שליפת פלטי אופ סיכום באמצעות Session.run() וקראו FileWriter.add_summary(output, step) . v1.summary.merge_all() op הקל זאת באמצעות אוסף גרף כדי לצבור את כול תפוקות אופ הסיכום, אך גישה זו עדיין עבדה היטב לביצוע להוט ובקרת זרימה, מה שהופך אותו במיוחד חולה מתאים עבור 2.X. TF

ב-TF 2.X

שני החצאים משולבים באופן הדוק, ועכשיו הפרט tf.summary ops לכתוב את הנתונים שלהם באופן מיידי כאשר להורג. השימוש ב-API מקוד הדגם שלך עדיין אמור להיראות מוכר, אך כעת הוא ידידותי לביצוע נלהב בעודו תואם למצב גרף. שילוב שני החצאים של אמצעי API את summary.FileWriter הוא עכשיו חלק מהקשר ביצוע TensorFlow ומקבל לגשת ישירות tf.summary ops, כך תצורת סופרים הוא החלק העיקרי שנראה שונה.

שימוש לדוגמה עם ביצוע להוט, ברירת המחדל ב-TF 2.x:

writer = tf.summary.create_file_writer("/tmp/mylogs/eager")

with writer.as_default():
  for step in range(100):
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)
    writer.flush()
ls /tmp/mylogs/eager
events.out.tfevents.1633086727.kokoro-gcp-ubuntu-prod-1386032077.31590.0.v2

דוגמה לשימוש עם ביצוע גרף tf.function:

writer = tf.summary.create_file_writer("/tmp/mylogs/tf_function")

@tf.function
def my_func(step):
  with writer.as_default():
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)

for step in tf.range(100, dtype=tf.int64):
  my_func(step)
  writer.flush()
ls /tmp/mylogs/tf_function
events.out.tfevents.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.1.v2

דוגמה לשימוש עם ביצוע גרף TF 1.x מדור קודם:

g = tf.compat.v1.Graph()
with g.as_default():
  step = tf.Variable(0, dtype=tf.int64)
  step_update = step.assign_add(1)
  writer = tf.summary.create_file_writer("/tmp/mylogs/session")
  with writer.as_default():
    tf.summary.scalar("my_metric", 0.5, step=step)
  all_summary_ops = tf.compat.v1.summary.all_v2_summary_ops()
  writer_flush = writer.flush()


with tf.compat.v1.Session(graph=g) as sess:
  sess.run([writer.init(), step.initializer])

  for i in range(100):
    sess.run(all_summary_ops)
    sess.run(step_update)
    sess.run(writer_flush)
ls /tmp/mylogs/session
events.out.tfevents.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.2.v2

המרת הקוד שלך

המרת הקיים tf.summary השימוש ל- API 2.x TF לא יכול להיות אוטומטי באופן מהימן, ולכן tf_upgrade_v2 סקריפט פשוט משכתב את הכל כדי tf.compat.v1.summary . כדי לעבור ל-TF 2.x, תצטרך להתאים את הקוד שלך באופן הבא:

  1. סט סופר ברירת המחדל באמצעות .as_default() חייב להיות נוכח כדי ops סיכום השימוש

    • משמעות הדבר היא ביצוע פעולות בשקיקה או שימוש באופציות בבניית גרפים
    • ללא כותב ברירת מחדל, פעולות סיכום הופכות ל-Silent No-Ops
    • סופרי ברירה לא (עדיין) הפיצו ברחבי @tf.function גבול ביצוע - הם מזוהים רק כאשר הפונקציה לייחס - כך התרגול הטוב ביותר הוא לקרוא writer.as_default() בגוף הפונקציה, ועל מנת להבטיח כי האובייקט סופר ממשיכה להתקיים כל עוד @tf.function נמצא בשימוש
  2. הערך "צעד" יש להעביר אל כל op באמצעות step טיעון

    • TensorBoard דורש ערך צעד כדי להציג את הנתונים כסדרת זמן
    • יש צורך במעבר מפורש מכיוון שהצעד הגלובלי מ-TF 1.x הוסר, כך שכל פעולה חייבת לדעת את משתנה הצעד הרצוי לקריאה
    • כדי להפחית מוכן מראש, תמיכה ניסיונית רישום ערך צעד ברירת מחדל היא זמינה tf.summary.experimental.set_step() , אבל זה פונקציונאלי זמני שעשוי להשתנות ללא הודעה
  3. חתימות הפונקציות של פעולות סיכום בודדות השתנו

    • ערך ההחזרה הוא כעת בוליאני (מציין אם סיכום נכתב בפועל)
    • שם הפרמטר השני (אם משתמשים בו) השתנה מן tensor עד data
    • collections הפרמטר הוסר; האוספים הם TF 1.x בלבד
    • family פרמטר הוסר; השימוש פשוט tf.name_scope()
  4. [רק עבור משתמשי מצב גרף / ביצוע הפעלה מדור קודם]

    • ראשית לאתחל את הסופר עם v1.Session.run(writer.init())

    • השתמש v1.summary.all_v2_summary_ops() כדי לקבל את כל ops סיכום 2.x TF עבור הגרף הנוכחי, למשל לבצע אותם באמצעות Session.run()

    • שטוף את הסופר עם v1.Session.run(writer.flush()) וכך גם לגבי close()

אם הקוד 1.x TF שלך היה במקום באמצעות tf.contrib.summary API, זה הרבה יותר דומה ל- API 2.x TF, כך tf_upgrade_v2 התסריט יהיה להפוך את רוב השלבים הגירה (ואזהרות לפלוט או שגיאות עבור כל שימוש שלא יכול להיות מועבר במלואו). על פי רוב זה רק משכתב את שיחות ה- API כדי tf.compat.v2.summary ; אם אתה רק צריך תאימות עם 2.x TF תוכל לשחרר את compat.v2 ופשוט להתייחס אליה כמו tf.summary .

טיפים נוספים

בנוסף לאזורים הקריטיים לעיל, השתנו גם כמה היבטי עזר:

  • להקלטה מותנית (כמו "תיעוד כל 100 צעדים") יש מראה חדש

    • כדי ops המלאה קודים נלווים, לעטוף אותם בהצהרה אם קבוע (אשר עובדת במצב להוט וב @tf.function באמצעות חתימה ) או tf.cond
    • כדי לשלוט סיכומים רק, במבנה החדש של tf.summary.record_if() מנהל בהקשר, ולהעביר לו את מצבו בוליאני על פי בחירתך
    • אלה מחליפים את תבנית TF 1.x:

      if condition:
        writer.add_summary()
      
  • אין כתיבה ישירה של tf.compat.v1.Graph - במקום פונקציות עקבות השימוש

  • אין במטמון סופר הגלובלי יותר לכול logdir עם tf.summary.FileWriterCache

    • משתמשים צריכים גם ליישם במטמון משלהם / שיתוף חפצים סופר, או פשוט להשתמש סופרים נפרדים (תמיכת TensorBoard עבור שהאחרון הוא בהתקדמות )
  • הייצוג הבינארי של קובץ האירוע השתנה

    • TensorBoard 1.x כבר תומך בפורמט החדש; הבדל זה משפיע רק על משתמשים שמנתחים באופן ידני נתוני סיכום מקובצי אירועים
    • נתוני סיכום מאוחסנים כעת כבייטים טנסוריים; אתה יכול להשתמש tf.make_ndarray(event.summary.value[0].tensor) כדי להמיר אותו numpy