1 Overview

Pada kesempatan kali ini, saya akan melakukan prediksi terhadap dataset wholesale dengan melihat pengaruh variabel-variabel yang ada untuk mengelompokkan data pada channel tertentu. Variabel target yang akan digunakan pada prediksi kali ini yaitu Channel. Prediksi yang dilakukan akan menggunakan 2 metode yaitu Logistic Regression dan K-NN. Kami akan membandingkan kedua jenis metode dan akan menyimpulkan metode mana yang paling baik untuk digunakan pada prediksi kali ini.

2 Library & Setup

Sebelum kita memulai proses prediksi, kita harus meng-install beberapa package yang diperlukan. Apabila package-package tersebut sudah berhasil diinstall, selanjutnya dapat kita jalankan dengan menggunakan fungsi library()

library(tidyverse)
library(gtools)
library(caret)
library(GGally)
library(ggplot2)

3 Data Preparation

3.1 Data Import

Pertama-tama kita akan mengimport data yang akan kita gunakan menggunakan fungsi read.csv(). Dataset yang akan kita gunakan hari ini yaitu data yang berisikan informasi mengenai customer dari wholesale.

wholesale <- read.csv("data_input/wholesale.csv")
glimpse(wholesale)
## Rows: 440
## Columns: 8
## $ Channel          <int> 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1…
## $ Region           <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3…
## $ Fresh            <int> 12669, 7057, 6353, 13265, 22615, 9413, 12126, 7579, …
## $ Milk             <int> 9656, 9810, 8808, 1196, 5410, 8259, 3199, 4956, 3648…
## $ Grocery          <int> 7561, 9568, 7684, 4221, 7198, 5126, 6975, 9426, 6192…
## $ Frozen           <int> 214, 1762, 2405, 6404, 3915, 666, 480, 1669, 425, 11…
## $ Detergents_Paper <int> 2674, 3293, 3516, 507, 1777, 1795, 3140, 3321, 1716,…
## $ Delicassen       <int> 1338, 1776, 7844, 1788, 5185, 1451, 545, 2566, 750, …

3.2 Data Manipulation

Pada bagian ini, kita akan menghilangkan data Region dan mengubah tipe data Channel menjadi Factor. Selain itu, kita juga mengubah isi dari variabel Channel yang pada awalnya berisi angka 1 dan 2, menjadi 1 = Horeca (Hotel, Restaurant, Cafe) dan 2 = Retail Industry.

wholesale <- wholesale %>% 
  select(-Region) %>% 
  mutate(Channel = ifelse(Channel == 1, "Horeca", "Retail")) %>% 
  mutate(Channel = as.factor(Channel))

Selanjutnya, kita akan mengecek apakah terdapat missing values pada dataset wholesale.

colSums(is.na(wholesale))
##          Channel            Fresh             Milk          Grocery 
##                0                0                0                0 
##           Frozen Detergents_Paper       Delicassen 
##                0                0                0

Berdasarkan hasil di atas, tidak ditemukan missing values pada data.

4 Pre-Processing Data

4.1 Splitting Train-Test

Selanjutnya, kita akan membagi dataset wholesale menjadi dua yaitu data_train yang akan kita gunakan dan juga data_test. Dari sini kita akan menggunakan 80% dari data awal untuk data_train dan juga menggunakan seed 189 untuk melakukan sampling.

RNGkind(sample.kind = "Rounding")
## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
set.seed(189)
row_data <- nrow(wholesale)
index <- sample(row_data, row_data*0.8)

data_train <- wholesale[index, ]
data_test <- wholesale[-index, ] 

4.2 Class Imbalance

4.2.1 Check Imbalance Class

Sebelum melakukan modelling, kita akan mengecek proporsi dari target variabel yang kita miliki apakah sudah seimbang atau belum.

prop.table(table(data_train$Channel))
## 
##    Horeca    Retail 
## 0.6818182 0.3181818

4.2.2 Handling Imbalance Class

Berdasarkan data pada check imbalance class, ternyata proporsi dari data yang kita miliki kurang seimbang. Maka dari itu, akan dilakukan handling imbalance class menggunakan metode Upsampling. Alasan penggunaan metode ini yaitu karena jumlah data yang tidak banyak, sehingga dengan metode Upsampling tidak akan menghilangkan data-data yang penting.

train_up <- upSample(x = data_train %>% select(-Channel),
                     y = data_train$Channel,
                     list = F,
                     yname = "Channel")
train_up

Setelah melakukan handling imbalance class, sekarang proporsi dari data Channel sudah seimbang sehingga bisa dilakukan tahap selanjutnya.

prop.table(table(train_up$Channel))
## 
## Horeca Retail 
##    0.5    0.5

5 Logistic Regression

5.1 Modelling

Sekarang kita masuk pada bagian modelling menggunakan logistic regression. Fungsi yang digunakan untuk modelling yaitu glm() dan variabel target yang kita gunakan yaitu Channel diikuti dengan variabel .

model_logistic <- glm(Channel ~ ., train_up, family = "binomial") 
summary(model_logistic)
## 
## Call:
## glm(formula = Channel ~ ., family = "binomial", data = train_up)
## 
## Deviance Residuals: 
##      Min        1Q    Median        3Q       Max  
## -3.09653  -0.35406  -0.00125   0.13849   3.05999  
## 
## Coefficients:
##                      Estimate   Std. Error z value            Pr(>|z|)    
## (Intercept)      -3.196812680  0.411859232  -7.762 0.00000000000000837 ***
## Fresh             0.000006809  0.000015140   0.450              0.6529    
## Milk              0.000054149  0.000049694   1.090              0.2759    
## Grocery           0.000167428  0.000067970   2.463              0.0138 *  
## Frozen           -0.000139233  0.000079103  -1.760              0.0784 .  
## Detergents_Paper  0.000845446  0.000140175   6.031 0.00000000162599306 ***
## Delicassen       -0.000221163  0.000112320  -1.969              0.0489 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 665.42  on 479  degrees of freedom
## Residual deviance: 228.49  on 473  degrees of freedom
## AIC: 242.49
## 
## Number of Fisher Scoring iterations: 8

5.1.1 Model Fitting

Kita akan melakukan model fitting dengan menggunakan metode stepwise untuk menemukan AIC yang terendah.

model_step <- step(model_logistic, direction = "both", trace = 0)
summary(model_step) 
## 
## Call:
## glm(formula = Channel ~ Grocery + Frozen + Detergents_Paper + 
##     Delicassen, family = "binomial", data = train_up)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -3.1628  -0.3562  -0.0014   0.1423   2.9418  
## 
## Coefficients:
##                     Estimate  Std. Error z value             Pr(>|z|)    
## (Intercept)      -3.12561694  0.37975072  -8.231 < 0.0000000000000002 ***
## Grocery           0.00019578  0.00006416   3.052              0.00228 ** 
## Frozen           -0.00011520  0.00006917  -1.665              0.09583 .  
## Detergents_Paper  0.00085128  0.00013864   6.140       0.000000000823 ***
## Delicassen       -0.00019399  0.00010817  -1.793              0.07291 .  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 665.42  on 479  degrees of freedom
## Residual deviance: 229.94  on 475  degrees of freedom
## AIC: 239.94
## 
## Number of Fisher Scoring iterations: 8

5.2 Model Prediction

Selanjutnya kita akan memprediksi data_test menggunakan model yang sudah dibuat menggunakan metode logistic regression.

pred_test <- predict(model_step, data_test, type = "response")

Berdasarkan grafik di bawah, dapat diinterpretasikan bahwa hasil prediksi yang dilakukan lebih condong ke arah 0 yaitu Horeca.

ggplot(data_test, aes(x=pred_test)) +
  geom_density(lwd=0.5) +
  labs(title = "Distribution of Probability Prediction Data") +
  theme_minimal()

Lalu, kita akan mengubah prediksi yang masih berupa peluang menjadi kategori dengan ketentuan jika peluang > 0.5 maka Retail.

pred_class_test <- ifelse(pred_test > 0.5, "Retail", "Horeca") %>% as.factor()

5.3 Model Evaluation

Selanjutnya, kita akan masuk ke tahap evaluasi terhadap model yang sudah kita buat. Evaluasi model dapat kita lakukan dengan menggunakan confusion matrix.

confusionMatrix(pred_class_test, data_test$Channel, positive = "Retail")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction Horeca Retail
##     Horeca     52      5
##     Retail      6     25
##                                           
##                Accuracy : 0.875           
##                  95% CI : (0.7873, 0.9359)
##     No Information Rate : 0.6591          
##     P-Value [Acc > NIR] : 0.000003595     
##                                           
##                   Kappa : 0.7241          
##                                           
##  Mcnemar's Test P-Value : 1               
##                                           
##             Sensitivity : 0.8333          
##             Specificity : 0.8966          
##          Pos Pred Value : 0.8065          
##          Neg Pred Value : 0.9123          
##              Prevalence : 0.3409          
##          Detection Rate : 0.2841          
##    Detection Prevalence : 0.3523          
##       Balanced Accuracy : 0.8649          
##                                           
##        'Positive' Class : Retail          
## 

Terdapat 4 faktor yang bisa kita gunakan untuk mengevaluasi model, di antaranya yaitu:

  • Accuracy = seberapa mampu model saya menebak dengan benar target Y.
  • Re-call/Sensitivity = dari semua data aktual yang positif, seberapa mampu proporsi model saya menebak benar.
  • Specificity = dari semua data aktual yang negatif, seberapa mampu proporsi model saya menebak yang benar.
  • Precision = dari semua hasil prediksi, seberapa mampu model saya dapat menebak benar kelas positif.

Berdasarkan hasil dari confusionMatrix di atas, kita dapat memperoleh informasi yaitu kemampuan model yang sudah kita buat untuk menebak Channel yaitu Horeca dan Retail yaitu sebesar 87.5%. Lalu berdasarkan seluruh data aktual Retail, model dapat menebak dengan benar sebesar 83.33%. Lalu untuk keseluruhan data aktual Horeca, model dapat menebak dengan benar sebesar 89.66%. Dan yang terakhir yaitu, dari keseluruhan prediksi yang berhasil ditebak oleh model, model mampu menebak dengan benar kelas positif atau Retail sebesar 80.65%.

6 K-Nearest Neighbour

6.1 Data Preprocessing

Pada proses ini kita akan membuang target variabel pada train_up dan kita simpan sebagai train_x, lalu menyimpan target variabel dari data_train pada train_y. Selain itu kita juga melakukan scaling sekaligus pada tahap ini.

train_x <- train_up %>% 
select(-Channel) %>% 
scale() 

train_y <- train_up$Channel

Lalu, kita akan melakukan proses yang sama pada data_test. Tetapi scaling yang dilakukan pada data_test ini berdasarkan informasi dari data_train.

test_x <- data_test %>% 
select(-Channel) %>% 
scale(center = attr(train_x,"scaled:center"), 
scale = attr(train_x, "scaled:scale")) 

test_y <- data_test$Channel

6.2 Model Fitting & Prediction

Sekarang kita masuk pada bagian model fitting dan prediction menggunakan KNN. Fungsi yang digunakan yaitu knn3Train(). Perbedaan yang dimiliki oleh KNN sendiri yaitu kita dapat melakukan kegiatan modelling dan predicting secara bersamaan.

pred_knn <- knn3Train(train = train_x, 
                      test = test_x, 
                      cl = train_y, 
                      k = sqrt(nrow(train_x)) %>% round()
                      ) %>% 
  as.factor()

6.3 Model Evaluation

Selanjutnya, kita akan masuk ke tahap evaluasi terhadap model yang sudah kita buat. Evaluasi model dapat kita lakukan dengan menggunakan confusion matrix.

confusionMatrix(pred_knn, test_y, positive = "Retail")
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction Horeca Retail
##     Horeca     53      3
##     Retail      5     27
##                                           
##                Accuracy : 0.9091          
##                  95% CI : (0.8287, 0.9599)
##     No Information Rate : 0.6591          
##     P-Value [Acc > NIR] : 0.00000004718   
##                                           
##                   Kappa : 0.8009          
##                                           
##  Mcnemar's Test P-Value : 0.7237          
##                                           
##             Sensitivity : 0.9000          
##             Specificity : 0.9138          
##          Pos Pred Value : 0.8438          
##          Neg Pred Value : 0.9464          
##              Prevalence : 0.3409          
##          Detection Rate : 0.3068          
##    Detection Prevalence : 0.3636          
##       Balanced Accuracy : 0.9069          
##                                           
##        'Positive' Class : Retail          
## 

Berdasarkan hasil dari confusionMatrix di atas, kita dapat memperoleh informasi yaitu kemampuan model yang sudah kita buat untuk menebak Channel yaitu Horeca dan Retail yaitu sebesar 90.91%. Lalu berdasarkan seluruh data aktual Retail, model dapat menebak dengan benar sebesar 90%. Lalu untuk keseluruhan data aktual Horeca, model dapat menebak dengan benar sebesar 91.38%. Dan yang terakhir yaitu, dari keseluruhan prediksi yang berhasil ditebak oleh model, model mampu menebak dengan benar kelas positif atau Retail sebesar 84.38%.

7 Conclusion

Berdasarkan hasil yang telah diperoleh dari prediksi menggunakan logistic regression dan K-NN, saya dapat menyimpulkan kedua metode memiliki kemampuan yang sama baiknya dalam melakukan prediksi. Hal ini dikarenakan kedua model memiliki hasil accuracy, sensitivity, spesificity, dan precision di atas 80% yang berarti sudah baik. Tetapi untuk secara keseluruhan sendiri, K-NN memiliki hasil yang lebih baik dibandingkan dengan logistic regression.