Friday, October 14, 2022

מבוא לבדיקות קסם

 

English

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

יצא לי להאזין לפרק של The testing show על בדיקות AI. הפרק היה, למרבה הצער, עוד פרק על גבול הפרסומי בו הביאו מישהי אחת לדבר על המוצר שהיא מוכרת. סליחה, על אילו אתגרים בבדיקות יש במוצר הזה. זה לא היה גרוע כמו בפעמים בהן מגיע מומחה מטעם Qualitest, אבל זה לא היה רחוק מזה. בכל מקרה, הנושא היה למידת מכונה, ומעט התוכן שהיה שם ולא היה סתם היכרות או קשקשת ידידותית, היה בעיקר חזרה על "יש פה משהו חדש לגמרי ושונה מכל מה שהכרנו עד היום, ותראו אילו אתגרים יש פה! כבר אמרתי שזה קשה?". 

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

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

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

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

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

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

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

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

  • כמה זה מטומטם? יש טענות (כמו היכולת לזהות פושעים לפי תווי פנים) שהם מספיק לא הגיוניים עד שאין צורך לחפש את הבעיה בנתונים כדי לדעת שיש אחת כזו.
  • יש מלא נאצים שם בחוץ: האם המודל ממשיך ללמוד תוך כדי שהמוצר נמצא בשטח? אם כן, עד כמה המידע שם אמין? איזה מאמץ יידרש כדי להטות את המודל בצורה שלא תמצא חן בעיני?
  • מוצא האדם מן הקוף: מניין השגנו את הנתונים עליהם אימנו ובחנו את המודל? האם הם מייצגים את המציאות שהמוצר שלנו יפגוש?
  • העולם דפוק: האם יש איזו בעיה בעולם האמיתי שהאלגוריתם שלנו מנציח? אם כשבני אדם מקבלים החלטה הם עושים את זה בצורה מוטה ומפלה, ללמד תוכנה להחליט כמונו רק ייתן להחלטה המוטה סמכות כי "המחשב החליט".
  • בוא נציק לערבים: האם התוכנה שלנו תייצר מעגל משוב מזיק? הרעיון הגיע מהספר של קת'י אוניל "Weapons of Math Destruction" שם היא מדברת על מוצרים שנועדו לעזור לכוחות משטרה (בארה"ב) לחלק את כוח האדם המוגבל שלהם בצורה אפקטיבית יותר ושלח יותר שוטרים לשכונות מוכות פשע. אלא מה? נתוני הפשיעה מגיעים ממה שהמשטרה כבר מצאה. אז גם התחלנו עם הטייה נגד שחורים, וגם עכשיו נמשיך למצוא יותר פשיעה בשכונות האלה, כי מי שנוהג שיכור בשכונה אחרת פשוט לא ייתפס באותה מידה, אז נמשיך לשלוח שוטרים לאותן שכונות ולמצוא בהן יותר פשעים משכונות אחרות. 
  • אל תשאל, לא תשמע שקרים: האם התוכנה שלנו משתמשת במידע אסור כדי לקבל החלטות? אם נחזור לסינון קורות החיים, אנחנו אולי חושבים שהתוכנה לא תפסול מועמדים רק כי הם השתחררו מצה"ל בדרגת רס"ן וטוחנים מילואים, אבל עם מספיק קורות חיים היא תמצא סימנים מקשרים (למשל, לימודים באמצע השירות הצבאי או כניסה מאוחרת לשוק העבודה) שיאפשרו לזהות מי קצין בכיר גם בלי שזה יהיה כתוב באופן מפורש. אם המודל שלנו סתום, הצלחה לנו עם למצוא את זה. 

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

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

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

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

No comments:

Post a Comment