Graduate Admission Prediction

Yahma Nurhasanah

2/11/2022

Latar Belakang

Pada projek kali ini, kita akan memprediksi tingkat kelulusan mahasiswa dalam mendaftar universitas yang sesuai dengan profil mereka. Projek ini ditujukan bagi mahasiswa yang ingin mengetahui tingkat kelulusan mereka dalam mendaftar suatu universitas.

Library

library(dplyr) # untuk data wrangling
library(GGally) # untuk mengecek korelasi
library(Metrics) # untuk melakukan evaluasi model
library(car) # untuk mengecek multikolinearitas

Persiapan Data

Data yang akan kita gunakan pada projek ini berasal dari website Kaggle.

adm <- read.csv("Admission_Predict_Ver1.1.csv")
str(adm)
## 'data.frame':    500 obs. of  9 variables:
##  $ Serial.No.       : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ GRE.Score        : int  337 324 316 322 314 330 321 308 302 323 ...
##  $ TOEFL.Score      : int  118 107 104 110 103 115 109 101 102 108 ...
##  $ University.Rating: int  4 4 3 3 2 5 3 2 1 3 ...
##  $ SOP              : num  4.5 4 3 3.5 2 4.5 3 3 2 3.5 ...
##  $ LOR              : num  4.5 4.5 3.5 2.5 3 3 4 4 1.5 3 ...
##  $ CGPA             : num  9.65 8.87 8 8.67 8.21 9.34 8.2 7.9 8 8.6 ...
##  $ Research         : int  1 1 1 1 0 1 1 0 0 0 ...
##  $ Chance.of.Admit  : num  0.92 0.76 0.72 0.8 0.65 0.9 0.75 0.68 0.5 0.45 ...

Pada dataset yang akan kita pakai, kita akan mengubah tipe data pada kolom Research menjadi faktor.

adm <- adm %>% 
  mutate(Research = as.factor(Research)) %>% 
  select(-c(Serial.No.))

Kemudian kita cek apakah dalam data kita terdapat missing value

anyNA(adm)
## [1] FALSE

Karena hasilnya False, berarti data kita sudah aman dari missing value.

Selanjutnya, kita akan menggunakan ggcorr dari package GGally untuk mengecek apakah terdapat korelasi di antara variabelnya.

ggcorr(adm, label = T, hjust = 1, layout.exp = 3)
## Warning in ggcorr(adm, label = T, hjust = 1, layout.exp = 3): data in column(s)
## 'Research' are not numeric and were ignored

# Train-Test Split Sebelum melakukan pemodelan, kita akan membagi data menjadi data train dan data test. Data test nantinya akan digunakan untuk menguji apakah model dapat melakukan prediksi terhadap unseen data.

RNGkind(sample.kind = "Rounding") 
## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
set.seed(417)

index <- sample(nrow(adm), nrow(adm)*0.8) 
adm_train <- adm[index,] 
adm_test <- adm[-index,] 

Model Fitting

Dari proses eksplorasi data, diketahui bahwa hampir semua variabel menunjukkan korelasi yang kuat dengan variabel Chance.of.Admit. Namun, variabel yang memiliki korelasi paling kuat dengan variabel Chance.of.Admit adalah variabel CGPA. Maka, untuk model pertama, kita akan membuat model regresi menggunakan fungsi lm() untuk memprediksi Chance.of.Admit berdasarkan CGPA. Kemudian, kita cek summary dari model tersebut.

model_coa <- lm(Chance.of.Admit ~ CGPA, adm_train)
summary(model_coa)
## 
## Call:
## lm(formula = Chance.of.Admit ~ CGPA, data = adm_train)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.278658 -0.026732  0.007236  0.038514  0.173809 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -1.026711   0.045939  -22.35   <2e-16 ***
## CGPA         0.204113   0.005343   38.20   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.06591 on 398 degrees of freedom
## Multiple R-squared:  0.7857, Adjusted R-squared:  0.7852 
## F-statistic:  1459 on 1 and 398 DF,  p-value: < 2.2e-16

Dari output di atas, dapat kita lihat bahwa nilai Multiple R-Squared dari model adalah sebesar 0.7857. Kemudian, slope (kemiringan) dari CGPA menunjukkan nilai yang positif yaitu sebesar 0.204113 dan signifikan secara statistik (p-value lebih kecil dari 0.05).

Kemudian, kita akan mencoba membuat model regresi baru dengan menggunakan semua variabel prediktor.

model_coa_all <- lm(Chance.of.Admit ~ ., adm_train)
summary(model_coa_all)
## 
## Call:
## lm(formula = Chance.of.Admit ~ ., data = adm_train)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.270700 -0.023131  0.009303  0.033413  0.149355 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -1.2433991  0.1148134 -10.830  < 2e-16 ***
## GRE.Score          0.0017262  0.0005603   3.081  0.00221 ** 
## TOEFL.Score        0.0030926  0.0009802   3.155  0.00173 ** 
## University.Rating  0.0051267  0.0044043   1.164  0.24512    
## SOP                0.0072423  0.0051493   1.406  0.16038    
## LOR                0.0120247  0.0046033   2.612  0.00934 ** 
## CGPA               0.1157812  0.0106360  10.886  < 2e-16 ***
## Research1          0.0242427  0.0073516   3.298  0.00106 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.05953 on 392 degrees of freedom
## Multiple R-squared:  0.8278, Adjusted R-squared:  0.8247 
## F-statistic: 269.2 on 7 and 392 DF,  p-value: < 2.2e-16

Dapat kita lihat dari output di atas, nilai Adjusted R-Squared menunjukkan 0.8247, yaitu lebih tinggi dari model sebelumnya. Kemudian, tidak semua variabel menunjukkan hasil yang signifikan secara statistik.

Kemudian untuk model terakhir, kita akan menggunakan salah satu teknik pemilihan variabel prediktor dengan algoritma stepwise regression. Kita akan menggunakan fungsi step() dengan parameter direction = "backward".

model_backward <- step(object = model_coa_all,
                       direction = "backward",
                       trace = F)
summary(model_backward)
## 
## Call:
## lm(formula = Chance.of.Admit ~ GRE.Score + TOEFL.Score + SOP + 
##     LOR + CGPA + Research, data = adm_train)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.271478 -0.025299  0.008715  0.033685  0.149731 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -1.2778948  0.1109730 -11.515  < 2e-16 ***
## GRE.Score    0.0017627  0.0005597   3.149 0.001762 ** 
## TOEFL.Score  0.0031991  0.0009764   3.276 0.001144 ** 
## SOP          0.0095475  0.0047554   2.008 0.045356 *  
## LOR          0.0127637  0.0045614   2.798 0.005392 ** 
## CGPA         0.1177694  0.0105027  11.213  < 2e-16 ***
## Research1    0.0244923  0.0073518   3.331 0.000946 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.05956 on 393 degrees of freedom
## Multiple R-squared:  0.8272, Adjusted R-squared:  0.8246 
## F-statistic: 313.6 on 6 and 393 DF,  p-value: < 2.2e-16

Dari output hasil di atas, dapat dilihat bahwa nilai Adjusted R-Squared-nya sebesar 0.8246, lebih besar dari model yang hanya menggunakan variabel prediktor CGPA serta hampir sama dengan model yang menggunakan semua variabel prediktor. Kemudian, dapat kita lihat juga bahwa semua variabel prediktornya menunjukkan hasil yang signifikan secara statistik.

Prediksi

Selanjutnya, kita akan melakukan prediksi dengan menggunakan data adm_test. kita akan menggunakan semua model untuk membandingkan model mana yang memiliki performa paling baik.

pred_coa <- predict(model_coa, newdata = adm_test) 
pred_coa_all <- predict(model_coa_all, newdata = adm_test) 
pred_model_backward <- predict(model_backward, newdata = adm_test) 

Untuk membandingkan performa ketiga model, kita dapat melihatnya dari nilai r squared (untuk model dengan 1 prediktor) dan adjusted r square (untuk model yang lebih dari 1 prediktor).

summary(model_coa)$r.squared # pakai r.squared (multiple r squared) karena 1 prediktor
## [1] 0.7857312
summary(model_coa_all)$adj.r.squared
## [1] 0.8247485
summary(model_backward)$adj.r.squared
## [1] 0.8245902

Kita juga dapat mengevaluasi dari nilai error model. Untuk kasus ini, kita akan menggunakan metrics RMSE.

rmse(predicted = pred_coa, actual = adm_test$Chance.of.Admit) 
## [1] 0.06885397
rmse(predicted = pred_coa_all, actual = adm_test$Chance.of.Admit)
## [1] 0.06255868
rmse(predicted = pred_model_backward, actual = adm_test$Chance.of.Admit)
## [1] 0.06287739

dari output di atas, dapat kita lihat bahwa model yang menggunakan semua prediktor memiliki nilai adjusted r squared yang paling besar. Selain itu, model ini juga memiliki nilai error yang paling kecil. Oleh karena itu, model yang akan kita gunakan yaitu model model_coa_all

Uji Asumsi

Normalitas Residual

Salah satu asumsi model regresi linier menyatakan bahwa error yang diperoleh dari model harus terdistribusi secara normal di sekitar mean 0. Kita akan memvalidasi asumsi ini dengan melakukan visualisasi error dari data

# visualisasi residual/errror
hist(model_coa_all$residuals)

Selain itu, kita juga melakukan uji asumsi dengan menggunakan shapiro.test()

# uji asumsi dengan shapiro.test()
shapiro.test(model_coa_all$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  model_coa_all$residuals
## W = 0.92043, p-value = 1.03e-13

Shapiro-Wilk hypothesis test:

  • H0: error/residual berdistribusi normal
  • H1: error/residual tidak berdistribusi normal

Kesimpulan: Dari hasil visualisasi serta hasil uji shapiro wilk, dapat kita simpulkan bahwa error/residual tidak berdistribusi normal, maka uji asumsi normalitas tidak terpenuhi.

Homoskedastisitas

Asumsi lain yang perlu diuji adalah apakah error pada model terdistribusi dengan variansi yang sama/konstan di rentang data yang berbeda atau tidak. Kita bisa melakukan visualisasi antara fitted values (hasil prediksi ke data untuk training model) dengan error. Kemudian, kita bisa melakukan uji kembali dengan fungsi bptest dari packagelmtest.

# visualisasi fitted values vs residual/error
plot(model_coa_all$fitted.values, model_coa_all$residuals)
abline(h=0, col="red")

# uji asumsi dengan bptest()
library(lmtest)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
bptest(model_coa_all)
## 
##  studentized Breusch-Pagan test
## 
## data:  model_coa_all
## BP = 23.496, df = 7, p-value = 0.001396

Breusch-Pagan hypothesis test:

  • H0: error menyebar konstan (Homoscedasticity)
  • H1: error menyebar tidak konstan/membentuk pola (Heteroscedasticity)

Kesimpulan: Dari hasil visualisasi serta hasil uji breusch-Pagan, dapat disimpulkan bahwa error menyebar tidak konstan/membentuk pola sehingga terdapat heteroscedasticity, maka uji asumsi homoskedastisitas tidak terpenuhi.

Multikolinearitas

Dengan menggunakan nilai VIF, kita dapat menentukan ada tidaknya multikolinearitas antar variabel prediktor. Nilai VIF yang tinggi menunjukkan korelasi yang tinggi antar variabel prediktor. Kita dapat menggunakan fungsi vif dari packagecar.

# uji asumsi dengan vif()
vif(model_coa_all)
##         GRE.Score       TOEFL.Score University.Rating               SOP 
##          4.667379          4.136433          2.818546          2.892376 
##               LOR              CGPA          Research 
##          2.019346          4.857383          1.504708

Penentuan:

  • nilai VIF > 10 : ada multicollinearity
  • nilai VIF < 10 : tidak ada multicollinearity

Kesimpulan: Karena semua nilai VIF < 0, sehingga dapat disimpulkan bahwa tidak terdapat multicollinearity, uji asumsi pun terpenuhi

Kesimpulan

Kita dapat memprediksi tingkat kelulusan mahasiswa yang mendaftar suatu universitas dengan menggunakan model_coa_all. Model tersebut menggunakan seluruh prediktor yang ada. Model ini merupakan model terbaik karena memiliki nilai adjusted r squared yang terbaik yaitu sebesar 0.8247485 atau 82.47% serta memiliki nilai error yang paling kecil yaitu sebesar 0.06255868.

Akan tetapi, sangat disayangkan bahwa untuk uji asumsi model tersebut, untuk uji asumsi normalitas dan homoskedastisitas belum terpenuhi. Maka dari itu, penggunaan model ini belum menjadi pilihan yang terbaik.