# 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)
Ada banyak frameworks (template) yang bisa kita gunakan untuk membangun neural network/deep learning model:
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.
keras
installationlibrary(tidyverse)
library(keras)
library(tensorflow)
model <- keras_model_sequential()
Goals hari ke 3 itu apa si?
Seperti yang sudah disampaikan di awal, deep learning merupakan
sebuah framework yang sering digunakan ketika menghadapi data
unstructured. Maka dari itu mari kita lakukan image
classification menggunakan deep learning dengan framework
keras
. Kita akan gunakan data MNIST yang berisi data image
tentang tulisan tangan untuk beragam angka. Kita akan coba
klasifikasikan setiap tulisan tangan ke label angka yang sesuai.
Data Source: kaggle
Data MNIST ada pada folder data_input/mnist
:
# Read mnist train
mnist_train <- read.csv("data_input/mnist/train.csv")
# Read mnist train
mnist_test <- read.csv("data_input/mnist/test.csv")
Pada tahapan eksplorasi data kali ini, mari coba jawab beberapa pertanyaan di bawah ini.
# Please type your answer
mnist_train %>%
dim()
#> [1] 42000 785
Row: 42000 Column: 785
# Please type your answer
mnist_train$label %>%
unique()
#> [1] 1 0 4 7 3 5 8 9 2 6
Category: 10 target variable
Kita akan mencoba untuk meprediksi gambar tersebut berisikan angka berapa, dari angka 0-9
mnist_train$label %>%
table() %>%
prop.table()
#> .
#> 0 1 2 3 4 5 6
#> 0.09838095 0.11152381 0.09945238 0.10359524 0.09695238 0.09035714 0.09850000
#> 7 8 9
#> 0.10478571 0.09673810 0.09971429
Proporsi target variable yang kita miliki dapat dikategorikan sebagai data yang balanced.
# Please type your answer
mnist_train %>%
ncol() - 1
#> [1] 784
Jumlah prediktor: 784
Dari keseluruhan kolom yang ada, kita perlu kurangi 1 karena 1 kolom tersebut untuk menampung data target variable
# Please type your answer
mnist_train %>%
select(-label) %>% # menghilangkan kolom target, karena kita hanya mau menghitung range predictornya
range()
#> [1] 0 255
Range value predictor: 0 - 255
Gambar yang kita miliki, itu memiliki hitam & putih.
Jika sebuah prediktor memiliki nilai mendekati 0 -> warna pada prediktor tersebut adalah putih
Jika sebuah prediktor memiliki nilai mendekati 255 -> warna pada prediktor tersebut adalah hitam
# Please type your answer
sqrt(784)
#> [1] 28
Gambar kita: 28 x 28 Pixel
Sebagai bagian terkecil dari sebuah gambar. Pixel tersebut, akan mewakili resolusi pada gambar kita.
Resolusi tersebut akan diwakili oleh nilai pixel yang memiliki rentan dari 0-255
Semakin kecil pixelnya (mendekati 0), maka warnanya akan semakin putih (jika Grey Scale) dan semakin muda (jika RGB)
Semakin kecil pixelnya (mendekati 255), maka warnanya akan semakin hitam (jika Grey Scale) dan semakin gelap (jika RGB)
Visualisasi gambar
vizTrain <- function(input) {
dimmax <- sqrt(ncol(mnist_train[, -1]))
dimn <- ceiling(sqrt(nrow(input)))
par(mfrow = c(dimn, dimn), mar = c(0.1, 0.1, 0.1,
0.1))
for (i in 1:nrow(input)) {
m1 <- matrix(input[i, 2:ncol(input)], nrow = dimmax,
byrow = T)
m1 <- apply(m1, 2, as.numeric)
m1 <- t(apply(m1, 2, rev))
image(1:dimmax, 1:dimmax, m1, col = grey.colors(255),
xaxt = "n", yaxt = "n")
text(2, 20, col = "white", cex = 1.2, mnist_train[i,
1])
}
}
# visualisasi
vizTrain(mnist_train[1:25, ])
Lakukan cross validation menggunakan initial_split dengan proporsi 80% data untuk data training.
library(rsample)
set.seed(100)
# Spliting
mnist_split <- initial_split(data = mnist_train, # nama data train
prop = 0.8, # proporsi untuk data train
strata = "label") # nama kolom target variable
# Data train
mnist_train <- training(mnist_split)
# Data validation
mnist_validation <- testing(mnist_split)
Sebelum membuat model dengan Keras
, ada beberapa hal
yang perlu dilakukan untuk mempersiapkan data:
Kenapa si kita perlu memisahkan target dengan prediktornya karena
Scalling dengan membagi data dengan angka 255 agar range data yang dimiliki menjadi 0 hingga 1.
# ambil prediktor dan lakukan scaling
#prediktor
train_x <- mnist_train %>%
select(-label) %>%
as.matrix() / 255
validation_x <- mnist_validation %>%
select(-label) %>%
as.matrix() / 255
#target
train_y <- mnist_train %>%
select(label)
validation_y <- mnist_validation %>%
select(label)
Framework keras menerima data dalam bentuk array. Sehingga
data prediktor dalam bentuk matrix perlu diubah ke dalam bentuk array
menggunakan array_reshape()
.
Keras : mengenal tipe data yang ada di python (array)
# prediktor
train_x_keras <- train_x %>%
array_reshape(dim = dim(train_x))
validation_x_keras <- validation_x %>%
array_reshape(dim = dim(validation_x))
Ubah target (data kategorik) menjadi variable One Hot
Encoding menggunakan fungsi to_categorical()
:
# Please type your answer
train_y_keras <- train_y %>%
as.matrix() %>%
to_categorical()
validation_y_keras <-validation_y %>%
as.matrix() %>%
to_categorical()
Tahapan pembuatan model neural network/deep learning di Keras:
Tahapan yang pertama kali kita lakukan adalah membangun arsitektur dari model deep learning kita. Berikut, ada beberapa ketentuan dalam membantu arsitektur model deep learning dengan menggunakan Keras.
Step 1 Selalu diawali
keras_model_sequential()
# keras initialization
model <- keras_model_sequential()
Note: - keras_model_sequential()
adalah inisialisasi
awal pembuatan model - Ketika ingin mengubah sedikit saja parameter dari
model, maka harus di run ulang dari
keras_model_sequential()
Step 2 Membangun setiap layer (Input, Hidden & Output)
Dalam membangun setiap layer yang ada, Keras akan mengimplementasikan sistem layer by layer. Dimana, layer pertama yang dibuat akan menjadi hidden layer pertama dan layer terakhir yang dibuat akan menjadi output layer.
Fungsi yang dapat kita gunakan dalam membangun setiap layer adalah
layer_dense()
, pada fungsi tersebut nantinya akan kita isi
dengan beberapa parameter berikut ini.
input_shape
: mendefinisikan jumlah input nodes.
layer_dense()
yang paling pertama.units
: mendefinisikan jumlah nodes dalam layer
tersebut.activation
: mendefinisikan Activation Function yang
digunakan.
name
: untuk penamaan layer (demi kemudahan
visualisasi/summary).# Untuk mengunci random
tensorflow::tf$random$set_seed(123)
# Please type your answer
model %>%
layer_dense(input_shape = 784, # membuat input layer
units = 128, # hidden layer 1
activation = "relu", #Activation function
name = "Hidden_1") %>%
layer_dense(units = 64,
activation = "relu",
name = "Hidden_2") %>%
layer_dense(units = 32,
activation = "relu",
name = "Hidden_3") %>%
layer_dense(units = 10, # kita sesuaikan dengan jumlah target vriable kita
activation = "softmax", # AF kita ganti dengan bentuk output yg diinginkan
name = "Output")
# Untuk melihat hasil arsitektur yang sudah dibuat
summary(model)
#> Model: "sequential_1"
#> ________________________________________________________________________________
#> Layer (type) Output Shape Param #
#> ================================================================================
#> Hidden_1 (Dense) (None, 128) 100480
#> Hidden_2 (Dense) (None, 64) 8256
#> Hidden_3 (Dense) (None, 32) 2080
#> Output (Dense) (None, 10) 330
#> ================================================================================
#> Total params: 111,146
#> Trainable params: 111,146
#> Non-trainable params: 0
#> ________________________________________________________________________________
Keterangan:
Total params
= Jumlah bobot yang dimiliki oleh
modelTrainable param
= parameter/koneksi yang bobotnya bisa
berubah sesuai dengan proses trainingNon-trainable param
= nilai bobot/parameter tidak
berubah atau dikunci nilainyaPada tahapan membangun arsitektur, kita belum memberikan perhitungan
error yang akan digunakan. Pada tahapan inilah kita akan memberikan cara
perhitungan error, dengan menggunakan fungsi compile()
.
Jenis perhitungan error dapat kita definisikan dengan menggunakan
parameter loss =
. Pada parameter tersebut dapat kita isi
dengan 3 value, seperti di bawah ini.
categorical_crossentropy
binary_crossentropy
.mean_square_error
Akan tetapi, setelah kita mendapatkan hasil dari perhitungan error
yang terjadi, model kita perlu untuk melakukan back propagation
untuk memperbaiki bobo agar errornya berkurang. Untuk melakukan hal
tersebut kita juga dapat menambahkan parameter optimizer =
.
Pada parameter optimizer terdapat 2 fungsi yang dapat kita isi, yaitu
optimizer_sgd()
dan optimizer_adam()
.
optimizer_sgd()
: Merupakan pembaharuaan
dari cara perhitungan Gradient Decent yang sudah di-implementasikan pada
fungsi neuralnet()
.optimizer_adam()
: Merupakan pembaharuaan
dari metode Optimizer SGD.
learning_rate =
untuk mengatur
seberapa cepat penurunan bobotnya.Parameter terakhir yang dapat kita tambahkan juga ke fungsi
compile()
adalah parameter metric =
. Parameter
tersebut dapat kita isi denagn accuracy
untuk melihat nilai
accuracy-nya yang dihasilkan.
# Please type your answer
model %>%
compile(loss= "categorical_crossentropy",
optimizer = optimizer_adam(learning_rate = 0.001),
metrics = "accuracy")
— End of Day —
Goals Hari 4:
Menyelesaikan pembuatan arsitektur Deep Learning w/ Keras
Setelah arsitektur dari model Deep Learning kita sudah siap, kita
akan memulai tahapan trainingnya. Untuk melakukan training model, kita
akan memnggunakan fungsi fit()
. Pada fungsi tersebut dapat
kita isi dengan beberapa parameter berikut ini,
x
: Prediktory
: Target variabelepochs
: Jumlah epoch atau jumlah iterasi yang dilakukan
untuk model belajar
neuralnet()
validation_data
: Data validation/unseen data untuk
dilihat metrik evaluasinyaverbose
: Apakah ingin menampilkan visualisasi selama
training berlangsungbatch_size
: Model akan mengupdate bobot setiap
n dataApa itu batch size?
Terminologi pada neuralnet yang kita pelajari sebelumnya & keras agak berbeda. Pada keras, model yang dibuat hanya 1 buah, namun proses trainingnya dapat dilakukan beberapa kali. Pada tiap proses training, dilakukan pembagian data ke beberapa batch melalui random sampling. Model akan ditraining menggunakan data pada batch 1 terlebih dahulu, kemudian batch selanjutnya, hingga digunakan seluruh data (1 epoch).
Model dapat ditraining lebih dari 1 epoch (berarti melakukan pembagian batch dengan random sampling yang berbeda dari sebelumnya). Pada tiap epoch, error dan accuracy (metrics) model dapat di track. Bila ditinjau, semakin bertambah epoch, model akan memiliki error semakin kecil dan accuracy yang semakin tinggi.
knitr::include_graphics("assets/batch.png")
Neural Network
Proses update bobot di model NN:
Input Data 100 -> Hasil Akhir -> Update Bobot -> 1 Step
Deep Learning
Proses update bobotnya di DL:
1 . . . 100
Batch 1: 1-20 Batch 2: 21-40
Hal yang perlu di HIGHLIGHT:
# JANGAN RUN 2X! Karena akan melanjutkan proses training. Bila ingin run lagi, ulang dari `keras_model_sequential()`
# LossHistory <- R6::R6Class("LossHistory",
# inherit = KerasCallback,
#
# public = list(
#
# losses = NULL,
#
# on_batch_end = function(batch, logs = list()) {
# self$model <- c(self$model, logs[["accuracy" > 0.95]])
# }
# ))
history <- model %>%
fit(x = train_x_keras, # predictor
y = train_y_keras, # target variable
epochs = 10,
validation_data = list(validation_x_keras, validation_y_keras), # data validasi
verbose = T, # untuk melihat plot
batch_size = 100,# banyak data yang akan dimasukan perlahan lahan
callback_early_stopping(monitor = "accuracy", patience = 2,mode = "max", baseline = 0.95))
Rule of Thumbs:
Plotting Model:
plot(history)
Melakukan prediksi pada data validation
validation_x_keras
dengan menggunakan fungsi
predict()
# Please type your answer
predict_class <- predict(model, # nama model
validation_x_keras) %>% # prediktor data validasi
k_argmax() %>% # untuk mengambil nilai prob paling tinggi
as.array() %>% # untuk mengubah dari bentuk TF -> array
as.factor() # untuk mengubah bentuk array -> factor
# melihat hasil prediksi
predict_class %>%
head()
#> [1] 1 3 9 3 7 6
#> Levels: 0 1 2 3 4 5 6 7 8 9
Evaluasi kebaikan model dalam memprediksi menggunakan
confusionMatrix()
:
# Please type your answer
caret::confusionMatrix(data = predict_class,
reference = mnist_validation$label %>% as.factor())
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1 2 3 4 5 6 7 8 9
#> 0 814 0 7 3 0 2 1 0 4 1
#> 1 0 913 0 0 2 1 2 0 2 0
#> 2 1 4 829 1 4 0 1 5 6 2
#> 3 0 0 0 844 0 8 0 1 7 7
#> 4 0 0 2 0 767 0 1 2 2 6
#> 5 2 0 1 8 1 735 4 2 9 3
#> 6 4 0 1 1 6 4 803 0 5 0
#> 7 2 1 6 7 7 1 0 884 4 14
#> 8 3 3 1 4 0 1 1 0 752 1
#> 9 2 1 2 4 26 2 0 6 11 815
#>
#> Overall Statistics
#>
#> Accuracy : 0.9707
#> 95% CI : (0.9669, 0.9742)
#> No Information Rate : 0.1097
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.9675
#>
#> Mcnemar's Test P-Value : NA
#>
#> Statistics by Class:
#>
#> Class: 0 Class: 1 Class: 2 Class: 3 Class: 4 Class: 5
#> Sensitivity 0.98309 0.9902 0.97644 0.9679 0.94342 0.97480
#> Specificity 0.99762 0.9991 0.99682 0.9969 0.99829 0.99608
#> Pos Pred Value 0.97837 0.9924 0.97186 0.9735 0.98333 0.96078
#> Neg Pred Value 0.99815 0.9988 0.99735 0.9963 0.99396 0.99751
#> Prevalence 0.09855 0.1097 0.10105 0.1038 0.09676 0.08974
#> Detection Rate 0.09688 0.1087 0.09867 0.1005 0.09129 0.08748
#> Detection Prevalence 0.09902 0.1095 0.10152 0.1032 0.09284 0.09105
#> Balanced Accuracy 0.99036 0.9947 0.98663 0.9824 0.97085 0.98544
#> Class: 6 Class: 7 Class: 8 Class: 9
#> Sensitivity 0.98770 0.9822 0.93766 0.9600
#> Specificity 0.99723 0.9944 0.99816 0.9929
#> Pos Pred Value 0.97451 0.9546 0.98172 0.9379
#> Neg Pred Value 0.99868 0.9979 0.99345 0.9955
#> Prevalence 0.09676 0.1071 0.09545 0.1010
#> Detection Rate 0.09557 0.1052 0.08950 0.0970
#> Detection Prevalence 0.09807 0.1102 0.09117 0.1034
#> Balanced Accuracy 0.99247 0.9883 0.96791 0.9764
NOTE: Bila hasil metrics masih ingin ditingkatkan, kita dapat melakukan model tuning kembali pada pembuatan model nn maupun tahap pre-processing lainnya.
Dikarenakan dalam proses training model memerlukan waktu yang tidak
sebentar, kita akan menyimpan terlebih dahulu model yang sudah semmpat
kita buat dengan menggunakan fungsi save_model_tf()
# save
model %>%
save_model_tf(filepath = "model_keras_rhea")
Untuk memanggil hasil model yang disimpan dengan menggunakan fungsi
save_model_tf()
, kita dapat menggunakan funsi
load_model_tf()
model_loaded <- load_model_tf(filepath = "model_keras_rhea")
summary(model_loaded)
#> Model: "sequential_6"
#> ________________________________________________________________________________
#> Layer (type) Output Shape Param #
#> ================================================================================
#> Hidden_1 (Dense) (None, 128) 100480
#> Hidden_2 (Dense) (None, 64) 8256
#> Hidden_3 (Dense) (None, 32) 2080
#> Output (Dense) (None, 10) 330
#> ================================================================================
#> Total params: 111,146
#> Trainable params: 111,146
#> Non-trainable params: 0
#> ________________________________________________________________________________
Buat model deep learning baru menggunakan data train yang sama dan
simpan ke dalam objek model_nama-anda
.
Step 1: Build architecture
model_victor <- keras_model_sequential()
tensorflow::tf$random$set_seed(123)
model_victor %>%
layer_dense(input_shape = 784,
units = 512,
activation = "relu",
name = "H1") %>%
layer_dense(units = 128,
activation = "relu",
name = "H2") %>%
layer_dense(units = 32,
activation = "relu",
name = "H3") %>%
layer_dense(units = 10,
activation = "softmax",
name = "O")
Step 2: Compile model
model_victor %>%
compile(loss = "categorical_crossentropy",
optimizer = optimizer_adam(learning_rate = 0.01),
metrics = "accuracy")
Step 3: Fit (training) model
model_victor %>%
fit(x = train_x_keras,
y = train_y_keras,
validation_data = list(validation_x_keras, validation_y_keras),
verbose = T,
epochs = 15,
batch_size = 100)
Step 4: Plot model
plot(model_victor
Step 5: Lakukan prediksi ke data validation:
predict_label <- predict(model_victor, validation_x_keras) %>%
k_argmax() %>%
as.array() %>%
as.factor()
Step 6: Evaluasi
caret::confusionMatrix(data = predict_label, mnist_validation$label %>% as.factor())
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1 2 3 4 5 6 7 8 9
#> 0 815 0 3 1 2 3 2 1 1 2
#> 1 0 907 2 0 3 0 0 2 2 1
#> 2 0 3 821 6 1 1 0 4 3 1
#> 3 1 3 6 836 0 19 0 1 5 2
#> 4 0 2 3 1 780 0 1 3 1 11
#> 5 0 0 0 4 0 708 0 0 2 3
#> 6 6 2 0 0 6 7 807 0 2 0
#> 7 0 0 4 4 1 1 0 879 3 9
#> 8 6 5 9 15 3 7 3 2 778 12
#> 9 0 0 1 5 17 8 0 8 5 808
#>
#> Overall Statistics
#>
#> Accuracy : 0.9687
#> 95% CI : (0.9647, 0.9723)
#> No Information Rate : 0.1097
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.9652
#>
#> Mcnemar's Test P-Value : NA
#>
#> Statistics by Class:
#>
#> Class: 0 Class: 1 Class: 2 Class: 3 Class: 4 Class: 5
#> Sensitivity 0.98430 0.9837 0.96702 0.9587 0.95941 0.93899
#> Specificity 0.99802 0.9987 0.99748 0.9951 0.99710 0.99882
#> Pos Pred Value 0.98193 0.9891 0.97738 0.9576 0.97257 0.98745
#> Neg Pred Value 0.99828 0.9980 0.99630 0.9952 0.99566 0.99401
#> Prevalence 0.09855 0.1097 0.10105 0.1038 0.09676 0.08974
#> Detection Rate 0.09700 0.1080 0.09771 0.0995 0.09284 0.08427
#> Detection Prevalence 0.09879 0.1091 0.09998 0.1039 0.09545 0.08534
#> Balanced Accuracy 0.99116 0.9912 0.98225 0.9769 0.97826 0.96891
#> Class: 6 Class: 7 Class: 8 Class: 9
#> Sensitivity 0.99262 0.9767 0.97007 0.95171
#> Specificity 0.99697 0.9971 0.99184 0.99417
#> Pos Pred Value 0.97229 0.9756 0.92619 0.94836
#> Neg Pred Value 0.99921 0.9972 0.99683 0.99457
#> Prevalence 0.09676 0.1071 0.09545 0.10105
#> Detection Rate 0.09605 0.1046 0.09260 0.09617
#> Detection Prevalence 0.09879 0.1072 0.09998 0.10140
#> Balanced Accuracy 0.99479 0.9869 0.98096 0.97294
mnist_test %>%
head(1)
Data Pre-Processing MNIST TEST
# Scalling
mnist_test_keras <- mnist_test %>%
as.matrix()/255
# Mengubah menjadi bentuk array
mnist_test_keras <- mnist_test_keras %>%
array_reshape(dim = dim(mnist_test_keras))
Prediksi
prediksi_mnist_test <- predict(model_victor, mnist_test_keras) %>%
k_argmax() %>%
as.array() %>%
as.factor()
Persiapan File Submit
2 kolom - ImageId - Label -.csv
label_submit <- data.frame(ImageId = 1:nrow(mnist_test),
Label = prediksi_mnist_test)
head(label_submit)
write.csv(label_submit,
file = "label_victor_submit.csv",
row.names = F)
Data Pre-processing untuk Keras
data.frame
diubah terlebih dahulu
menjadi array
karena keras menerima input dalam bentuk
array. Tahapan: data.frame -> matrix -> array.array_reshape()
to_categorical()
Tahapan Model Building di Keras:
Panduan Model Building & Tuning:
optimizer_sgd()
di
Keras)optimizer_adam()
)