גיוס קמפוס: בעיית סיווג עם רגרסיה לוגיסטית

גיוס קמפוס: בעיית סיווג עם רגרסיה לוגיסטית

צומת המקור: 1996810

מבוא

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

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

בעיה במדעי הנתונים עם רגרסיה לוגיסטית

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

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

תוכן העניינים

  1. שלבים המעורבים בפתרון הבעיה
  2. הכן נתונים
  3. בניית מודל רגרסיה לוגיסטית
  4. תוצאות מודל הרגרסיה הלוגיסטית
  5. סיכום

שלבים המעורבים בפתרון הבעיה

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

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

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

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

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

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

לבסוף, לפני שנצלול לתוך העבודה, בואו נכיר את עצמנו עם הספריות שבהן נשתמש לזרוק את הפרויקט. ראשית, נייבא את הנתונים שלנו למחברת Google Colabe לספריית io. לאחר מכן, כשנשתמש במודל רגרסיה לוגיסטית, נייבא את זה מ-skit-learn. אחרי זה, גם מ סקיקיט-לימוד, נייבא את מדדי הביצועים שלנו, את ציון הדיוק ופיצול הרכבת-מבחן.

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

בואו נקפוץ להכנת הנתונים.

#import libraries
import io
import warnings import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn.preprocessing import LabelEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler warnings.simplefilter(action="ignore", category=FutureWarning)

הכן נתונים

תבואו

כדי להתחיל בהכנת הנתונים, בואו נתחיל בעבודה החשובה שלנו. ראשית, אנו טוענים את קובץ הנתונים שלנו, ולאחר מכן עלינו להכניס אותם ל-DataFrame `df.`

from google.colab import files
uploaded = files.upload()
# Read CSV file
df = pd.read_csv(io.BytesIO(uploaded["Placement_Data_Full_Class.csv"]))
print(df.shape)
df.head()
מערך נתונים עבור רגרסיה לוגיסטית

אנחנו יכולים לראות את ה-DataFrame היפה שלנו, ויש לנו 215 רשומות ו-15 עמודות הכוללות את תכונת ה'סטטוס', היעד שלנו. זהו התיאור עבור כל התכונות.

רגרסיה לוגיסטית

חקור

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

# Inspect DataFrame
df.info() <class 'pandas.core.frame.DataFrame'>
RangeIndex: 215 entries, 0 to 214
Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 sl_no 215 non-null int64 1 gender 215 non-null object 2 ssc_p 215 non-null float64 3 ssc_b 215 non-null object 4 hsc_p 215 non-null float64 5 hsc_b 215 non-null object 6 hsc_s 215 non-null object 7 degree_p 215 non-null float64 8 degree_t 215 non-null object 9 workex 215 non-null object 10 etest_p 215 non-null float64 11 specialisation 215 non-null object 12 mba_p 215 non-null float64 13 status 215 non-null object 14 salary 148 non-null float64
dtypes: float64(6), int64(1), object(8)
memory usage: 25.3+ KB

כעת, כאשר אנו מסתכלים על מידע `df`, ישנם כמה דברים שאנו מחפשים, יש לנו 215 שורות ב-dataframe שלנו, והשאלה שאנו רוצים לשאול את עצמנו היא, האם חסרים נתונים? ואם נסתכל כאן, נראה שלא חסרים לנו נתונים מלבד עמודת השכר, כצפוי, בגלל מועמדים שלא התקבלו לעבודה.

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

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

df.drop(columns="salary", inplace=True)

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

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

# Plot class balance
df["status"].value_counts(normalize=True).plot( kind="bar", xlabel="Class", ylabel="Relative Frequency", title="Class Balance"
);
חוסר איזון כיתתי עבור רגרסיה לוגיסטית

המחלקה החיובית שלנו 'מוצבת' נחשבת ליותר מ-65% מהתצפיות שלנו, והמחלקה השלילית 'לא ממוקמת' היא בערך 30%. עכשיו, אם אלה היו סופר לא מאוזנים, כאילו, אם זה היה יותר כמו 80 או אפילו יותר מזה, הייתי אומר שאלו מחלקות לא מאוזנות. והיינו צריכים לעשות קצת עבודה כדי לוודא שהמודל שלנו יתפקד בצורה הנכונה. אבל זה איזון בסדר.

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

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

fig,ax=plt.subplots(5,2,figsize=(15,35))
for index,i in enumerate(df.select_dtypes("number").drop(columns="sl_no")): plt.suptitle("Visualizing Distribution of Numerical Columns Indivualy and by Class",size=20) sns.histplot(data=df, x=i, kde=True, ax=ax[index,0]) sns.boxplot(data=df, x='status', y=i, ax=ax[index,1]);
"רגרסיה לוגיסטית

בעמודה הראשונה מהעלילה שלנו, ניתן לראות כי כל ההתפלגויות עוקבות אחר התפלגות נורמלית, ומרבית הביצועים החינוכיים של המועמד הם בין 60-80%.

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

fig,ax=plt.subplots(7,2,figsize=(15,35))
for index,i in enumerate(df.select_dtypes("object").drop(columns="status")): plt.suptitle("Visualizing Count of Categorical Columns",size=20) sns.countplot(data=df,x=i,ax=ax[index,0]) sns.countplot(data=df,x=i,ax=ax[index,1],hue="status")
"רגרסיה לוגיסטית

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

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

corr = df.select_dtypes("number").corr()
# Plot heatmap of `correlation`
plt.title('Correlation Matrix')
sns.heatmap(corr, vmax=1, square=True, annot=True, cmap='GnBu');
מטריצת מתאם

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

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

# Check for high- and low-cardinality categorical features
df.select_dtypes("object").nunique() gender 2
ssc_b 2
hsc_b 2
hsc_s 3
degree_t 3
workex 2
specialisation 2
status 2
dtype: int64

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

df.drop(columns="sl_no", inplace=True)

תכונות קידוד

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

lb = LabelEncoder () cat_data = ['gender', 'ssc_b', 'hsc_b', 'hsc_s', 'degree_t', 'workex', 'specialisation', 'status']
for i in cat_data: df[i] = lb.fit_transform(df[i]) df.head()
פלט קוד

לְפַצֵל

ייבאנו וניקינו את הנתונים שלנו. עשינו קצת ניתוח נתונים חקרני, ועכשיו אנחנו צריכים לפצל את הנתונים שלנו. יש לנו שני סוגים של פיצול: פיצול אנכי או תכונות-יעד ופיצול אופקי או קבוצות בדיקות רכבת. בואו נתחיל עם האנכי. אנו ניצור את מטריצת התכונות שלנו 'X' ואת וקטור היעד 'y'. המטרה שלנו היא "סטטוס". התכונות שלנו צריכות להיות כל העמודות שנותרו ב-'df'.

#vertical split
target = "status"
X = df.drop(columns = target)
y = df[target]

מודלים בדרך כלל מתפקדים טוב יותר כאשר יש להם נתונים מנורמלים להתאמן איתם, אז מהי נורמליזציה? נוֹרמָלִיזָצִיָה הוא הופך את הערכים של מספר משתנים לטווח דומה. המטרה שלנו היא לנרמל את המשתנים שלנו. אז טווחי הערכים שלהם יהיו מ-0 עד 1. בוא נעשה את זה, ואני אשתמש ב-'StandardScaler'.

scaler = StandardScaler()
X = scaler.fit_transform(X)

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

X_train, X_test, y_train, y_test = train_test_split( X, y, test_size = 0.2, random_state = 42 ) print("X_train shape:", X_train.shape)
print("y_train shape:", y_train.shape)
print("X_test shape:", X_test.shape)
print("y_test shape:", y_test.shape) X_train shape: (172, 12)
y_train shape: (172,)
X_test shape: (43, 12)
y_test shape: (43,)

בניית מודל רגרסיה לוגיסטית

Baseline

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

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

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

אנו יכולים להשתמש בשיטת 'value_counts' עם הארגומנט 'normalize = True' כדי לחשב את דיוק הבסיס:

acc_baseline = y_train.value_counts(normalize=True).max()
print("Baseline Accuracy:", round(acc_baseline, 2)) Baseline Accuracy: 0.68

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

לְחַזֵר

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

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

גרף עבור רגרסיה לוגיסטית

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

תואר p עבור רגרסיה לוגיסטית

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

לְחַזֵר

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

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

נבואה

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

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

img

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

פונקציה עבור רגרסיה לוגיסטית

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

פונקציה עבור רגרסיה לוגיסטית

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

- רגרסיה לוגיסטית

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

- רגרסיה לוגיסטית

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

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

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

תואר p

אז עכשיו יש לי פונקציה שנותנת לי חיזוי בין אפס לאחד, ואני מתייחס לזה כאל הסתברות. ואם ההסתברות הזו היא מעל 0.5 או 50%, אני אומר, בסדר, מחלקה אחת חיובית. ואם זה מתחת ל-50%, אני אומר, זה מחלקה שלילית, אפס. אז זו הדרך בה פועלת הרגרסיה הלוגיסטית. ועכשיו אנחנו מבינים את זה, בואו נקודד אותו ונתאים אותו. אקבע את ההיפרפרמטר 'max_iter' ל-1000. פרמטר זה מתייחס למספר המרבי של איטרציות שהפותרים יתכנסו.

# Build model
model = LogisticRegression(max_iter=1000) # Fit model to training data
model.fit(X_train, y_train) LogisticRegression(max_iter=1000)

להעריך

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

acc_train = accuracy_score(y_train, model.predict(X_train))
acc_test = model.score(X_test, y_test) print("Training Accuracy:", round(acc_train, 2))
print("Test Accuracy:", round(acc_test, 2)) Training Accuracy: 0.9
Test Accuracy: 0.88

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

תוצאות מודל הרגרסיה הלוגיסטית

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

model.predict(X_train)[:5] array([0, 1, 1, 1, 1])

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

y_train_pred_proba = model.predict_proba(X_train)
print(y_train_pred_proba[:5]) [[0.92003219 0.07996781] [0.03202019 0.96797981] [0.00678421 0.99321579] [0.03889446 0.96110554] [0.00245525 0.99754475]]

אנו יכולים לראות מעין רשימה מקוננת עם שתי עמודות שונות בתוכה. העמודה משמאל מייצגת את ההסתברות שמועמד לא הוצב או את הכיתה השלילית שלנו 'לא ממוקם'. העמודה השנייה מייצגת את המחלקה החיובית 'מוצב' או את ההסתברות להצבת מועמד. נתמקד בעמודה השנייה. אם נסתכל נכון על אומדן ההסתברות הראשון, נוכל לראות שזה 0.07. אז מכיוון שזה מתחת ל-50%, אומר המודל שלנו, התחזית שלי היא אפס. ולגבי התחזיות הבאות, אנו יכולים לראות שכולם מעל 0.5, וזו הסיבה שהמודל שלנו חזה אחד בסופו של דבר.

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

# Features names
features = ['gender', 'ssc_p', 'ssc_b', 'hsc_p', 'hsc_b', 'hsc_s', 'degree_p' ,'degree_t', 'workex', 'etest_p', 'specialisation', 'mba_p']
# Get importances
importances = model.coef_[0]
# Put importances into a Series
odds_ratios = pd.Series(np.exp(importances), index= features).sort_values()
# Review odds_ratios.head() mba_p 0.406590
degree_t 0.706021
specialisation 0.850301
hsc_b 0.876864
etest_p 0.877831
dtype: float64

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

# Horizontal bar chart, five largest coefficients
odds_ratios.tail().plot(kind="barh")
plt.xlabel("Odds Ratio")
plt.ylabel("Feature")
plt.title("High Importance Features");
# תרשים עמודות אופקי, חמשת המקדמים הגדולים ביותר odds_ratios.tail().plot(kind=

עכשיו אני רוצה שתדמיינו קו אנכי ממש ב-5, ואני רוצה להתחיל בהסתכלות עליו. בואו נדבר על כל אחד מהם בנפרד או רק על הזוג הראשון. אז בואו נתחיל כאן עם ה-'ssc_p', המתייחס ל'אחוז ההשכלה התיכונית – כיתה י'. ואנחנו יכולים לראות שיחס הסיכויים הוא 10. עכשיו, מה זה אומר? זה אומר שאם למועמד יש 'ssc_p' גבוה, הסיכויים להצבתו גדולים פי שישה ממועמדים אחרים, כשהכל שווה. אז דרך נוספת לחשוב על זה היא כאשר למועמד יש `ssc_p`, הסיכוי לגיוס של המועמד גדל פי שש.

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

odds_ratios.head().plot(kind="barh")
plt.xlabel("Odds Ratio")
plt.xlabel("Odds Ratio")
plt.ylabel("Feature")
plt.title("Low Importance Features");
תכונת חשיבות נמוכה

הדבר הראשון שאנחנו צריכים לראות כאן הוא ששים לב על ציר ה-x הכל אחד או מתחת. עכשיו, מה זה אומר? אז בואו נסתכל על יחס הסיכויים הקטן ביותר שלנו כאן. זה mba_p שמתייחס לאחוז ה-MBA. אנחנו יכולים לראות שזה מוכן בערך ב-0.45. עכשיו, מה זה אומר? ובכן, ההבדל בין 0.45 ל-1 הוא 0.55. בסדר? ומה אומר המספר הזה? מועמדים בעלי MBA נוטים פחות להגייס ב-55%, כל שאר הדברים שווים. בסדר? אז זה הפחית את סיכויי הגיוס בשיעור של 0.55 או 55%. וזה נכון לכל דבר כאן.

סיכום

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

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

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

קוד מקור הפרויקט: https://github.com/SawsanYusuf/Campus-Recruitment.git

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

בול זמן:

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