# clear-up the environment
rm(list = ls())

# chunk options
knitr::opts_chunk$set(
  message = FALSE,
  warning = FALSE,
  fig.align = "center",
  comment = "#>"
)

# scientific notation
options(scipen = 9999)

1 Training Objective

Berikut adalah beberapa tujuan yang akan kita capai dengan belajar Neural Network:

  • Mengenal Neural Network
    • Konsep Neural Network
    • Neural Network dan Deep Learning
  • Arsitektur Neural Network
    • Input Layer
    • Hidden Layer
    • Output Layer
    • Activation Function
    • Weigth
    • Bias
  • Proses Belajar Neural Network
    • Error/Cost Function
    • Learning Rate
    • Feed Forward
    • Backpropagation

Goals Hari 1:

  • Mengetahui perbedaan antara Nerual Network & Traditional Machine Learning
    • Secara konsep dan fungsi (belom sampai ke prediksi)
  • Mempelajari tentang proses training dari Neural Network
  • Perbedaan antara NN & Deep Learning
    • Secara fungsinya

2 Neural Network and Deep Learning

Welcome to the last stage of Machine Learning Specialization, Neural Network & Deep learning! Topik ini erat kaitannya dengan teknologi mutakhir yang menjadi sorotan dunia saat ini yaitu Artifical Intellegence. Topik ini akan membuka gerbang ke perjalanan yang lebih menarik sekaligus menantang di ranah Artificial Intellegence.

2.1 Flashback Machine Learning

Kita refresh kembali materi awal tentang model regresi, baik regresi linear dan regresi logistik agar nantinya lebih familiar perbedaannya dengan arsitektur neural network.

2.1.1 Linear Regression

Misalkan, kita mempunyai data harga rumah seperti berikut:

# Please run the code 
house_prc_linear <- read.csv("data_input/house_price.csv")

head(house_prc_linear)

Deskripsi data:

  • age : usia rumah
  • distance_to_mrt : jarak ke stasiun MRT terdekat
  • num_conv_store : jumlah toko kelontong di lingkungan sekitar
  • price : kisaran harga rumah

Mari kita coba buat Linear Model untuk memprediksi harga rumah dengan menggunakan keseluruhan predictor.

# Please type your answer
house_prc_linear_model <- lm(formula = price ~ ., # target ~ prediktor apa 
                             data = house_prc_linear)

house_prc_linear_model
#> 
#> Call:
#> lm(formula = price ~ ., data = house_prc_linear)
#> 
#> Coefficients:
#>     (Intercept)              age  distance_to_mrt   num_conv_store  
#>       45.759308        -0.346455        -0.005375         1.240674

Persamaan model regresi yang dihasilkan:

price = 45.759308 + -0.346455 age + -0.005375 distance_to_mrt + 1.240674 num_conv_store

Intepretasi:

  • Setiap penambahan 1 age, akan menurunkan harga ruma sebesar 0.346
  • Setiap penambahan 1 distance to mrt, akan menurunkan hara rumah sebesar 0.005
  • Setiap penambahan 1 convenience store, akan menambahkan harga rumah sebesar 1.24

Jika diilustrasikan dengan grafik menjadi sebagai berikut. Tanda \(\Sigma\) menunjukkan bahwa House Price atau target variabel adalah hasil penjumlahan dari nilai masing-masing input atau prediktor yang dikali dengan bobot atau koefisiennya.

2.1.2 Logistic Regression

Sekarang kita coba beralih ke masalah klasifikasi, dengan data yang sama tapi variabel targetnya diubah menjadi kategori (low/high).

# Please run the code 
house_prc_logistic <- read.csv("data_input/house_price_2.csv")

head(house_prc_logistic)

Deskripsi data:

  • age : usia rumah
  • distance_to_mrt : jarak ke stasiun MRT terdekat
  • num_conv_store : jumlah toko kelontong di lingkungan sekitar
  • price : kategori harga rumah (1 = high & 0 = low)

Mari kita coba buat Logistic Model untuk memprediksi harga rumah dengan menggunakan keseluruhan predictor.

# Please type your answer
house_prc_logistic_model <- glm(formula =  price ~ ., 
                                data = house_prc_logistic, 
                                family = "binomial")

house_prc_logistic_model
#> 
#> Call:  glm(formula = price ~ ., family = "binomial", data = house_prc_logistic)
#> 
#> Coefficients:
#>     (Intercept)              age  distance_to_mrt   num_conv_store  
#>        5.103873        -0.093332        -0.003873         0.004009  
#> 
#> Degrees of Freedom: 99 Total (i.e. Null);  96 Residual
#> Null Deviance:       138 
#> Residual Deviance: 61.09     AIC: 69.09

Persamaan log of odds yang dihasilkan oleh model logistic:

price = 5.103873 -0.093332 age -0.003873 distance_to_mrt + 0.004009 num_conv_store

Agar dapat menjadi sebuah nilai peluang untuk menentukan apakah harga rumah itu tinggi (1) atau rendah(0), maka kita menggunakan Sigmoid function untuk mengkonversi nilai peluangnya.

\[P(price) = \frac{1}{1 + e^{-Y}}\]

Contoh jika hasil dari model kita input ke visualisasi Sigmoid Function

# Please run the code 
library(tidyverse)

data.frame(log_of_odd = predict(house_prc_logistic_model, house_prc_logistic)) %>% 
  mutate(prob = 1/(1 + exp(-log_of_odd))) %>% 
  ggplot(aes(log_of_odd, prob)) +
  geom_point(color = "red")+
  geom_line() +
  labs(x = "Log of Odds",
       y = "Probability") +
  theme_minimal()

Jika kita ilustrasikan dengan gambar, maka sebenarnya regresi logistik sama seperti regresi linear, yakni hasil perkalian nilai prediktor dengan nilai koefisiennya dijumlahkan terlebih dahulu, kemudian yang membedakan degnan regresi linear adalah setelah dijumlahkan hasilnya kemudian dikonversi menjadi sebuah peluang dengan range 0-1 menggunakan Sigmoid function.

2.2 Neural Network

Sistem saraf yang dimiliki manusia terdiri dari sel saraf yang dinamakan neuron, dan neuron tersebut amat banyak hingga membentuk jaringan. Tiap stimulus/input dari luar akan diterima oleh panca indra sebagai signal kemudian akan dialirkan melalui sel saraf satu ke sel saraf lainnya. Jaringan sel saraf tersebar dari ujung jari hingga otak dan berlanjut kembali ke seluruh tubuh kita.

Jaringan sel saraf terus mengalirkan informasi dari stimulus/input, diproses melalui otak, hingga diekspresikan melalui reaksi/aktivitas tubuh sebagai output atau respon yang kita berikan.

2.2.1 Arsitektur Neural Network

Komponen Neural Network:

  • Neural Network terdiri dari 3 komponen utama :
    • Input layer : variabel input (x1, x2, …, xn)
    • Hidden layer : layer pemrosesan dan pembobotan data dari setiap variable input
    • Output layer : target variabel

Berikut adalah contoh komponen neural network untuk kasus klasifikasi harga rumah:

Karakteristik Setiap Komponen Neural Network:

  • Input Layer:
    • Jumlah node pada input layer akan sesuai dengan jumlah variable prediktor
    • Selain node untuk variable prediktor, akan ada 1 node juga untuk nilai intercept/bias
  • Hidden Layer:
    • Jumlah node pada hidden layer ditentukan oleh user
    • Akan ada 1 node juga untuk nilai intercept/bias
  • Output Layer:
    • Jumlah node pada output layer sesuai dengan jumlah target variabel

Quick Glossary

  • Node/Neuron: Unit terkecil pada arsitektur neural network yang berfungsi untuk menyimpan informasi dan meneruskan informasi tersebut, sering disebut sebagai neuron.
  • Weight/Bobot: Bobot yang menggambarkan besar informasi yang diteruskan dari setiap nodes. Pada gambar di atas, weight dilambangkan dengan garis.
    • Bobot yang diberikan pada setiap nodenya di-inisiasi secara random
  • Fully Connected: Setiap node pada setiap layer yang ada harus saling terhubung.

2.2.2 Kasus Regresi

Kita coba buat model Neural Network untuk data price dengan target variabel harga rumah (linear). Kita bisa menggunakan package neuralnet untuk membuat model Neural Network.

# Please run the code 
library(neuralnet)

Dari package tersebut, fungsi yang akan kita gunakan adalah neuralnet(). Terdapat 4 parameter yang dapat kita gunakan pada fungsi tersebut, yaitu:

  • formula : menentukan mana yang target mana yang prediktor yang ingin digunakan
  • data : data yang ingin digunakan
  • hidden : berapa jumlah node yang mau kita pakai di hidden layer tsb.
  • rep : berapa banyak jumlah model yang ingin kita buat.

Additional Notes: parameter rep itu intuisinya sama dengan jumlah model DT(Decission Tree) yang dibuat pada model RF (Random Forest).

Sebagai langkah awal, mari kita coba buat sebuah model neuralnet dengan jumlah node di hidden layernya sama dengan jumlah variable inputnya.

head(house_prc_linear)
# Please type your answer
set.seed(100)
model_nn_reg <- neuralnet(formula = price ~ ., 
                          data = house_prc_linear, 
                          hidden = 3, 
                          rep = 3)

Quick Notes:

Setiap membuat model NN kita harus memberikan set.seed() karena pada step pertama bobot di inisiasi secara acak. Dengan adanya set.seed() berfungsi untuk mengunci acakan tersebut, sehingga tiap kali pemodelan dilakukan/dijalankan hasilnya tidak berubah2.

Untuk melihat hasil terbaik dari beberapa model yang dibuat, kita dapat melihatnya dengan menggunakan fungsi di bawah ini.

plot(model_nn_reg, # nama object model
     rep = "best") # untuk mengambil model yang plg baik

2.2.2.1 Proses Training Model

Proses pelatihan model dengan menggunakan konsep belajar neural network adalah belajar dari kesalahan. Proses belajarnya akan terus dilakukan sampai dengan model konvergen. Berikut runtut proses training model

Step 1:

Tahapan pertama yang dilakukan adalah memberikan pembobotan/weight awal secara random.

Step 2:

Aliran informasi terjadi untuk melakukan prediksi dari Input Layer -> Hidden Layer -> Output Layer, aliran informasi tersebut biasanya disebut dengan Feed Forward.

Step 2.1:

Pada tahapan ini, setiap informasi yang masuk ke Hiden dan Output Layer akan dilakukan scalling. Tahapan scalling yang dilakukan sering juga disebut dengan Activation Function. Tujuan dilakukannya scaling ataupun peletakan Activation Function adalah:

  • Menjaga agar nilai yang diteruskan ke node-node selanjutnya tidak semakin besar dan memperberat komputasi.
  • Nilai yang diteruskan sudah dalam bentuk sepatutnya, misal output klasifikasi berupa peluang: 0~1.
knitr::include_graphics("assets/activation_example2.gif")

Berikut adalah beberapa Activation Fucntion yang dapat digunakan:

  • Linear
    • Activation ini digunakan untuk kasus regregsi (range: -inf ~ inf)
    • Merupakan default activation function pada fungsi neuralnet()
  • Logistic
    • Activation ini digunakan untuk kasus klasifikasi biner (range: 0 ~ 1)
  • Softmax
    • Activation ini digunakan untuk kasus klasifikasi multiclass (range 0 ~ 1)
    • Softmax akan menghasilkan nilai peluang untuk masing-masing kelas target yang bila dijumlahkan adalah 1. Data baru akan diklasifikasikan ke kelas target yang memiliki peluang paling tinggi.
  • ReLu/Rectified Linear Unit
    • Activation ini cocok di hidden layer untuk kasus data image (range: 0 ~ inf)
  • tanh
    • Activation ini cocok di hidden layer bila nilai prediktor banyak yang negatif (range: -1 ~ 1)

Step 3:

Setelah satu proses Feed Foward selesai dan hasilnya sudah didapatkan, akan dilakukan perhitungan error dari hasil yang didapatkan. Proses perhitungan error tersebut dinamakan Cost Function.

Cost function adalah nilai acuan kebaikan model; nilai untuk mengevaluasi kebaikan model; dapat juga dianalogikan sebagai error. Model dapat “belajar” dengan mengetahui cost function yang harus ia gunakan untuk mengevaluasi dirinya sendiri. Cost function yang digunakan berbeda untuk tiap kasus:

  • Kasus Regresi:
    • Sum of Squared Error(sse)

\[SSE = \frac{1}{2} {\Sigma (y - \hat y)^2}\]

  • Kasus Klasifikasi:
    • 2 Target Variable: Binary Cross-entropy (ce)

\[Binary\ Cross-Entropy = -p(x)\ log\ q(x) + (1-p(x))\ log\ (1-q(x))\]

Keterangan:

  • \(p(x)\) : Peluang aktual ( 1 atau 0)
  • \(q(x)\) : Peluang hasil prediksi oleh model

Misalkan kita punya target aktual 1 (price = high) dan prediksi model mengeluarkan peluang 0.75

\[Binary\ Cross-Entropy = -1\ ( log\ 0.75 + (1-1)\ log\ (1-0.75) )= - (1\ ( -0.287) + 0) = 0.287\]

Step 4:

Seperti yang disampaikan di awal, bahwa konsep belajar Neural Network adalah belajar dari kesalahan. Maka dari itu, setelah mendapatkan nilai error, model akan memanfaatkan informasi error tersebut untuk memperbaiki bobot awal yang sudah diberikan. Proses perbaikan bobot tersebut sering disebut juga sebagai proses Back Propagation.

Manusia tidak serta merta terlahir pintar. Selama manusia hidup, selama itu pula manusia belajar.

NOTE: 1x feed forward & 1x back propagation akan dihitung sebagai 1 Step/Epoch.

Step 4.1:

Proses optimasi bobot dan bias tersebut dilakukan dengan metode Gradient Descent.

  • Gradient: Kemiringan
  • Descent: Penurunan

Berikut tahapan Gradient Descent untuk suatu bobot:

  1. Memplotkan kurva perubahan cost function (error) terhadap bobot
  2. Mengupdate dari bobot awal (yang sedang digunakan) dengan mencari turunan parsialnya (kalkulasi kalkulus)

\[\nabla g(W_{k-1}) = \frac{\partial\ Cost}{\partial\ {Output}} * \frac{\partial\ Out}{\partial\ {Input}} * \frac{\partial\ Input}{\partial\ W_{n}}\]

  • Nilai Error akan kita bandingkan dengan nilai dari nilai outputnya, karena nilai Error baru bisa kita dapatkan jika kita sudah memiliki nilai outputnya
  • Nilai Output akan kita bandingkan dengan nilai Input, karena nilai Output baru bisa kita dapatkan jika kita sudah meiliki nilai input.
  • Nilai Inputnya akan kita badningan dengan nilai bobot, karena nilai inputnya akan kita kalkulasikan dengan bobotnya

Keterangan:

\(\nabla g(W_{k-1}\): Gradient dari iterasi k-1
\(\frac{\partial\ Cost}{\partial\ {Output}}\): Menghitung turunan parsial berdasarkan nilai error yang terjadi \(\frac{\partial\ Out}{\partial\ {Input}}\): Menghitung turunan parsial berdasarkan nilai output yang dihasilkan (linear/logistic) \(\frac{\partial\ Input}{\partial\ W_{n}}\): Mehgitung turunan parsial berdasarkan nilai input

  1. Besar penambahan/penurunan bobot adalah bobot awal - (learning rate x gradient). Learning rate adalah seberapa cepat model melakukan update bobot (range: 0 ~ 1):

\[W_k = W_{k-1} - \alpha \nabla g(W_{k-1})\]

Keterangan:

\(W_k\) : Bobot pada iterasi k \(W_{k-1}\) : Bobot pada iterasi k-1 \(\alpha\) : Learning rate \(\nabla g(W_{k-1})\) : gradient dari iterasi k-1

  • Learning rate rendah:
    • penaikan/penurunan bobot akan dilakukan perlahan-lahan (perubahannya kecil)
    • waktu untuk mencapai titik lokal optimum dari bobot akan lebih lama
  • Learning rate tinggi:
    • penaikan/penurunan bobot akan dilakukan secara cepat (perubahannya besar)
    • waktu untuk mencapai titik lokal optimum dari bobot akan lebih cepat
    • ada kemungkinan untuk melewati titik local optimum.

Step 5:

Model akan secara terus-menerus memperbaiki bobotnya hingga didapatkan error terkecil.

Step itu berenti 120?

Step 120 itu error -> 1.5 Step 121 error -> 1.6

plot(model_nn_reg, "best")

plot(model_nn_reg, 3)

Quick Glossary

  • weight: informasi yang dibawa oleh setiap neuron, sama seperti slope pada regresi. Awalnya bobot ini akan di inisialisasi secara random.
  • bias: sama seperti intercept pada regresi.Awalnya bias akan di inisialisasi secara random
  • Activation function : fungsi untuk standarisasi hasil perhitungan
  • Forward propagation: proses membawa data input melewati tiap neuron pada hidden layer sampai pada output layer yang nantinya akan dihitung errornya
  • Backpropogation: proses membawa error yang didapat dari forward propagation untuk mengupdate setiap weight dan bias.
  • Cost function: Error. Selisih antara hasil prediksi dan data aktual. Cross entropy (ce) untuk klasifikasi dan SSE untuk regresi.
  • Step: Banyaknya proses iterasi (1x forward dan 1x backward = 1 step) dalam training model.

2.2.2.2 Highlight on Hidden Layer

Lalu bagaimana jika kita membuat model regresi dengan menggunakan fungsi neuralnet() tapi kita tidak mengisi nilai hidden nodenya.

# Please type your answer

model_nn_reg_wo_hidden <- neuralnet(formula = price ~ ., 
                                    data = house_prc_linear, 
                                    hidden = 0, # tidak menggunakan hidden layer 
                                    rep = 0)
plot(model_nn_reg_wo_hidden, rep = "best")

Jika kita membuat model neural network tanpa hidden layer, nilai weight/bobot dan interceptnya kurang lebih akan sama dengan model regresi linear yang sudah kita buat di awal. Mari kita coba bandingkan dengan model linear yang sudah kita simpan kedalam objek house_prc_linear_model.

house_prc_linear_model
#> 
#> Call:
#> lm(formula = price ~ ., data = house_prc_linear)
#> 
#> Coefficients:
#>     (Intercept)              age  distance_to_mrt   num_conv_store  
#>       45.759308        -0.346455        -0.005375         1.240674

2.2.3 Kasus Klasifikasi

Dalam membuat model neural network untuk kasus klasifikasi, kita masih akan menggunakan fungsi neuralnet() akan tetapi terdapat beberapa parameter baru yang akan kita gunakan, yaitu:

  • err.fct = parameter ini digunakan untuk menghitung nilai error atau sering disebut juga Cost Function.
    • Pada kasus klasifikasi (2 target variable) kita bisa isi dengan ce (Cross Entropy)
    • Pada kasus klasifikasi (> 2 target variable) kita bisa isi dengan categorical
    • Pada kasus regresi kita bisa isi dengan sse (Sum of Square Error) -> default
  • act.fct = parameter ini digunakan untuk melakukan scaling atau transformasi nilai pada node, sebelum nilai dilanjutkan ke node berikutnya. Parameter ini sering disebut juga sebagai Activation Function.
    • Pada kasus klasifikasi kita bisa isi dengan logistic
    • Pada kasus regresi kita bisa isi dengan linear -> default
  • linear.output = parameter ini bisa kita isi dengan logical value TRUE/FALSE. Tujuannya untuk mengatur hasil yang diteruskan setelah melewati Activation Function.
    • Pada kasus klasifikasi kita bisa isi dengan FALSE
    • Pada kasus regresi kita bisa isi dengan TRUE
# Please type your answer
set.seed(100)
model_nn_log <- neuralnet(formula = price ~ ., 
                          data = house_prc_logistic, 
                          hidden = 3, 
                          rep = 0, # ktia hanya membuat satu model
                          err.fct = "ce",
                          act.fct = "logistic",
                          linear.output = F,
                          stepmax = 1e7) 

Notes: Ketika kita ingin menambahkan step pada model neuralnet kita, kita dapat menambahkan parameter stepmax.

plot(model_nn_log, "best")

Notes: Ketika kita ingin melihat hasil model yang kita buat dengan menggunakan fungsi plot(), kita harus menambahkan parameter "best".

— End of Day 1 —

Goals Hari ke 2:

  • Memahami perbedaan antara NN & DL
    • Secara fungsinya
    • Bagaimana melakukan prediksi dengan menggunakan model NN & DL
  • Memahami Deep Learning dengan menggunakan kasus baru
    • Mengulang implementasi dari fungsi neuralnet() terutama pada pembuatan model DL
    • Addtional step Data Pre-Processing
  • Menginstallasi Framework KERAS

2.3 Deep Learning with neuralnet

Kita telah mengetahui tentang neural network. Namun apa hubungannya dengan Deep Learning? Deep learning ternyata hanyalah suatu neural network yang memiliki jumlah hidden layer yang lebih dari satu. Untuk membuatnya, kita dapat mengubah nilai pada parameter hidden.

2.3.1 Kasus Regresi

Model Regresi dengan 2 hidden layer

Notes: Jika kita ingin menambahkan hiddlen layer, kita bisa menggunakan fungsi c() pada parameter hidden.

# Please type your answer
set.seed(100)
model_regresi_2layer <- neuralnet(formula = price ~ ., 
                                  data = house_prc_linear, 
                                  hidden = c(5, 3), # c(nodes hidden layer 1, nodes hidden layer 2) 
                                  rep = 3)
plot(model_regresi_2layer, rep = "best")

Model Regresi dengan 3 hidden layer

Bu Leni: 5, 3, 1, Step: 199, Error: 8996.34 Pak Reynaldi: 5, 3, 2, Step: 149, Error: 8996.34 Pak Jeremi: 5, 3, 5, Step: 98, Error: 8996.34 Bu Sofi: 5, 4, 3, Step: 129, Error: 8996.34 Pak Ibrahim: 5, 3, 2, Step: 149, Error: 8996.34

# Please type your answer
set.seed(100)
model_regresi_3layer <- neuralnet(formula = price ~.,
                                  data = house_prc_linear,
                                  hidden = c(7, 5, 3),
                                  rep = 3) # kita membuat beberapa model sekaligus
plot(model_regresi_3layer, rep = 1)

plot(model_regresi_3layer, rep = 2)

plot(model_regresi_3layer, rep = 3)

Noted: Rule of Thumbs menentukan jumlah nodes pada hidden layer

  • 2^n (n -> nilai yang mendekati dari jumlah input nodesnya)
  • Untuk hidden layer 1, jumlah nodesnya minimal sama (lebih boleh)
  • Setiap ada hidden layer setelahnya (hidden 2, dst), jumlah nodesnya akan diperkecil berdasarkan perhitungan 2^n

Contoh:

Input Nodes = 10 Hidden layer 1 = 2^4 = 16 Hidden layer 2 = 2^3 = 8 Hidden layer 3 = 2^2 = 4

2.3.2 Prediksi Model neuralnet

Kalo misalkan kita rewind kita, dipembelajaran RM/ C1 / C2. Fungsi apakah yang akan kita gunakan? predict()

Setelah berhasil membuat model DL, mari kita coba pelajari bagaimana melakukan prediksi dengan menggunakan model regresi dengan 2 layer yang sudah kita buat. Untuk memprediksi data menggunakan package neuralnet, bisa digunakan fungsi compute() dengan parameter:

  • x = model NN/DL
  • covariate = object data yang digunakan
  • rep = repetisi ke berapa yang ingin digunakan
    • Jika kita hanya membuat satu mode, kita tidak ush menggunakan parameter ini
    • Jika kita menggunakan rep pada pembuatan model, kita harus isi dengan model kebreapa yang menghasilkan error terkecil

Jika kita ingin mencari tahu secara manual model keberapa yang memberikan error terkecil, kita dapat menggunakan fungsi which.min(). Berikut contohnya:

which.min(model_regresi_2layer$result.matrix[1,])
#> [1] 1
model_regresi_2layer$result.matrix[1, ]
#> [1] 8996.34 8996.34 8996.34
which.min(model_regresi_2layer$result.matrix[1, ])
#> [1] 1
model_regresi_3layer$result.matrix[1,]
#> [1] 8996.34 8996.34 8996.34

Notes: Setiap penambahan 1 hidden layer tidak menjamin akan menurunkan nilai error.

Dislacimer: Disini kita tidak melakukan tahapan Cross Validation, maka dari itu kita akan langsung memprediksi terhadap data yang sudah kita gunakan untuk membuat model.

# Please type your answer
dl_prediction <- compute(x = model_regresi_2layer,
                         covariate = house_prc_linear,
                         rep = 1)

Untuk mengeluarkan hasil prediksinya kita dapat memangilnya dengan menambahkan $net.result pada object tempat menyimpan hasil prediksinya.

dl_prediction$net.result %>% head()
#>          [,1]
#> [1,] 38.44002
#> [2,] 38.44002
#> [3,] 38.44002
#> [4,] 38.44002
#> [5,] 38.44002
#> [6,] 38.44002
# install.packages("MLmetrics")

2.3.3 Kasus Klasifikasi

Kita adalah seorang analis dari suatu perusahaan bank. Perusahaan ingin menganalisis data bank telemarketing campaigns yang dilakukan baru-baru ini, dengan tujuan, memprediksi apakah seorang calon pelanggan akan setuju mengajukan program deposit atau tidak?

Business Question: Memprediksi apakah seorang calon pelanggan akan setuju mengajukan program deposit atau tidak?

2.3.3.1 Read Data

Sumber data: Bank Marketing Dataset, UCI Machine Learning Repository

Direteory & nama data: data_input/bank-full.csv

# Please type your answer
bank <- read.csv("data_input/bank-full.csv", 
                 sep = ";") # untuk memisahkan value pada DF
  
head(bank)

Deskripsi kolom:

  • age: umur
  • job: kategori pekerjaan
  • marital: status menikah
  • education: tingkat pendidikan
  • default: apakah memiliki kredit gagal bayar (default)?
  • balance: uang yang tersimpan dalam rekening
  • housing: apakah memiliki kredit rumah?
  • loan: apakah memiliki kredit pribadi?
  • contact: metode kontak/telefon
  • day: day-of-month dari kontak terakhir
  • month: bulan dari kontak terakhir
  • duration: durasi kontak pada campaign ini
  • campaign: jumlah kontak yang dilakukan pada campaign ini
  • pdays: jumlah hari berlalu setelah kontak dari campaign sebelumnya
  • previous: jumlah kontak yang dilakukan pada campaign sebelumnya
  • poutcome: outcome dari campaign sebelumnya
  • y: outcome dari campaign ini (target variable)

2.3.3.2 Data Wrangling

  • Apakah beberapa kolom ini month, contact, pdays, day & duration perlu kita hilangkan?

  • contact-> boleh kita hilangkan karena ada unknown dan data yang kita memang data telemarking dimana device yang adalah telfon dan hal tersebut bisa dianggap tidak penting

unique(bank$contact)
#> [1] "unknown"   "cellular"  "telephone"
bank$contact %>% table()
#> .
#>  cellular telephone   unknown 
#>     29285      2906     13020
  • month & day: bisa dihilangkan karena kita tidak berhubungan dengan tanggal

  • pdays: karena itu sudah berlalu, dan dari bisnis case kita inign melihatnya yang sekarang maka dari itu kita tidak memerlukan hal tersebut

  • duration: kolom duration tidak boleh kita gunakan karena akan menyebabkan Data Leakage karena data tersebut baru akan kita dapatkan setelah kita menelfon orang tersebut. Selain itu data tersebut akan membuat model kita menjadi model yang perfect separation.

  • Adakah tipe data yang belum sesuai?

# Please type your answer
bank_clean <- bank %>% 
  select(-month, -day, -pdays, -duration, -contact) %>% 
  mutate_if(is.character, as.factor)

bank_clean %>% 
  head()

2.3.3.3 Exploratory Data Analysis

  • Apakah terdapat missing value?
# Please type your answer
bank_clean %>% 
  is.na() %>% 
  colSums()
#>       age       job   marital education   default   balance   housing      loan 
#>         0         0         0         0         0         0         0         0 
#>  campaign  previous  poutcome         y 
#>         0         0         0         0
bank_clean %>% 
  anyNA()
#> [1] FALSE
  • Apakah proporsi kelas target seimbang?
# Please type your answer
bank_clean$y %>% 
  table() %>% 
  prop.table()
#> .
#>        no       yes 
#> 0.8830152 0.1169848

2.3.3.4 Data Pre-Processing

  • One Hot Encoding

Karena fungsi neuralnet() tidak dapat secara otomatis mengubah prediktor bertipe factor menjadi dummy variable kita haru mengubahnya menggunakan fungsi model.matrix(). Proses transformasi tersebut sering juga disebut sebagai One Hot Encoding.

Ilustrasi fungsi model.matrix():

levels(bank_clean$marital)
#> [1] "divorced" "married"  "single"
head(bank_clean$age)
#> [1] 58 44 33 47 33 35
# model.matrix(~variabel, data)
model.matrix(~marital, bank_clean) %>% head()
#>   (Intercept) maritalmarried maritalsingle
#> 1           1              1             0
#> 2           1              0             1
#> 3           1              1             0
#> 4           1              1             0
#> 5           1              0             1
#> 6           1              1             0
model.matrix(~age, bank_clean) %>% head()
#>   (Intercept) age
#> 1           1  58
#> 2           1  44
#> 3           1  33
#> 4           1  47
#> 5           1  33
#> 6           1  35
bank$education %>% unique()
#> [1] "tertiary"  "secondary" "unknown"   "primary"
bank_clean$education %>% levels()
#> [1] "primary"   "secondary" "tertiary"  "unknown"
model.matrix(~education, bank_clean) %>% head()
#>   (Intercept) educationsecondary educationtertiary educationunknown
#> 1           1                  0                 1                0
#> 2           1                  1                 0                0
#> 3           1                  1                 0                0
#> 4           1                  0                 0                1
#> 5           1                  0                 0                1
#> 6           1                  0                 1                0

Notes: Level yang dihilangkan adalah level yang paling rendah dari factor di kolom tersebut.

Mari kita coba implementasikan kepada data kita, lalu kita simpan ke objek baru bank_ohe.

# Please type your answer
bank_ohe <- model.matrix(object = y ~ ., # target ~ kolom yang mau diubah
                         data = bank_clean)

bank_ohe %>% head()
#>   (Intercept) age jobblue-collar jobentrepreneur jobhousemaid jobmanagement
#> 1           1  58              0               0            0             1
#> 2           1  44              0               0            0             0
#> 3           1  33              0               1            0             0
#> 4           1  47              1               0            0             0
#> 5           1  33              0               0            0             0
#> 6           1  35              0               0            0             1
#>   jobretired jobself-employed jobservices jobstudent jobtechnician
#> 1          0                0           0          0             0
#> 2          0                0           0          0             1
#> 3          0                0           0          0             0
#> 4          0                0           0          0             0
#> 5          0                0           0          0             0
#> 6          0                0           0          0             0
#>   jobunemployed jobunknown maritalmarried maritalsingle educationsecondary
#> 1             0          0              1             0                  0
#> 2             0          0              0             1                  1
#> 3             0          0              1             0                  1
#> 4             0          0              1             0                  0
#> 5             0          1              0             1                  0
#> 6             0          0              1             0                  0
#>   educationtertiary educationunknown defaultyes balance housingyes loanyes
#> 1                 1                0          0    2143          1       0
#> 2                 0                0          0      29          1       0
#> 3                 0                0          0       2          1       1
#> 4                 0                1          0    1506          1       0
#> 5                 0                1          0       1          0       0
#> 6                 1                0          0     231          1       0
#>   campaign previous poutcomeother poutcomesuccess poutcomeunknown
#> 1        1        0             0               0               1
#> 2        1        0             0               0               1
#> 3        1        0             0               0               1
#> 4        1        0             0               0               1
#> 5        1        0             0               0               1
#> 6        1        0             0               0               1

Setelah berhasil melakukan One Hot Encoding, ada 3 hal lagi yang harus kita lakukan yaitu, menjadikan hasil fungsi model.matrix() ke dataframe, menghilangkan nilai intercept dan menambahkan kolom target.

# Please type your answer
bank_ohe_clean <- bank_ohe %>% 
  as.data.frame() %>% 
  select(-"(Intercept)") %>% 
  mutate(y = bank_clean$y)
bank_ohe_clean %>% head()
  • Transformasi Nama Kolom

Setelah melakukan One Hot Encoding, terdapat beberapa nama kolom baru yang memiliki simbol -. Sedangkan model neuralnet tidak bisa menerima sebuah nama kolom yang memiliki simbol, maka dari itu kita harus menghilangkan simbol tersebut.

Kita dapat menghilangkan simbol tersebut dengan menggunakan fungsi gsub(). Pada fungsi tersebut terdapat 3 parameter yang dapat kita gunakan:

  • pattern: simbol yang ingin kita hilangkan
  • replacement: apa yang ingin di-isi ke pattern yang dihilangkan
  • x: nama datanya

Intuisi fungsi gsub():

temp <- c("bank-tele","jobblue-collar")
gsub(pattern = "-",replacement = "",x = temp)
#> [1] "banktele"      "jobbluecollar"

Mari kita coba implementasikan ke objek data kita.

# Please type your answer
colnames(bank_ohe_clean) <- gsub(pattern = "-",
                                 replacement = "",
                                 x = colnames(bank_ohe_clean))
bank_ohe_clean %>% colnames()
#>  [1] "age"                "jobbluecollar"      "jobentrepreneur"   
#>  [4] "jobhousemaid"       "jobmanagement"      "jobretired"        
#>  [7] "jobselfemployed"    "jobservices"        "jobstudent"        
#> [10] "jobtechnician"      "jobunemployed"      "jobunknown"        
#> [13] "maritalmarried"     "maritalsingle"      "educationsecondary"
#> [16] "educationtertiary"  "educationunknown"   "defaultyes"        
#> [19] "balance"            "housingyes"         "loanyes"           
#> [22] "campaign"           "previous"           "poutcomeother"     
#> [25] "poutcomesuccess"    "poutcomeunknown"    "y"

2.3.3.5 Build Model

Buat model deep learning untuk kasus klasifikasi dengan parameter:

  • Gunakan set.seed(100)
  • Jumlah hidden layer: 2
    • node hidden layer 1: 5
    • node hidden layer 2: 3
  • Jumlah percobaan pembuatan model: 1
# Please type your answer
# set.seed(100)
# 
# model_bank <- neuralnet(formula = y ~ .,
#                         data = bank_ohe_clean,
#                         hidden = c(5,3),
#                         rep = 1,
#                         stepmax = 1e7,
#                         act.fct = "logistic",
#                         err.fct = "ce",
#                         linear.output = F)

Bila kita nanti membuat model deep learning, ada baiknya kita simpan model secara lokal dalam bentuk RDS agar fleksibel untuk digunakan kembali.

# save model
#saveRDS(model_bank, file = "bank_marketing_nn.rds")

File RDS bisa untuk menyimpan data hasil cleaning dan hasil training model/

Agar kita dapat melihat hasil dari training dengan parameter yang sudah kita atur di atas, mari kita coba baca model yang sebelumnya sudah ditraining dan disimpan ke dalam file rds, dengan nama bank_marketing_nn.rds yang terletak di folder model. Model tersebut akan kita coba simpan kedalam object dengan nama model_klasifikasi_2layer

# Please type your answer
model_klasifikasi_2layer <- readRDS("model/bank_marketing_nn.rds")
plot(model_klasifikasi_2layer, "best")

2.3.3.6 Prediction

Dalam melakukan prediksi, langkah-langkahnya sama dengan kasus regresi. Kita akan menggunakan fungsi compute() dan hasil prediksinya akan kita simpan ke bank_pred_result

# Please type your answer
bank_pred_result <- compute(x = model_klasifikasi_2layer,
                            covariate = bank_ohe_clean)
bank_pred_result$net.result %>% 
  head()
#>        [,1]
#> 1 0.1319202
#> 2 0.4003350
#> 3 0.4003350
#> 4 0.1319202
#> 5 0.4003350
#> 6 0.3766056

Setelah mendapatkan hasilnya, jangan lupa untuk mengubahnya kedalam bentuk label agar bisa dimasukan ke fungsi confusionMatrix().

# Please type your answer
bank_pred_label <- ifelse(test = bank_pred_result$net.result > 0.5,
                          yes = "yes", #hasil dari kondisi jika parameter test terpenuhi
                          no = "no") # hasil dari kondisi jika parameter test gagal

# mengubah menjadi factor
bank_pred_label <- bank_pred_label %>% 
  as.factor()
bank_pred_label %>% head()
#> [1] no no no no no no
#> Levels: no yes

2.3.3.7 Model Evaluation

Business Question: Memprediksi apakah seorang calon pelanggan akan setuju mengajukan program deposit atau tidak?

  • Kelas positif: yes
  • Kelas negatif: no

Notes: ketika kita menentukan manakah yang masuk ke kelas positif atau negatif, kita melihat value mana yang ingin kita capai. Karena yes yang kita inginkan, maka value tersebut yang kita letakan pada kelas positif.

# Please type your answer
caret::confusionMatrix(data = bank_pred_label,
                       reference = bank_ohe_clean$y,
                       positive = "yes")
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction    no   yes
#>        no  39793  5025
#>        yes   129   264
#>                                               
#>                Accuracy : 0.886               
#>                  95% CI : (0.883, 0.8889)     
#>     No Information Rate : 0.883               
#>     P-Value [Acc > NIR] : 0.02422             
#>                                               
#>                   Kappa : 0.078               
#>                                               
#>  Mcnemar's Test P-Value : < 0.0000000000000002
#>                                               
#>             Sensitivity : 0.049915            
#>             Specificity : 0.996769            
#>          Pos Pred Value : 0.671756            
#>          Neg Pred Value : 0.887880            
#>              Prevalence : 0.116985            
#>          Detection Rate : 0.005839            
#>    Detection Prevalence : 0.008693            
#>       Balanced Accuracy : 0.523342            
#>                                               
#>        'Positive' Class : yes                 
#> 
  • Accuracy: (TP + TN)/Total
    • Itu cocok kalo nilai dari target variable kita itu seimbang
    • Kalo kita menitik beratkan pada sebuah value, kita juga gk bisa pake accuracy
  • Recall/Sensitivity: TP / (TP + FN)
    • Ketika nilai recallnya tinggi, berarti orang yang kita prediksi menolak itu aktualnya akan menerima
  • Precission/Pos Pred Value: TP / (TP + FP)
    • Ketika nilainya tinggi, berarti orang yang kita prediksi menerima itu aktualnya menolak
  • Specificity
    • Untuk mempertimbangkan kelas negatif

Jadinya nilai yang kita pentingkan adalah nilai Recall

3 Deep Learning with Keras

Ada banyak frameworks (template) yang bisa kita gunakan untuk membangun neural network/deep learning model:

  • Tensor Flow
  • Keras
  • Pytorch
  • Caffe
  • Theano, etc.

Untuk selanjutnya, kita akan menggunakan Keras dalam membuat arsitektur dan melakukan training model. Keras adalah package yang membantu kita mengimplementasikan model Deep Learning dengan cepat. Keras memanfaatkan tensorflow, sebuah tools open source yang dikembangkan oleh Google untuk implementasi Deep Learning.

3.1 Verify keras installation

library(keras)
library(tensorflow)
use_condaenv("r-tensorflow")
model <- keras_model_sequential()