مدلسازی دادههای جدولی، بررسی شانس تحصیل در دانشگاه تحصیلات تکمیلی
هدف از انجام تحلیل پیشرو این است که مهمترین عواملی را که بر راهیابی دانشآموزان به دانشکده تحصیلات تکمیلی تأثیر دارند برررسی کنیم و مدلی که با بیشترین نرخ دقت میتواند شانس دانشآموزان را برای دریافت پذیرش از سوی دانشکده تحصیلات تکمیلی پیشبینی کند، انتخاب کنیم.
من برای انجام پروژه پیشرو از دیتاست Graduates Admission 2 استفاده خواهم کرد که بر روی وبسایت Kaggle در دسترس است و از دیتاست UCLA Admissions الهام گرفته است.
بارگذاری کتابخانههای مورد نیاز
#import required libraries from pandas.api.types import is_string_dtype, is_numeric_dtype, is_categorical_dtype from fastai.tabular.all import * from sklearn.ensemble import RandomForestRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error from IPython.display import Image, display_svg, SVG import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import statsmodels.api as sm import numpy as np
تحلیل کاوشگرانه داده
پیش از هر چیز باید فایل csv را در Pandas DataFrame بارگذاری کنیم و ستونهایی را که به آنها نیاز نداریم حذف کنیم:
#load csv into Pandas dataframes data_df = pd.read_csv('../input/graduate-admissions/Admission_Predict_Ver1.1.csv') #drop the serial no. of the students as we dont need it data_df.drop('Serial No.', axis = 1, inplace = True)
سپس برای درک بهتر دادهها و تشخیص الگوهای موجود در دادهها باید عملیات EDA را انجام دهیم.
برای نشان دادن همبستگی میان متغیرها میتوانیم یک هیتمپ رسم کنیم:
corr = data_df.corr() #plot correlation matrix heatmap hm = sns.heatmap(data = corr, annot = True, cmap = sns.color_palette("flare", as_cmap=True) )
با نگاهی به هیتمپ ماتریس همبستگی متوجه میشویم میان تمامی متغیرها و شانس پذیرش در دانشکده تحصیلات تکمیلی همبستگی مثبتی برقرار است و نمره CGPA، GRE و تافل بیشترین همبستگی را با شانس پذیرش در دانشکده تحصیلات تکمیلی دارند.
برای مصورسازی دادهها، نمودار نقطهای شانس پذیرش در دانشکده تحصیلات تکمیلی و متغیرها را ترسیم میکنیم:
#plot scatter plots of Chance of Admission to each of the variables column_names = list(data_df.columns) column_names.pop(-1) fig = plt.figure(figsize = (20,10)) fig.subplots_adjust(hspace=0.4, wspace=0.4) for i in range(0, len(column_names)): ax = fig.add_subplot(2, 4,i+1) sns.scatterplot(x = data_df[column_names[i]], y = data_df['Chance of Admit '], hue = data_df[column_names[i]] )
همانگونه که در نمودارهای فوق مشاهده میکنید، رابطه نمرات CGPA، تافل و GRE و شانس پذیرش در دانشکده خطی است. دانشجویانی که در دانشگاههایی با رتبه بالاتر (ranking) مشغول به تحصیل بودهاند، شانس بیشتری برای پذیرش در مقطع تحصیلات تکمیلی دارند. دانشجویانی که انگیزهنامه (SOP) و توصیهنامههای (LOR) بهتری دارند، برای پذیرش در مقطع تحصیلات تکمیلی نیز شانس بیشتری دارند. علاوه بر این، دانشجویانی که سابقه پژوهشی دارند نیز شانس بالایی برای پذیرش در این مقطع دارند.
[irp posts=”20954″]مدلسازی
برای انجام این پروژه، سه مدل را برازش میکنیم: مدل رگرسیون خطی چندگانه، جنگل تصادفی و شبکه عصبی. علاوه بر این تلاش میکنیم مدلها را با یکدیگر ترکیب کنیم تا یک مدل دقیقتر به دست آوریم. برای ارزیابی دادهها از معیار خطای میانگین مربعات (MSE) کمک خواهیم گرفت. هرچه MSE کمتر باشد، مدل دقیقتر است.
پیش از برازش مدلهای یادگیری ماشین، دیتاست را به دو بخش، دیتاست آموزشی و آزمایشی، تقسیم میکنیم:
#split our data into train and test data Y = data_df['Chance of Admit '] X = data_df.drop(columns = {'Chance of Admit '}) X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)
رگرسیون خطی
برای برازش مدل رگرسیون خطی OLS بر روی دادهها از کتابخانه statsmodel استفاده خواهیم کرد ، زیرا کتابخانه statsmodel اطلاعات بیشتری در مورد مدل در اختیار ما میگذارد، اما نتایج هر دو کتابخانه یکسان خواهد بود.
در نهایت مدل زیر را بدون هیچ عبارت تعاملی (interaction terms) برازش میکنیم:
شانس پذیرش = beta_0 + beta_1 * GRE نمره + beta_2 * TOEFL نمره + beta_3 * رتبه دانشگاه + beta_4 * SOP + beta_5 * LOR + beta_6 * CGPA + beta_7 * سابقه پژوهشی
#fit a multiple linear regression model using statsmodels #add a constant X1_train = sm.add_constant(X_train) X1_test = sm.add_constant(X_test) #fit model model = sm.OLS(Y_train, X1_train).fit() predictions = model.predict(X1_test) print_model = model.summary() print(print_model) #i used statsmodels as it provides additional insights about the model but both would work perfectly fine #below is the code for fitting with sklearn """ from sklearn.linear_model import LinearRegression # with sklearn regr = linear_model.LinearRegression() regr.fit(X_train, Y_train) """
خروجی کد بالا:
با نگاهی به خروجی فوق متوجه میشویم R2 مدل برابر با 821/0 است و به این معنا است که مدل به خوبی بر روی دادهها برازش شده است. همانگونه که مشاهده میکنید، ضریب رتبه دانشگاه و SOP زیاد نیست و مقدار پی (p-value) آنها به ترتیب برابر با 541/0 و 721/0 است. MSE مدل بر روی دیتاست آزمایشی برابر با 003705/0 بود. در صورتی که متغیرهای کم اهمیتتر را حذف کنیم، MSE مدل افزایش (003773/0) و مجذور R آن کاهش مییابد.
توجه داشته باشید که در عمل و زمانیکه دقت مدل فقط کمی کاهش پیدا میکند، سادهترین مدل را انتخاب میکنیم، به این دلیل که تفسیر مدلهای ساده آسانتر است.
جنگل تصادفی
من برای برازش مدل جنگل تصادفی بر روی دادهها از کتابخانه sklearn استفاده خواهم کرد:
forest = RandomForestRegressor(n_estimators=1100,max_depth =6 ,max_features = 0.5) forest.fit(X_train, Y_train) predictions_rf = forest.predict(X_test) #calculate the mean squared error mean_squared_error(predictions_rf, Y_test)
پس از برازش مدل جنگل تصادفی، علاوه بر اینکه میخواهیم بدانیم مدل چه اندازه دقت دارد، میخواهیم بدانیم که چگونه پیشبینی میکند. اهمیت ویژگی به ما کمک میکند اطلاعاتی در این خصوص به دست آوریم.
def rf_feat_importance(m, df): return pd.DataFrame({'cols':df.columns, 'imp':m.feature_importances_} ).sort_values('imp', ascending=False) #check most important features fi = rf_feat_importance(forest, X_train) def plot_fi(fi): return fi.plot('cols', 'imp', 'barh', figsize=(12,7), legend=False) plot_fi(fi);
با نگاهی به نمودار بالا متوجه میشویم، ویژگیهایی همچون CGPA، نمره GRE و تافل اهمیت زیادی برای مدل دارند و در مقابل ویژگیهایی همچون سابقه پژوهشی و LOR اهمیت کمتری برای مدل دارند. با توجه به اینکه مقدار اهمیت ویژگی هیچ یک از ویژگیها خیلی پایین نیست، کماکان میتوانیم این ویژگیها را در مدل حفظ کنیم.
MSE مدل جنگل تصادفی بر روی دیتاست آزمایشی برابر با 003922/0 بود.
[irp posts=”14096″]شبکه عصبی
من برای برازش شبکه عصبی بر روی دادهها از کتابخانه FastAI استفاده میکنم که بر اساس PyTorch ساخته شده است. برای انجام این کار باید عملیات پیشپردازش دادهها را بر روی دادهها انجام دهیم و برای تغذیه دادهها به شبکه عصبی dataloaderهایی ایجاد کنیم. برای کار کردن با متغیرهای گسسته و پیوسته میتوانیم از تابع fastai یعنی cont_cat_split() کمک بگیریم؛ این تابع به صورت خودکار متغیرهای گسسته و پیوسته را تقسیم میکند. توجه داشته باشد که این تابع “SOP” را ،که یک متغیر گسسته است، با متغیر پیوسته اشتباه میگیرد زیرا مقدار آن 5/0 است.
train_df = X_train test_df = X_test train_df = train_df.join(Y_train) test_df = test_df.join(Y_test) #split the variables into continuous variables and categorical variables using fastai's factory method cont_nn,cat_nn = cont_cat_split(train_df, dep_var='Chance of Admit ')
اکنون میتوانیم dataloaderها را ایجاد کنیم:
#create dataloaders procs_nn = [Categorify, FillMissing, Normalize] to_nn = TabularPandas(train_df, procs_nn, cat_nn, cont_nn, y_names='Chance of Admit ',splits = RandomSplitter(valid_pct=0.4)(range_of(train_df)) ) dls = to_nn.dataloaders()
پس از ساخت dataloaderها میتوانیم در FastAI یک learner جدولی ایجاد کنیم:
#create tabular learner learn = tabular_learner(dls, y_range=(0.3,1),n_out=1, loss_func=F.mse_loss)
سپس میتوانیم با استفاده از fit_one_cycleمدل را 15 مرحله (epoch) آموزش دهیم و نتایج را مشاهده کنیم:
learn.lr_find()
learn.fit_one_cycle(15, 1e-2)
MSE شبکه عصبی بر روی دیتاست آزمایشی برابر با 003744/0 بود.
test_df.drop(['Chance of Admit '], axis=1, inplace=True) dl = learn.dls.test_dl(test_df) preds = learn.get_preds(dl=dl) #convert the predictions into a list y = [] for i in range(0,len(Y_test)): x = preds[0][i].tolist() y += x mean_squared_error(y,Y_test)
ادغام
مدلهای رگرسیون خطی، جنگل تصادفی و شبکه عصبی هر کدام مزایا و معایب خود را دارند. بهترین کاری که میتوانیم انجام دهیم این است که این سه مدل را در کنار یکدیگر قرار دهیم و یک مدل دقیقتر بسازیم. روشهای زیادی برای انجام این کار وجود دارد اما ما روش سادهتر را انتخاب میکنیم و میانگین پیشبینیهای این سه مدل را به دست میآوریم:
ens_preds = (predictions + predictions_rf + y) /3 mean_squared_error(ens_preds, Y_test)
در نتیجه ترکیب مدلها، MSE بر روی دیتاست آزمایشی 003607/0 خواهد بود که از MSEهایی که مدلها به صورت جداگانه بر روی دیتاست آزمایشی به دست آوردند، بهتر است.
چکیده
به نظر میرسد عملکرد رگرسیون خطی نسبت به شبکه عصبی و جنگل تصادفی بهتر بوده و این به این معناست که مدلهای پیچیده لزوماً نتایج خوبی به همراه ندارند. با این حال، نتیجه ترکیب مدلها با هم بهتر از نتایج این سه مدل به صورت جداگانه بود.
برای دانلود کد به Github مراجعه کنید.