המרות מודרניות, סתימות, Xception, עם Keras ומעבדי TPU

1. סקירה כללית

בשיעור ה-Lab הזה תלמדו על ארכיטקטורה רגולרית מודרנית, ותשתמשו בידע שלכם כדי להטמיע רשת נוירונים רגולרית פשוטה אך יעילה שנקראת 'squeezenet'.

הסדנה הזו כוללת את ההסברים התיאורטיים הנדרשים על רשתות נוירונים קונבולוציוניות, והיא נקודת התחלה טובה למפתחים שמתחילים ללמוד על למידת עומק.

שיעור ה-Lab הזה הוא חלק 4 בסדרה "Keras on TPU". אפשר לעשות את זה בסדר הבא או בנפרד.

ca8cc21f6838eccc.png

מה תלמדו

  • לשלוט בסגנון הפונקציונלי של Keras
  • בניית מודל באמצעות ארכיטקטורת סקוויזנט
  • להשתמש במעבדי TPU כדי לאמן מהר ואיטרציה על הארכיטקטורה
  • הטמעת הגדלת נתונים באמצעות tf.data.dataset
  • כדי לבצע כוונון עדין של מודל גדול שעבר אימון מקדים (Xception) ב-TPU

משוב

אם משהו נראה לא בסדר בסדנת הקוד הזו, נשמח לדעת. אפשר לשלוח משוב דרך בעיות ב-GitHub [קישור למשוב].

2. התחלה מהירה של Google Colaboratory

הסדנה הזו מתבססת על Google Collaboratory ואין צורך לבצע הגדרות כלשהן. Colaboratory היא פלטפורמת notebook אונליין למטרות חינוכיות. התוכנית כוללת הכשרה בחינם לגבי מעבדים (CPU), מעבדי GPU ו-TPU.

688858c21e3beff2.png

אפשר לפתוח את ה-notebook לדוגמה ולעבור דרך שני תאים כדי להכיר את Colaboratory.

c3df49e90e5a654f.png Welcome to Colab.ipynb

בחירת קצה עורפי של TPU

8832c6208c99687d.png

בתפריט של Colab, בוחרים באפשרות Runtime > Change runtime type (סביבת זמן ריצה > שינוי הסוג של סביבת זמן הריצה) ואז בוחרים באפשרות TPU. בשיעור ה-Lab הזה תלמדו להשתמש ב-TPU (יחידת עיבוד Tensor) חזקה, לגיבוי לצורך אימון עם האצת חומרה. החיבור לסביבת זמן הריצה יתבצע באופן אוטומטי בביצוע הראשון. אפשר גם ללחוץ על הלחצן Connect (התחברות) בפינה הימנית העליונה.

ביצוע של Notebook

76d05caa8b4db6da.png

כדי להריץ תאים אחד אחרי השני, לוחצים על תא ומקישים על Shift-Enter. אפשר גם להריץ את כל ה-notebook באמצעות סביבת זמן הריצה > הפעלת הכול.

תוכן העניינים

429f106990037ec4.png

לכל מחברת יש תוכן עניינים. אפשר לפתוח אותו באמצעות החץ השחור שמימין.

תאים מוסתרים

edc3dba45d26f12a.png

בחלק מהתאים יוצג רק השם שלהם. זוהי תכונה ספציפית למסמכי notebook ב-Colab. אפשר ללחוץ עליהן לחיצה כפולה כדי לראות את הקוד שבפנים, אבל בדרך כלל זה לא מעניין במיוחד. בדרך כלל פונקציות תמיכה או פונקציות של תצוגה חזותית. עדיין צריך להריץ את התאים האלה כדי להגדיר את הפונקציות שבתוכה.

אימות

cdd4b41413100543.png

ל-Colab יש גישה לקטגוריות הפרטיות שלכם ב-Google Cloud Storage, בתנאי שתבצעו אימות באמצעות חשבון מורשה. קטע הקוד שלמעלה יפעיל תהליך אימות.

3. [מידע] מהן יחידות עיבוד של Tensor (TPU)?

בקצרה

f88cf6facfc70166.png

הקוד לאימון מודל על TPU ב-Keras (ומפסיקים להשתמש ב-GPU או במעבד אם ה-TPU לא זמין):

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

היום נשתמש ב-TPU כדי ליצור ולבצע אופטימיזציה של סיווג פרחים במהירות אינטראקטיבית (דקות לכל הרצה של אימון).

688858c21e3beff2.png

למה כדאי להשתמש ב-TPU?

מעבדי GPU מודרניים מאורגנים לפי 'ליבות' שניתנות לתכנות, ארכיטקטורה גמישה מאוד שמאפשרת להם להתמודד עם מגוון משימות כמו רינדור בתלת-ממד, למידה עמוקה (Deep Learning), סימולציות פיזיות וכו'. מצד שני, יחידות TPU יוצרות התאמה בין מעבד וקטורי קלאסי עם יחידת הכפלה ייעודית של מטריצה, ומתבלטות בכל משימה שבה הכפולות של המטריצה הגדולה שולטות, כמו רשתות נוירונים.

8eb3e718b8e2ed08.png

איור: שכבת רשת נוירונים צפופה ככפלת מטריצה, עם קבוצה של שמונה תמונות שעוברות עיבוד ברשת העצבית בבת אחת. בצעו את ההכפלה של עמודה אחת בשורה x כדי לוודא שהיא אכן מבצעת סכום משוקלל של כל ערכי הפיקסלים של תמונה. אפשר לייצג שכבות עיבוד קוונטי גם כמכפילות מטריצות, אבל זה קצת יותר מורכב (הסבר כאן, בקטע 1).

החומרה

MXU ו-VPU

ליבת TPU v2 מורכבת מיחידת הכפלת מטריצות (MXU) שמפעילה הכפלת מטריצות ויחידה לעיבוד וקטורים (VPU) לכל המשימות האחרות כמו הפעלות, softmax וכו'. ה-VPU מטפל בחישובים של float32 ו-int32. לעומת זאת, ה-MXU פועל בפורמט של נקודה צפה (floating-point) עם דיוק משולב של 16 עד 32 ביט.

7d68944718f76b18.png

נקודה צפה (floating-point) מעורבת ו-bfloat16

ה-MXU מחשב כפל מטריצות באמצעות קלט bfloat16 ופלט float32. הצטברות הביניים מתבצעת ברמת דיוק float32.

19c5fc432840c714.png

האימון של רשת נוירונים עמיד בדרך כלל לרעש שנוצר על ידי דיוק מופחת של נקודה צפה (floating-point). יש מקרים שבהם רעש אפילו עוזר לכלי האופטימיזציה להתכנס. בעבר נעשה שימוש בדיוק של נקודה צפה (floating-point) של 16 ביט כדי להאיץ את החישובים, אבל לפורמטים float16 ו-float32 יש טווחים שונים מאוד. הפחתת רמת הדיוק מ-float32 ל-float16 בדרך כלל מובילה לזרימה חוזרת ונשנית. יש פתרונות, אבל בדרך כלל נדרשת עבודה נוספת כדי לגרום ל-float16 לפעול.

לכן Google הציגה את הפורמט bfloat16 ב-TPUs.‏ bfloat16 הוא float32 קטועה עם אותם ביטויים של מעריך ורשת כמו float32. זאת, בנוסף לעובדה שיחידות TPU מחשבים הכפלות של מטריצות ברמת דיוק מעורבת עם קלט bfloat16 אבל פלט float32, ופירוש הדבר שבדרך כלל לא נדרשים שינויים בקוד כדי לשפר את הביצועים ברמת דיוק מופחתת.

מערך סיסטולי

ה-MXU מטמיע כפל מטריצות בחומרה באמצעות ארכיטקטורה שנקראת 'מערך סיסטולי', שבה רכיבי הנתונים זורמים דרך מערך של יחידות חישוב בחומרה. (ברפואה, "סיסטולי" מתייחס להתכווצות לב ולזרימת הדם, כאן לזרימת הנתונים).

הרכיב הבסיסי של כפל מטריצות הוא מכפלת נקודות בין שורה ממטריצה אחת לעמודה ממטריצה אחרת (ראו איור בחלק העליון של הקטע הזה). בהכפלת מטריצות Y=X*W, רכיב אחד של התוצאה יהיה:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

ב-GPU, משתמש יתכנת את מוצר הנקודה הזה ב'ליבה' של GPU ולאחר מכן יפעיל אותו במקביל בכמה 'ליבות' זמינות כדי לנסות לחשב כל ערך של המטריצה שמתקבלת בבת אחת. אם המטריצה שמתקבלת היא 128x128 גדולה, תידרש "ליבות" של 128x128=16K שיהיו זמינות. בדרך כלל זה לא אפשרי. ליחידות ה-GPU הגדולות ביותר יש כ-4,000 ליבות. לעומת זאת, ב-TPU נעשה שימוש בחומרה מינימלית בלבד ליחידות המחשוב ב-MXU: רק bfloat16 x bfloat16 => float32 מכפילים-מצטברים, כלום חוץ מזה. היחידה הזו קטנה כל כך ש-TPU יכול להטמיע 16,000 יחידות כאלה ב-MXU בגודל 128x128 ולעבד את הכפלת המטריצות הזו בבת אחת.

f1b283fc45966717.gif

איור: המערך הסיסטולי של MXU. רכיבי המחשוב הם מכפילים-מצברים. הערכים של מטריצה אחת נטענים במערך (הנקודות האדומות). ערכי המטריצה השנייה עוברים דרך המערך (נקודות אפורות). קווים אנכיים מעבירים את הערכים למעלה. קווים אופקיים מפיצים סכומים חלקיים. המשתמשים יכולים לבדוק בעצמם שבזמן שהנתונים עוברים דרך המערך, מתקבלת תוצאת כפל המטריצות בצד שמאל.

בנוסף לכך, בזמן שמוצרי הנקודות מחושבים ב-MXU, סכומי הביניים פשוט עוברים בין יחידות מחשוב סמוכות. אין צורך לאחסן אותם ולאחזר אותם מהזיכרון או אפילו מקובץ רישום. התוצאה הסופית היא שלמערך הסיסטולי של TPU יש יתרון משמעותי בצפיפות ובצריכת האנרגיה, וגם יתרון מהותי במהירות בהשוואה ל-GPU, כשמחשבים כפל מטריצות.

Cloud TPU

כשמבקשים Cloud TPU v2 אחד בפלטפורמת Google Cloud, מקבלים מכונה וירטואלית (VM) עם לוח TPU שמחובר ל-PCI. ללוח ה-TPU יש ארבעה צ'יפים של TPU עם שני ליבות. כל ליבת TPU כוללת VPU (יחידת עיבוד וקטורי) ו-MXU 128x128 (יחידת הכפלה של MatriX). לאחר מכן, ה-"Cloud TPU" הזה מחובר בדרך כלל דרך הרשת ל-VM שביקשה אותו. התמונה המלאה נראית כך:

dfce5522ed644ece.png

איור: המכונה הווירטואלית עם מואץ Cloud TPU שמחובר לרשת. "Cloud TPU" עצמו עשוי מ-VM עם לוח TPU מחובר PCI ועליו ארבעה שבבי TPU עם שתי ליבות.

מארזי TPU

במרכזי הנתונים של Google, צ'יפים מסוג TPU מחוברים לממשק קישורי של מחשוב עתיר ביצועים (HPC), וכך הם יכולים להיראות כמאיץ אחד גדול מאוד. Google מכנה אותם Pods והם יכולים לכלול עד 512 ליבות TPU v2 או 2048 ליבות TPU v3.

2ec1e0d341e7fc34.jpeg

איור: אשכול TPU v3. לוחות ומדפים של TPU שמחוברים דרך חיבור HPC.

במהלך האימון, הדרגתיות מוחלפת בין ליבות TPU באמצעות אלגוריתם הצמצום כולו ( הסבר טוב על ההפחתה המלאה) המודל שנמצא בתהליך אימון יכול לנצל את החומרה על ידי אימון על קבוצות גדולות של נתונים.

d97b9cc5d40fdb1d.gif

איור: סנכרון של שיפועים במהלך אימון באמצעות אלגוריתם all-reduce ברשת HPC של Google TPU עם רשת טורואידית דו-ממדית של רשתות.

התוכנה

הדרכה לקבוצות גדולות

גודל האצווה האידיאלי ל-TPU הוא 128 פריטים של נתונים לכל ליבה של TPU, אבל כבר אפשר לראות ניצול יעיל של החומרה עם 8 פריטים של נתונים לכל ליבה של TPU. חשוב לזכור של-Cloud TPU אחד יש 8 ליבות.

בשיעור ה-Lab הזה נשתמש ב-Keras API. ב-Keras, המקבץ שאתם מציינים הוא גודל האצווה הגלובלי של כל ה-TPU. הקבוצות (batches) יתחלקו באופן אוטומטי ל-8 וייבצעו ב-8 הליבות של ה-TPU.

da534407825f01e3.png

טיפים נוספים לשיפור הביצועים מפורטים במדריך לביצועים של TPU. במודלים מסוימים, יכול להיות שיהיה צורך בטיפול מיוחד בקבוצות גדולות מאוד. פרטים נוספים זמינים במאמר LARSOptimizer.

מה קורה מאחורי הקלעים: XLA

תוכניות TensorFlow מגדירות גרפי חישוב. ה-TPU לא מפעיל קוד Python ישירות, אלא מפעיל את תרשים החישובים שמוגדר על ידי תוכנית Tensorflow. אבל בקצרה, מהדר בשם XLA (מהדר (compiler לינארי) מואץ' ממיר את תרשים Tensorflow של צומתי החישוב לקוד של מכונת TPU. המהדר הזה מבצע גם הרבה אופטימיזציות מתקדמות בקוד שלכם ובפריסת הזיכרון שלכם. ה-compilation מתבצע באופן אוטומטי כשהעבודה נשלחת ל-TPU. אין צורך לכלול XLA באופן מפורש בשרשרת ה-build.

edce61112cd57972.png

איור: כדי להריץ ב-TPU, תרשים החישוב שהוגדר על ידי תוכנית Tensorflow מתורגם קודם לצורך ייצוג ב-XLA (מקודד אלגברה לינארית מואצת), ולאחר מכן XLA מקצה אותו לקוד מכונה של TPU.

שימוש במעבדי TPU ב-Keras

TPU נתמכים דרך Keras API החל מגרסה 2.1 של TensorFlow. התמיכה ב-Keras פועלת ב-TPU וב-TPU Pods. דוגמה שפועלת ב-TPU, ב-GPU וב-CPU:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

בקטע הקוד הזה:

  • TPUClusterResolver().connect() מוצא את ה-TPU ברשת. התוכנה פועלת ללא פרמטרים ברוב מערכות Google Cloud (משימות AI Platform, Colaboratory, Kubeflow, מכונות וירטואליות של למידה עמוקה שנוצרו באמצעות הכלי ctpu up). המערכות האלה יודעות איפה נמצא ה-TPU שלהן באמצעות משתנה הסביבה TPU_NAME. אם יוצרים TPU באופן ידני, אפשר להגדיר את סביבת TPU_NAME env. var ב-VM שבה משתמשים בו, או לקרוא ל-TPUClusterResolver עם פרמטרים מפורשים: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy הוא החלק שמיישם את ההתפלגות ואת האלגוריתם לסנכרון הדרגתי של "all-reduce".
  • האסטרטגיה מיושמת באמצעות היקף. המודל חייב להיות מוגדר בתוך ההיקף() של האסטרטגיה.
  • הפונקציה tpu_model.fit מצפה לאובייקט tf.data.Dataset כקלט לאימון TPU.

משימות נפוצות של ניוד TPU

  • יש הרבה דרכים לטעון נתונים במודל Tensorflow, אבל ב-TPUs צריך להשתמש ב-tf.data.Dataset API.
  • מעבדי TPU מהירים מאוד ומטמיעים נתונים בדרך כלל הופכים לצוואר בקבוק כשהם פועלים עליהם. במדריך לביצועים של TPU מפורטים כלים שאפשר להשתמש בהם כדי לזהות צווארי בקבוק בנתונים וטיפים נוספים לשיפור הביצועים.
  • מספרי int8 או int16 נחשבים כ-int32. ל-TPU אין חומרה של מספרים שלמים שפועלת בפחות מ-32 ביט.
  • אין תמיכה בחלק מהפעולות של Tensorflow. הרשימה כבר כאן. החדשות הטובות הן שההגבלה הזו חלה רק על קוד אימון, כלומר המעבר קדימה ואחורה במודל שלכם. עדיין אפשר להשתמש בכל פעולות Tensorflow בצינור עיבוד הנתונים של קלט הנתונים כי הן יבוצעו במעבד (CPU).
  • tf.py_func לא נתמך ב-TPU.

4. [INFO] מסווג רשת נוירונים 101

בקצרה

אם כבר ידועים לכם כל המונחים שמופיעים בכתב מודגש בפסקה הבאה, אתם יכולים לעבור לתרגול הבא. אם אתם רק מתחילים בתחום הלמידה העמוקה, אתם מוזמנים להמשיך לקרוא.

עבור מודלים שנוצרו כרצף של שכבות, Keras מציעה את Sequential API. לדוגמה, אפשר לכתוב ב-Keras סיווג תמונות באמצעות שלוש שכבות צפופות כך:

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

רשת נוירונים צפופה

זו רשת הנוירונים הפשוטה ביותר לסיווג תמונות. הוא עשוי מ"נוירונים" שמסודרים בשכבות. השכבה הראשונה מעבדת את נתוני הקלט ומעבירה את הפלט שלה לשכבות אחרות. היא נקראת 'דחוס' כי כל נוירונים מחובר לכל נוירונים בשכבה הקודמת.

c21bae6dade487bc.png

כדי להזין תמונה לרשת כזו, צריך לשטח את ערכי ה-RGB של כל הפיקסלים שלה וקטור ארוך ולהשתמש בו כקלט. זו לא השיטה הטובה ביותר לזיהוי תמונות, אבל נשפר אותה בהמשך.

נוירונים, הפעלות, RELU

'נוירון' מחשב סכום משוקלל של כל ערכי הקלט שלו, מוסיף ערך שנקרא 'הטיה' ומזין את התוצאה באמצעות פונקציית הפעלה שנקראת 'פונקציית הפעלה'. המשקולות וההטיה לא ידועים בהתחלה. הם יופעלו באופן אקראי ו"ילמדו" על ידי אימון של רשת הנוירונים על כמות גדולה של נתונים ידועים.

644f4213a4ee70e5.png

פונקציית ההפעלה הפופולרית ביותר נקראת RELU (יחידה לינארית מתוקנת). זוהי פונקציה פשוטה מאוד, כפי שאפשר לראות בתרשים שלמעלה.

הפעלה של Softmax

הרשת שלמעלה מסתיימת בשכבה של 5 נוירונים כי אנחנו מסווגים פרחים ל-5 קטגוריות (ורד, צבעוני, שן-ארי, חמנית, איריס). נוירונים בשכבות ביניים מופעלים באמצעות פונקציית ההפעלה הקלאסית של RELU. בשכבה האחרונה אנחנו רוצים לחשב את המספרים בין 0 ל-1, שמייצגים את ההסתברות שבה פרח זה יהיה ורד, צבעוני וכן הלאה. לשם כך, נשתמש בפונקציית הפעלה שנקראת softmax.

כדי להחיל פונקציית softmax על וקטור, מחשבים את החזקה של כל רכיב ואז מבצעים נורמליזציה של הווקטור, בדרך כלל באמצעות נורמלי L1 (סכום הערכים המוחלטים) כך שהערכים יתווספו ל-1 וניתן יהיה לפרש אותם כprobabilities.

ef0d98c0952c262d.png d51252f75894479e.gif

הפסד חוצה-אנטרופיה

עכשיו, כשרשת הנוירונים שלנו מייצרת חיזויים מתמונות קלט, אנחנו צריכים למדוד עד כמה הן טובות, כלומר, המרחק בין מה שהרשת אומרת לנו לבין התשובות הנכונות, שנקראות גם 'תוויות'. חשוב לזכור שיש לנו תוויות נכונות לכל התמונות במערך הנתונים.

כל מרחק יכול להתאים, אבל במקרה של בעיות סיווג, "מרחק באנטרופיה חוצה" הוא היעיל ביותר. נקרא לפונקציה הזו פונקציית השגיאה או פונקציית 'הפסד':

7bdf8753d20617fb.png

ירידה הדרגתית

"אימון" של רשת הנוירונים פירושו שימוש בתמונות ובתוויות אימון כדי להתאים משקולות והטיות ולצמצם את פונקציית האיבוד החוצה-אנטרופיה. כך זה עובד.

ה-cross-entropy הוא פונקציה של משקולות, הטיות, פיקסלים של תמונת האימון והסיווג הידוע שלה.

אם נחשב את הנגזרות החלקיות של ה-Cross-entropy ביחס לכל המשקולות ולכל ההטיות, נקבל 'הדרגתיות', המחושב עבור תמונה, תווית וערך נוכחי של משקולות והטיות. חשוב לזכור שיכולים להיות לנו מיליוני משקלים ונטיות, ולכן חישוב השיפוע נשמע כמו הרבה עבודה. למזלנו, Tensorflow עושה את זה בשבילנו. התכונה המתמטית של שיפוע הוא שהוא מצביע "למעלה". מכיוון שאנחנו רוצים להגיע למיקום שבו ההסתברות הצולבת נמוכה, אנחנו הולכים בכיוון ההפוך. אנחנו מעדכנים את המשקלים וההטיות לפי חלק מהמ gradient. לאחר מכן אנחנו חוזרים על אותו תהליך שוב ושוב, באמצעות קבוצות התמונות והתוויות הבאות של אימון, בלולאת אימון. יש לקוות שהיא תגיע לנקודה שבה האנטרופיה ההצטלבותית תהיה מינימלית, אבל אין ערובה שהמינימום הזה יהיה ייחודי.

הדרגתיות של ירידה2.png

קבוצות קטנות של בקשות ותגובה מהירה לשינויים

אפשר לחשב את שיפוע הגרדיאנטים בתמונה לדוגמה אחת בלבד ולעדכן את המשקלים וההטיות באופן מיידי, אבל ביצוע הפעולה הזו על קבוצה של, למשל, 128 תמונות נותן שיפוע שמייצג טוב יותר את האילוצים שהוטלו על ידי תמונות לדוגמה שונות, ולכן סביר להניח שהוא יגיע לפתרון מהר יותר. גודל המיני-אצווה הוא פרמטר שניתן לשנות.

לשיטה הזו, שנקראת לפעמים 'ירידה סטוכסטית בגרדינט', יש יתרון פרגמטי נוסף: עבודה עם קבוצות (batches) היא גם עבודה עם מטריצות גדולות יותר, ובדרך כלל קל יותר לבצע אופטימיזציה שלהן ב-GPU וב-TPU.

עם זאת, ההתכנסות עדיין יכולה להיות קצת כאוטית, ואפילו להיפסק אם וקטור המדרון כולל רק אפסים. האם זה אומר שמצאנו ערך מינימום? לא תמיד. רכיב שיפוע יכול להיות אפס בערכים מינימלי או מקסימלי. אם וקטור שיפוע מכיל מיליוני רכיבים, והם כולם אפס, הסבירות שכל אפס תואם לנקודת מינימום ואף אחת מהן לא תואמת לנקודת מקסימום היא קטנה למדי. במרחב עם הרבה מאפיינים, נקודות רכס הן נפוצות למדי, ואנחנו לא רוצים לעצור בהן.

52e824fe4716c4a0.png

איור: נקודת אוכף. שיפוע של 0, אבל הוא לא מינימום בכל הכיוונים. (שיוך תמונה Wikimedia: By Nicoguaro - Own work, CC BY 3.0)

הפתרון הוא להוסיף קצת מומנטום לאלגוריתם האופטימיזציה כדי שיוכל לעבור נקודות רכס בלי לעצור.

מילון מונחים

batch או mini-batch: תמיד מתבצע אימון על קבוצות של נתוני אימון ותוויתות. כך אפשר לעזור לאלגוריתם להגיע להסכמה. המאפיין 'אצווה' הוא בדרך כלל המאפיין הראשון של מזנוני הנתונים. לדוגמה, טינסור בפורמט [100, 192, 192, 3] מכיל 100 תמונות בגודל 192x192 פיקסלים עם שלושה ערכים לכל פיקסל (RGB).

הפסד באנטרופיה אחת: פונקציית הפסד מיוחדת שמשמשת לעיתים קרובות במסווגים.

שכבה צפופה: שכבה של נוירונים שבה כל נוירונים מחובר לכל נוירונים בשכבה הקודמת.

תכונות: ערכי הקלט של רשת נוירונים נקראים לפעמים 'תכונות'. האמנות של זיהוי החלקים בקבוצת נתונים (או שילובים של חלקים) שצריך להזין לרשת נוירונים כדי לקבל תחזיות טובות נקראת 'פיתוח מאפיינים'.

labels: שם נוסף ל'כיתות' או לתשובות נכונות בבעיה של סיווג בפיקוח

קצב למידה: החלק מתוך ההדרגתיות שבו מתעדכנים המשקולות וההטיות בכל איטרציה של לולאת האימון.

logits: הפלט של שכבת נוירונים לפני הפעלת פונקציית ההפעלה נקראות 'logits'. המונח מגיע מהפונקציה הלוגיסטית, שנקראת גם פונקציית sigmoid, שהייתה בעבר פונקציית ההפעלה הפופולרית ביותר. 'פלט נוירונים לפני פונקציה לוגיסטי' קוצר ל-'logits'.

loss: פונקציית השגיאה שמשויכת בין הפלט של רשת העצבים לתשובות הנכונות

neuron: מחשב את הסכום המשוקלל של הקלט, מוסיף הטיה ומזין את התוצאה באמצעות פונקציית הפעלה.

קידוד חם אחד: מחלקה 3 מתוך 5 מקודדת בתור וקטור של 5 רכיבים, כל אפסים חוץ מהאפס השלישי שהוא 1.

relu: יחידה לינארית מתוקנת. פונקציית הפעלה פופולרית לנוירונים.

sigmoid: פונקציית הפעלה נוספת שבעבר הייתה פופולרית ועדיין שימושית במקרים מיוחדים.

softmax: פונקציית הפעלה מיוחדת שפועלת על וקטור, מגדילה את ההפרש בין הרכיב הגדול ביותר לכל שאר הרכיבים, וגם מבצעת נורמליזציה של הווקטור כך שהסכום שלו יהיה 1, כדי שניתן יהיה לפרש אותו כוקטור של הסתברויות. משמש כשלב האחרון במסווגים.

tensor: 'tensor' הוא כמו מטריצה, אבל עם מספר שרירותי של מאפיינים. טנזור חד-ממדי הוא וקטור. מפריד דו-ממדי הוא מטריצה. לאחר מכן יכולים להיות רכיבי Tensor עם 3, 4, 5 או יותר מאפיינים.

5. [INFO] רשתות נוירונים מלאכותיות (CNN)

בקצרה

אם כל המונחים המודגשים בפסקה הבאה כבר מוכרים לכם, אפשר לעבור לתרגיל הבא. אם אתם רק מתחילים לעבוד עם רשתות נוירונים קונבולוציה, כדאי להמשיך לקרוא.

convolutional.gif

איור: סינון תמונה עם שני פילטרים עוקבים שמורכבים מ-48 x 4 x 48 משקולות לכל אחד מהם.

כך נראית רשת נוירונים מלאכותית פשוטה ב-Keras:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

מבוא לרשתות נוירונים מלאכותיות (CNN)

בשכבה של רשת נוירונים קונבולוציונית, "נוירון" אחד מבצע סכום משוקלל של הפיקסלים שמעליו, באזור קטן בתמונה בלבד. הוא מוסיף הטיה ומעביר את הסכום דרך פונקציית הפעלה, בדיוק כמו נוירון בשכבה צפופה רגילה. לאחר מכן, הפעולה הזו חוזרת על עצמה בכל התמונה באמצעות אותם משקלים. חשוב לזכור שבשכבות צפופות, לכל נוירון יש משקלים משלו. כאן, "תיקון" אחד של משקולות מחליק על התמונה בשני הכיוונים ("קובולציה"). הפלט כולל ערכים רבים ככל האפשר בתמונה (מספר הפיקסלים בתמונה (עם זאת, יש צורך במרווח פנימי מסוים בקצוות). זוהי פעולת סינון שבה נעשה שימוש במסנן של משקולות 4x4x3=48.

עם זאת, 48 משקלים לא יספיקו. כדי להוסיף עוד דרגות חופש, חוזרים על אותה פעולה עם קבוצה חדשה של משקלים. הפעולה הזו תפיק קבוצה חדשה של פלט מסננים. נקראים לו 'ערוץ' של תוצאות, בהתאם לערוצי R,‏ G ו-B בתמונה הקלט.

Screen Shot 2016-07-29 at 16.02.37.png

אפשר לסכם את שתי קבוצות המשקולות (או יותר) כטנזור אחד על ידי הוספת מאפיין חדש. כך אנחנו מקבלים את הצורה הגנרית של טינסור המשקלים בשכבת עיבוד קוונטי. מכיוון שמספר ערוצי הקלט והפלט הם פרמטרים, אפשר להתחיל לערום שכבות עיבוד קוונטי ולקשר אותן בשרשור.

d1b557707bcd1cb9.png

איור: רשת עצבית מתקפלת הופכת 'קוביות' נתונים ל'קוביות' אחרות של נתונים.

קיפולים (קונבולציות) ברצף, צבירה מקסימלית

אם מבצעים את הקונבולוציות בקצב של 2 או 3, אפשר גם לכווץ את קוביית הנתונים שמתקבלת בממדים האופקיים שלה. יש שתי דרכים נפוצות לעשות זאת:

  • קונבולציה זזה: מסנן הזזה כמו שלמעלה, אבל עם צעדים גדולים מ-1
  • קיבוץ מקסימלי: חלון הזזה שמבצע את הפעולה MAX (בדרך כלל בתיקונים בגודל 2x2, שחוזר על עצמו כל 2 פיקסלים)

2b2d4263bb8470b.gif

איור: החלקת חלון המחשוב ב-3 פיקסלים תוביל לפחות ערכי פלט. קונבולוציות חדות או צבירה מקסימלית (מקסימום בחלון של 2x2 עם החלקה בצעד של 2) הן דרך לכווץ את קוביית הנתונים במידות האופקיות.

מסווג מסתובב

לבסוף, אנחנו מחברים ראש סיווג על ידי שטחת את קוביית הנתונים האחרונה ומעבירים אותה דרך שכבה צפופה שמופעלת על ידי softmax. מסווג קונבולוציה טיפוסי יכול להיראות כך:

4a61aaffb6cba3d1.png

איור: מסווג תמונות באמצעות שכבות קונבולוציה ושכבות softmax. היא משתמשת במסננים ביחס של 3x3 ו-1x1. שכבות ה-maxpool צריכות לכלול עד 2x2 נקודות נתונים. ראש הסיווג מוטמע בשכבה צפופה עם הפעלה softmax.

ב-Keras

אפשר לכתוב את מקבץ ה-convolutional שמוצג למעלה ב-Keras כך:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

6. [מידע חדש] ארכיטקטורות קונבולוציה מודרניות

בקצרה

7968830b57b708c0.png

איור: 'מודול' קוונטי. מה הכי מתאים בשלב הזה? האם שכבת המאגר המקסימלי ולאחר מכן שכבה קונבולוטית של 1x1 או שילוב אחר של שכבות? נסו את כולן, צרפו את התוצאות והרשו לרשת להחליט. בצד ימין: הארכיטקטורה המתקפלת של " inception" באמצעות מודולים כאלה.

ב-Keras, כדי ליצור מודלים שבהם זרימת הנתונים יכולה להסתעף פנימה והחוצה, צריך להשתמש בסגנון המודל 'פונקציונלי'. לדוגמה:

l = tf.keras.layers # syntax shortcut

y = l.Conv2D(filters=32, kernel_size=3, padding='same',
             activation='relu', input_shape=[192, 192, 3])(x) # x=input image

# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation

# many more layers ...

# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)

688858c21e3beff2.png

טריקים זולים אחרים

פילטרים קטנים ביחס גובה-רוחב של 3x3

40a7b15fb7dbe75c.png

באיור הזה מוצגת התוצאה של שני פילטרים ביחס גובה-רוחב של 3x3. נסו לזהות את נקודות הנתונים שתרמו לתוצאה: שני המסננים הרציפים האלה מסוג 3x3 מחשבים שילוב כלשהו של אזור בגודל 5x5. זה לא בדיוק אותו שילוב שחישוב מסנן 5x5 יניב, אבל כדאי לנסות כי שני מסננים רצופים בגודל 3x3 זולים יותר ממסנן יחיד בגודל 5x5.

1x1 convolutions ?

fd7cac16f8ecb423.png

במונחים מתמטיים, עיבוד '1x1' הוא כפל בקבוע, ולא מושג שימושי במיוחד. עם זאת, חשוב לזכור שברשתות נוירונליות קונבולוציוניות, המסנן מיושם על קוביית נתונים ולא רק על תמונה דו-ממדית. לכן, מסנן מסוג '1x1' מחשב סכום משוקלל של עמודת נתונים בגודל 1x1 (ראו איור) ותוך כדי הסטה של הנתונים על פני הנתונים, מתקבל שילוב לינארי של הערוצים של הקלט. זה למעשה שימושי. אם נחשוב על הערוצים כתוצאות של פעולות סינון נפרדות, לדוגמה: מסנן ל"אוזניים מחודדות", מסנן נוסף ל"שפמים" ומסנן נוסף ל"עיניים חסומות", השכבה "1x1" תחשב שילובים ליניאריים אפשריים בין התכונות האלה. סינון כזה יכול להיות שימושי לחיפוש "חתול". בנוסף, בשכבות בגודל 1x1 נעשה שימוש בפחות משקולות.

7. Squeezenet

במאמר 'מעטפה' אפשר למצוא דרך פשוטה לחבר את הרעיונות האלה. המחברים מציעים תכנון פשוט מאוד של מודול קונבולוציה, באמצעות שכבות קונבולוציה בגודל 1x1 ו-3x3 בלבד.

1730ac375379269b.png

איור: ארכיטקטורת מעיכה שמבוססת על 'מודולים של אש'. הם משתמשים בשכבה 1x1 שמצמצמת את הנתונים הנכנסים במאפיין האנכי, ואחריה בשתי שכבות עיבוד מקבילות של 1x1 ו-3x3 שמרחיבות שוב את עומק הנתונים.

הדרכה מעשית

ממשיכים ב-notebook הקודם ויוצרים רשת עצבית מתקפלת בהשראת סקוץ'. תצטרכו לשנות את קוד המודל ל'סגנון פונקציונלי' של Keras.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

מידע נוסף

כדאי להגדיר פונקציית עזר למודול squeezenet כדי לבצע את התרגיל הזה:

def fire(x, squeeze, expand):
  y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
  y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
  y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
  return tf.keras.layers.concatenate([y1, y3])

# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
  return lambda x: fire(x, squeeze, expand)

# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)

המטרה הפעם היא להגיע לרמת דיוק של 80%.

דברים שכדאי לנסות

מתחילים בשכבת convolve אחת, ואז ממשיכים עם "fire_modules", לסירוגין עם שכבות MaxPooling2D(pool_size=2). אפשר להתנסות עם 2 עד 4 שכבות max pooling ברשת, וגם עם 1, 2 או 3 מודולים של הפעלה רצופות בין שכבות ה-max pooling.

במודולים של אש, הפרמטר 'squeeze' צריך להיות בדרך כלל קטן מהפרמטר 'expand'. הפרמטרים האלה הם למעשה מספרי מסננים. בדרך כלל, הם יכולים לנוע בין 8 ל-196. אפשר להתנסות בארכיטקטורות שבהן מספר המסננים עולה בהדרגה לאורך הרשת, או בארכיטקטורות פשוטות שבהן לכל המודולים של הפעלת הבקשות יש אותו מספר מסננים.

לדוגמה:

x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB

y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)

model = tf.keras.Model(x, y)

בשלב הזה, יכול להיות שתבחינו שהניסויים לא מתקדמים כל כך טוב ויעד הדיוק של 80% נראה רחוק. הגיע הזמן לעוד כמה טריקים זולים.

נירמול באצווה

נורמה באצווה תעזור לכם לפתור את בעיות ההתכנסות שאתם נתקלים בהן. הסברים מפורטים על השיטה הזו יוצגו בסדנה הבאה. בינתיים, אפשר להשתמש בה כעוזר 'קסם' בתיבה שחורה על ידי הוספת השורה הזו אחרי כל שכבה קונבולוציה ברשת, כולל השכבות שבתוך פונקציית Fire_Module:

y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context

צריך להקטין את ערך ברירת המחדל של הפרמטר 'תנופה' מ-0.99 ל-0.9 כי מערך הנתונים שלנו קטן. אל להתייחס לפרטים האלה כרגע.

הגדלת נפח הנתונים

תקבל עוד כמה נקודות אחוזים על ידי הרחבת הנתונים באמצעות טרנספורמציות קלות כמו שינויי רוויה לשמאליים:

4ed2958e09b487ca.png

ad795b70334e0d6b.png

קל מאוד לעשות את זה ב-Tensorflow באמצעות ה-API של tf.data.Dataset. מגדירים פונקציית טרנספורמציה חדשה לנתונים:

def data_augment(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_saturation(image, lower=0, upper=2)
    return image, label

לאחר מכן משתמשים בו בטרנספורמציה הסופית של הנתונים (מערכי נתונים של אימון ואימות, פונקציה "get_batched_dataset"):

dataset = dataset.repeat() # existing line
# insert this
if augment_data:
  dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line

חשוב לזכור להגדיר את הוספת הנתונים כאופציונלית ולהוסיף את הקוד הנדרש כדי לוודא שרק מערך הנתונים של האימון יתווספו לו נתונים. אין טעם להגדיל את מערך הנתונים של האימות.

עכשיו אפשר להגיע לדיוק של 80% ב-35 מחזורים.

פתרון

הנה ה-notebook של הפתרון. אפשר להשתמש בו אם נתקעתם.

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

מה עסקנו בו

  • 🤔 מודלים מסוג 'סגנון פונקציונלי' של Keras
  • 🤓 ארכיטקטורת מעיכה
  • 🤓 נתונים באמצעות tf.data.datset

כדאי להקדיש כמה רגעים כדי לעבור על רשימת המשימות הבאה בראש שקט.

8. Xception עם כוונון עדין

מיזוגים נפרדים

דרך אחרת ליישום שכבות קונבולוציה צברה לאחרונה פופולריות: קונבולוציות עם הפרדה בעומק. אני יודעת, שפע של פה, אבל הקונספט די פשוט. הם מוטמעים ב-Tensorflow וב-Keras בתור tf.keras.layers.SeparableConv2D.

גם ב-convolution נפרד מריצים מסנן על התמונה, אבל הוא משתמש בקבוצה נפרדת של משקלים לכל ערוץ של תמונת הקלט. אחריו מופיעה "קונבולוציה של 1x1", סדרה של מוצרי נקודות שהתוצאה שלה היא סכום משוקלל של הערוצים המסוננים. עם משקלים חדשים בכל פעם, הרכבים המשוקללים רבים של הערוצים מחושבים לפי הצורך.

615720b803bf8dda.gif

איור: עיבוד נתונים (convolution) שניתן להפרדה. שלב 1: קונבולציות עם מסנן נפרד לכל ערוץ. שלב 2: שילובים לינאריים של ערוצים. חוזרים על הפעולה עם קבוצה חדשה של משקלים עד שמגיעים למספר הרצוי של ערוצי הפלט. אפשר גם לחזור על שלב 1 עם משקלים חדשים בכל פעם, אבל בפועל זה קורה לעיתים רחוקות.

נעשה שימוש בתכונות convolve נפרדות במרבי הארכיטקטורות של רשתות קוונטיות: MobileNetV2,‏ Xception ו-EfficientNet. דרך אגב, MobileNetV2 הוא המודל שבו השתמשתם בעבר לצורך למידה שהועברה.

הם זולים יותר מקונבולוציות רגילות, והם הוכיחו שהם יעילים באותה מידה בפועל. זהו ספירת המשקלים של הדוגמה שמוצגת למעלה:

שכבת convolutin: 4 x 4 x 3 x 5 = 240

שכבה מתקפלת שניתנת להפרדה: 4 x 4 x 3 + 3 x 5 = 48 + 15 = 63

זה נשאר לתרגיל על ידי הקורא לחשב את מספר ההכפלות הנדרש כדי ליישם כל סגנון של סולמות שכבות קונבולוציה בצורה דומה. קונבולציות הניתנות להפרדה הן קטנות יותר ויעילות הרבה יותר מבחינה חישובית.

הדרכה מעשית

מתחילים מחדש מהמחברות של 'transfer learning', אבל הפעם בוחרים ב-Xception בתור המודל שעבר אימון מראש. ב-Xception נעשה שימוש רק בהתנזקות ניתנות להפרדה. משאירים את כל המשקלים ככאלה שאפשר לאמן. אנחנו נכוונן את המשקולות לפני אימון על הנתונים שלנו במקום להשתמש ככה בשכבות שאומנו מראש.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

המטרה: דיוק של יותר מ-95% (לא, ברצינות, זה אפשרי!)

זה התרגיל האחרון, וצריך עוד קצת עבודה על קוד ומדעי הנתונים.

מידע נוסף על כוונון עדין

Xception זמין במודלים הרגילים שעברו אימון מראש באפליקציה tf.keras.application.* הפעם לא לשכוח להשאיר את כל המשקולות כאימון.

pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
                                                  include_top=False)
pretrained_model.trainable = True

כדי לקבל תוצאות טובות בזמן כוונון של המודל, צריך לשים לב לקצב הלמידה ולהשתמש בלוח זמנים של קצב הלמידה עם תקופת הרצה. כך:

9b1af213b2b36d47.png

התחלה עם קצב למידה רגיל תפריע למשקלים המאומנים מראש של המודל. בתור התחלה, המערכת שומרת בהדרגה את הנתונים עד שהמודל נצמד לנתונים שלכם כדי לשנות אותם בצורה סבירה. אחרי התקופה של העלייה, אפשר להמשיך בקצב למידה קבוע או בקצב למידה שפתאום יורד באופן מעריכי.

ב-Keras, קצב הלמידה מצוין באמצעות פונקציית קריאה חוזרת (callback) שבה אפשר לחשב את קצב הלמידה המתאים לכל תקופת אימון. Keras יעביר את קצב הלמידה הנכון לאופטימיזטור בכל תקופת אימון.

def lr_fn(epoch):
  lr = ...
  return lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)

model.fit(..., callbacks=[lr_callback])

פתרון

הנה ה-notebook של הפתרון. אפשר להשתמש בו אם נתקעתם.

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

אילו נושאים דיברנו?

  • 🤔 הסרה בקישורי עומק
  • 🤓 לוחות זמנים לקצב למידה
  • 😈. כוונון עדין של מודל שעבר אימון מראש.

כדאי להקדיש כמה רגעים כדי לעבור בראש את רשימת המשימות הזו.

9. מעולה!

יצרתם את רשת העצבים הקוונטית המודרנית הראשונה שלכם ואומנתם אותה לרמת דיוק של יותר מ-90%, תוך ביצוע איטרציות של אימון עוקב תוך דקות ספורות בלבד, בזכות TPUs. הגענו לסוף של 4 "Keras on TPU Codelabs":

מעבדי TPU בפועל

מעבדי TPU ומעבדי GPU זמינים ב-Cloud AI Platform:

לבסוף, אנחנו אוהבים לקבל משוב. נשמח לדעת אם משהו השתבש בשיעור ה-Lab הזה או אם לדעתכם צריך לשפר אותו. אפשר לשלוח משוב דרך בעיות ב-GitHub [קישור למשוב].

HR.png

Martin Görner ID Small.jpg
המחבר: מרטין גורנר (Martin Görner)
Twitter: ‎@martin_gorner

tensorflow logo.jpg
www.tensorflow.org