רשת קונבולוציה

**רשת קונבולוציה** (לפי האקדמיה ללשון העברית: רשת עֲצַבִּית מתקפלת; באנגלית: **CNN** – **C**onvolutional **N**eural **N**etwork, נקראת גם **Space Invariant Artificial Neural Networks** או **SIANN**) היא סוג של רשת נוירונים המשתמשת בפעולת הקונבלוציה במקום בכפל מטריצות כללי לפחות באחת מהשכבות שלה. סוג זה של רשת נוירונים משמש בעיקר לעיבוד תמונה וראיה ממוחשבת, אך יש לו שימושים גם במערכות המלצה, עיבוד שפה טבעית וממשק מוח-מחשב.

הליבה של הרשת מבוססת על **שכבות כינוס** (באנגלית: convolution layers) הממומשות על ידי העברת מסננת (filter) או ליבה (kernel) על גבי הקלט וביצוע כפל מטריצות. הפלט נקרא feature map.

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

## ארכיטקטורה
[ממוזער|371x371 פיקסלים|השוואה בין ארכיטקטורת LeNet ו-[AlexNet]]
רשת קונבולוציה עושה שימוש בדרך כלל ב, שכבות כינוס (convolution) שכבות אגרגציה (pooling) ופונקציית שפעול (activation function).

בדרך כלל תחילה תכיל מספר שכבות כינוס, אגרגציה (pooling) ו-ReLU נוספות אחריה, ולאחר מכן מספר שכבות בקישור מלא.

### שכבת כינוס (Convolution)
הקלט לשכבה זאת הוא טנזור המייצג את התמונה, בגודל *(מספר קלטים) x (מספר ערוצי קלט) x ( גובה הקלט) x (רוחב הקלט)*. לאחר שהקלט מסיים לעבור בשכבה מתקבל טנזור המייצג תמונה מופשטת יותר הנקראת feature map, בגודל (מספר קלטים) x (מספר ערוצי ה-feature map) x ( גובה ה-feature map) x (רוחב ה-feature map).

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

לדוגמה, שכבה fully connected לתמונה בגודל 100x100 תיצור לנו כ-10,000 משקולות חדשות עבור כל נוירון בשכבה הבאה, דבר שיכול מהר מאוד להפוך ל"יקר" מאוד. לעומת זאת, שכבת כינוס עם ליבה (kernel) בגודל 5x5 תיצור לנו רק כ-25 משתנים למידים חדשים. שימוש במשקולות שעברו נרמול על פחות משתנים עוזר להימנע מבעיית הגרדיאנט הנעלם.

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

### שכבת קישור מלא (fully connected)
מכילה מערך נוירונים; מקבלת כקלט מערך נוירונים ומחברת בין כל נוירון במערך זה לכל נוירון הנמצא בתוכה (לפירוט נוסף ראה ערך רשת עצבית מלאכותית).

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

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

## אבניי בניין
רשת קונבולוציה מורכבת ממספר שכבות כגוון שכבת כינוס, שכבת אגרגציה ושכבה קישור מלא.

יכול להיות שימוש בעוד סוגי שכבות רבים אבל אלה הנפוצות והבסיסיות ביותר. ממוזער|קונבולוציה על תמונה בגודל 4x4 (כחול) עם ליבה בגודל 3x3 (צל כחול כהה) וקפיצות בגודל 1 היוצרת תמונה חדשה בגודל 2x2 (טורקיז)
### שכבת כינוס
עוברים על הטנזור ומכפילים עם הליבה (באנגלית: kernel) שהיא טנזור בגודל \ k_{1}\times k_{2}עם קפיצות בגודל (s_{1},s_{2}) כאשר \ s_{1} מייצג את גודל הקפיצה בציר ה-\ x  ו-\ s_{2} מייצג את גודל הקפיצה בציר ה-\ y  (בדרך כלל \ k_{1} ו-\ k_{2}יהיו באותו גודל ולכן פשוט יקראו \ kכנ"ל לגבי \ s), כאשר כל ליבה יכולה לשמש לצורך מטרה שונה.

או פשוט g(x,y)= \omega *f(x,y)=\sum_{dx=-a}^a{\sum_{dy=-b}^b{ \omega (dx,dy)f(x+dx,y+dy)}}.

כאשר g(x,y) מייצג את התמונה החדשה, f(x,y) מייצג את התמונה המקורית ו-\omega מייצג את הליבה.

גודל הפלט של שכבת כינוס עם חלון בגודל \ k_{w}\times k_{h} וקפיצות (strides) בגודל \ s_{w}\times s_{h} טנזור קלט בגודל \ t_{w}\times t_{h}

\ o_{w}= \lfloor {\frac{t_{w}-k_{w}}{s_{w}} } \rfloor +1  \ o_{h}= \lfloor {\frac{t_{h}-k_{h}}{s_{h}} } \rfloor +1  כאשר \ o_{w}\times o_{h}הם ממדיי הפלט.
### שכבת אגרגציה (pooling)
ממוזער|max pooling עם ליבה בגודל 2x2 וקפיצות בגודל של 2
עוברים עם חלון בגודל \ p_{w}\times p_{h} ועושים פעולה מתמטית המוציאה מספר אחד. למשל, במקרה של max pooling ניקח את המספר הגדול ביותר שיצא בגבולות החלון שלנו בכל החלקה. במקרה של average pooling ניקח את כל המספרים שיצאו בגבולות החלון שלנו ונעשה להם ממוצע.

ביצוע max pooling עם חלון בגודל \ p_{w}\times p_{h} וקפיצות (strides) בגודל \ s_{w}\times s_{h} טנזור קלט בגודל \ t_{w}\times t_{h}

כאשר \ o_{w}\times o_{h}הם ממדיי הפלט ו-\ 0\leq x  \ 0\leq y .

o_{x,y} = max (\sum_{i=(x-1)*p_{w}}^{x*p_{w}}\sum_{j=(y-1)*p_{h}}^{y*p_{h}} t_{i,j})

גודל הפלט של שכבת אגרגציה עם חלון בגודל \ p_{w}\times p_{h} וקפיצות (strides) בגודל \ s_{w}\times s_{h} טנזור קלט בגודל \ t_{w}\times t_{h}

\ o_{w}= \lfloor {\frac{t_{w}-p_{w}}{s_{w}} } \rfloor +1  \ o_{h}= \lfloor {\frac{t_{h}-p_{h}}{s_{h}} } \rfloor +1  כאשר \ o_{w}\times o_{h}הם ממדיי הפלט.

### שכבת ReLU (Rectified linear unit)
זוהי פונקציית שפעול מאוד פופולרית בקרב רשתות קונבולוציה. הפונקציה עוברת על כל נוירון ומבצעת בו פונקציית יחידה ליניארית מתוקנת.

הפונקציה עבור כל נוירון היא: f(x) = \begin{cases}
	0 & \text{for } x 

הטווח של פונקציה זאת הוא [0,\infty). 130x130 פיקסלים

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

השכבה פועלת בצורה כזו: היא מקבלת את \ 0 וקלט של שכבת נוירונים, והיא תתעלם מנוירונים אקראיים, כלומר, לכל נוירון יש \ pסיכוי להישמר או \ 1-pסיכויים להישמט.

## משתנים כלליים
### גודל הליבה (kernel)
הליבה היא טנזור, וצריך לבחור את ממדי הטנזור. בדרך כלל הגדלים יהיו \ 3\times 3 או \ 5\times 5 או \ 7\times 7אבל אפשר לבחור כל גודל רצוי כל עוד הוא גדול מאפס.

### ריפוד
ריפוד (באנגלית: padding) נועד על מנת לפתור שתי בעיות:

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

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

למשל, לתמונה בגודל של 5\times5 עם ליבה בגודל 3\times3 וקפיצות בגודל של אחד, אם נוסיף שכבת ריפוד אחת מכל כיוון לאחר כינוס נשאר עם תמונה בגודל 5\times5 כלומר לא הקטנו אותה.

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

### גודל פסיעה (Stride)
משתנה זה מייצג את גודל הפסיעה/קפיצה שנעשית בכל פעם עם הליבה. בדרך כלל יהיה בגודל \ 2\times 2 או \ 1\times 1 אבל יכול להיות בכל גודל רצוי כל עוד הוא גדול מאפס.

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

### גודל אגרגציה
אגרגציה היא הרי טנזור העובר על תמונת הקלט וצריך לבחור את ממדיי הטנזור. בדרך כלל הגדלים יהיו \ 2\times 2 או \ 4\times 4 אבל אפשרי לבחור כל גודל רצוי כל עוד הוא גדול מאפס.

### סוג אגרגציה
ישנם כמה סוגי אגרגציה:
* אגרגציה מקסימלית (max pooling)
* אגרגציה מינימלית (min pooling)
* אגרגציה ממוצעת (average pooling)

## קוד
מודל רשת קונבולוציה ב-TensorFlow:
```python
def build_classifier():
 model = Sequential(name="classifier")

 model.add(Conv2D(64, kernel_size=5, strides=2, input_shape=img_shape, padding='same'))
 model.add(LeakyReLU(alpha=0.2))
 model.add(Dropout(0.3))

 model.add(Conv2D(128, kernel_size=5, strides=2, padding='same'))
 model.add(LeakyReLU(alpha=0.2))
 model.add(Dropout(0.3))

 model.add(Conv2D(256, kernel_size=5, strides=2, padding='same'))
 model.add(LeakyReLU(alpha=0.2))
 model.add(Dropout(0.3))

 model.add(Conv2D(512, kernel_size=5, strides=2, padding='same'))
 model.add(LeakyReLU(alpha=0.2))
 model.add(Dropout(0.3))

 model.add(Flatten())
 model.add(Dense(1, activation='sigmoid'))

 model.summary()
 image = Input(shape=img_shape)
 validity = model(image)
 return Model(image, validity)
```


## הערות שוליים

קטגוריה:בינה מלאכותית
קטגוריה:אלגוריתמים
קטגוריה:למידת מכונה