סקירה כללית
המאפיין העיקרי של TensorBoard הוא ה- GUI האינטראקטיבי שלו. עם זאת, משתמשים לפעמים רוצה לקרוא את יומני נתונים תוכניתי מאוחסן TensorBoard, למטרות כגון ביצוע פוסט-הוק ניתוחים ויצירת חזותיים מותאמים אישית של נתוני יומן.
TensorBoard 2.3 תומך מקרה השימוש הזה עם tensorboard.data.experimental.ExperimentFromDev()
. זה מאפשר גישה תוכניתית של TensorBoard יומני סקלר . דף זה מדגים את השימוש הבסיסי של ה- API החדש הזה.
להכין
כדי להשתמש ב- API התכנותי, הקפד להתקין pandas
לצד tensorboard
.
נשתמש matplotlib
ו seaborn
עבור חלקות מנהג במדריך זה, אבל אתה יכול לבחור הכלי המועדף שלך כדי לנתח ולהציג DataFrame
ים.
pip install tensorboard pandas
pip install matplotlib seaborn
from packaging import version
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
from scipy import stats
import tensorboard as tb
major_ver, minor_ver, _ = version.parse(tb.__version__).release
assert major_ver >= 2 and minor_ver >= 3, \
"This notebook requires TensorBoard 2.3 or later."
print("TensorBoard version: ", tb.__version__)
TensorBoard version: 2.3.0a20200626
טוען scalars TensorBoard בתור pandas.DataFrame
פעם logdir TensorBoard הועלתה TensorBoard.dev, הוא הופך להיות מה שאנחנו מכנים כניסוי. לכל ניסוי יש מזהה ייחודי, אותו ניתן למצוא בכתובת ה- TensorBoard.dev של הניסוי. להדגמה שלנו להלן, נשתמש בניסוי TensorBoard.dev ב: https://tensorboard.dev/experiment/c1KCv3X3QvGwaXfgX1c4tg
experiment_id = "c1KCv3X3QvGwaXfgX1c4tg"
experiment = tb.data.experimental.ExperimentFromDev(experiment_id)
df = experiment.get_scalars()
df
df
הוא pandas.DataFrame
המכיל את כל יומני סקלר של הניסוי.
עמודי DataFrame
הם:
-
run
: כל אחד מהם מקביל ריצה בספריית משנה של logdir המקורי. בניסוי זה, כל ריצה היא מתוך אימון מלא של רשת עצבית מתפתחת (CNN) במערך הנתונים של MNIST עם סוג נתון אופטימיזציה נתון (היפרפרמטר אימון). זהDataFrame
מכיל ריצות מרובות כגון, אשר מתאימות ריצות אימונים חוזרים ונשנים תחת סוגים שונים האופטימיזציה. -
tag
: זה מתאר מהvalue
באותו האמצעי בשורה, כי הוא, מה מטר הערך מייצג בשורה. בניסוי זה, יש לנו רק שני תגים ייחודיים:epoch_accuracy
וepoch_loss
עבור מדדי הדיוק ואובדן בהתאמה. -
step
: זהו מספר שמשקף את סדר סדרתי של השורה המתאימה הריצה שלה. הנהstep
בעצם מתייחס למספר עידן. אם ברצונך לקבל את חותמות זמן נוסף עלstep
ערכים, אתה יכול להשתמש בטיעון מילתinclude_wall_time=True
כאשר קוראיםget_scalars()
. -
value
: זהו הערך המספרי האמיתי של עניין. כפי שתואר לעיל, כלvalue
בפרט זהDataFrame
הוא או הפסד או דיוק, תלויtag
של השורה.
print(df["run"].unique())
print(df["tag"].unique())
['adam,run_1/train' 'adam,run_1/validation' 'adam,run_2/train' 'adam,run_2/validation' 'adam,run_3/train' 'adam,run_3/validation' 'adam,run_4/train' 'adam,run_4/validation' 'adam,run_5/train' 'adam,run_5/validation' 'rmsprop,run_1/train' 'rmsprop,run_1/validation' 'rmsprop,run_2/train' 'rmsprop,run_2/validation' 'rmsprop,run_3/train' 'rmsprop,run_3/validation' 'rmsprop,run_4/train' 'rmsprop,run_4/validation' 'rmsprop,run_5/train' 'rmsprop,run_5/validation' 'sgd,run_1/train' 'sgd,run_1/validation' 'sgd,run_2/train' 'sgd,run_2/validation' 'sgd,run_3/train' 'sgd,run_3/validation' 'sgd,run_4/train' 'sgd,run_4/validation' 'sgd,run_5/train' 'sgd,run_5/validation'] ['epoch_accuracy' 'epoch_loss']
קבלת DataFrame (צורה רחבה)
בניסוי שלנו, את שני התגים ( epoch_loss
ו epoch_accuracy
) נוכחים באותו סט של צעדים בכל ריצה. זה מאפשר לקבל "רחב-טופס" DataFrame
ישירות get_scalars()
על ידי שימוש pivot=True
טיעון מילות מפתח. מנהל-טופס DataFrame
יש כל התגים שלה כלול עמודות של DataFrame, וזה יותר נוח לעבוד עם ובמקרים מסוימים כולל זו הנוכחית.
עם זאת, צריך להיזהר כי אם התנאי של החזקת מכשירים אחידים של ערכי צעד בכול תגיות בכול ריצות לא נפגש, באמצעות pivot=True
תגרום לשגיאה.
dfw = experiment.get_scalars(pivot=True)
dfw
שים לב כי במקום טור "ערך" יחיד, DataFrame הרחב-הטופס כולל שני תגים (מדדים) כעמוד שלה במפורש: epoch_accuracy
ו epoch_loss
.
שמירת ה- DataFrame כ- CSV
pandas.DataFrame
יש יכולת פעולה הדדית טובה עם CSV . אתה יכול לאחסן אותו כקובץ CSV מקומי ולטעון אותו מאוחר יותר. לדוגמה:
csv_path = '/tmp/tb_experiment_1.csv'
dfw.to_csv(csv_path, index=False)
dfw_roundtrip = pd.read_csv(csv_path)
pd.testing.assert_frame_equal(dfw_roundtrip, dfw)
ביצוע ויזואליזציה וניתוח סטטיסטי בהתאמה אישית
# Filter the DataFrame to only validation data, which is what the subsequent
# analyses and visualization will be focused on.
dfw_validation = dfw[dfw.run.str.endswith("/validation")]
# Get the optimizer value for each row of the validation DataFrame.
optimizer_validation = dfw_validation.run.apply(lambda run: run.split(",")[0])
plt.figure(figsize=(16, 6))
plt.subplot(1, 2, 1)
sns.lineplot(data=dfw_validation, x="step", y="epoch_accuracy",
hue=optimizer_validation).set_title("accuracy")
plt.subplot(1, 2, 2)
sns.lineplot(data=dfw_validation, x="step", y="epoch_loss",
hue=optimizer_validation).set_title("loss")
Text(0.5, 1.0, 'loss')
החלקות לעיל מציגות את זמני הזמן של דיוק האימות ואובדן האימות. כל עקומה מציגה את הממוצע על פני 5 ריצות תחת סוג אופטימיזציה. הודות תכונה מובנית של seaborn.lineplot()
, כל עקומה גם מציג ± 1 סטיית התקן סביב הממוצע, אשר נותן לנו תחושה ברורה של השתנות עקומות אלה ואת המשמעות של ההבדלים בין סוגי האופטימיזציה שלוש. הדמיה זו של השתנות עדיין אינה נתמכת ב- GUI של TensorBoard.
ברצוננו ללמוד את ההשערה כי אובדן האימות המינימלי שונה באופן משמעותי בין ה"אדם "," rmsprop "ו-" sgd ". אז אנו מחלצים DataFrame עבור אובדן האימות המינימלי תחת כל אחד מהאופטימיזורים.
לאחר מכן אנו מכינים קרטל לדימוי ההבדל בהפסדי האימות המינימליים.
adam_min_val_loss = dfw_validation.loc[optimizer_validation=="adam", :].groupby(
"run", as_index=False).agg({"epoch_loss": "min"})
rmsprop_min_val_loss = dfw_validation.loc[optimizer_validation=="rmsprop", :].groupby(
"run", as_index=False).agg({"epoch_loss": "min"})
sgd_min_val_loss = dfw_validation.loc[optimizer_validation=="sgd", :].groupby(
"run", as_index=False).agg({"epoch_loss": "min"})
min_val_loss = pd.concat([adam_min_val_loss, rmsprop_min_val_loss, sgd_min_val_loss])
sns.boxplot(data=min_val_loss, y="epoch_loss",
x=min_val_loss.run.apply(lambda run: run.split(",")[0]))
<matplotlib.axes._subplots.AxesSubplot at 0x7f5e017c8150>
# Perform pairwise comparisons between the minimum validation losses
# from the three optimizers.
_, p_adam_vs_rmsprop = stats.ttest_ind(
adam_min_val_loss["epoch_loss"],
rmsprop_min_val_loss["epoch_loss"])
_, p_adam_vs_sgd = stats.ttest_ind(
adam_min_val_loss["epoch_loss"],
sgd_min_val_loss["epoch_loss"])
_, p_rmsprop_vs_sgd = stats.ttest_ind(
rmsprop_min_val_loss["epoch_loss"],
sgd_min_val_loss["epoch_loss"])
print("adam vs. rmsprop: p = %.4f" % p_adam_vs_rmsprop)
print("adam vs. sgd: p = %.4f" % p_adam_vs_sgd)
print("rmsprop vs. sgd: p = %.4f" % p_rmsprop_vs_sgd)
adam vs. rmsprop: p = 0.0244 adam vs. sgd: p = 0.9749 rmsprop vs. sgd: p = 0.0135
לכן, ברמת מובהקות של 0.05, הניתוח שלנו מאשר את השערתנו כי אובדן האימות המינימלי גבוה משמעותית (כלומר גרוע יותר) במייעל rmsprop בהשוואה לשני האופטימיזורים האחרים הכלולים בניסוי שלנו.
לסיכום, הדרכה זו מדגימה כיצד לגשת לנתונים סקלר כמו panda.DataFrame
ים מ TensorBoard.dev. זה מדגים את סוג של ניתוחים גמישים ורבי עוצמה להדמיה אתה יכול לעשות עם DataFrame
ים.