![]() | ![]() | ![]() |
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, יהיה עליך להתאים את הקוד שלך באופן הבא:
כותב ברירת מחדל המוגדר באמצעות
.as_default()
חייב להיות נוכח כדי להשתמש.as_default()
סיכום- המשמעות היא ביצוע אופ בשקיקה או שימוש באופציות בבניית גרפים
- ללא סופר ברירת מחדל, אופ סיכום הופך ללא-אופ שקט
- כותבי ברירת מחדל אינם מתפשטים על פני גבול הביצוע
@tf.function
- הם מזוהים רק כאשר מעקב אחר הפונקציה - לכן השיטה הטובה ביותר היא להתקשר ל-writer.as_default()
בגוף הפונקציה, ולוודא שהכותב מתנגד. ממשיך להתקיים כל עוד נעשה שימוש ב-@tf.function
יש להעביר את ערך "הצעד" לכל אופציה באמצעות טיעון
step
- TensorBoard דורש ערך צעד כדי להציג את הנתונים כסדרת זמן
- העברה מפורשת היא הכרחית מכיוון שהצעד הגלובלי מ- TF 1.x הוסר, ולכן כל פעולה חייבת לדעת את משתנה הצעד הרצוי לקריאה
- כדי להפחית את boilerplate, תמיכה ניסיונית לרישום ערך שלב ברירת מחדל זמינה כ
tf.summary.experimental.set_step()
, אך זו פונקציונליות זמנית שניתן לשנות ללא הודעה מוקדמת
חתימות הפונקציות של אופציות סיכום בודדות השתנו
- ערך ההחזר הוא כעת בוליאני (המציין אם אכן נכתב סיכום)
- שם הפרמטר השני (אם משתמשים בו) השתנה
tensor
data
- פרמטר
collections
הוסר; האוספים הם TF 1.x בלבד - הפרמטר
family
הוסר; פשוט השתמש ב-tf.name_scope()
[רק למשתמשים במצב גרף מדור קודם / ביצוע הפעלה]
ראשית אתחל את הכותב עם
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 צעדים") יש מראה חדש
- כדי לשלוט על אופ וקוד משויך, עוטף אותם בהצהרת if רגילה (שעובדת במצב להוט וב-
@tf.function
באמצעות חתימה ) או ב-tf.cond
- כדי לשלוט בסיכומים בלבד, השתמש
tf.summary.record_if()
ההקשרtf.summary.record_if()
החדשtf.summary.record_if()
אותו למצב הבוליאני שבחרת. אלה מחליפים את דפוס ה- TF 1.x:
if condition: writer.add_summary()
- כדי לשלוט על אופ וקוד משויך, עוטף אותם בהצהרת if רגילה (שעובדת במצב להוט וב-
אין כתיבה ישירה של
tf.compat.v1.Graph
- במקום זאת השתמש בפונקציות מעקב- ביצוע גרפים ב- TF 2.0 משתמש ב-
@tf.function
במקום בגרף המפורש - ב- TF 2.0, השתמש בממשקי ה- API החדשים בסגנון מעקב
tf.summary.trace_on()
ו-tf.summary.trace_export()
כדי להקליט גרפים של פונקציות המבוצעות
- ביצוע גרפים ב- TF 2.0 משתמש ב-
אין עוד אחסון במטמון סופר גלובלי בכל logdir עם
tf.summary.FileWriterCache
- על המשתמשים ליישם מטמון / שיתוף משלהם של אובייקטים של כותבים, או פשוט להשתמש בכותבים נפרדים (תמיכת TensorBoard עבור אלה בעיצומה )
הייצוג הבינארי של קובץ האירוע השתנה
- TensorBoard 1.x כבר תומך בפורמט החדש; הבדל זה משפיע רק על משתמשים המנתחים באופן ידני נתוני סיכום מקבצי אירועים
- נתוני סיכום מאוחסנים כעת כבת-בתים; אתה יכול להשתמש ב-
tf.make_ndarray(event.summary.value[0].tensor)
כדי להמיר אותו לטשטוש