דף זה תורגם על ידי Cloud Translation API.
Switch to English

העברת שימוש tf.summary ל TF 2.0

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

TensorFlow 2.0 כולל שינויים משמעותיים בממשק ה- API tf.summary המשמש לכתיבת נתוני סיכום להדמיה ב- TensorBoard.

מה השתנה

כדאי לחשוב על ממשק ה- API tf.summary כשני ממשקי משנה:

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

ב- TF 2.X

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

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

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.1599908770.kokoro-gcp-ubuntu-prod-1849198075.22428.5.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.1599908771.kokoro-gcp-ubuntu-prod-1849198075.22428.1013.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.1599908771.kokoro-gcp-ubuntu-prod-1849198075.22428.1446.v2

המרת הקוד שלך

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

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

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

    • TensorBoard דורש ערך צעד כדי להציג את הנתונים כסדרת זמן
    • העברה מפורשת היא הכרחית מכיוון שהצעד הגלובלי מ- TF 1.x הוסר, ולכן כל פעולה חייבת לדעת את משתנה הצעד הרצוי לקריאה
    • כדי להפחית את boilerplate, תמיכה ניסיונית לרישום ערך שלב ברירת מחדל זמינה כ 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() כדי לקבל את כל v1.summary.all_v2_summary_ops() הסיכום של TF 2.0 עבור הגרף הנוכחי, למשל כדי לבצע אותם באמצעות Session.run()

    • שטוף את הכותב עם v1.Session.run(writer.flush()) וכמו כן close()

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

טיפים נוספים

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

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

  • אין כתיבה ישירה של tf.compat.v1.Graph - במקום זאת השתמש בפונקציות מעקב

    • ביצוע גרפים ב- TF 2.0 משתמש ב- @tf.function במקום בגרף המפורש
    • ב- TF 2.0, השתמש בממשקי ה- API החדשים בסגנון מעקב tf.summary.trace_on() ו- tf.summary.trace_export() כדי להקליט גרפים של פונקציות המבוצעות
  • אין עוד אחסון במטמון סופר גלובלי בכל logdir עם tf.summary.FileWriterCache

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

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