TensorFlow, Keras ו-Deep Learning, ללא תואר דוקטורט

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

ב-codelab זה נעשה שימוש במערך הנתונים MNIST, אוסף של 60,000 ספרות שתויגו שבזכותו הדורות של דוקטורטים עמוסים כבר כמעט שני עשורים. פותרים את הבעיה עם פחות מ-100 שורות של קוד Python / TensorFlow.

מה תלמדו

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

מה תצטרך להכין

רק דפדפן. ניתן להפעיל את הסדנה הזו לחלוטין עם Google Colaboratory.

משוב

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

בשיעור Lab זה נעשה שימוש ב-Google Colaboratory ולא נדרשת הגדרה מצדך. אתם יכולים להפעיל אותו מ-Chromebook. יש לפתוח את הקובץ שבהמשך, ולהריץ את התאים כדי להכיר את המחברות של Colab.

Welcome to Colab.ipynb

הוראות נוספות מופיעות בהמשך:

בחירת קצה עורפי ל-GPU

בתפריט Colab, בוחרים באפשרות Runtime > משנים את סוג זמן הריצה ובוחרים באפשרות GPU. החיבור לזמן הריצה יתבצע באופן אוטומטי בהפעלה הראשונה, או באמצעות הלחצן "Connect" בפינה השמאלית העליונה.

הוצאה לאור של פנקס

כדי לבצע תאים בנפרד, לוחצים על תא ומשתמשים ב-Shift-ENTER. אפשר גם להריץ את המחשב הנייד כולו באמצעות הפונקציה Runtime > הפעלת הכול

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

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

תאים מוסתרים

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

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

keras_01_mnist.ipynb

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

נתוני הכשרה

יש לנו מערך נתונים של ספרות בכתב יד שסומנו בתווית כדי שנוכל לדעת מה כל תמונה מייצגת, כלומר מספר בין 0 ל-9. בפנקס יופיע קטע טקסט:

רשת הנוירונים שאנחנו מפתחים תסווג את הספרות בכתב יד ב-10 הכיתות שלהן (0, .., 9). הוא מתבסס על פרמטרים פנימיים שצריכים להיות לו ערך נכון כדי שהסיווג יפעל היטב. "הערך הנכון" נלמד באמצעות תהליך הדרכה שמחייב מערך נתונים "בתווית&&; עם תמונות והתשובות הנכונות המשויכות.

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

הדרכה

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

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

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

ציר ה-X מייצג את מספר ה-"epochs;או את החזרות דרך מערך הנתונים כולו.

חיזויים

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

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

חיישנים

הנתונים מאוחסנים במטריצות. תמונה בגווני אפור של 28x28 פיקסלים מתאימה למטריצת 28x28 מימדים. אך לגבי תמונה צבעונית, אנו זקוקים למידות נוספות. יש 3 ערכי צבעים לכל פיקסל (אדום, ירוק, כחול), כך שיש צורך בטבלה תלת-ממדית עם מידות [28, 28, 3]. כדי לאחסן קבוצה של 128 תמונות צבעים, יש צורך בטבלה בעלת ארבע מימדים עם מאפיינים: [128, 28, 28, 3].

הטבלאות הרב-ממדיות האלה נקראות "tenors" ורשימת המאפיינים שלהן היא "shape" .

בקצרה

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

מכשפה

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

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[28, 28, 1]),
    tf.keras.layers.Dense(200, activation="relu"),
    tf.keras.layers.Dense(60, activation="relu"),
    tf.keras.layers.Dense(10, activation='softmax') # classifying into 10 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, ... )

שכבה צפופה אחת

ספרות בכתב יד במערך הנתונים MNIST הן תמונות בגווני אפור בגודל 28x28 פיקסלים. הגישה הפשוטה ביותר לסיווג שלהם היא להשתמש בפיקסלים 28x28=784 כקלט של רשת נוירונים חד-שכבתית.

צילום מסך 2016-07-26 בשעה 12.32.24.png

כל "neuron" ברשת נוירונים מסכם סכום משוקלל של כל הקלט שלו, מוסיף קבוע בשם "bias" ולאחר מכן מזין את התוצאה באמצעות מספר "activate function". הפרמטרים "weights" ו- "biases" הם פרמטרים שייקבעו באמצעות אימון. המערכת מאתחלת אותם בערכים אקראיים בהתחלה.

התמונה שלמעלה מייצגת רשת נוירונים בעלת שכבה אחת עם 10 נוירונים. אנחנו רוצים לסווג ספרות ל-10 כיתות (0 עד 9).

עם הכפלת מטריצות

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

Mattmul.gif

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

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

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

צילום מסך 2016-07-26 בשעה 16.02.36.png

בקראס

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

tf.keras.layers.Dense(10, activation='softmax')

ניתוח מעמיק

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

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

פונקציות הפעלה: relo, softmax ו-sigmoid

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

שוב, "neuron" מחשבת סכום משוקלל של כל ערכי הקלט שלו, מוסיף ערך בשם "bias&quot ושולח את התוצאה באמצעות פונקציית ההפעלה.

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

פונקציית ההפעלה המסורתית ברשתות נוירונים היא "sigmoid" , אבל ה-"relu" הוכח שיש לו מאפייני המרה טובים יותר כמעט בכל מקום, ועכשיו הוא מועדף.

הפעלה של Softmax לסיווג

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

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

הפלט של השכבה האחרונה, לפני ההפעלה, נקרא לפעמים "logits" . אם הוקטור הזה הוא L = [L0, L1, L2, L3, L4, L5, L6, L7, L8, L9], אז:

אובדן חוצי

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

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

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

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

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

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

22 צבעים

מיני-עטוף ומומנטום

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

לטכניקה הזו, שנקראת לפעמים "sochastic דרגת הירידה

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

איור: נקודת אוכף. ההדרגה היא 0 אבל היא לא מינימום בכל הכיוונים. (ייחוס תמונה Wikimedia: של Nicoguaro – בבעלות עצמה, CC BY 3.0)

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

מילון מונחים

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

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

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

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

labels (שמות): שם אחר עבור "classes" או את התשובות הנכונות בבעיית סיווג בפיקוח

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

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

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

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

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

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

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

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

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

חזרו לפנקס המחקר והפעם קראו את הקוד.

keras_01_mnist.ipynb

נעבור על כל התאים בפנקס הזה.

Cell "Parameters"

הגודל של האצווה, מספר תקופות האימון והמיקום של קובצי הנתונים מוגדרים כאן. קובצי נתונים מתארחים בקטגוריה של Google Cloud Storage (GCS) ולכן הכתובת שלהם מתחילה בצירוף gs://

C ≪ייבוא"

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

תא &מירכאות;כלי עזר להצגה חזותית [RUN ME]"

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

Cell "tf.data.Dataset: מנתחים קבצים ומכינים מערכי נתונים של הדרכה ואימות"

תא זה השתמש ב-tf.data.Dataset API כדי לטעון את מערך הנתונים מסוג MNIST. אין צורך לבזבז יותר מדי זמן על התא הזה. אם אתם מעוניינים ב-tf.data.Dataset API, הנה מדריך שמסביר זאת: צינורות נתונים של TPU. בשלב הזה, העקרונות הבסיסיים הם:

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

imagedataset = tf.data.FixedLengthRecordDataset(image_filename, 28*28, header_bytes=16)

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

def read_image(tf_bytestring):
    image = tf.decode_raw(tf_bytestring, tf.uint8)
    image = tf.cast(image, tf.float32)/256.0
    image = tf.reshape(image, [28*28])
    return image

אנחנו מחילים את הפונקציה הזו על מערך הנתונים באמצעות .map ומקבלים מערך נתונים של תמונות:

imagedataset = imagedataset.map(read_image, num_parallel_calls=16)

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

dataset = tf.data.Dataset.zip((imagedataset, labelsdataset))

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

dataset = dataset.cache()
dataset = dataset.shuffle(5000, reshuffle_each_iteration=True)
dataset = dataset.repeat()
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)

ה-tf.data.Dataset API כולל את כל פונקציות השימוש הנדרשות להכנת מערכי נתונים:

.cache שומר את מערך הנתונים במטמון ב-RAM. זהו מערך נתונים זעיר כך שהוא יפעל. .shuffle: בסדר אקראי, עם מאגר של 5,000 רכיבים. חשוב לא לשנות את נתוני האימון בצורה אקראית. .repeat לולאה של מערך הנתונים. נלמד עליה מספר פעמים (בתקופות רבות). ב-.batch מתבצע שליפה של תמונות ותוויות מרובות יחד עם מיני אובייקטים. לבסוף, .prefetch יכול להשתמש במעבד כדי להכין את הקבוצה הבאה בזמן שהאימון הנוכחי נמצא באימון ב-GPU.

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

Cell "Keras model"

כל המודלים שלנו יהיו רצפים ישרים של שכבות, כדי שנוכל להשתמש בסגנון tf.keras.Sequential כדי ליצור אותם. בהתחלה, היא שכבה צפופה. הוא מכיל 10 נוירונים כי אנחנו מסווגים ספרות בכתב יד ל-10 כיתות. היא משתמשת ב-"softmax" מאחר שהיא השכבה האחרונה במסווג.

בנוסף, מודל Keras צריך לדעת את צורת הקלט שלו. אפשר להשתמש ב-tf.keras.layers.Input כדי להגדיר אותו. כאן, וקטורים לקלט הם וקטורים שטוחים של ערכי פיקסלים באורך 28*28.

model = tf.keras.Sequential(
  [
    tf.keras.layers.Input(shape=(28*28,)),
    tf.keras.layers.Dense(10, activation='softmax')
  ])

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

# print model layers
model.summary()

# utility callback that displays training curves
plot_training = PlotTraining(sample_rate=10, zoom=1)

הגדרת המודל מתבצעת ב-Kera באמצעות הפונקציה model.compile. כאן אנחנו משתמשים בכלי האופטימיזציה הבסיסי 'sgd' (ירידה מדורגת במדורג). למודל סיווג נדרש פונקציית אובדן בין אנטרופיות, שנקראת 'categorical_crossentropy' ב-Kras. לבסוף, אנחנו מבקשים מהמודל לחשב את המדד 'accuracy', שהוא אחוז התמונות שמסווגות בצורה נכונה.

Keras מציע את שירות model.summary() הנחמד מאוד, שמדפיס את פרטי המודל שיצרת. המורה מסוג שלך הוסיף את כלי התשתיות PlotTraining (מוגדר בתא '&ומיזציה חזותית' &&quot, תא) שמציג עקומות אימון שונות במהלך האימון.

תא "הדרכה ואימות של המודל"

כאן מתבצעת ההכשרה על ידי קריאה ל-model.fit והעברת מערכי הנתונים של האימון והאימות. כברירת מחדל, קראס עורכת סבב אימות בסוף כל תקופה.

model.fit(training_dataset, steps_per_epoch=steps_per_epoch, epochs=EPOCHS,
          validation_data=validation_dataset, validation_steps=1,
          callbacks=[plot_training])

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

תא "הצגת חיזויים"

אחרי שהמודל ייכשל, נוכל לקבל ממנו חיזויים באמצעות שיחה אל model.predict():

probabilities = model.predict(font_digits, steps=1)
predicted_labels = np.argmax(probabilities, axis=1)

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

כדי להבין מדוע יש צורך בפרמטר axis=1, זכור שעיבדנו 128 תמונות ולכן המודל מחזיר 128 וקטורים של הסתברות. הצורה של טנור הפלט היא [128, 10]. אנחנו מחשבים את הפרמטר argmax ב-10 ההסתברות חלקיות לכל תמונה, ולכן axis=1 (הציר הראשון הוא 0).

מודל פשוט זה כבר מזהה 90% מהספרות. לא רע, אבל אתם יכולים לשפר את זה עכשיו באופן משמעותי.

godeep.png

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

צילום מסך 2016-07-27 בשעה 15.36.55.png

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

לדוגמה, המודל עשוי להיראות כך (חשוב לזכור פסיקים, tf.keras.Sequential יוצר רשימה של שכבות מופרדות בפסיקים):

model = tf.keras.Sequential(
  [
      tf.keras.layers.Input(shape=(28*28,)),
      tf.keras.layers.Dense(200, activation='sigmoid'),
      tf.keras.layers.Dense(60, activation='sigmoid'),
      tf.keras.layers.Dense(10, activation='softmax')
  ])

מעיינים ב-"סיכום&מירכאות; של המודל שלכם. עכשיו יש בה לפחות פי 10 פרמטרים. התמונה צריכה להיות גבוהה פי 10! אבל מסיבה כלשהי, זה לא ...

נראה שהאבד לקבל את הגג. משהו לא בסדר.

לאחרונה נתקלת ברשתות נוירונים, מכיוון שאנשים השתמשו בהן כדי לעצב אותן בשנות ה-80 וה-90. לא פלא שהם נתנו את הרעיון, ומיזירו את מה שמכונה "AI חורף" אכן, ככל שמוסיפים שכבות, רשתות נוירונים מתקשים יותר ויותר להתרכז.

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

הפעלה של ReLU

relu.png

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

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

כלי אופטימיזציה טוב יותר

בחללים עם מידות גדולות מאוד, כמו כאן – יש לנו סדר גודל של 10,000 משקולות והטיה – &&quot אלו הן נקודות שאינן מינימה מקומית, אך שדרגה היא אפס לעומת זאת, וכלי הטיפוס הדרגתי נשאר תקוע. TensorFlow מציעה מגוון רחב של כלי אופטימיזציה זמינים, כולל כאלה שעובדים עם כמות גדולה של התעמלות, ושיטיפו באופן מאובטח את נקודות האוכף.

אתחול אקראי

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

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

NaN ???

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

בטוח? בעולם היפהפה של המתמטיקה, אנחנו נהיה בטוחים, אבל בעולם המחשב, exp(-150), מיוצג בפורמט float32, הוא כמו שהוא מאפס ומתרחשת בו קרוסלת אנטרופיה.

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

הצלחת?

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

בכל מקרה של בעיה, זה הפתרון:

keras_02_mnist_dense.ipynb

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

נראה שקצב מהיר יותר לא עוזר הרבה, ומה כל הרעש הזה?

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

האטה.png

הפתרון הטוב הוא להתחיל במהירות ולעכב באופן משמעותי את שיעור הלמידה. ב-Karas אפשר לעשות זאת עם השיחה החוזרת ב-tf.keras.callbacks.LearningRateScheduler.

קוד שימושי להדבקת עותק:

# lr decay function
def lr_decay(epoch):
  return 0.01 * math.pow(0.6, epoch)

# lr schedule callback
lr_decay_callback = tf.keras.callbacks.LearningRateScheduler(lr_decay, verbose=True)

# important to see what you are doing
plot_learning_rate(lr_decay, EPOCHS)

לא לשכוח להשתמש בlr_decay_callback שיצרת. יש להוסיף אותו לרשימת הקריאות החוזרות ב-model.fit:

model.fit(...,  callbacks=[plot_training, lr_decay_callback])

ההשפעה הקטנה הזו מדהימה. אתם רואים שרוב הרעש נעלם והדיוק בבדיקה גדול עכשיו מ-98% באופן קבוע.

נראה שהמודל מעניין עכשיו. בואו ננסה להעמיק עוד יותר.

האם זה עוזר?

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

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

נשלף

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

זה עבד?

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

נראה שהנשירה לא הייתה הפתרון הנכון, או אולי "overfiting" האם מושג מורכב יותר וחלק מהסיבות שלו לא מתאפשרות כפתרון &מירכאות.

מה זה "overfitting"? התאמה עודפת מתרחשת כשרשת נוירונים לומדת "badly&QUOTE; יש שיטות תחזוקה כמו נשירה שיכולות לאלץ למידה בצורה טובה יותר, אבל יש גם שורשים גבוהים מדי.

overfitt.png

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

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

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

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

בכל מקרה של בעיה, זה הפתרון:

keras_03_mnist_dense_lrdecay_dropout.ipynb

בקצרה

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

volulution.gif

איור

כך נראה רשת נוירונים מסובכת פשוטה בקראס:

model = tf.keras.Sequential([
    tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1)),
    tf.keras.layers.Conv2D(kernel_size=3, filters=12, activation='relu'),
    tf.keras.layers.Conv2D(kernel_size=6, filters=24, strides=2, activation='relu'),
    tf.keras.layers.Conv2D(kernel_size=6, filters=32, strides=2, activation='relu'),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(10, activation='softmax')
])

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

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

צילום מסך 2016-07-29 בשעה 16.02.37.png

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

איור: רשת נוירונים מומרת טרנספורמציה של "cubes" של נתונים ב-"cubes" של נתונים אחרים.

המרות מורכבות, מאגר מקסימלי

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

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

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

השכבת הסופית

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

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

במקום להשתמש בשכבה צפופה וגבוהה, אנחנו יכולים גם לפצל את הנתונים הנכנסים &quot ;cucu&quot כך נהוג ליצור את סיווג הסיווג בלי שקלול. בקראס, יש שכבה עבורה: tf.keras.layers.GlobalAveragePooling2D().

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

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

שימו לב שהשכבות העליונות והשלישיות כוללות רצף של שתיים, שמסבירות מדוע הן מנמיכות את מספר ערכי הפלט מ-28x28 ל-14x14 ולאחר מכן 7x7.

בנות את קוד קראס.

יש לשים לב במיוחד לפני שכבת ההמרה הראשונה. אכן, היא מצפה ל'קובייה'' של נתונים תלת-ממדיים אנחנו צריכים לשנות את הגודל שלהם לתמונות 28x28x1 (ערוץ אחד לתמונות בגווני אפור):

tf.keras.layers.Reshape(input_shape=(28*28,), target_shape=(28, 28, 1))

ניתן להשתמש בשורה הזו במקום בשכבת tf.keras.layers.Input הנוכחית.

ב-Keras, התחביר של שכבת המרה ממופעלת ב-relu' הוא:

tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu')

לקבלת פיתול מסובך, יש לכתוב:

tf.keras.layers.Conv2D(kernel_size=6, filters=24, padding='same', activation='relu', strides=2)

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

tf.keras.layers.Flatten()

ובשכבת הצפיפות, התחביר לא השתנה:

tf.keras.layers.Dense(200, activation='relu')

האם המודל שלך שבר את מחסום הדיוק של 99%? די קרוב... אבל עיינתם בעקומה של אובדן האימות. האם מושמע צלצול בפעמון?

מעיינים גם בחיזויים. בפעם הראשונה אתם אמורים לראות שרוב 10,000 ספרות הבדיקה מוכרות עכשיו. נותרו רק כ-41⁄2 שורות של זיהוי שגוי (כ-110 ספרות מתוך 10,000)

בכל מקרה של בעיה, זה הפתרון:

keras_04_mnist_convolutional.ipynb

האימון הקודם מציג סימנים ברורים לגבי יתרות (ועדיין אינו מדויק ב-99%). האם כדאי לנסות שוב את העזיבה?

איך היה הזמן הזה?

נראה שהנשירה עבדה הפעם. אובדן האימות לא גדל יותר, והדיוק הסופי צריך להיות גבוה מ-99%. מעולה!

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

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

לבסוף, ננסה להוסיף נירמול של אצווה.

זו התיאוריה, בפועל, חשוב לזכור כמה כללים:

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

# Modify each layer: remove the activation from the layer itself.
# Set use_bias=False since batch norm will play the role of biases.
tf.keras.layers.Conv2D(..., use_bias=False),
# Batch norm goes between the layer and its activation.
# The scale factor can be turned off for Relu activation.
tf.keras.layers.BatchNormalization(scale=False, center=True),
# Finish with the activation.
tf.keras.layers.Activation('relu'),

מה מידת הדיוק?

עם שינוי קל שיעור הלמידה והתאמות הנשימה בוצעו בהתאם ל &שיטת העבודה המשוערת;&לשימוש בנורמות בקבוצה:

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

על גבי פנקס הפתרונות יש ריצה של 99.5%:

keras_05_mnist_batch_norm.ipynb

תוכלו למצוא גרסה מוכנה של הקוד בתיקיית mlEngine ב-GitHub, וכן הוראות להפעלתה ב-Google Cloud AI Platform. לפני שתוכלו להריץ את החלק הזה, עליכם ליצור חשבון Google Cloud ולהפעיל את החיוב. המשאבים הנדרשים להשלמת המעבדה צריכים להיות קטנים משני דולרים (בהנחה על שעה אחת של אימון במכשיר GPU אחד). כדי להכין את החשבון:

  1. יוצרים פרויקט Google Cloud Platform (http://cloud.google.com/console).
  2. הפעלת חיוב.
  3. להתקין את הכלים של שורת הפקודה של GCP (GCP SDK כאן).
  4. אפשר ליצור קטגוריה של Google Cloud Storage (לאזור us-central1). היא תשמש לשלב קוד האימון ואחסון המודל המיומן.
  5. מפעילים את ממשקי ה-API הנחוצים ומבקשים את המכסות הדרושות (מפעילים את פקודת האימון פעם אחת, ומקבלים הודעות שגיאה שמסבירות מה להפעיל).

יצרתם רשת נוירונים ראשונה ולמדתם אותה עד 99% מהדיוק. הטכניקות שלמדנו לאורך הדרך אינן ספציפיות למערך הנתונים MNIST, אלא הן בשימוש נרחב בעבודה עם רשתות נוירונים. כמתנה למטרות חלוקה, הנה כרטיס הפתקים &&q;cliff'שלה לשיעור ה-Lab, בגרסת אנימציה. ניתן להשתמש בו כדי לזכור את הדברים שלמדתם:

צוקים הערות Tenorflow Lab.png

מה אפשר לעשות?

  • אחרי שמתחברים לרשתות מסוג 'התחברות באופן מלא', צריך לעיין ברשתות נוירונים חוזרות.
  • כדי להריץ את ההדרכות או ההסקות שלכם בענן בתשתיות מבוזרות, Google Cloud מספק AI Platform.
  • לבסוף, אנחנו אוהבים לקבל משוב. נשמח לשמוע אם ראית משהו שגוי בשיעור ה-Lab הזה, או שלדעתך צריך לשפר אותו. אנחנו מטפלים במשוב באמצעות בעיות GitHub [קישור למשוב].

HR.png

מזהה מרטין גורנר Small.jpg

המחבר: מרטין גורנר

Twitter: @martin_gorner

כל התמונות מצוירות בזכויות היוצרים האלה במעבדה: alexpokusay / 123RF תמונות ממאגר