מדריך להתפתחות 4j

1. הקדמה

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

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

2. מהי למידה עמוקה?

רשתות עצביות הן מודלים חישוביים המורכבים משכבות צמתים מקושרות זו בזו.

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

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

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

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

3. הגדרת הפרויקט

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

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

$ java- גרסת Java גרסה "1.8.0_131" Java (TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot (TM) 64-bit Server Server (build 25.131-b11, מצב מעורב)

ראשית, בואו נוסיף את הספריות הנדרשות ל- Maven שלנו pom.xml קוֹבֶץ. אנו נחלץ את גרסת הספרייה לערך נכס (לקבלת הגרסה האחרונה של הספריות, עיין במאגר Maven Central):

 0.9.1 org.nd4j nd4j-native-platform $ {dl4j.version} org.deeplearning4j deeplearning4j-core $ {dl4j.version} 

ציין זאת nd4j-native-platform תלות היא אחת ממספר היישומים הזמינים.

זה מסתמך על ספריות מקומיות הזמינות לפלטפורמות רבות ושונות (MacOS, Windows, Linux, Android וכו '). נוכל גם להחליף את ה- backend ל- nd4j-cuda-8.0 פלטפורמה, אם היינו רוצים לבצע חישובים בכרטיס גרפי התומך במודל תכנות CUDA.

4. הכנת הנתונים

4.1. הכנת קובץ DataSet

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

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

אנו נשתמש בגרסת CSV של נתונים אלה, כאשר העמודות 0..3 מכילות את התכונות השונות של המין ועמודה 4 מכילה את המחלקה של הרשומה, או את המין, המקודד לערך 0, 1 או 2:

5.1,3.5,1.4,0.2,0 4.9,3.0,1.4,0.2,0 4.7,3.2,1.3,0.2,0 … 7.0,3.2,4.7,1.4,1 6.4,3.2,4.5,1.5,1 6.9,3.1,4.9,1.5,1 …

4.2. וקטורציה וקריאת הנתונים

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

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

נסה (RecordReader recordReader = CSVRecordReader חדש (0, ',')) {recordReader.initialize (FileSplit חדש (ClassPathResource חדש ("iris.txt"). getFile ())); // ...}

כדי לחזור על הרשומות, אנו יכולים להשתמש בכל אחת מהיישומים המרובים של ה- DataSetIterator מִמְשָׁק. מערכי הנתונים יכולים להיות מסיביים למדי, והיכולת לדף או לשמור את הערכים במטמון יכולה להיות שימושית.

אך מערך הנתונים הקטן שלנו מכיל רק 150 רשומות, אז בואו נקרא את כל הנתונים בזיכרון בבת אחת עם שיחה של iterator.next ().

אנו מציינים גם את אינדקס העמודה בכיתה שבמקרה שלנו זהה לספירת תכונות (4) ומספר השיעורים הכולל (3).

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

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

DataSetIterator iterator = RecordReaderDataSetIterator חדש (recordReader, 150, FEATURES_COUNT, CLASSES_COUNT); DataSet allData = iterator.next (); allData.shuffle (42);

4.3. מנרמל ומתפצל

דבר נוסף שעלינו לעשות עם הנתונים לפני האימון הוא לנרמל אותם. הנורמליזציה היא תהליך דו-שלבי:

  • איסוף נתונים סטטיסטיים אודות הנתונים (התאמה)
  • שינוי (שינוי) הנתונים בדרך כלשהי כדי להפוך אותם לאחידים

הנורמליזציה עשויה להיות שונה בסוגים שונים של נתונים.

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

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

מנרמל DataNormalization = NormalizerStandardize חדש (); normalizer.fit (allData); normalizer.transform (allData);

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

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

זה יאפשר לנו לאמת שהסיווג עובד כהלכה. ניקח 65% מהנתונים (0.65) לאימון ונשאיר את השאר 35% לבדיקה:

SplitTestAndTrain testAndTrain = allData.splitTestAndTrain (0.65); DataSet trainingData = testAndTrain.getTrain (); DataSet testData = testAndTrain.getTest ();

5. הכנת תצורת הרשת

5.1. בונה תצורה שוטף

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

תצורת MultiLayerConfiguration = NeuralNetConfiguration.Builder () .iterations (1000) .activation (Activation.TANH) .weightInit (WeightInit.XAVIER) .learningRate (0.1). Regularization (true) .l2 (0.0001) .list () .layer ( 0, DenseLayer.Builder חדש (). NIn (FEATURES_COUNT) .nOut (3) .build ()). שכבה (1, DenseLayer.Builder חדש (). NIn (3) .nOut (3) .build ()). שכבה (2, OutputLayer.Builder חדש (LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD). activation (Activation.SOFTMAX) .nIn (3) .nOut (CLASSES_COUNT) .build ()). backprop (true). pretrain (false) .build (building). );

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

5.2. הגדרת פרמטרים ברשת

ה חזרות () שיטת builder מציין את מספר חזרות האופטימיזציה.

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

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

ה הַפעָלָה() היא פונקציה הפועלת בתוך צומת כדי לקבוע את תפוקתה.

פונקציית ההפעלה הפשוטה ביותר תהיה ליניארית f (x) = x. אך מתברר שרק פונקציות לא ליניאריות מאפשרות לרשתות לפתור משימות מורכבות באמצעות כמה צמתים.

יש הרבה פונקציות הפעלה שונות שניתן לחפש ב org.nd4j.linalg.activations.Activation enum. נוכל גם לכתוב את פונקציית ההפעלה שלנו במידת הצורך. אך נשתמש בפונקציית המשיק ההיפרבולי (tanh) המסופק.

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

ניתן לחפש את כל שיטות האתחול האחרות במשקל org.deeplearning4j.nn.weights.WeightInit enum.

שיעור למידה הוא פרמטר מכריע המשפיע עמוקות על יכולת הרשת ללמוד.

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

אחת הבעיות באימון רשתות עצביות היא מקרה של התאמת יתר כאשר רשת "משננת" את נתוני ההדרכה.

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

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

5.3. בניית שכבות רשת

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

השכבה הראשונה צריכה להכיל את אותה כמות צמתים כמו העמודות בנתוני האימון (4).

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

שכבת הפלט הסופית צריכה להכיל את מספר הצמתים התואמים את מספר הכיתות (3). מבנה הרשת מוצג בתמונה:

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

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

6. יצירה והכשרה של רשת

עכשיו בואו ניצור רשת עצבית מהתצורה, נאתחל אותה ונפעיל אותה:

מודל MultiLayerNetwork = MultiLayerNetwork חדש (תצורה); model.init (); model.fit (trainingData);

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

פלט INDArray = model.output (testData.getFeatureMatrix ()); הערכת הערכה = הערכה חדשה (3); eval.eval (testData.getLabels (), פלט);

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

דוגמאות שתויגו כ- 0 מסווגות לפי דגם כ- 0: 19 פעמים דוגמאות מסומנות כ- 1 מסווגות לפי דגם כ- 1: 16 פעמים דוגמאות מסומנות כ- 1 מסווגות לפי דגם כ- 2: 3 פעמים דוגמאות מסומנות כ- 2 מסווגות לפי דגם כ- 2: 15 פעמים == ========================= ציונים =========================== ================ מספר הכיתות: 3 דיוק: 0.9434 דיוק: 0.9444 זיכרון: 0.9474 ציון F1: 0.9411 דיוק, זיכרון & F1: ממוצע ממקרו (ממוצע משוקלל שווה של 3 כיתות ) ===================================================== =========================

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

7. מסקנה

במאמר זה, בנינו רשת עצבית פשוטה אך עוצמתית באמצעות ספריית deeplearning4j.

כמו תמיד, קוד המקור של המאמר זמין באתר GitHub.


$config[zx-auto] not found$config[zx-overlay] not found