מבוא
אל האני יער אקראי אלגוריתם הוא אלגוריתם למידה מפוקח מבוסס עצים המשתמש במכלול של תחזיות של עצי החלטה רבים, כדי לסווג נקודת נתונים או לקבוע את הערך המשוער שלה. פירוש הדבר שניתן להשתמש בו לסיווג או רגרסיה.
כאשר הגשת בקשה לסיווג, המעמד של נקודת הנתונים נבחר על סמך המחלקה שהכי הצביעו על העצים; וכאשר מוחל על רגרסיה, הערך של נקודת הנתונים הוא הממוצע של כל הערכים המופקים על ידי העצים.
דבר שחשוב לזכור בעת שימוש ב-Random Forests הוא שמספר העצים הוא היפרפרמטר והוא יוגדר לפני הפעלת המודל.
כשעובדים במדעי הנתונים, אחת הסיבות לכך שנבחר מודל של יער אקראי לפרויקט ספציפי עשויה להיות קשורה ליכולת להסתכל על עצים מורכבים ולהבין למה נעשה סיווג, או למה ניתן ערך - זה נקרא הסבר.
בהתחשב באלגוריתמים מבוססי עצים, הניסיון להסביר מודל יכול לעשות בכמה דרכים, על ידי הצגה והסתכלות על כל עץ (יכול להיות קשה אם המודל מכיל 200 עצים או יותר), באמצעות ערכי Shapley (או SHAP)., תוך הסתכלות על התכונות שנלקחו הכי הרבה בחשבון על ידי המודל, באמצעות ליים כדי לחקור את הקשרים בין קלט ותפוקה של המודל וכו'. בדרך כלל, נעשה שימוש בשילוב של כל השיטות.
במדריך המהיר הזה, נתמקד ביצירת תרשים של התכונות שנחשבו חשובות עבור המודל כדי לקבל החלטה בעת סיווג פינגווינים. זה ידוע בתור חקירת חשיבות תכונה, וניתן להעביר אותו לחברים אחרים בצוות (טכניים ולא טכניים) כדי להציע הצצה לאופן קבלת ההחלטות.
לשם כך, בואו לייבא את הספריות הדרושות, לטעון את מערך הנתונים של Palmer Penguins, לפצל את הנתונים, ליצור את המודל, לקבל את חשיבות התכונות, ולהשתמש ב- Seaborn כדי לשרטט אותם! לא נתעמק הרבה בנתונים, ב-EDA או במודל עצמו - אלה הם הנושא של המדריך הייעודי.
הערה: אתה יכול להוריד את מערך הנתונים מ GitHub או ישירות מהקוד.
יבוא ספריות
נתחיל בייבוא מספר ספריות שבהן נשתמש:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
raw_data_url = "https://gist.githubusercontent.com/cassiasamp/197b4e070f5f4da890ca4d226d088d1f/raw/38c9d4906ed121481b4dc201fa2004f2b3d0065f/penguins.csv"
df = pd.read_csv(raw_data_url)
פיצול הנתונים
בואו נחלק את הנתונים לאימון ובדיקה:
df = df.dropna().drop("rowid", axis=1)
y = df["species"]
X = df[["bill_length_mm", "bill_depth_mm", "flipper_length_mm"]]
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
השגת חשיבות תכונה
לבסוף - אנו יכולים לאמן מודל ולייצא את חשיבות התכונות באמצעות:
rf = RandomForestClassifier()
rf.fit(X_train, y_train)
rf.feature_importances_
תפוקות אלה:
array([0.41267633, 0.30107056, 0.28625311])
אלו הם ערכי התכונה, כדי לראות שמות תכונה, הפעל:
rf.feature_names_in_
זה מביא לשם התואם של כל תכונה:
array(['bill_length_mm', 'bill_depth_mm', 'flipper_length_mm'],
dtype=object)
זה אומר שהתכונה החשובה ביותר להחלטה על שיעורי פינגווין עבור הדגם המסוים הזה הייתה bill_length_mm
!
החשיבות היא יחסית למדד עד כמה הנתונים מופרדים בכל פיצול צומת - במקרה זה, המידה ניתנת על ידי ה- אינדקס ג'יני - ערך הג'יני משוקלל לפי מספר השורות שפוצלו בעת השימוש ב- bill_length_mm
תכונה וממוצע של מעל 100 העצים בהרכב. התוצאה של הצעדים הללו מסבירה 0.41267633
, או יותר מ-40% במקרה זה.
הדמיית חשיבות התכונה
דרך נפוצה לייצוג ערכי חשיבות היא באמצעות צ'אטים בבר. בואו ניצור תחילה מסגרת נתונים עם שמות התכונות והחשיבות המתאימות שלהן, ולאחר מכן נראה אותן באמצעות ה-Seaborn's barplot()
:
importances_df = pd.DataFrame({"feature_names" : rf.feature_names_in_,
"importances" : rf.feature_importances_})
g = sns.barplot(x=importances_df["feature_names"],
y=importances_df["importances"])
g.set_title("Feature importances", fontsize=14);
עֵצָה: תרגול טוב בעת הצגת מידע הוא סדר ערכים בסדר עולה או יורד. במקרה זה, הנתונים כבר מסודרים, כאשר הערך הראשון הוא הראשון שאנו רוצים לדעת. כאשר זה לא המקרה, אתה יכול להזמין את מסגרת הנתונים עם sort_values
. ניתן לעשות זאת בכל עמודה בסדר עולה או יורד: importances_df.sort_values(by="importances", ascending=False)
.
כשמסתכלים על העלילה הראשונה הזו, קשה יותר לפרש את הערך של חשיבותה של כל תכונה. ברור שאורך השטר גדול יותר משני הפסים האחרים, אבל לא בדיוק bill_depth_mm
שווה 0.30107056
, וכי flipper_length_mm
הוא 0.28625311. אז, ניתן לשפר את התרשים הראשון הזה על ידי הצגת הערך של כל סרגל. ניתן לעשות זאת על ידי גישה אל Seaborn's containers
לְהִתְנַגֵד. הוא מאחסן מידע על כל סרגל ומעביר את הערכים בתור תוויות סרגל:
עיין במדריך המעשי והמעשי שלנו ללימוד Git, עם שיטות עבודה מומלצות, סטנדרטים מקובלים בתעשייה ודף רמאות כלול. תפסיק לגוגל פקודות Git ולמעשה ללמוד זה!
g = sns.barplot(data=importances_df,
x="importances",
y="feature_names")
g.set_title("Feature importances", fontsize=14)
for value in g.containers:
g.bar_label(value)
כעת, אנו יכולים לראות כל ערך חשיבות בבירור, או כמעט בבירור, כי bill_length_mm
הערך נחתך על ידי קו אנכי המהווה חלק מהגבול החיצוני של התרשימים. גבולות משמשים כדי להקיף אזור כאמצעי למקד בו יותר תשומת לב, אבל במקרה זה, אנחנו לא צריכים להקיף, כי יש רק גרף אחד. בואו נסיר את הגבול ונשפר את קריאות המספרים:
g = sns.barplot(data=importances_df,
x="importances",
y="feature_names")
sns.despine(bottom=True, left=True)
g.set_title("Feature importances", fontsize=14)
for value in g.containers:
g.bar_label(value)
נראה שהתרשים קל יותר לקריאה, אבל נראה שהתיקיות על ציר ה-X צפות וכבר יש לנו את הערכים יחד עם הפסים, כך שנוכל להסיר את xticks
:
g = sns.barplot(data=importances_df,
x="importances",
y="feature_names")
sns.despine(bottom=True, left=True)
g.set(xticks=[])
g.set_title("Feature importances", fontsize=14)
for value in g.containers:
g.bar_label(value)
שימו לב כיצד לאחר הסרת הקרציות, התוויות Y ו-X מעט קשות לקריאה. תווית Y, feature_names
, הוא אנכי ובציר X, יש רק importances
. מכיוון שהכותרת כבר מציינת שהתרשים הוא של חשיבות תכונה, נוכל גם להסיר את תוויות הציר:
g = sns.barplot(data=importances_df,
x="importances",
y="feature_names")
sns.despine(bottom=True, left=True)
g.set_title("Feature importances", fontsize=14)
g.set(xticks=[])
g.set(xlabel=None)
g.set(ylabel=None)
for value in g.containers:
g.bar_label(value)
אתה יכול לראות כיצד התרשים הזה נקי יותר, קל לקריאה והבנה בהשוואה לתרשים הראשון. יש עדיין כמה דברים שאנחנו יכולים לעשות. שימו לב שהמספרים ממש קרובים לסורגים, יהיה קל יותר לקרוא אם היה קצת יותר מרווח ביניהם.
מרכיב נוסף בעלילה זו הם הצבעים, כאשר משתמשים בצבעים מנוגדים, זה משדר רעיון של הפרדה, להיפך, כאשר משתמשים בצבעים דומים, הם מתקשרים רעיון של אחדות, או חלקים של שלם. מכיוון שהתכונות הן כולן חלק מהפינגווינים, אנו יכולים להשתמש בצבעים המבדילים כל סרגל תוך שמירה על אחדות:
g = sns.barplot(data=importances_df,
x="importances",
y="feature_names",
palette="mako")
sns.despine(bottom=True, left=True)
g.set_title("Feature importances", fontsize=14)
g.set(xticks=[])
g.set(xlabel=None)
g.set(ylabel=None)
for value in g.containers:
g.bar_label(value,
padding=2)
אם תרצו להפוך את התוצאות ישירות יותר, תוכלו לשנות את הכותרת ולהוסיף את המסקנה. מה שידוע הוא שאורך השטר נחשב למאפיין החשוב ביותר על פי הקריטריונים עליהם עמדנו בעבר. זה יכול להיות המידע הראשון עבור מישהו שמסתכל על העלילה, אפשר לומר זאת אורך הגזע של הפינגווין היה המאפיין החשוב ביותר לסיווג מינים במודל הבסיס של היער האקראי (RF) :
g = sns.barplot(data=importances_df,
x="importances",
y="feature_names",
palette="mako")
sns.despine(bottom=True, left=True)
g.set_title("The penguin's bill length was the most important feature for species classification (RF base model)", fontsize=14)
g.set(xticks=[])
g.set(xlabel=None)
g.set(ylabel=None)
for value in g.containers:
g.bar_label(value, padding=2)
זו התוצאה הסופית של תרשים חשיבות התכונות:
סיכום
במדריך זה – בנינו מחלק יער אקראי – ובדקנו את חשיבות התכונות ששימשו לאימון המודל בניסיון להסביר מה מודל למד, ומה משפיע על ההיגיון שלו.