Latar Belakang

Credit risk adalah risiko yang harus ditanggung oleh seorang individu atau lembaga ketika memberikan sebuah pinjaman – biasanya dalam bentuk uang – ke individu atau pihak lain. Risiko ini berupa pokok dan bunga pinjaman yang tidak dapat dibayarkan oleh peminjam, sehingga mengakibatkan kerugian berikut:

  • Gangguan aliran kas (cash flow) sehingga modal kerja terganggu.
  • Meningkatkan biaya operasional untuk mengejar pembayaran tersebut (collection).

Untuk memperkecil risiko kredit ini, perlu dilakukan proses credit scoring atau credit rating terhadap pihak peminjam. Output proses ini akan menjadi basis untuk menentukan apakah aplikasi pengajuan pinjaman baru diterima atau ditolak.

Penentuan aplikasi pengajuan pinjaman baru diterima atau ditolak dapat dilakukan dengan cara klasifikasi data menggunakan metode Decision Tree. Algoritma Decision Tree yang digunakan pada penelitian ini adalah C5.0.

Data Preparation

Data Understanding

Dataset yang digunakan adalah data histori lamanya proses pengembalian pinjaman oleh nasabah pinjaman. Data ini berupa data sekunder yang diambil dari materi yang disediakan oleh DQLab.

Link Website DQLab: https://academy.dqlab.id/

Data ini berjumlah 900 data dengan 7 atribut sebagai berikut:

Variabel Keterangan
kode_kontrak nomor kode kontrak
pendapatan_setahun_juta pendapatan peminjam per tahun (juta)
durasi_pinjaman_bulan durasi pinjaman (bulan)
jumlah_tanggungan jumlah tanggungan
kpr_aktif status kpr (aktif atau tidak)
rata_rata_overdue rata-rata waktu keterlambatan pembayaran
risk_rating tingkat risiko keterlambatan pembayaran (1-5)

Data Preprocessing

1. Import Library dan dataset yang ingin dianalisis

library("openxlsx")
library("C50")
library("reshape2")

# Mempersiapkan Data 
dataCreditRating <- read.xlsx("credit_scoring.xlsx")

# Menampilkan 5 Data teratas
head(dataCreditRating)
##   kode_kontrak pendapatan_setahun_juta kpr_aktif durasi_pinjaman_bulan
## 1   AGR-000001                     295        YA                    48
## 2   AGR-000011                     271        YA                    36
## 3   AGR-000030                     159     TIDAK                    12
## 4   AGR-000043                     210        YA                    12
## 5   AGR-000049                     165     TIDAK                    36
## 6   AGR-000063                     220     TIDAK                    24
##   jumlah_tanggungan rata_rata_overdue risk_rating
## 1                 5      61 - 90 days           4
## 2                 5      61 - 90 days           4
## 3                 0       0 - 30 days           1
## 4                 3      46 - 60 days           3
## 5                 0      31 - 45 days           2
## 6                 5       0 - 30 days           1

2. Melihat struktur data

str(dataCreditRating)
## 'data.frame':    900 obs. of  7 variables:
##  $ kode_kontrak           : chr  "AGR-000001" "AGR-000011" "AGR-000030" "AGR-000043" ...
##  $ pendapatan_setahun_juta: num  295 271 159 210 165 220 70 88 163 100 ...
##  $ kpr_aktif              : chr  "YA" "YA" "TIDAK" "YA" ...
##  $ durasi_pinjaman_bulan  : num  48 36 12 12 36 24 36 48 48 36 ...
##  $ jumlah_tanggungan      : num  5 5 0 3 0 5 3 3 5 6 ...
##  $ rata_rata_overdue      : chr  "61 - 90 days" "61 - 90 days" "0 - 30 days" "46 - 60 days" ...
##  $ risk_rating            : num  4 4 1 3 2 1 2 2 2 2 ...

Berdasarkan hasil struktur data, variabel risk_rating berupa data numerik. Namun dalam Algoritma C5.0, class variable atau variabel yang ingin diteliti harus berupa faktor, yang artinya variabel risk_rating tidak boleh berupa numerik. Oleh karena itu, perlu dilakukan konversi pada data risk_rating dari data numerik menjadi faktor.

Variabel kpr_aktif dan variabel rata_rata_overdue juga perlu dikonversi dari string menjadi faktor karena variabel tersebut berupa variabel kategorik.

3. Konversi Tipe Data

dataCreditRating$risk_rating <- as.factor(dataCreditRating$risk_rating)
dataCreditRating$kpr_aktif <- as.factor(dataCreditRating$kpr_aktif)
dataCreditRating$rata_rata_overdue <- as.factor(dataCreditRating$rata_rata_overdue)

#Melihat struktur data setelah konversi
str(dataCreditRating)
## 'data.frame':    900 obs. of  7 variables:
##  $ kode_kontrak           : chr  "AGR-000001" "AGR-000011" "AGR-000030" "AGR-000043" ...
##  $ pendapatan_setahun_juta: num  295 271 159 210 165 220 70 88 163 100 ...
##  $ kpr_aktif              : Factor w/ 2 levels "TIDAK","YA": 2 2 1 2 1 1 1 1 1 1 ...
##  $ durasi_pinjaman_bulan  : num  48 36 12 12 36 24 36 48 48 36 ...
##  $ jumlah_tanggungan      : num  5 5 0 3 0 5 3 3 5 6 ...
##  $ rata_rata_overdue      : Factor w/ 5 levels "> 90 days","0 - 30 days",..: 5 5 2 4 3 2 3 3 3 3 ...
##  $ risk_rating            : Factor w/ 5 levels "1","2","3","4",..: 4 4 1 3 2 1 2 2 2 2 ...

4. Feature selection

Feature selection adalah tahap untuk seleksi atau melakukan filtering input variable yang akan digunakan. Berdasarkan data, variabel rata_rata_overdue berkaitan erat dengan risk_rating dimana variabel risk_rating ditentukan berdasarkan rata_rata_overdue, sehingga variabel rata_rata_overdue tidak digunakan. Variabel kode_kontrak juga tidak digunakan karena tidak ada hubungannya dengan penentuan nilairisk_rating.

Atribut yang akan digunakan sebagai input variable adalah variabel durasi_pinjaman_bulan dan jumlah_tanggungan. Hasil filtering tersebut akan disimpan ke variabel baru dengan nama input_data.

input_columns <- c("durasi_pinjaman_bulan", "jumlah_tanggungan")
input_data <- dataCreditRating[,input_columns]

#Melihat struktur input_data
str(input_data)
## 'data.frame':    900 obs. of  2 variables:
##  $ durasi_pinjaman_bulan: num  48 36 12 12 36 24 36 48 48 36 ...
##  $ jumlah_tanggungan    : num  5 5 0 3 0 5 3 3 5 6 ...

Modeling

1. Memisahkan Training dan Testing Dataset

Sebelum melakukan pemodelan, dataset perlu dibagi menjadi dua, yaitu:

  • Training set: porsi dataset yang dijadikan sebagai input yang nantinya akan dianalisis oleh algoritma.

  • Testing set: porsi dataset yang digunakan untuk menguji model yang telah ditraining.

Data akan dibagi secara acak dimana dari 900 data, 800 data akan dijadikan sebagai training set dan 100 data sebagai testing set.

#Mempersiapkan indeks acak untuk training set dan testing set
set.seed(100) #Memastikan nilai acak yang diambil selalu sama
indeks_training_set <- sample(900,800)

#Membuat training set dan testing set

input_training_set <- input_data[indeks_training_set,]
class_training_set <- dataCreditRating[indeks_training_set,]$risk_rating

input_testing_set <-input_data[-indeks_training_set,]

#Menampilkan hasil training set dan testing set
str(input_training_set)
## 'data.frame':    800 obs. of  2 variables:
##  $ durasi_pinjaman_bulan: num  36 24 36 36 36 24 12 48 48 12 ...
##  $ jumlah_tanggungan    : num  1 1 5 1 5 3 3 3 0 0 ...
str(class_training_set)
##  Factor w/ 5 levels "1","2","3","4",..: 1 1 4 1 5 3 3 3 2 1 ...
length(class_training_set)
## [1] 800
str(input_testing_set)
## 'data.frame':    100 obs. of  2 variables:
##  $ durasi_pinjaman_bulan: num  12 36 48 36 48 48 12 12 12 12 ...
##  $ jumlah_tanggungan    : num  0 0 3 3 6 5 0 0 0 4 ...

Berdasarkan hasil output, dapat dilihat bahwa pembagian data menjadi training set dan testing set telah berhasil dimana training set baik untuk input variable maupun class variable terdapat 800 baris data sedangkan testing set memuat 100 baris data.

2. Melakukan pemodelan decision tree dengan Algoritma C5.0

model_C50 <- C5.0(input_training_set, class_training_set, control = C5.0Control(label="Risk Rating"))
summary(model_C50)
## 
## Call:
## C5.0.default(x = input_training_set, y = class_training_set, control
##  = C5.0Control(label = "Risk Rating"))
## 
## 
## C5.0 [Release 2.07 GPL Edition]      Thu Oct 12 10:28:31 2023
## -------------------------------
## 
## Class specified by attribute `Risk Rating'
## 
## Read 800 cases (3 attributes) from undefined.data
## 
## Decision tree:
## 
## jumlah_tanggungan > 4:
## :...durasi_pinjaman_bulan <= 24: 4 (105/30)
## :   durasi_pinjaman_bulan > 24: 5 (120/51)
## jumlah_tanggungan <= 4:
## :...jumlah_tanggungan > 2: 3 (216/20)
##     jumlah_tanggungan <= 2:
##     :...durasi_pinjaman_bulan <= 36: 1 (264/80)
##         durasi_pinjaman_bulan > 36:
##         :...jumlah_tanggungan <= 0: 2 (37/7)
##             jumlah_tanggungan > 0: 3 (58/4)
## 
## 
## Evaluation on training data (800 cases):
## 
##      Decision Tree   
##    ----------------  
##    Size      Errors  
## 
##       6  192(24.0%)   <<
## 
## 
##     (a)   (b)   (c)   (d)   (e)    <-classified as
##    ----  ----  ----  ----  ----
##     184     2     5     6     6    (a): class 1
##      80    30    19     6    11    (b): class 2
##             3   250                (c): class 3
##             2          75    34    (d): class 4
##                        18    69    (e): class 5
## 
## 
##  Attribute usage:
## 
##  100.00% jumlah_tanggungan
##   73.00% durasi_pinjaman_bulan
## 
## 
## Time: 0.0 secs

Interpretasi Hasil Model

Penjelasan dari hasil output pemodelan decision tree pada gambar di atas adalah sebagai berikut:

  • Warna biru: menunjukkan node dan kriteria split.
  • Warna merah : menunjukkan leaf node.
  • Warna hijau : menunjukkan statistik kesalahan dalam bentuk (jumlah klasifikasi / jumlah kesalahan).

Berikut adalah interpretasi dari hasil pemodelan decision tree:

  1. Apabila jumlah tanggungan > 4 dan durasi pinjaman <= 24 bulan, maka risk rating = 4.
  • 105 : 105 data diklasifikasikan nilai risk ratingnya 4.
  • 30 : 30 data dari 105 data salah klasifikasi.
  1. Apabila jumlah tanggungan > 4 dan durasi pinjaman > 24 bulan, maka risk rating = 5.
  • 120 : 120 data diklasifikasikan nilai risk ratingnya 5.
  • 51 : 51 data dari 120 data salah klasifikasi.
  1. Apabila jumlah tanggungan <= 4 dan jumlah tanggungan > 2, maka risk rating = 3.
  • 216 : 216 data diklasifikasikan nilai risk ratingnya 3
  • 20 : 20 data dari 216 data salah klasifikasi
  1. Apabila jumlah tanggungan <= 2, dan durasi pinjaman <= 36 bulan, maka risk rating = 1.
  • 264 : 264 data diklasifikasikan nilai risk ratingnya 1.
  • 80 : 80 data dari 264 data salah klasifikasi.
  1. Apabila jumlah tanggungan = 0 dan durasi pinjaman > 36 bulan, maka risk rating = 2.
  • 37 : 37 data diklasifikasikan nilai risk ratingnya 2.
  • 7 : 7 data dari 37 data salah klasifikasi.
  1. Apabila jumlah tanggungan <= 2, durasi pinjaman > 36 bulan, dan jumlah tanggungan > 0, maka risk rating = 3
  • 58 : 58 data diklasifikasikan nilai risk ratingnya 2.
  • 4 : 4 data dari 58 data salah klasifikasi.

Membuat plot decision tree

Hasil decision tree dapat divisualisasikan dalam bentuk plot sebagai berikut:

plot(model_C50)

3. Evaluasi Model Training

Persentase Kesalahan Klasifikasi

  • Size = 6 = terdapat 6 leaf node pada decision tree yang terbentuk.
  • Errors = 192 (24.0%) = total jumlah kesalahan klasifikasi ada 192 data atau 24% dari keseluruhan data training set (800 data). Atau dalam kata lain, model yang terbentuk menghasilkan output dengan akurasi 76%.

Confusion Matrix

Selain melihat persentase kesalahan klasifikasi, untuk mengukur akurasi dari model yang dibentuk dapat menggunakan confusion matrix.

  • header kolom menunjukkan nilai risk_rating yang diprediksi oleh model.
  • header baris menunjukkan nilai risk_rating pada data sebenarnya.

Berikut adalah penjelasan dari output confusion matrix dari hasil pemodelan decision tree sebelumnya:

  • Pada matriks [1,1] dengan nilai 184 menunjukkan jumlah data yang hasil prediksinya benar.
    • nilai risk_rating hasil klasifikasi adalah 1.
    • nilai risk_rating data sebenarnya adalah 1.
  • Pada matriks [1,2] dengan nilai 2 menunjukkan jumlah data yang hasil prediksinya salah.
    • nilai risk_rating hasil klasifikasi adalah 2.
    • nilai risk_rating data sebenarnya adalah 1.
  • Pada matriks [1,3] dengan nilai 5 menunjukkan jumlah data yang hasil prediksinya salah.
    • nilai risk_rating hasil klasifikasi adalah 3.
    • nilai risk_rating data sebenarnya adalah 1.
  • Pada matriks [1,4] dengan nilai 6 menunjukkan jumlah data yang hasil prediksinya salah.
    • nilai risk_rating hasil klasifikasi adalah 4.
    • nilai risk_rating data sebenarnya adalah 1.
  • Pada matriks [1,5] dengan nilai 6 menunjukkan jumlah data yang hasil prediksinya salah.
    • nilai risk_rating hasil klasifikasi adalah 5.
    • nilai risk_rating data sebenarnya adalah 1.
  • Pada matriks [2,1] dengan nilai 80 menunjukkan jumlah data yang hasil prediksinya salah.
    • nilai risk_rating hasil klasifikasi adalah 1.
    • nilai risk_rating data sebenarnya adalah 2.
  • Pada matriks [2,2] dengan nilai 30 menunjukkan jumlah data yang hasil prediksinya benar.
    • nilai risk_rating hasil klasifikasi adalah 2.
    • nilai risk_rating data sebenarnya adalah 2.
  • dst

Berdasarkan hasil interpretasi tersebut, dapat disimpulkan bahwa diagonal dari matriks tersebut {[1,1],[2,2],[3,3],[4,4], dan [5,5]}, menunjukkan jumlah hasil prediksi/klasifikasi model yang benar.

  • Total jumlah prediksi yang benar = 184 + 30 + 250 + 75 + 69 = 608 data
  • Total jumlah prediksi yang salah = 2 + 5 + 6 + 6 + 80 + 19 + 6 + 11 + 3 + 2 + 34 + 18 = 192 data

Gambar berikut adalah hasil persentase penggunaan atribut untuk pemodelan:

  • 100% jumlah_tanggungan menunjukkan 100% data jumlah_tanggungan digunakan untuk membentuk model.
  • 73% durasi_pinjaman_bulan menunjukkan 73% data durasi_pinjaman_bulan digunakan untuk membentuk model.

Evaluation

Selanjutnya dapat dilakukan evaluasi atau pengujian model terhadap data testing.

1. Membandingkan hasil prediksi dengan data sebenarnya pada testing set

#Menyimpan data risk_rating sebenarnya pada testing set
input_testing_set$risk_rating <- dataCreditRating[-indeks_training_set,]$risk_rating

#Menyimpan hasil prediksi berdasarkan model yang telah dibuat terhadap testing set
input_testing_set$hasil_prediksi <- predict(model_C50, input_testing_set)

#Menyimpan keterangan perbandingan hasil prediksi dengan data sebenarnya
input_testing_set$compare <- input_testing_set$risk_rating == input_testing_set$hasil_prediksi

#Menampilkan 5 data teratas dari testing set
head(input_testing_set)
##    durasi_pinjaman_bulan jumlah_tanggungan risk_rating hasil_prediksi compare
## 3                     12                 0           1              1    TRUE
## 5                     36                 0           2              1   FALSE
## 8                     48                 3           2              3   FALSE
## 40                    36                 3           2              3   FALSE
## 41                    48                 6           2              5   FALSE
## 44                    48                 5           2              5   FALSE
summary(input_testing_set$compare)
##    Mode   FALSE    TRUE 
## logical      13      87

Hasil summary menunjukkan bahwa model menghasilkan 87 prediksi benar dan 13 prediksi salah. Artinya, model dapat memprediksi klasifikasi risk rating dengan akurasi 87%.

2. Membuat confusion matrix

Berikut adalah hasil confusion matrix dari hasil prediksi terhadap data testing:

dcast(hasil_prediksi ~ risk_rating, data=input_testing_set)
## Using compare as value column: use value.var to override.
## Aggregation function missing: defaulting to length
##   hasil_prediksi  1 2  3 4  5
## 1              1 24 6  0 0  0
## 2              2  0 3  1 0  0
## 3              3  0 2 37 0  0
## 4              4  0 0  0 7  0
## 5              5  0 2  0 2 16

Kesimpulan

Hasil pemodelan jumlah tanggungan dan durasi pinjaman terhadap risk rating menghasilkan akurasi 76% pada data train dan akurasi 87% pada data test, sehingga dapat disimpulkan bahwa model yang dibuat cukup baik diterapkan untuk memprediksi risk rating dari calon peminjam.