التوظيف في الحرم الجامعي: مشكلة تصنيف مع الانحدار اللوجستي

التوظيف في الحرم الجامعي: مشكلة تصنيف مع الانحدار اللوجستي

عقدة المصدر: 1996810

المُقدّمة

في هذا المشروع ، سنركز على البيانات من الهند. وهدفنا هو إنشاء ملف النموذج التنبئي، مثل الانحدار اللوجستي ، وما إلى ذلك ، بحيث عندما نعطي خصائص المرشح ، يمكن للنموذج أن يتنبأ بما إذا كان سيتم تجنيده أم لا.

• بيانات يدور حول موسم التنسيب في كلية إدارة الأعمال في الهند. تحتوي مجموعة البيانات على عوامل مختلفة تتعلق بالمرشحين ، مثل خبرة العمل ونسبة الامتحان وما إلى ذلك. وأخيرًا ، تحتوي على حالة التوظيف وتفاصيل المكافآت.

مشكلة علم البيانات مع الانحدار اللوجستي

التوظيف في الحرم الجامعي هو استراتيجية لتحديد مصادر المواهب الشابة وإشراكها وتوظيفها للتدريب الداخلي والمبتدئين. غالبًا ما ينطوي على العمل مع مراكز الخدمات المهنية بالجامعة وحضور معارض التوظيف للقاء شخصيًا مع طلاب الجامعات والخريجين الجدد.

تم نشر هذه المقالة كجزء من مدونة علوم البيانات.

جدول المحتويات

  1. الخطوات المتبعة في حل المشكلة
  2. تحضير البيانات
  3. بناء نموذج الانحدار اللوجستي
  4. نتائج نموذج الانحدار اللوجستي
  5. وفي الختام

الخطوات المتبعة في حل المشكلة

في هذه المقالة ، سنستورد مجموعة البيانات هذه وننظفها ثم نجهزها لبناء نموذج انحدار لوجستي. أهدافنا هنا هي ما يلي:

أولاً ، سنقوم بإعداد مجموعة البيانات الخاصة بنا لـ تصنيف ثنائي. الآن ماذا أعني؟ عندما نحاول التنبؤ بقيمة مستمرة ، مثل سعر الشقة ، يمكن أن يكون أي رقم بين صفر وعدة ملايين من الدولارات. نسميها مشكلة الانحدار.

لكن في هذا المشروع ، الأمور مختلفة قليلاً. بدلاً من توقع قيمة مستمرة ، لدينا مجموعات أو فئات منفصلة نحاول التنبؤ بها فيما بينها. هذا يسمى مشكلة التصنيف ، ولأنه في مشروعنا ، سيكون لدينا مجموعتان فقط نحاول الاختيار بينهما ، وهذا يجعله تصنيفًا ثنائيًا.

الهدف الثاني هو إنشاء نموذج انحدار لوجستي للتنبؤ بالتجنيد. وهدفنا الثالث هو شرح تنبؤات نموذجنا باستخدام نسبة الأرجحية.

الآن فيما يتعلق بسير عمل التعلم الآلي ، والخطوات التي سنتبعها ، وبعض الأشياء الجديدة ، سوف نتعلم على طول الطريق. لذلك في مرحلة الاستيراد ، سنجهز بياناتنا للعمل مع هدف ثنائي. في مرحلة الاستكشاف ، سننظر في توازن الفصل. إذن ، ما هي نسبة المرشحين التي كانت ضعيفة ، وما هي النسب التي لم تكن كذلك؟ وفي مرحلة ترميز الميزات ، سنقوم بتشفير ميزاتنا الفئوية. في الجزء المنقسم ، سنفعل تقسيمًا عشوائيًا لاختبار القطار.

بالنسبة لمرحلة بناء النموذج ، أولاً ، سنحدد خط الأساس ، ولأننا سنستخدم درجات الدقة ، سنتحدث أكثر عن ماهية درجة الدقة وكيفية بناء خط أساس عندما يكون هذا هو المقياس الذي نهتم به. ثانيًا ، سنفعل الانحدار اللوجستي. ثم أخيرًا وليس آخرًا ، ستكون لدينا مرحلة التقييم. سنركز مرة أخرى على درجة الدقة. أخيرًا ، لتوصيل النتائج ، سننظر في نسبة الأرجحية.

أخيرًا ، قبل الغوص في العمل ، دعنا نقدم أنفسنا للمكتبات التي سنستخدمها في طرح المشروع. أولاً ، سنقوم باستيراد بياناتنا إلى دفتر ملاحظات Google Colabe إلى مكتبة io. بعد ذلك ، حيث سنستخدم نموذج الانحدار اللوجستي ، سنقوم باستيراده من scikit-Learn. بعد ذلك أيضا من تعلم الحروف، سنقوم باستيراد مقاييس الأداء الخاصة بنا ودرجة الدقة وتقسيم اختبار القطار.

سوف نستخدم ماتبلوتليب و seaborn لتصورنا ، و نمباي  سيكون فقط للرياضيات الصغيرة.
نحن نحتاج الباندا للتلاعب ببياناتنا ، والتسمية المشفرة لتشفير متغيراتنا الفئوية ، والقياس القياسي لتطبيع البيانات. ستكون هذه هي المكتبات التي نحتاجها.

دعنا ننتقل إلى إعداد البيانات.

#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 عمودًا تتضمن سمة "status" ، هدفنا. هذا هو الوصف لجميع الميزات.

الانحدار اللوجستي

إكتشف المزيد

الآن لدينا كل هذه الميزات التي سنستكشفها. لذلك دعونا نبدأ تحليل البيانات استكشافية. أولاً ، دعنا نلقي نظرة على المعلومات الخاصة بإطار البيانات هذا ونرى ما إذا كان يتعين علينا الاحتفاظ بأي منها أو ربما نحتاج إلى إسقاطها.

# 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 صفًا في إطار البيانات لدينا ، والسؤال الذي نريد طرحه على أنفسنا هو ، هل هناك أي بيانات مفقودة؟ وإذا نظرنا هنا ، فيبدو أنه ليس لدينا بيانات مفقودة باستثناء عمود الراتب ، كما هو متوقع ، بسبب المرشحين الذين لم يتم تعيينهم.

مصدر قلق آخر بالنسبة لنا هنا هو ، هل هناك أي ميزات مسربة من شأنها أن تعطي معلومات لنموذجنا لم يكن ليحصل عليها إذا تم نشره في العالم الحقيقي؟ تذكر أننا نريد أن يتنبأ نموذجنا بما إذا كان المرشح سيقدم أم لا ، ونريد أن يقوم نموذجنا بهذه التنبؤات قبل حدوث التوظيف. لذلك لا نريد إعطاء أي معلومات عن هؤلاء المرشحين بعد التوظيف.

لذلك ، من الواضح أن ميزة "الراتب" هذه توفر معلومات حول الراتب الذي تقدمه الشركة. ولأن هذا الراتب للمقبولين فهذه الميزة هنا تشكل تسريبًا وعلينا إسقاطها.

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

الشيء الثاني الذي أريد إلقاء نظرة عليه هو أنواع البيانات لهذه الميزات المختلفة. لذلك ، بالنظر إلى أنواع البيانات هذه ، لدينا ثماني ميزات فئوية مع هدفنا وسبع ميزات رقمية ، وكل شيء صحيح. والآن بعد أن أصبح لدينا هذه الأفكار ، فلنأخذ بعض الوقت لاستكشافها بعمق أكبر.

نحن نعلم أن هدفنا يتكون من فئتين. لقد وضعنا مرشحين ولم نضع مرشحين. السؤال هو ، ما هي النسبة النسبية لهاتين الفئتين؟ هل هم تقريبا نفس التوازن؟ أم أن أحدهما أكثر بكثير من الآخر؟ هذا شيء تحتاج إلى إلقاء نظرة عليه عند حل مشاكل التصنيف. لذا فهذه خطوة مهمة في أكاديمية الإمارات الدبلوماسية.

# 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٪.

في العمود الثاني ، لدينا مخطط مربع مزدوج مع فئة "Placed" على اليمين ، ثم فئة "Not Placed" على اليسار. بالنسبة إلى ميزتي "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٪ من إجمالي بياناتنا. ولا ننسى تعيين حالة عشوائية لإمكانية التكاثر.

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,)

بناء نموذج الانحدار اللوجستي

خط الأساس

الآن علينا البدء في بناء نموذجنا ، وسنحتاج إلى البدء في الترتيب لتعيين خط الأساس. تذكر أن نوع المشكلة التي نتعامل معها هو مشكلة تصنيف ، وهناك مقاييس مختلفة لتقييم نماذج التصنيف. الشيء الذي أريد التركيز عليه هو درجة الدقة.

الآن ، ما هي درجة الدقة؟ درجة الدقة في التعلم الآلي هي مقياس تقييم يقيس عدد التنبؤات الصحيحة التي قدمها نموذج إلى العدد الإجمالي للتنبؤات التي تم إجراؤها. نحسبها بقسمة عدد التنبؤات الصحيحة على العدد الإجمالي للتنبؤات. ما يعنيه ذلك هو أن درجة الدقة تتراوح بين 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 للانحدار اللوجستي

لنفترض الآن أننا أردنا عمل انحدار خطي بهذا. لنفترض أننا أردنا رسم خط.
الآن ، إذا فعلنا ذلك ، ما سيحدث هو أن هذا الخط سيتم رسمه بطريقة تجعله أقرب ما يكون إلى جميع النقاط. ومن المحتمل أن ينتهي بنا المطاف بسطر يشبه هذا. هل سيكون هذا نموذجًا جيدًا؟

أعاد

ليس حقيقيًا. ما سيحدث بغض النظر عن الدرجة p للمرشح ، سنحصل دائمًا على نوع من القيمة. وهذا لن يساعدنا لأن الأرقام ، في هذا السياق ، لا تعني شيئًا. يجب أن تكون مشكلة التصنيف هذه إما صفرًا أو واحدًا. لذلك ، لن تعمل بهذه الطريقة.

من ناحية أخرى ، لأن هذا سطر ، ماذا لو كان لدينا مرشح بدرجة p_egree منخفضة جدًا؟ حسنًا ، فجأة ، أصبح تقديرنا رقمًا سالبًا. ومرة أخرى ، هذا لا معنى له. لا يوجد رقم سالب يجب أن يكون صفرًا أو واحدًا. وبنفس الطريقة ، إذا كان لدينا مرشح بدرجة p_degree عالية جدًا ، فقد يكون لديّ إيجابي ، شيء أعلى من ذلك. ومرة أخرى ، هذا لا معنى له. نحتاج إما أن يكون لدينا صفر أو واحد.

تنبؤ

إذن ما نراه هنا هو بعض القيود الجادة لاستخدام الانحدار الخطي في التصنيف. إذن ماذا علينا أن نفعل؟ نحتاج إلى إنشاء نموذج رقم واحد: لا يقل عن الصفر أو أعلى من واحد ، لذلك يجب ربطه بين صفر وواحد. والرقم الثاني ، بغض النظر عن ما يأتي من هذه الوظيفة ، تلك المعادلة التي أنشأناها ، ربما لا ينبغي أن نتعامل معها على أنها التنبؤ بحد ذاته ولكن كخطوة نحو صنع توقعنا النهائي.

الآن ، اسمحوا لي أن أفهم ما قلته للتو ، ودعونا نذكر أنفسنا أنه عندما نقوم بعمل نماذج الانحدار الخطي ، فإننا ننتهي بهذه المعادلة الخطية ، وهي أبسط صورة. وهذه هي المعادلة أو الدالة التي تعطينا هذا الخط المستقيم.

IMG

هناك طريقة لربط هذا الخط بين 0 و 1. وما يمكننا فعله هو أن نأخذ هذه الوظيفة التي أنشأناها للتو ونضعها في دالة أخرى ، ما يسمى بالدالة السينية.

وظيفة الانحدار اللوجستي

لذا ، سأأخذ المعادلة الخطية التي لدينا للتو ، وسأقوم بتقليصها في الدالة السينية ووضعها على أنها الأسية.

وظيفة الانحدار اللوجستي

ما يحدث هو أنه بدلاً من الحصول على خط مستقيم ، نحصل على خط يبدو كهذا نوعًا ما. عالق في واحد. يأتي ويتلوى لأسفل. ثم عالق عند الصفر.

الانحدار اللوجستي

حسنًا ، هذا ما يبدو عليه الخط ، ويمكننا أن نرى أننا حللنا مشكلتنا الأولى. أيًا كان ما سنخرجه من هذه الوظيفة سيكون بين 0 و 1. في الخطوة الثانية ، لن نتعامل مع أي شيء يخرج من هذه المعادلة على أنه التنبؤ النهائي. بدلاً من ذلك ، سوف نتعامل معه على أنه احتمال.

الانحدار اللوجستي

ماذا اقصد؟ هذا يعني أنه عندما أقوم بالتنبؤ ، سأحصل على بعض قيمة الفاصلة العائمة بين 0 و 1. وما سأفعله هو التعامل معها على أنها احتمالية أن تنبؤي ينتمي إلى الفئة الإيجابية.

لذلك حصلت على قيمة أعلى عند 0.9999. سأقول إن احتمال أن ينتمي هذا المرشح إلى صفنا الإيجابي الموضع هو 99٪. لذلك أنا على يقين من أنه ينتمي إلى الفئة الإيجابية. على العكس من ذلك ، إذا انخفض عند النقطة 0.001 أو أيًا كان ، فسأقول أن هذا الرقم منخفض. احتمال أن تنتمي هذه الملاحظة الخاصة إلى الفئة الموجبة ، فإن الفئة الموضوعة هي صفر تقريبًا. ولذا ، سأقول إنها تنتمي إلى الفئة صفر.

لذلك يكون هذا منطقيًا بالنسبة للأرقام القريبة من واحد أو قريبة من الصفر. لكن قد تسأل نفسك ، ماذا أفعل بالقيم الأخرى بينهما؟ الطريقة التي تعمل بها هي وضع خط قطع عند 0.5 ، لذا فإن أي قيمة أحصل عليها أسفل هذا الخط ، سأضعها عند الصفر ، لذا فإن توقعي هو لا ، وإذا كانت أعلى من ذلك الخط ، إذا كانت أعلى من النقطة الخامسة ، سأضع هذا في فئة إيجابية ، وتوقعي واحد.

ع درجة

إذن ، لدي الآن وظيفة تعطيني توقعًا بين صفر وواحد ، وأتعامل معها على أنها احتمال. وإذا كان هذا الاحتمال أعلى من 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. يمكن حساب دقة النموذج باستخدام دالة دقة_سكور. تتطلب الوظيفة وسيطتين ، التسميات الحقيقية والتسميات المتوقعة.

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])

إذن كانت تلك هي التوقعات النهائية ، ولكن ما هي الاحتمالات وراءها؟ للحصول على هؤلاء ، نحتاج إلى عمل رمز مختلف قليلاً. بدلاً من استخدام طريقة "التنبؤ" مع نموذجنا ، سأستخدم "التنبؤ" مع بيانات التدريب الخاصة بنا.

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 ()

الآن أريدك أن تتخيل خطًا رأسيًا عند 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 التي تشير إلى نسبة ماجستير إدارة الأعمال. يمكننا أن نرى أنه جاهز عند حوالي 0.45. الآن ماذا يعني ذلك؟ حسنًا ، الفرق بين 0.45 و 1 يساوي 0.55. حسنًا؟ وماذا يعني هذا الرقم؟ أولئك المرشحين الحاصلين على ماجستير في إدارة الأعمال هم أقل عرضة للتعيين بنسبة 55 ٪ ، مع تساوي جميع الأشياء الأخرى. حسنًا؟ لذا فقد خفضت احتمالات الاستقدام بنسبة 0.55 أو 55٪. وهذا صحيح بالنسبة لكل شيء هنا.

وفي الختام

إذن ماذا تعلمنا؟ أولاً ، في مرحلة البيانات المعدة ، علمنا أننا نعمل على التصنيف ، وبالتحديد التصنيف الثنائي ، باستخدام الانحدار اللوجستي. فيما يتعلق باستكشاف البيانات ، قمنا بالعديد من الأشياء ، ولكن من حيث النقاط البارزة ، نظرنا إلى توازن الفصل ، أليس كذلك؟ نسبة فئاتنا الإيجابية والسلبية. ثم نقوم بتقسيم بياناتنا.

نظرًا لأن الانحدار اللوجستي هو نموذج تصنيف ، فقد تعلمنا عن مقياس أداء جديد ، درجة الدقة. الآن ، درجة الدقة تتراوح بين 0 و 1. الصفر سيئ ، وواحد جيد. عندما كنا نكرر ، تعلمنا عن الانحدار اللوجستي. هذه طريقة سحرية ، حيث يمكنك أخذ معادلة خطية ، وخط مستقيم ، ووضعها داخل دالة أخرى ، ودالة سينية ، ودالة تنشيط ، والحصول على تقدير احتمالي منها وتحويل تقدير الاحتمال هذا إلى تنبؤ.

أخيرًا ، تعلمنا عن نسبة الأرجحية والطريقة التي يمكننا بها تفسير المعاملات لمعرفة ما إذا كانت ميزة معينة ستزيد من احتمالات توظيفنا لمرشح أم لا.

كود مصدر المشروع: https://github.com/SawsanYusuf/Campus-Recruitment.git

الوسائط الموضحة في هذه المقالة ليست مملوكة لـ Analytics Vidhya ويتم استخدامها وفقًا لتقدير المؤلف. 

الطابع الزمني:

اكثر من تحليلات Vidhya