רשת עצבית לסיווג עם Tensorflow

צומת המקור: 1570297

מאמר זה פורסם כחלק מה- בלוגאת מדע הנתונים

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

האם רשת עצבית?

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

מהו סיווג?

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

סוגי סיווג

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

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

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

ייבוא ​​numpy בתור np
לייבא פנדות כ-pd
ייבא matplotlib.pyplot בתור plt
יבוא tensorflow כ-tf
print(tf.__version__)

יצירת מערך נתונים

הגיע הזמן ליצור מערך נתונים לעבודה עליו:

מ-sklearn.datasets ייבוא ​​make_circles דוגמאות = 1000
X, y = make_circles(דגימות, רעש = 0.03, מצב_אקראי = 42)

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

print(X
>>[[ 0.75424625 0.23148074] [-0.75615888 0.15325888] [-0.81539193 0.17328203] ... [-0.13690036 -0.81001183 -0.67036156 -0.76750154] 0.28105665 0.96382443]]
print(y) >> [1 1 1 1 0 1 1 1 1 0]

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

circle = pd.DataFrame({ 'X0' : X[:, 0], 'X1' : X[:, 1], 'label' : y})
circle.head()
רשת עצבית לסיווג עם ראש נתונים של Tensorflow

כאן עולה שאלה אחת, עם איזה סוג של תוויות יש לנו עסק?

circle.label.value_counts()
>> 1 500 0 500 שם: תווית, dtype: int64

נראה שיש לנו עסק עם בעיית סיווג בינארי, כי יש לנו 2 תוויות (0 ו-1).

plt.scatter(X[:,0], X[:,1], c = y, cmap = plt.cm.RdYlBu)
רשת עצבית לסיווג עם עלילת פיזור Tensorflow

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

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

print(X.shape, y.shape)
print(len(X), len(y))
>> (1000, 2) (1000,) 1000 1000

יש לנו אותה כמות של ערכים עבור כל תכונה, אבל הצורה של X שונה? למה? בוא נבדוק את זה.

X[0], y[0]
>> (מערך([0.75424625, 0.23148074]), 1)

אוקיי, יש לנו 2 תכונות X למשך שנה אחת. אז נוכל להתקדם בלי שום בעיה.

שלבים בעיצוב רשת עצבית לסיווג עם Tensorflow

ב-TensorFlow ישנם שלבים קבועים ליצירת מודל:

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

אנו נשתמש ב-Sequential API. אז בואו נתחיל

tf.random.set_seed(42)
model_1 = tf.keras.Sequential([tf.keras.layers.Dense(1)])

model_1.compile(loss = tf.keras.losses.BinaryCrossentropy(),

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

 optimizer = tf.keras.optimizers.SGD(), ‎#SGD מייצג מדדי ירידה בדרגה סטוקהסטית = ['דיוק']) model_1.fit(X, y, epochs = 5)
>> עידן 1/5 32/32 [=========================================] - 1 שניות 1ms/צעד - הפסד: 2.8544 - דיוק: 0.4600 עידן 2/5 32/32 [=========================================] - 0 שניות 2ms/צעד - הפסד : 0.7131 - דיוק: 0.5430 עידן 3/5 32/32 [========================================================================================================= - הפסד: 0 - דיוק: 2 פרק 0.6973/0.5090 4/5 [================================================================================ /שלב - הפסד: 32 - דיוק: 32 עידן 0/2 0.6950/0.5010 [=========================================== 5s 5ms/צעד - הפסד: 32 - דיוק: 32

הדיוק של הדגם הוא בערך 50% מה שבעצם אומר שהדגם רק מנחש, בואו ננסה לאמן אותו יותר זמן

model_1.fit(X, y, epochs = 200, verbose = 0) #הגדרנו verbose = 0 כדי להסיר את הליך ההדרכה )
model_1.evaluate(X, y)
>> 32/32 [=====================================] - 0 שניות 1ms/צעד - הפסד: 0.6935 - דיוק: 0.5000 [0.6934829950332642, 0.5]

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

tf.random.set_seed(42)
model_2 = tf.keras.Sequential([ tf.keras.layers.Dense(1), tf.keras.layers.Dense(1) ]) model_2.compile(loss = tf.keras.losses.BinaryCrossentropy(), אופטימיזציה = tf.keras.optimizers.SGD(), מדדים = ['דיוק']) model_2.fit(X, y, epochs = 100, מילולית = 0)
 model_2.evaluate(X,y)
>> 32/32 [=====================================] - 0 שניות 1ms/צעד - הפסד: 0.6933 - דיוק: 0.5000 [0.6933314800262451, 0.5]

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

שיפור מודל הרשת העצבית לסיווג עם Tensorflow

ישנן דרכים שונות לשיפור מודל בשלבים שונים:

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

בואו ננסה להוסיף נוירונים נוספים ונסה אדם מייעל

tf.random.set_seed(42)
model_3 = tf.keras.Sequential([ tf.keras.layers.Dense(100), # הוסף 100 נוירונים צפופים tf.keras.layers.Dense(10), # הוסף שכבה נוספת עם 10 נוירונים tf.keras.layers.Dense (1) ]) model_3.compile(loss=tf.keras.losses.BinaryCrossentropy(), optimizer=tf.keras.optimizers.Adam(), metrics=['accuracy']) model_3.fit(X, y, epochs =100, מילולי=0)
model_3.evaluate(X,y)
>> 32/32 [=====================================] - 0 שניות 1ms/צעד - הפסד: 0.6980 - דיוק: 0.5080 [0.6980254650115967, 0.5080000162124634]

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

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

כדי להמחיש את התחזיות של המודל שלנו, ניצור פונקציה plot_decision_boundary() אשר:

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

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

CS231n עשוי עם יסודות ML 

def plot_decision_boundary(model, X, y): # הגדר את גבולות הציר של העלילה וצור רשת רשת x_min, x_max = X[:, 0].min() - 0.1, X[:, 0].max() + 0.1 y_min, y_max = X[:, 1].min() - 0.1, X[:, 1].max() + 0.1 xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100), np .linspace(y_min, y_max, 100)) # צור ערכי X (אנחנו הולכים לחזות על כל אלה) x_in = np.c_[xx.ravel(), yy.ravel()] # בצע חיזויים באמצעות השיטות המאומנות model y_pred = model.predict(x_in) # בדוק אם יש ריבוי מחלקות
 if len(y_pred[0]) > 1: print("doing multiclassification...") # עלינו לעצב מחדש את התחזיות שלנו כדי להכין אותן לשרטוט y_pred = np.argmax(y_pred, axis=1).reshape( xx.shape) else: print("עושה סיווג בינארי...") y_pred = np.round(y_pred).reshape(xx.shape) # גבול החלטה עלילה plt.contourf(xx, yy, y_pred, cmap=plt. cm.RdYlBu, alpha=0.7) plt.scatter(X[:, 0], X[:, 1], c=y, s=40, cmap=plt.cm.RdYlBu) plt.xlim(xx.min( ), xx.max()) plt.ylim(yy.min(), yy.max()) plot_decision_boundary(model_3, X, y)
גבול החלטה

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

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

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

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

A = tf.cast(tf.range(-12,12), tf.float32)
הדפס (א)
>> tf.Tensor( [-12. -11. -10. -9. -8. -7. -6. -5. -4. -3. -2. -1. 0. 1. 2. 3 4. 5. 6. 7. 8. 9. 10. 11.], shape=(24,), dtype=float32)

בואו נראה איך נראה טנזור הצעצועים שלנו?

plt.plot(A)
פונקציות הפעלה עבור רשתות עצביות

זה נראה ככה, קו ישר! 

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

סיגמואיד:

def sigmoid(x): return 1 / (1 + tf.exp(-x))
sigmoid(A)
plt.plot(sigmoid(A))‎
פונקצית sigmoid

קו לא ישר!

ReLu:

עכשיו בואו נבדוק מה ReLu עושה? Relu הופך את כל הערכים השליליים ל-0 והערכים החיוביים נשארים זהים.

def relu(x): return tf.maximum(0,x)
plt.plot(relu(A))‎
ReLu

עוד קו לא ישר!

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

X_train, y_train = X[:800], y[:800]
X_test, y_test = X[800:], y[800:]
X_train.shape, X_test.shape
>>((800, 2), (200, 2))

 

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

tf.random.set_seed(42)
model_4 = tf.keras.Sequential([ tf.keras.layers.Dense(4, activation = 'relu'), #ייתכן שנתקן את זה גם "tf.keras.activations.relu" tf.keras.layers.Dense(4 , activation = 'relu'), tf.keras.layers.Dense(1, activation = 'sigmoid') ]) model_4.compile( loss= tf.keras.losses.binary_crossentropy, optimizer = tf.keras.optimizers.Adam( lr = 0.01), מדדים = ['דיוק']) model_4.fit(X_train, y_train, epochs = 25, מילולית = 0)

הערך את המודל

הפסד, דיוק = model_4.evaluate(X_test, y_test)
print(f' אובדן דגם בערכת הבדיקה: {loss}')
print(f' דיוק הדגם בערכת הבדיקה: {100*דיוק}')
>> 7/7 [===============================] - 0 שניות 2ms/צעד - הפסד: 0.1247 - דיוק: 1.0000 אובדן דגם בסט הבדיקה: 0.1246885135769844 דיוק הדגם בסט הבדיקה: 100.0

וואלה! 100% דיוק! בוא נראה את התוצאה הזו חזותית

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title("רכבת")
plot_decision_boundary(model_4, X=X_train, y=y_train)
plt.subplot(1, 2, 2)
plt.title("מבחן")
plot_decision_boundary(model_4, X=X_test, y=y_test)
plt.show()
רשת עצבית בינארית לסיווג עם Tensorflow

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

סיכום

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

אני מקווה שהמאמר היה קצת מועיל לך ותרם כמה תרומות.

המדיה המוצגת במאמר זה אינה בבעלות Analytics Vidhya ונעשה בהם שימוש לפי שיקול דעתו של המחבר

מקור: https://www.analyticsvidhya.com/blog/2021/11/neural-network-for-classification-with-tensorflow/

בול זמן:

עוד מ אנליטיקה וידיה