צייר לי 4 – חלק שני: האם זה נקניקייה?

צייר לי 4 – חלק שני: האם זה נקניקייה?

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

מדריך ההייטקיסט לגלקסיה, מהדורה 7.983, 3021

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

בניית המודל

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

במקרה שלנו אנחנו מעוניינים לבנות וקטור המייצג תמונה (נשטח את ה28×28 פיקסלים לוקטור של 784) כאשר 0 מייצג שחור ו 1 מייצג לבן וכל פיקסל יכול לקבל כל מספר בדרך. לאחר מכן נאסוף הרבה דוגמאות שונות (לדוגמא 10,000) מתוכם 2,000 יהיו של ציורים של 4 והשאר יהיו ציורים של ספרות אחרות או סתם שרבוטים חסרי פשר. נחלק את הדוגמאות לשתי קבוצות קבוצת האימון וקבוצת הבדיקה. נאמן את המודל על קבוצת האימון ובעזרת קבוצת הבדיקה נעריך עד כמה המודל שלנו מצליח לזהות את הספרה 4 בעולם האמיתי.

לצורך כך אנחנו צריכים הרבה ציורים של 4 ולא של 4 מאיפה נאסוף אותם?

יצירת המדגם 

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

אני בחרתי להשתמש באוטומציה של דפדפן בפרויקט puppeteer המשתמש ב chromedriver כך שבעזרת קצת html+css וקוד js – שדווקא רץ בNode.js מחוץ לדפדפן אני יכול לייצר במהירות את התמונות הנדרשות. ראשית יצרתי קובץ html פשוט אליו הוספתי קובץ css המכיל 1317 פונטים חינמיים של גוגל (השתמשתי בסיפרייה honeysilvas/google-fonts כדי רשימה גדולה של גוגל פונטס ולהכין את הcss). לאחר מכן כתבתי סקריפט קצר שרץ בלולאה על הפונטים והתווים השונים (וגם משחק מעט בזווית שלהם) שומר את התוצאות בקובץ תמונה הרזולוציה נמוכה של 28×28. ובסוף כדי לשפר את המדגם יצרתי כמה אלפי תמונות שהם סתם שירבוטים של 3 קווים רנדומליים ותייגתי אותם כ״לא 4״.

לאחר מכן יצרתי 2 קבצים המתייגים את כל התמונות כאשר קובץ אחד מכיל את הרשימה של כל התמונות של ה4 והרשימה השנייה מכילה את כל התמונות שהם לא 4.

אימון המודל

את המודל עצמו אימנתי באופן דומה למודל שמאמן את MINST (דאטהסט המכיל 70,000 דוגמאות של הספרות 0-9 בכתב יד), בניסיון הראשון שלי ניסיתי פשוט להשתמש במודל הזה אבל במקרה שלי (פונט של שלוש קווים) היו ממש ממש גרועים.

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

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

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

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

נבנה את המודל ונתאמן עליו (האימון לוקח בין 5-20 דקות תלוי בחוזק של המחשב ובמספר האיטרציות שנבחרו)

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

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

נוח מאוד לבנות מודלים במחברות של jupyter שכן לא צריך לטעון את כל המידע מחדש בכל פעם שמשנים קונפיגורציה של המודל. (והכי נוח זה לעבוד בjupyter מתוך vs-code משלב את היתרונות של המחברת עם ההשלמות האוטומטיות והנוחות של editor מודרני).

שימוש במודל

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

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

תוצאות

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

עמוד רנדומאלי של תוצאות

האלגוריתם יצר אלפי תמונות אך רק בערך 10% מהם הזכירו את הספרה 4 כאשר חלקם היו ייצוג הפוך או מסובב של הספרה. לא התייאשתי והרצתי בדיקה של כלי OCR של גוגל בשם tesseract שיש לו את היכולת לזהות אות בודדת ולהגיד עד כמה הוא בטוח בזיהוי. בעזרת כלי זה בחרתי רק את התוצאות שגם בכלי זה קיבלו את הזיהוי של 4 ומיינתי אותם לפי הסדר:

תוצאות מפולטרות וממויינות בעזרת tesseract

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

Cherry picking

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

making 4 in action

רעיונות לעתיד

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

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

כרגיל, הקוד שהשתמשתי בו זמין לצפייה בgithub.

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

*