Ayelet Sapirshtein

שאלת מתנה-ספרי לי על פרויקט שעשית

מיועד ל- כל אחד (כתבה לא טכנית)

נכתב על ידי Ayelet Sapirshtein

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

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

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

  1. שיש לכם הבנה עמוקה של הדברים שנעשו, למה עשיתם X ולא Y.
  2. אתם יודעים להסביר דברים שעשיתם.
  3. אתם יודעים להסיק מסקנות לגבי מה עובד ומה לא.
  4. יש לכם יכולת לקרוא ולהבין מאמר.
  5. איך אתם מתמודדים עם בעיות.
  6. האם הקוד שלכם קריא, מסודר ומתועד.
  7. יכולת עבודה עם git.
  8. עשיית פרויקט יכול להצביע על אוטו-דידקטיות, זיקה לתחום ומוטיבציה.
  9. זה טבעי שלא תדעו הכל, פרויקט יכול לכוון את המרואיינים במה אתם מבינים ועל מה אפשר לשאול אתכם.

איך מתכוננים?

  1. כתבו תיאור מפורט של הפרויקט ומה עשיתם.
  2. vanishing gradient, עבר זמן ובטח יהיו פרטים ששכחתם. השלימו את הפרטים החסרים על ידי חזרה אל הקוד במידת האפשר. אם הקוד לא ברשותכם השלימו לפני ההיגיון. במה הייתם משתמשים אם הייתם צריכים לעשות את הפרוייקט היום.
  3. לטשו את הסיפור ופשטו את ההסברים. הסבירו את הסטינג של הבעייה, תארו את התהליך, מה הייתה המטרה, איך נגשתם לבעייה, מאיפה אספתם את הדאטה, מה הפתרונות הטריוויאלים שניסיתם בהתחלה ומדוע הם לא הספיקו או לא פתרו את הבעייה ? מה האתגרים בהם נתקלתם ? כיצד התמודדתם איתם? אחת הטעויות הנפוצות היא לחשוב שהמטרה היא להרשים ולכן מגיעים מהר מדי לפאנץ׳ – לפתרון המתוחכם שבניתם, התמקדו קודם להסביר את הקשיים והמטרה מדוע הפתרון שבחרת בו היה נחוץ.
  4. ספרו על הפרויקט לחברים שעובדים בתחום, תוודאו שהסיפור מוציא אותכם טוב. אם השתמשתם בשיטה לא יעילה, או הייתה לכם טעות, תתקנו.
  5. הסתכלו על דרישות המשרה שאתם מתראיינים אליה ונסו לחשוב אילו נקודות בסיפור שווה להדגיש כדי להראות שאתם עומדים בדרישות.
  6. טיפ למתקדמים: אנחנו רוצים ליחצן את היתרונות היחסיים שלנו, אבל לא רוצים להישמע שחצנים. במקום להגיד כל השיחה אני ואני ועשיתי ועשיתי ולדבר על עצמך יותר מידי באופן שיכול לגרום לנו להשמע שחצנים וקצת לא אמינים. בנוסף זה מחייב אותך גם לתת דוגמאות מדוע אני טוב בכל הדברים שאני אומר. אז מה פתרון הביניים?.אפשר לספר סיפור ולשזור בו נתונים על הרזומה והפעילויות שלנו, וכך המראיין יבין לבד. למשל “את הרעיון לפרויקט קיבלתי מהרצאה ששמעתי במיטאפ\כנס בחו”ל\ קורס מקוון שלקחתי\אהקטון שהשתתפתי בו\summer internship שעשיתי ב…, בתוכנית מצטיינים, קוד אופן סורס שאני תורם לו”. וכך אתם יכולים להעיד על עצמכם בעקיפין שאתם הולכים להרבה האקטונים, מיטאפים, תורמים לקוד פתוח, מצטיינים וכו’..
  7. ציירו שמש אסוציאציות וחשבו על כל השאלות שיכולים לשאול אתכם על הפרויקט למשל:

1. איזו בעייה ניסית לפתור?

2. באיזה דאטה השתמשת? איך היית מתמודד עם המשימה עם דאטא שונה ממה שהיה לך?

3. באיזה אלגוריתם\ארכיטקטורה השתמשת? למה דווקא בו? מה החסרונות והיתרונות שלו לעומת אחרים? איך הוא עובד?

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

5. איך מדדת את הביצועים? מה היו היתרונות והחסרונות של שיטת המדידה?

6. וריאציות על הפרויקט, מה היה קורה אם במקום X היית עושה Y?

7. למה בחרת בגישה שבחרת?

8. מה היית עושה אם היינו מורידים אילוץ X ? או מוסיפים אילוץ Y?

9. מה הייתה עושה אם היה לה עוד כמה שבועות לעבוד על זה?

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

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

  1. כתבו תשובות להכל, תשננו תתאמנו מול מצלמה, מול המראה או מול חברים, ויש לכם שאלת מתנה בכיס.

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

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

פרויקטי צד כדרך חיים

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

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

איך אתה מגדיר פרוייקט אישי?

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

 איך אתה בוחר על אילו פרויקטים לעבוד?

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

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

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

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

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

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

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

אילו פרויקטים עצמאיים יצא לך לעשות בינתיים בתחום?

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

היו מספר פרוייקטים בסיסים של ML מקאגל.

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

פרוייקטי סיווג אודיו באמצעים קלאסיים ולא קלאסיים.

על מה אתה עובד עכשיו?

קורס NLP של fastai וקורס reinforcement learning של david silver.

רעיונות לפרויקטים

      • לקחת את בעיית ה Object Detection ולאמן אותה על DB ייחודי כמו למשל זיהוי אמבות.
        וריאציה נוספת אפשרית, אם למשל משתמשים ב YOLO לעשות anchors שאינם בהכרח מלבנים אלא צורות אחרות. (כוכבים, אליפסות…)
      • לקחת הקלטות (voice) של משפטים שכוללים את המילה “קורנה” וכאלו שלא, ולסווג. פה היכולת לעשות אוגמנטציה חכמה כנראה תהיה מאתגרת.
      • לאמן רשת נוירונים שפותרת בעיה מתמטית. קל: מציאת צלע שלישית במשולש ישר זווית (מודל שמתאמן ללמוד את משפט פיתגרוס). קשה: פתרון למשוואה ממעלה 2,3,4,5… (מודל שמתאמן ללמוד את נוסחת השורשים)
      • לאמן רשת נוירונים שמבצעת קלסיפיקציה על נתונים מקוריים. לדוגמא Google’s Quickdraw
        דאטה סט של 50 מיליון ציורים מהירים מחולקים ל345 קטגוריות.
        קוד נחמד בפייתון שהופך את הדאטה סט הזה לפורמט של MNIST ומחלק אותו לנתוני אימון ונתוני בדיקה.
      • קלסיפיקציה של מאגרי נתונים איזוטריים כמו רגשות, תמרורים
      • פרוייקט Ai שמשחק במשחק הדינוזאור של chrome:
        בלוג פוסט שמסביר איך לעשות את זה
      • סיווג של תנוחות ידיים
        לקבוע את מחוות היד בזמן אמת באמצעות מצלמת רשת.
      • לממש style transfer (יצירתיות אפשרית פה לא חסר…)
      • סיווג ג’אנר מוזיקה
        רשת שמזהה ג’אנרים של מוזיקה
        מערך נתונים לסיווג זאנר מוסיקה
      • פרויקט נחמד לחג הפסח: מד שבוחן האם אתם מסבים לשמאל כמו שצריך בעזרת pose estimation
        https://github.com/Heladoo/HappyPassover

    https://www.facebook.com/elad.amira/videos/10158577390038470

 

יש לכם עוד רעיונות, או פרויקטים שעשיתם ?

רישמו בהערות פה או בפייסבוק ונשמח להוסיף לכתבה כדי לתת לאחרים השראה!

לקריאה נוספת

70 רעיונות לפרוייקטים ונתונים

Posted by Ayelet Sapirshtein in deep

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

מיועד ל-

נכתב על ידי Ayelet Sapirshtein

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

בשרשור שהתחלתי בקהילת , Machine & Deep learning Israel ,הקבוצה פעילה ביותר בתחום הדיפ לרנינג בארץ, שאלתי מהו היקף העבודה שיקח לאנשים ללא ניסיון עבור פרויקט שאפשר להציג בראיונות עבודה. הרוב המוחץ של התשובות היו חודש עבודה במשרה מלאה. 

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

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

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

 


Set Of Businessman Running On Loading Bar 3 Progress Steps Vectors by Vecteezy

הראל קין, ראש צוות במחלקת מחקר בחברת Lightricks

 

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

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

מה היתרונות של מסטרנט על מישהו שמגיע עם תואר ראשון?

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

מה ההיקף הנדרש לפרויקט צד שאפשר להציג בראיון?

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

מה חשוב שיהיה בפרויקט שמדברים עליו בראיון עבודה?

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

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

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

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

איך פרוייקט צד תורם בראיונות עבודה?

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

על איזה פרויקט הייתה ממליץ בתור פרויקט ראשון בדיפ לירנינג?

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

מה אתה מחפש לראות במועמד?

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

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

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

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

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

מה עבור דאטה סיינס קלאסי שרוצה to go deep?

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

 

רחל וויטיס -דאטה סיינטיסט לעיבוד טקסט בחברת זברה מדיקל בעלת מאסטר עם תזה בתחום NLP  מאוניברסיטת בר אילן

 

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

האם פרויקט בדיפ לרנינג זה משהו שנדרש בשביל להתקבל לעבוד בתחום?

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

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

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

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

אז למעשה פרוייקט צד מאפשר למקד את המראיין מה לשאול אותנו, ומה אנחנו אמורים לדעת?

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

מה חשוב שיהיה בפרויקט שמדברים עליו בראיון עבודה?

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

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

פרויקט טוב הוא פרויקט שמאפשר למרואיין לענות תשובות מעניינות ומעוררות דיון המשך לשאלות הבאות:

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

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

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

יש הבדל בהיקף הפרויקט הנדרש בהתאם לרקע המועמד?

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

יש סיבה לעשות פרוייקט צד מאוד גדול?

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

עצה למועמדים שמגיעים עם דוקטורט תיאורטי ללא ניסיון בתעשייה?

ללמוד לתכנת כמה שיותר מהר, לא משנה השפה או המסגרת.

 

יפה ויצנר HR בחברת SAIPS

 

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

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

איך מציגים פרויקטים בקורות החיים?

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

האם תואר שני הכרחי למציאת עבודה בתחום?

אין שום חובה לתואר שני

 

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

איך להתחיל ולסיים פרויקט צד בהצלחה?

Start Finish Vectors by Vecteezy

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

סיגל קורצ’ין

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

הגר סילו

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

דן עופר

שותפים ודדליין 

חמוטל זרד

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

ערן גבע 

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

איל גרוס

שותפים, דדליינים

דליה גרצמן

להתחיל- תתחילו מספיק פרויקטים, בסוף אחד מהם גם יהפוך לפרויקט.

להגדיר מוטיבציה לפרויקט, להתחייב עם דדליין, 

בשלב מסוים צריך להגיד זה מוכן. לא הכל חייב להיות מושלם.

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

ליאור דגן

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

תמיר נווה

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

איילת ספירשטיין 

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

 

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

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

 

התחלתם לעבוד על פרוייקט צד? ספרו לנו בתגובות על הפרויקט שבחרתם לעצמכם!

 

לקריאה נוספת

Build a Machine Learning Portfolio
לירון יצחקי-אלרהנד כיצד לבחור את פרוייקט הדאטה סיינס הראשון שלכם
Lines of Code That Got Me My Dream Job – Dalya Gartzma
How I was able to motivate myself on my first side project

Posted by Ayelet Sapirshtein in deep

צעד קטן לאדם צעד גדול להתכנסות

מיועד ל- מטיבי לכת (כתבה מאוד טכנית)

נכתב על ידי Ayelet Sapirshtein

“המסע הארוך ביותר נפתח בצעד הלא נכון”. (צ’ארלס כריסטופר מארק)

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

מהי אופטימיזציה למזעור פונקציית ההפסד (loss function) ?

פונקציית המחיר משמעותה עד כמה המודל שלנו צודק. ככל שהערך של פונקציית ההפסד (loss) נמוכה יותר, כך המודל “צודק” יותר. מודל “צודק” משמעו מודל שהפרדיקציה במוצאו קרובה ל Ground Truth, התוצאה שאמורה להיות בהתאם לתיוגים. למשל במודל סיווג בינארי לדואר (דואר זבל=1 דואר רגיל=0) עד כמה הציון שהמודל נותן קרוב ל1 בהינתן דואר זבל ו0 בהינתן מייל רגיל.

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

Gradient Descent

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

לדוגמה לחישוב Gradient descent עבור מודל רגרסיה לינארית n מימדית:

עבור קלט וקטור x, וקטור y שהינו ה Ground Truth (התחזית הרצויה) ו θ

וקטור הפרמטרים של מודל הרגרסייה.

ההיפותזה של התחזית עבור קלט x נראית כך:

h_0(x)=\sum_{j=0}^n\theta_jx_j

h_0 מייצגת את התחזית עבור דוגמא x

בהינתן m דגימות פונקצית ההפסד תראה כך:

J_{train}(\theta )=\frac{1}{2m}\sum _{i=1}^m\left ( h_{\theta}\left ( x^{(i)}\right )-y^{(i)} \right )^2

הגרדיאנט: 

\frac{1}{m}\sum _{i=1}^m\left ( h_{\theta}\left ( x^{(i)}\right )-y^{(i)} \right )x_j^{(i)}

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

עבור learning rate נקבל שצעד העדכון הייה:

\theta_j-\alpha\frac{1}{m}\sum _{i=1}^m\left ( h_{\theta}\left ( x^{(i)}\right )-y^{(i)} \right )x_j^{(i)}

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

בפועל חישוב הגרדיאנט לפי כל סט האימון (גודל batch ענקי) לוקחת זמן רב ולא ישים מבחינה חישובית. לעומת זאת SGD=Stochastic Gradient Descent, היא שיטה לפיה עוברים בלולאה מספר פעמים (כמספר ה-epochs) על סט האימון, ובכל איטרציה במקום לחשב את הגרדיאנט לפי כל סט האימון, מחשבים את הגרדיאנט לפי הדוגמא הנוכחית. (זהו למעשה batch בגודל אחד)

כדי לגרום לגרדיאנטים להיות פחות תנודתיים, במקום לחשב גרדיאנט לפי קלט יחיד, מחשבים לפי קבוצה קטנה של קלטים, שיטה זו נקראת Mini Batch Gradient Descent.

מקור 

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

ללא קשר לגודל ה Batch לשיטת ה-SGD יש לא מעט בעיות:

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

  1. התכנסות למינימום מקומי ולנקודות אוכף. כאשר SGD מגיע למינימום מקומי, או נקודת אוכף הגרדיאנט שווה ל0 וSGD יעצר. במימד גבוה זו סיטואציה שכיחה, למעשה הרבה יותר ממינימום מקומי. מסיבה זו הבעיה העיקרית היא עם נקודות אוכף ופחות עם מינימום מקומי. בעיה זו נוצרת גם בסביבת נקודת האוכף, שבה גרדיאנט מאוד קטן, וזו בעיה גדולה.מקור
  2. כיוון הגרדיאנט עלול לסבול מרעשים בעקבות העבודה עם mini batch, לדגימות חריגות (outliers) ב-Batch יכולה להיות השפעה חזקה.למרבה המזל יש אסטרטגייה פשוטה שעובדת טוב ברוב המקרים כדי להתמודד עם בעיית תנודתיות הגרדיאנטים והעצירה בנקודות אוכף.

    הוספת מומנטום ל-SGD

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

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

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

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

 

מקור

לרוב בוחרים את rho להיות 0.9 או 0.99.

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

AdaGrad

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

מה יקרה כתוצאה מהחילוק בהנחה שיש לנו קואורדינטה אחת שהנגזרת הכיוונית שלה תמיד קטנה קואורדינטה אחרת שהנגזרת הכיוונית שלה תמיד גדולה?

מקור

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

מה קורה לAdaGrad לאורך תהליך האימון כאשר סכום הריבועים הולך וגדל?

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

יש וריאציה קלה לAdaGrad שמתמודדת עם הבעיה הזו הנקראת RMSProp

RMSProp

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

מקור

הקורא הדקדקן שישווה בין Ada-Grad לבין RMSProp יבחין שאם נחליף במשוואות של RMSProp את הממוצע המשוכלל לפי פרמטרdecay_rate לסכום, כלומר להחליף את decay_rate ב-1 ואת 1-decay_rate ב-1 נקבל בדיוק את AdaGrad.

RMSProp שומר על המאפיין הנחמד של Ada-Grad להאיץ מהירות לאורך כיוון אחד ולהאט אותה בכיוון אחר, מבלי הבעיה של תמיד להאט.

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

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

למה לא גם וגם ? ? ?

Adam

משלב את השיטות הקדמות Momentum+ AdaGrad

מקור

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

מקור

המשתנים first_unbias ו second_unbias מתנהגים כמו המומנט הראשון והשני. כאשר t גדול וכאשר t קטן, השינוי של ה-unbias מקטין את first_unbias ו second_unbias ביחס למומנטים, אבל היות ובחישוב x אנחנו מפעילים שורש על second_unbias, נראה שיחס הגדלים בין המונה למכנה קטן, וכך גם צעדי ההתחלה.

פרמטרים מומלצים לAdam: bata1=0.9, bata2=0.999 ,learning_rate=1e-3

מה החסרונות של Adam וכיצד מתמודדים איתם?

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

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

דרך אחת להתמודד עם הבעיה הראשונה היא להתחיל לאמן בקצב נמוך, וכאשר המודל מתגבר על בעיית ההתייצבות הראשוניות, להגביר את הקצב. שיטה זו נקראת learning rate warm-up. חסרונה של השיטה הוא שמידת החימום הנדרש אינה ידועה ומשתנה מערך נתונים למערך נתונים. 

במקום שנגדיר בעצמנו את הפרמטרים עבור ה-warm-up ניתן להשתמש ב-RAdam .RAdam הוא אלגוריתם חדש שמחליף את ה-warm-up ב-Adam ולא מצריך הגדרת פרמטרים עבור תקופת החימום. חוקרים שפתחו את RAdam מצאו כי בעית ההתיצבות הראשונית נגרמת כתוצאה משונות לקויה ב-learning rate האדפטיבי כתוצאה מכמות הנתונים המוגבלת בתחילת האימון. הדרך בה (Rectified Adam)-RAdam פותר את הבעיה היא על ידי תיקון (Rectified) השונות של ה-learning rate האדפטיבי על סמך הגרדיאנטים.

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

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

איך בוחרים learning rate?

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

מקור 

לא חייבים לדבוק באותו learning rate לאורך כל האימון. מומלץ לרוב להקטין את ה-learning rate לאורך האימון ובכך לשלב בין היתרונות של קצב לימוד מהיר ואיטי. הקטנת ה -learning rate מקובלת לרוב בשימוש ב-SGD ופחות באלגוריתמים אדפטיבים שבהם שינוי ה-learning rate כבר נמצא באלגוריתם. בנוסף learning rate נמוך בתחילת האימון, warm-up, יכול להועיל, כפי שציינו קודם.

LookAhead

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

מתוך מאמר LookAhead

 

במה משתמשים בפועל?

נכון להיום השיטות הנפוצות ביותר הם Adam שמתכנס מהר ו-SGD עם מומנטום ו-learning rate decay משמש בדרך כלל עבור SOTA אבל דורש fine tuning. בין השיטות החדישות היום שנותנות תוצאות טובות ניתן למצוא את Ranger אופטימיזר שמשלב את RAdam עם LookAhead. כל אחד מהם מטפל בהיבטים שונים של אופטימיזציה. RAdam מייצב אימונים ההתחלתיים, ו-LookAhead מייצב את האימונים הבאים, מבצע אקספלורציה מזרז את תהליך ההתכנסות.

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

שאלות אפשריות לראיונות עבודה:

איך עובד backpropagation?

אילו שיטות אופטימיזציה לאימון רשתות אתה מכיר? ‍

כיצד משתמשים ב-SGD לאימוני רשת עצבית? ‍

מה היתרונות בשימוש במיני באצ’ים ב-gradient descent?

איך עובד Adam? מה ההבדל העיקרי בינו לבין SGD? ‍

למה לעיתים קרובות ל-Adam יש לוס נמוך יותר אבל SGD נותן תוצאות יותר טובות על ה-test ?
‍מה זה learning rate?

מה קורה כשה-learning rate גדול מדי? קטן מדי?

מה עדיף learning rate קבוע או משתנה לאורך האימון?

איך מחליטים מתי להפסיק לאמן רשת עצבית? 

מה זה model checkpointing?

חומר נוסף:

Gradient Descent Intuition Andrew Ng

Stochastic Gradient Descent  Andrew Ng 

cs231n Stanford Lecture 7

Ranger

Posted by Ayelet Sapirshtein in deep

5 שאלות על פונקציות אקטיבציה שעלולות להופיע בראיון העבודה הבא שלך

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Ayelet Sapirshtein

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

מדוע משתמשים בפונקציות אקטיבציה לא לינאריות?

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

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

z^{[1]}=W^{[1]}x+b^{[1]}

נשתמש בפונקציית הזהות בתור פונקציית אקטיבציה:

a^{[1]}=id\left ( z^{[1]} \right )=W^{[1]}x+b^{[1]}

נחשב את האקטיבציה של השכבה הבאה: 

z^{[2]}=W^{[2]}a^{[1]}+b^{[2]}

\inline a^{[2]}&=id\left ( \right z^{[2]})=W^{[2]}a^{[1]}+b^{[2]} =W^{[2]}\left ( W^{[1]}x+b^{[1]}\right )+b^{[2]} =\left (W^{[2]}W^{[1]}\right )x+\left ( W^{[2]}b^{[1]}+b^{[2]} \right )=\acute{W}x+\acute{b}

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

פונקציית האקטיבציה הראשונה שהייתה בשימוש ברשתות הייתה סיגמואיד 

סיגמואיד:

 

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

Saturation (רוויה)- הרוויה הורגת את הגרדיאנט. כאשר השיפוע מתיישר הגרדיאנט שואף ל-0 ולכן פעפוע לאחור לא יוכל לעדכן את המשקלים.

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

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

חישוב האקספוננט לוקח זמן רב 

כדי לפתור את הבעייה שנוצרה מכך שסיגמואיד לא ממורכז סביב ה-0 עברו להשתמש בפונקציית tanh.

(טנגנס היפרבולי) tanh

 tanh מתנהגת כמו סיגמואיד שעבר הזזה והכפלה בקבוע. גרסה אחרת של tanh נראית כך: tanh(x)=2\sigma(x)-1. tanh ממורכזת סביב ה-0 מכווץ את המספרים לטווח של [1,1-].

Saturation (רוויה)-  בדומה לסיגמואיד tanh סובל מבעייה של דעיכת גרדיאנטים (vanishing gradient) בגלל רוויה.

חישוב tanh לוקח זמן רב 

כיום tanh שימושי בעיקר עבור רשתות rnn.

ReLU

AlexNet הייתה הרשת הראשונה שהחליפה את פונקציית האקטיבציה ל-ReLU, וגרמה לרשת להתכנס פי 6 יותר מהר.

ReLU מהיר לחישוב ביחס לסיגמואיד ו-tanh.

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

 

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

Leaky ReLU

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

Maxout

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

ELU

 

חישוב אקספוננט לוקח זמן רב.

 ELU ו-MaxOut נמצאים בשימוש רק לעיתים רחוקות, מפני שאין עדיות חד משמעיות שהן עובדות טוב יותר מReLU והן יותר יקרות מבחינה חישובית. נראה שאין עדויות חד משמעיות לכך שפונקציות שלא מגיעת לרוויה כמו ELU ,MaxOut או Leaky ReLU משפרות תוצאות, אז נשאלת השאלה איך בכל זאת נוכל למנוע מנוירונים למות?

מה אפשר לעשות כדי למנוע מנוירונים ברשת למות ?

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

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

עם זאת בחירת learning rate נמוך מדי יאט את קצב ההתכנסות.
דרכים נוספות כדי למנוע מנוירונים למות הן pruning או dropout, ו-batch normalization.

מתכוננים לראיונות עבודה? ענו על השאלות הבאות בנושא:

  1. מדוע אנחנו זקוקים לפונקציות אקטיבציה?
  2. כתוב את פונקציית סיגמואיד ושרטט אותה?
  3. מה הנגזרת של פונקציית סיגמואיד?
  4. מה הבעיות בשימוש בפונקציית סיגמואיד בתור פונקציית אקטיבציה?
  5. מה גורם לתופעת ה vanishing gradient ברשתות, ובאילו דרכים אפשר להתמודד איתה?

כתבו את תשובותיכם בתגובות וקבלו מאיתנו פידבק. תפגיזו בראיונות!

מקורות:

046003, Spring 2019 טכניון
cs231n_2019  7 מצגת

Activation Functions (C1W3L06)

Why Non-linear Activation Functions (C1W3L07)

Lecture 0204 Gradient descent in practice II: Learning rate

 

 

Posted by Ayelet Sapirshtein in deep

על דיאגרמת וורונוי, ואיך היית נראה בתור קורי עכביש?

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Ayelet Sapirshtein

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

                                                                                     אחרי                                                                                                          לפני

תודה ל Photo by Alexandre Debiève on Unsplash

מהי דיאגרמת וורונוי?

בלונדון של 1854 התפרצות כולרה הרגה 10% מהאוכלוסייה. הרופאים של אותה תקופה חשבו שהמחלה מופצת על ידי “אוויר רע” הנובע מהביוב הפתוח המסריח. אבל לרופא אחד, ג’ון סנואו, האמין שהמשאבה הספציפית שברחוב ברוד היא מקור המחלה.

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

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

מי אמר שלא היה DataSciense פעם 🙂

תודה ל – https://plus.maths.org/content/uncovering-cause-cholera

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

תודה ל – Balu Ertl wikipedia

לחובבי האלגוריתמים – איך מחשבים דיאגרמת וורונוי ?

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

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

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

 

Connecting the triangulation's circumcenters gives the Voronoi diagram.

תודה ל -Hferee

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

כיוון שכך, ניתן לחשב את דיאגרמת וורונוי באמצעות אלגוריתמים למציאת טריאנגולציית דלאוני כמו Bowyer–Watson .Bowyer–Watson הוא אלגוריתם אינקרמנטלי. האלגוריתם מתבצע על ידי הוספת נקודה אחת בכל פעם ומעדכן את הטרנגולצייה של תת הקבוצה לאחר כל הוספה. זמן הריצה הממוצע של האלגוריתם הוא O(n\cdot log\left ( n \right )), אך קיימים מקרים בהם זמן הריצה גדול מO(n^{2}).

ויש גם אלגוריתמים יעילים למציאת דיאגרמת וורונוי ללא קשר לבעיה הדואלית. למשל בעזרת אלגוריתם שנקרא פורצ’ן (Fortune’s algorithm) ניתן למצוא את דיאגרמת וורונוי של n מרכזים בזמן O(n\cdot log\left ( n \right )) :

By Mnbayazit – https://en.wikipedia.org/wiki/File:Fortunes-algorithm.gif, Public Domain, https://commons.wikimedia.org/w/index.php?curid=32553992

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

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

בכל אופן כפי שתראו בקוד שלי אני משתמשת בפונקציה מוכנה של scipy.

איך זה עוזר לי להפוך לספיידרמן?

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

בוחרים תמונה ובשלב ראשון הופכים אותה לגווני אפור:

Photo by Alexandre Debiève on Unsplash

להלן מימוש בפייתון:

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

בתמונות עם אזורים כהים ברקע, עדיף להסיר קודם את הרקע.

שומרים במערך את הקורדינטות של הנקודות השחורות בתמונה:

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

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

וקיבלנו עכביש מקורי עכביש:

לסיום

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


[fvplayer id=”1″]

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

רוצים לשמוע יותר על ציור בעזרת מתמטיקה? בואו להרצאה איך מציירים מתמטיקה.

Posted by Ayelet Sapirshtein in deep

ערוכים לזה: עריכת וידאו בעזרת AI

מיועד ל- מתחילים (כתבה קצת טכנית)

נכתב על ידי Ayelet Sapirshtein

“מחקר בן שנתיים קובע שלמידה אורכת זמן כפול כשהטלוויזיה דלוקה. המחקר היה אמור לארוך רק שנה, אבל הטלוויזיה הייתה דלוקה.”- ג’יי לנו

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

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

להלן דוגמה של וידאו מקורי ומשעמם באורך 1:25 (הלקוח מאגר וידאוים לבעיית התימצות: tvsum)

ולהלן הוידאו המתומצת שלו באורך 12 שניות כפלט מאלגוריתם הזה (רק שיניתי אותו בזה שהחלפתי את הרשת שמקודדים איתה את הפריימים inception v3 במקוםinception v1)

איך קובעים את מידת החשיבות של פריים?

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

איך יוצרים רשת שמדרגת את החשיבות של כל פריים?

בניגוד לתמונה, רמת העניין של פריים תלויה ברצף הפריימים ומיקומו בתוך הוידאו. בשביל לתת ביטוי למיקום הפריים ברצף, משתמשים ברשתות נוירונים ממשפחת (Recurrent Neural Network (RNN או Self-Attention אשר נועדו לפענח מידע סדרתי. רשתות אלו יכולות לקבל מידע סדרתי בכל אורך, לצורך עניינינו סרטונים עם מספר פריימים שונה. בנוסף לכך הן כוללות מרכיב של זיכרון – כך שהרשת “יודעת להתחשב” בהיסטוריה.

רשת RNN בסיסית

תודה ל https://en.wikipedia.org/wiki/Recurrent_neural_network#/media/File:Recurrent_neural_network_unfold.svg

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

Xt הוא הקלט ה-t ברצף הזמן, במקרה שלנו הפריים ה -t

ht הוא מצב נסתר (hidden state) בזמן t, ה”זיכרון” של הרשת. ht מחושב על סמך המצב הנסתר הקודם (ht-1) והקלט בשלב הנוכחי (Xt).

ot הפלט של זמן t, במקרה שלנו התחזית של הרשת לגבי כמה מעניין הפריים ה-t.

בעיות זיכרון

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

  1. Down-Sampling לסרטון. במקום להתחשב ב-30 פריימים לשנייה אפשר להסתכל רק על 2, תחת ההנחה שאין הבדל גדול בין פריימים עוקבים.
  2. במקום לקחת את הפריימים עצמם, מתמצתים את המידע שנמצא בתמונה. דבר זה מתבצע על ידי הוצאת מאפיינים בעזרת רשתות קונבולוציה (CNN) שאומנו למטרות סיווג תמונות (כגון VGG, GoogLeNet, ResNet)

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

איך בוחרים אילו מקטעים לקחת? (בעיית תרמיל הגב)

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

בעייה זו שקולה לבעייה מפורסמת מאוד במדעי המחשב שנקראת בעיית תרמיל הגב (Knapsack problem) .

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

בעייה זו מוגדרת כבעייה np-קשה, עם זאת, כאשר משקלי כל הפריטים שלמים, ניתן לפתור אותה בעזרת תכנון דינאמי בסיבוכיות זמן (O(Wn, כאשר W הוא המשקל המירבי שניתן לסחוב ו-n כמות הפריטים. במקרה שלנו המשקלים הם מספר הפריימים בכל מקטע, כלומר מספרים שלמים.

איך אומדים את טיב הסרטון?

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

Recall = TP/(TP+FN)

 וב-

Precision = TP/(TP+FP)

כאשר TP=True Positive זה כשהאלגוריתם חזה שהקטע מעניין וצדק

ו FN=False Negative זה כשהאלגוריתם חזה שהקטע לא מעניין וטעה

ו FP=False Positive זה כשהאלגוריתם חזה שהקטע מעניין וטעה.

תודה ל https://en.wikipedia.org/wiki/F1_score#/media/File:Precisionrecall.svg

 מדד  F-score  מוגדר באופן הבא:

סיכום

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

  1. מייצגים כל פריים על ידי וקטור פיצ’רים, באמצעות רשת קונבולוציה.
  2. מחלקים את הוידאו לסצנות באמצעות אלגוריתם למציאת נק’ שינוי המקבל כקלט את וקטורי הפיצ’רים של הפריימים
  3. מורידים את ה-(fps (frame per second של הסרטון
  4. מכניסים את וקטורי הפיצ’רים לרשת מבוססת RNN שמחזירה את החשיבות של כל פריים.
  5. משתמשים בתכנון דינאמי לבעיית תרמיל הגב בשביל לבחור אילו מקטעים להכניס לסרט המקוצר בהתאם להגבלת אורך שהגדרנו.

הפוסט מבוסס ברובו על האלגוריתם המוצע במאמר Summarizing Videos with Attention שמבצע למידה מונחית (supervised)

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

קישורים

Posted by Ayelet Sapirshtein in deep