תוכן העניינים[להתחבא][הופעה]
המוח דומה לרשתות עצביות. זוהי האנלוגיה המשמשת בדרך כלל כדי לסייע למישהו חדש בנושא להבין את הרעיונות מאחורי למידת מכונה ורשתות עצביות מלאכותיות.
מכיוון שמאחורי הקלעים מתרחשים מספר רבדים של חישובים מתמטיים וסטטיסטיים, הגדרת הרשתות הללו כפונקציה מתמטית היא שיטה מתקדמת יותר.
זה מיועד לאנשים שממש מתעניינים בלמידת מכונה ורוצים לראות איך נכתב קוד הרשת העצבית של Python.
במאמר זה, נדגים כיצד לבנות רשת עצבית עמוקה מחוברת לחלוטין (DNN) מאפס. פיתון 3.
סקירה כללית של מבנה הקבצים עבור קוד הרשת העצבית של Python
יהיו שלושה קבצים שנוצרו כאן. הראשון הוא הקובץ הפשוט nn.py, שיידון ב"הגדרת פונקציות עוזר" ו"בניית הרשת העצבית מאפס".
יהיה לנו גם קובץ בשם mnist loader.py כדי לטעון את נתוני הבדיקה, כמתואר ב"טעינת נתוני MNIST".
לבסוף, יהיה לנו קובץ בשם test.py שיושק בטרמינל כדי לבדוק את הרשת העצבית שלנו.
קובץ זה מתואר בפירוט ב"בדיקות הרצת".
הַתקָנָה
יש להוריד את ספריית NumPy Python כדי לעקוב אחר הדרכה זו. אתה יכול להשיג זאת על ידי שימוש בפקודה הבאה בטרמינל:
ייבוא מודולים והגדרת פונקציית העזר
שתי הספריות היחידות שאנו דורשים הן אקראי ו-NumPy, אותן נייבא מיד. עבור המשקלים הראשוניים של הרשת העצבית שלנו, נערבב אותם באמצעות הספרייה האקראית.
על מנת להאיץ את החישובים שלנו, נשתמש ב-NumPy או np (על פי מוסכמה, זה מיובא לעתים קרובות כ-np). שתי פונקציות העוזר שלנו יתבצעו לאחר הייבוא שלנו. שתי פונקציות סיגמואידיות: אחת וסיגמואידית ראשונית.
רגרסיה לוגיסטית תסווג נתונים באמצעות הפונקציה הסיגמואידית, בעוד שההפצה האחורית תחשב את הדלתא או הגרדיאנט באמצעות הפונקציה הראשית של הסיגמואיד.
יצירת כיתת רשת
בניית רשת עצבית מקושרת לחלוטין היא המוקד היחיד של סעיף זה. מחלקת הרשת תקיף את כל הפונקציות שמגיעות לאחר מכן. הפונקציה Object() { [קוד מקורי] } תיווצר בתחילה במחלקת הרשת שלנו.
ארגומנט אחד, גדלים, נדרש על ידי הפונקציה Object() { [קוד מקורי] }. משתנה הגדלים הוא אוסף של ערכים מספריים המייצגים את מספר צמתי הקלט הקיימים בכל שכבה של הרשת העצבית שלנו.
אנו מאתחלים ארבעה מאפיינים בשיטת __init__ שלנו. משתני הקלט, הגדלים, משמשים להגדרת רשימת גדלי השכבות ומספר השכבות, מספר שכבות, בהתאמה.
הצעד הראשון הוא להקצות באופן אקראי את ההטיות הראשוניות של הרשת שלנו לכל שכבה שעוקבת אחרי שכבת הקלט.
לבסוף, לכל קישור בין שכבות הקלט והפלט, המשקולות שלו נוצרות באופן אקראי. Np.Random.Randn() נותן מדגם אקראי שנלקח מההתפלגות הנורמלית עבור הקשר.
פונקציית הזנה קדימה
ברשת עצבית, מידע נשלח קדימה על ידי פונקציית ההזנה קדימה. ארגומנט אחד, a, המציין את וקטור ההפעלה הנוכחי, יידרש לפונקציה זו.
פונקציה זו מעריכה את ההפעלות בכל שכבה על ידי איטרציה על כל ההטיות והמשקלים ברשת. התשובה שניתנה היא החיזוי, שהוא ההפעלה של השכבה האחרונה.
Mini-batch Gradient Descent
סוס העבודה של כיתת הרשת שלנו הוא Gradient Descent. בגרסה זו, אנו משתמשים בהשתלשלות שיפוע מיני-אצווה (סטוכסטית), וריאציה שונה של ירידה בשיפוע.
זה מצביע על כך שישמש אצווה קטנה של נקודות נתונים כדי לעדכן את המודל שלנו. ארבעה ארגומנטים נדרשים וארגומנט אופציונלי אחד מועברים לשיטה זו. ארבעת המשתנים הנדרשים הם מערך נתוני האימון, מספר העידנים, גודל המיני-אצט, וקצב הלמידה (eta).
נתוני בדיקה זמינים לפי בקשה. אנו נספק נתוני בדיקה כאשר בסופו של דבר נעריך את הרשת הזו. מספר הדגימות בפונקציה זו נקבע תחילה לאורך הרשימה לאחר שנתוני האימון הומרו לסוג רשימה.
אנחנו גם מיישמים את אותו תהליך על נתוני בדיקה שנמסרים. הסיבה לכך היא שבמקום להיות מוחזרים אלינו כרשימות, הם באמת רוכסנים של רשימות. כאשר נטען את דגימות הנתונים של MNIST מאוחר יותר, נלמד יותר על כך.
אם נוכל לוודא שאנו מספקים את שני סוגי הנתונים כרשימות, אז יציקת סוג זה אינה בהכרח חיונית.
ברגע שיש לנו את הנתונים, אנחנו עוברים על תקופות האימון בלולאה. תקופת אימון היא רק סבב אחד של אימון רשתות עצביות. ראשית, אנו מערבבים את הנתונים בכל תקופה כדי להבטיח אקראיות לפני יצירת רשימה של מיני-אצט.
פונקציית ה-Mini Batch העדכון, עליה נדון להלן, תיקרא עבור כל מיני-אצווה. דיוק הבדיקה יוחזר גם אם נתוני הבדיקה זמינים.
פונקציית עוזר נגזרת עלות
בואו נפתח תחילה פונקציית עוזר שנקראת נגזרת עלות לפני שניצור באמת את קוד ההפצה האחורית. אם אנחנו עושים טעות בשכבת הפלט שלנו, פונקציית נגזרת העלות תציג זאת.
הוא דורש שתי כניסות: מערך הפעלת הפלט וקואורדינטות ה-y של ערכי הפלט הצפויים.
פונקציית התפשטות לאחור
יש לזכור את וקטור ההפעלה הנוכחי שלנו, הפעלה, כמו גם כל וקטור הפעלה אחר, אקטיבציות ווקטור z, zs. שכבה הנקראת שכבת הקלט מופעלת תחילה.
נעבור בלולאה על כל הטיה ומשקל לאחר הנחתם. כל לולאה כוללת חישוב וקטור z כמכפלת הנקודות של המשקולות וההפעלה, הוספתו לרשימת ה-zs, חישוב מחדש של ההפעלה והוספת ההפעלה המעודכנת לרשימת ההפעלה.
לבסוף, המתמטיקה. הדלתא, ששווה לשגיאה מהשכבה הקודמת כפול ה-sigmoid prime של האלמנט האחרון של הוקטורים zs, מחושבת לפני שנתחיל במעבר לאחור.
השכבה האחרונה של nabla b מוגדרת להיות הדלתא, והשכבה הסופית של nabla w מוגדרת להיות מכפלת הנקודה של הדלתא ושכבת ההפעלה השנייה-לאחרונה (מומרה כך שנוכל לבצע את החישוב) .
אנחנו ממשיכים כמו קודם, מתחילים מהשכבה השנייה ומסיימים עם האחרונה, וחוזרים על התהליך לאחר השלמת השכבות האחרונות הללו. לאחר מכן מחזירים את הנאבלה כטופל.
עדכון השתלשלות שיפוע מיני-אצווה
שיטת ה-SGD שלנו (ירידה בשיפוע סטוכסטי) מלפני כן משלבת עדכון מיני-אצווה. מכיוון שהוא מנוצל ב-SGD אך גם דורש תמיכה אחורה, התלבטתי היכן לשים את הפונקציה הזו.
לבסוף, בחרתי לפרסם את זה כאן. זה מתחיל ביצירת 0 וקטורים של הנאבלות של הטיות ומשקולות, בדיוק כמו שעשתה פונקציית ה-backprop שלנו.
הוא דורש את המיני-אצווה ואת קצב הלמידה של eta כשני הקלטים שלו. ב-mini-batch, לאחר מכן אנו משתמשים בפונקציה backprop כדי לקבל את הדלתא של כל מערך nabla עבור כל קלט, x, ופלט, y. רשימות הנאבלה מתעדכנות לאחר מכן עם דלתות אלו.
לבסוף, אנו משתמשים בקצב הלמידה ובנאבלה כדי לעדכן את המשקולות וההטיות של הרשת. כל ערך מתעדכן לערך העדכני ביותר, בניכוי קצב הלמידה, מוכפל בגודל המיני-אצט, ולאחר מכן מתווסף לערך ה-nabla.
הערכת פונקציה
הפונקציה evaluate היא הפונקציה הסופית שאנחנו צריכים לכתוב. נתוני הבדיקה הם הקלט היחיד עבור פונקציה זו. בפונקציה זו, אנו משווים רק את התפוקות של הרשת עם התוצאה הצפויה, y. על ידי הזנת הקלט, x, קדימה, היציאות של הרשת נקבעות.
קוד מלא
כשאנו משלבים את כל הקוד, כך הוא מופיע.
בדיקת רשת עצבית
טוען נתוני MNIST
אל האני נתוני MNIST הוא בפורמט .pkl.gz, אותו נפתח באמצעות GZIP ונטען עם מלפפון חמוץ. בוא נכתוב שיטה מהירה לטעינת נתונים אלה בתור טופלה בגודל שלוש, המחולקת לנתוני אימון, אימות ונתוני בדיקה.
כדי להקל על ניהול הנתונים שלנו, נכתוב פונקציה נוספת לקידוד ה-y למערך של 10 פריטים. המערך יהיה כולו 0 למעט 1 שתואם את הספרה המתאימה של התמונה.
נשתמש בנתוני הטעינה הבסיסיים ובשיטת קידוד חמה אחת כדי לטעון את הנתונים שלנו לפורמט קריא. תיכתב פונקציה נוספת שתמיר את ערכי ה-x שלנו לרשימה בגודל 784, בהתאמה ל-784 הפיקסלים של התמונה, ואת ערכי ה-y שלנו לצורת הווקטור המקודדת החמה היחידה שלהם.
לאחר מכן נשלב את ערכי x ו-y כך שאינדקס אחד יתאים לשני. זה חל על מערכי נתוני ההדרכה, האימות והבדיקה. לאחר מכן נחזיר את הנתונים שהשתנו.
מבחני ריצה
אנו ניצור קובץ חדש בשם "mnist loader" שייבא גם את הרשת העצבית שהקמנו בעבר (nn פשוט) וגם את מטעין ערכות הנתונים של MNIST לפני שנתחיל בבדיקה.
בקובץ הזה, כל מה שאנחנו צריכים לעשות הוא לייבא את הנתונים, לבנות רשת עם גודל שכבת קלט של 784 וגודל שכבת פלט של 10, להפעיל את פונקציית SGD של הרשת על נתוני האימון, ואז לבדוק אותה באמצעות נתוני הבדיקה.
זכור כי עבור רשימת שכבות הקלט שלנו, אין הבדל מה מספרים בין 784 ל-10. אנו יכולים לשנות את השכבות האחרות בכל דרך שנרצה; רק גדלי הקלט והפלט קבועים.
אין צורך בשלוש שכבות; אנו עשויים להשתמש בארבעה, חמישה, או אפילו רק שניים. כיף להתנסות בזה.
סיכום
כאן, באמצעות Python 3, אנו יוצרים רשת עצבית מאפס. יחד עם מתמטיקה ברמה גבוהה, דנו גם בפרטי היישום.
התחלנו ביישום פונקציות עוזר. כדי שהנוירונים יפעלו, הפונקציות הראשוניות של הסיגמואידים והסיגמואידים הם קריטיים. לאחר מכן, הפעלנו את פונקציית ההזנה קדימה, שהיא התהליך הבסיסי להזנת נתונים לרשת העצבית.
לאחר מכן, יצרנו את פונקציית הירידה בשיפוע ב-Python, המנוע שמניע את הרשת העצבית שלנו. על מנת לאתר "מינימום מקומיים" ולייעל את המשקל וההטיות שלהם, הרשת העצבית שלנו משתמשת בירידה בשיפוע. יצרנו את פונקציית ההפצה לאחור באמצעות ירידת שיפוע.
על ידי אספקת עדכונים כאשר הפלטים אינם תואמים את התוויות המתאימות, פונקציה זו מאפשרת לרשת העצבית "ללמוד".
לבסוף, שמנו את הפייתון החדש שלנו רשת עצבית לבדיקה באמצעות ערכת הנתונים של MNIST. הכל תפקד בצורה חלקה.
קידוד שמח!
השאירו תגובה