Artificial Neural Network/Neural Network/Deep Learning adalah salah satu model machine learning yang arsitektur atau bentuk modelnya terinspirasi dari bagaimana otak manusia bekerja. Model Neural Network yang kompleks sering disebut dengan Deep Learning.
Neural Network terdiri dari 3 komponen utama :
Pada setiap layer, terdapat sejumlah node atau titik yang memiliki nilai tertentu.
Jumlah node pada input layer sesuai dengan jumlah variabel prediktor/feature + 1 node dari bias
Jumlah node pada output layer sesuai dengan jumlah target variabel
Pada hidden layer, jumlah node ditentukan oleh user
Pada input layer dan hidden layer terdapat bias/intercept
Kita akan menggunakan dataset MNIST, yakni data berisi ribuan gambar digit angka dari berbagai jenis tulisan tangan. Kita akan membuat sebuah model Machine Learning yang nantinya dapat mengenali digit angka 0 sampai 9 dengan belajar dari informasi yang diberikan.
problem question: memprediksi/mengklasifikasikan tulisan tangan berupa angka digit 0 - 9 dengan metode neural network.
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 dan tensorflow yang digunakan di R berfungsi sebagai
mediator saja, karena sebenarnya di belakang layar semua proses
dijalankan di python.
library(tidyverse)
library(keras)
library(dplyr)
library(rsample)
tensorflow::tf_version()#> [1] '2.9'
tensorflow::tf$random$set_seed(42)
theme_set(theme_minimal())
options(scipen = 999)Untuk menguji apakah model keras sudah terhubung dan dapat digunakan, dapat menjalankan code berikut:
p <- keras_model_sequential(name = "Model Pertama") %>%
# Hidden Layer Pertama
layer_dense(units = 3,
input_shape = 3,
activation = "sigmoid",
name = "Hidden_layer") %>%
# Output Layer
layer_dense(units = 2, activation = "sigmoid", name = "output")
p#> Model: "Model Pertama"
#> ________________________________________________________________________________
#> Layer (type) Output Shape Param #
#> ================================================================================
#> Hidden_layer (Dense) (None, 3) 12
#> output (Dense) (None, 2) 8
#> ================================================================================
#> Total params: 20
#> Trainable params: 20
#> Non-trainable params: 0
#> ________________________________________________________________________________
Setelah kita menjalan kode diatas, terlihat tidak adanya error yang berarti library keras dapat dijalankan.
Pertama kita muat terlebih dahulu datanya. Data MNIST sudah terbagi
ke dalam data train dan data test sehingga nantinya tidak perlu
dilakukan cross-validation. Data berupa tabel dengan informasi target
variabel (label) dan besarnya brightness dari masing-masing
pixel dalam grayscale (hitam putih).
train_mnist <- read.csv("data_input/mnist/train.csv")
test_mnist <- read.csv("data_input/mnist/test.csv")
dim(train_mnist)#> [1] 42000 785
Tiap gambar berdimensi 28 x 28, sehingga jumlah pixel yang dimiliki ada 784 pixel.
Informasi data: * 42000 gambar * label = variable target
* kolom pixel0 ~ 783 = 784 pixel menunjukkan informasi warna pada
masing-masing pixel * ukuran gambar = akar dari jumlah pixel = 28 x 28
pixel
kita akan lihat data kita dengan head()
head(train_mnist)Pada setiap gambar, terdapat pixel-pixel yang berisi informasi warna (misalkan gradasi terang-gelap). Kita akan memanfaatkan nilai dari informasi warna tersebut untuk mengenali digit angka. Kolom pertama (label) menunjukkan nilai target variabel, yakni digit angka yang muncul. Sisanya adalah nilai di tiap pixel pada masing-masing gambar.
range pixel gambar: [0 - 255]
Mari Kita lihat bagaimana data kita dengan gambar menggunakan function yang di dapatkan dari kelas pembelajaran di Algoritma.
vizTrain <- function(input){
dimmax <- sqrt(ncol(input[,-1]))
dimn <- ceiling(sqrt(nrow(input)))
par(mfrow=c(dimn, dimn), mar=c(.1, .1, .1, .1))
for (i in 1:nrow(input)){
m1 <- as.matrix(input[i,2:785])
dim(m1) <- c(28,28)
m1 <- apply(apply(m1, 1, rev), 1, t)
image(1:28, 1:28,
m1, col=grey.colors(255),
# remove axis text
xaxt = 'n', yaxt = 'n')
text(2, 20, col="white", cex=1.2, input[i, 1])
}
}
vizTrain(head(train_mnist, 30))Kita akan melakukan splitting pada data train menjadi 80% dan 20% untuk melatih model neuron serta mengetes model kita sebelum di gunakan pada data test.
RNGkind(sample.kind = "Rounding")
library(rsample)
set.seed(100)
index <- initial_split(data = train_mnist, prop = 0.8, strata = label)
data_train <- training(index)
data_test <- testing(index)
dim(data_train)#> [1] 33598 785
Cek Proporsi kelas target pada data train.
prop.table(table(data_train$label))#>
#> 0 1 2 3 4 5 6
#> 0.09768439 0.11161379 0.10006548 0.10327996 0.09726769 0.09110661 0.09762486
#> 7 8 9
#> 0.10491696 0.09783320 0.09860706
prop.table(table(data_test$label))#>
#> 0 1 2 3 4 5 6
#> 0.10116639 0.11116401 0.09700071 0.10485599 0.09569150 0.08736015 0.10199952
#> 7 8 9
#> 0.10426089 0.09235896 0.10414187
Sebelum membuat model dengan Keras, ada beberapa hal
yang perlu dilakukan untuk mempersiapkan data:
#data training
train_x <- data_train %>%
select(-label) %>%
as.matrix()/255
train_y <- data_train$label
#data testing/validation
test_x <- data_test %>%
select(-label) %>%
as.matrix()/255
test_y <- data_test$labelkita telah memisahkan target variable dan target prediktor,
selanjutnya kita akan menguba variable prediktor menjadi sebuah matrix
karena Framework keras menerima data dalam bentuk
array.
# array 2D
train_x <- array_reshape(x = train_x,
dim = dim(train_x))
test_x <- array_reshape(x = test_x,
dim = dim(test_x))Selanjutnya, Ubah target (data kategorik) menjadi variable dummy menggunakan one hot encoding, num_clasess diisi sesuai dengan jumalh target yang ada karena pada case ini targetnya 0-9 yang mana berjumlah 10 buah maka kita akan isi dengan 10.
# One-hot encoding target variable
train_y <- to_categorical(y = train_y,
num_classes = 10)
test_y <- to_categorical(y = test_y,
num_classes = 10)Langkah selanjutnya adalah membangun arsitektur Neural Network. Beberapa ketentuan ketika membuat arsitektur Neural Network:
keras_model_sequential()input_shape pada layer pertamaPertama, kita buat dulu object untuk menyimpan informasi jumlah kolom dari prediktor dan jumlah kategori dari target variabel.
# Membuat arsitektur
model <- keras_model_sequential(name = "model_mnist") %>%
layer_dense(units = 32,
input_shape = 784, #node sesuaikan dengan input layer
activation = "relu",
name = "hidden_1"
) %>%
layer_dense(units = 8,
activation = "relu",
name = "hidden_2"
) %>%
layer_dense(units = 10, #untuk target variabel angka digit 0,1,2,3,4,5,6,7,8,9
activation = "softmax",
name = "output")
summary(model)#> Model: "model_mnist"
#> ________________________________________________________________________________
#> Layer (type) Output Shape Param #
#> ================================================================================
#> hidden_1 (Dense) (None, 32) 25120
#> hidden_2 (Dense) (None, 8) 264
#> output (Dense) (None, 10) 90
#> ================================================================================
#> Total params: 25,474
#> Trainable params: 25,474
#> Non-trainable params: 0
#> ________________________________________________________________________________
dense layer: salah satu tipe layer pada library keras yang mengimplementasikan tipe layer berupa fully connected layer.
fully connected layer: layer yang semua nodenya harus terhubung dengan weight/bobot sebelumnya.
kolom output shape berisi informasi mengenai dimensi tiap layer.
pada kasus ini, tiap layer diawali dengan nilai None. Nilai
None merepresentasi/mewakili ukuran batch untuk setiap
layernya. None digunakan karena aslinya, ukuran batch dapat diinisiasi
oleh angka apa saja (asal masih dibawah jumlah data train).
kolom output shape setelah koma, berisi jumlah neuron/node/unit pada tiap layernya.
pada layer hidden_1, jumlah parameter = 50240. ini didapatkan dari: 50240 = 784 (input neuron/node) * 16 (hidden_1 neuron/node) + 16 (bias/intercept)
784 * 32 + 32#> [1] 25120
32 * 8 + 8#> [1] 264
Selanjutnya, Neural Network menggunakan keras akan
mengupdate bobot setelah memproses sebagian data dari data train, yang
biasa disebut dengan 1 batch. Ketika model sudah melakukan
feed forward dengan 1 batch data, misalkan dengan
batch size = 32 (1 batch = 32 data), model akan melakukan
back propagation dan mengupdate bobotnya. Baru setelah itu,
model akan melakukan feedforward lagi menggunakan 32 data
selanjutnya. Pada tahapan ini, 1 Epoch adalah ketika model sudah
berlatih dengan menggunakan seluruh data.
model %>%
compile(loss = "categorical_crossentropy", #untuk klasifikasi 10 kelas digit
optimizer = optimizer_sgd(learning_rate = 0.1),
metrics = "accuracy")history <- model %>%
fit(x = train_x, #predictor data rain
y = train_y, #target variable data train
epoch = 15, #pengulangan
validation_data = list(test_x, test_y), #data test
verbose = 1,
batch_size = 4200)plot(history)setelah membuat modelnya kita akan melakukan model evaluasi sebelum melakukan model evaluasi kit harus memprediksi data tersebut Untuk memprediksi hasilnya:
pred <- predict(model, test_x) %>%
k_argmax() %>% # untuk mengambil nilai probability yang paling besar diantara kelas 0 - 9 (angka digitnya)
as.array() %>% #mengubah objek Tensof menjadi array
as.factor() #untuk masukin ke confusionMatrix()kita evaluasi performa model menggunakan Confusion Matrix
library(caret)
confusionMatrix(data = pred,
reference = as.factor(data_test$label))#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1 2 3 4 5 6 7 8 9
#> 0 755 0 29 33 1 288 44 0 29 1
#> 1 0 870 3 20 2 6 1 28 33 10
#> 2 16 5 573 39 1 31 22 17 80 5
#> 3 3 9 66 717 0 65 1 3 45 18
#> 4 1 0 24 2 621 2 40 12 3 93
#> 5 27 2 8 13 0 202 19 2 55 2
#> 6 42 0 30 6 46 79 705 8 25 18
#> 7 0 18 20 19 11 3 2 673 8 39
#> 8 6 28 58 23 0 50 14 18 485 7
#> 9 0 2 4 9 122 8 9 115 13 682
#>
#> Overall Statistics
#>
#> Accuracy : 0.7478
#> 95% CI : (0.7384, 0.7571)
#> No Information Rate : 0.1112
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.7194
#>
#> Mcnemar's Test P-Value : NA
#>
#> Statistics by Class:
#>
#> Class: 0 Class: 1 Class: 2 Class: 3 Class: 4 Class: 5
#> Sensitivity 0.88824 0.9315 0.70307 0.81385 0.77239 0.27520
#> Specificity 0.94372 0.9862 0.97153 0.97208 0.97670 0.98331
#> Pos Pred Value 0.63983 0.8941 0.72624 0.77346 0.77820 0.61212
#> Neg Pred Value 0.98685 0.9914 0.96821 0.97806 0.97593 0.93409
#> Prevalence 0.10117 0.1112 0.09700 0.10486 0.09569 0.08736
#> Detection Rate 0.08986 0.1035 0.06820 0.08534 0.07391 0.02404
#> Detection Prevalence 0.14044 0.1158 0.09391 0.11033 0.09498 0.03928
#> Balanced Accuracy 0.91598 0.9588 0.83730 0.89296 0.87455 0.62926
#> Class: 6 Class: 7 Class: 8 Class: 9
#> Sensitivity 0.82264 0.76826 0.62500 0.77943
#> Specificity 0.96634 0.98406 0.97325 0.96253
#> Pos Pred Value 0.73514 0.84868 0.70392 0.70747
#> Neg Pred Value 0.97958 0.97332 0.96227 0.97405
#> Prevalence 0.10200 0.10426 0.09236 0.10414
#> Detection Rate 0.08391 0.08010 0.05772 0.08117
#> Detection Prevalence 0.11414 0.09438 0.08200 0.11473
#> Balanced Accuracy 0.89449 0.87616 0.79912 0.87098
secara overall model kita mendapatkan nilai Accuracy sebesar 83%, menurut saya dengan menggunakan 2 hidden layer yaitu hidden 1 : 32 node dan hidden 2 : 8 sudah cukup memuaskan dengan niali overall sebesar 83%, mari kita buat 2 model lain untuk perbandingan dengan menambah hidden ke 3 tapi menggunakan optimizer sgd, lalu dengan 2 hidden tapi menggunakan optimizer adam
Model ke 2
model2 <- keras_model_sequential(name = "model_mnist") %>%
layer_dense(units = 128,
input_shape = 784, #node sesuaikan dengan input layer
activation = "relu",
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, #untuk target variabel angka digit 0,1,2,3,4,5,6,7,8,9
activation = "softmax",
name = "output")
summary(model2)#> Model: "model_mnist"
#> ________________________________________________________________________________
#> 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
#> ________________________________________________________________________________
model2 %>%
compile(loss = "categorical_crossentropy", #untuk klasifikasi 10 kelas digit
optimizer = optimizer_sgd(learning_rate = 0.1),
metrics = "accuracy")history2 <- model2 %>%
fit(x = train_x, #predictor data rain
y = train_y, #target variable data train
epoch = 15, #pengulangan
validation_data = list(test_x, test_y), #data test
verbose = 1,
batch_size = 4200)plot(history2)pred2 <- predict(model2, test_x) %>%
k_argmax() %>% # untuk mengambil nilai probability yang paling besar diantara kelas 0 - 9 (angka digitnya)
as.array() %>% #mengubah objek Tensof menjadi array
as.factor() #untuk masukin ke confusionMatrix()confusionMatrix(data = pred2,
reference = as.factor(data_test$label))#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1 2 3 4 5 6 7 8 9
#> 0 815 0 7 6 2 17 8 2 5 10
#> 1 0 905 17 4 3 15 10 14 15 3
#> 2 5 5 706 21 6 7 22 16 23 4
#> 3 8 3 25 793 0 80 0 8 42 16
#> 4 1 0 14 2 699 19 6 4 6 21
#> 5 4 5 2 18 2 540 13 1 15 3
#> 6 5 1 13 7 14 14 795 0 8 0
#> 7 1 1 6 13 4 10 1 813 3 49
#> 8 11 13 22 14 3 20 2 3 647 13
#> 9 0 1 3 3 71 12 0 15 12 756
#>
#> Overall Statistics
#>
#> Accuracy : 0.889
#> 95% CI : (0.882, 0.8956)
#> No Information Rate : 0.1112
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.8765
#>
#> Mcnemar's Test P-Value : NA
#>
#> Statistics by Class:
#>
#> Class: 0 Class: 1 Class: 2 Class: 3 Class: 4 Class: 5
#> Sensitivity 0.9588 0.9690 0.86626 0.90011 0.86940 0.73569
#> Specificity 0.9925 0.9892 0.98563 0.97580 0.99039 0.99178
#> Pos Pred Value 0.9346 0.9178 0.86626 0.81333 0.90544 0.89552
#> Neg Pred Value 0.9954 0.9961 0.98563 0.98815 0.98624 0.97513
#> Prevalence 0.1012 0.1112 0.09700 0.10486 0.09569 0.08736
#> Detection Rate 0.0970 0.1077 0.08403 0.09438 0.08319 0.06427
#> Detection Prevalence 0.1038 0.1174 0.09700 0.11604 0.09188 0.07177
#> Balanced Accuracy 0.9756 0.9791 0.92595 0.93796 0.92990 0.86374
#> Class: 6 Class: 7 Class: 8 Class: 9
#> Sensitivity 0.92765 0.92808 0.83376 0.86400
#> Specificity 0.99178 0.98831 0.98676 0.98446
#> Pos Pred Value 0.92765 0.90233 0.86497 0.86598
#> Neg Pred Value 0.99178 0.99160 0.98315 0.98419
#> Prevalence 0.10200 0.10426 0.09236 0.10414
#> Detection Rate 0.09462 0.09676 0.07701 0.08998
#> Detection Prevalence 0.10200 0.10724 0.08903 0.10390
#> Balanced Accuracy 0.95972 0.95819 0.91026 0.92423
Model ke 3
model3 <- keras_model_sequential(name = "model_mnist") %>%
layer_dense(units = 128,
input_shape = 784, #node sesuaikan dengan input layer
activation = "relu",
name = "hidden_1"
) %>%
layer_dense(units = 32,
activation = "relu",
name = "hidden_2"
) %>%
layer_dense(units = 10, #untuk target variabel angka digit 0,1,2,3,4,5,6,7,8,9
activation = "softmax",
name = "output")
summary(model3)#> Model: "model_mnist"
#> ________________________________________________________________________________
#> Layer (type) Output Shape Param #
#> ================================================================================
#> hidden_1 (Dense) (None, 128) 100480
#> hidden_2 (Dense) (None, 32) 4128
#> output (Dense) (None, 10) 330
#> ================================================================================
#> Total params: 104,938
#> Trainable params: 104,938
#> Non-trainable params: 0
#> ________________________________________________________________________________
model3 %>%
compile(loss = "categorical_crossentropy", #untuk klasifikasi 10 kelas digit
optimizer = optimizer_adam(learning_rate = 0.1),
metrics = "accuracy")history3 <- model3 %>%
fit(x = train_x, #predictor data rain
y = train_y, #target variable data train
epoch = 15, #pengulangan
validation_data = list(test_x, test_y), #data test
verbose = 1,
batch_size = 4200)plot(history3)pred3 <- predict(model3, test_x) %>%
k_argmax() %>% # untuk mengambil nilai probability yang paling besar diantara kelas 0 - 9 (angka digitnya)
as.array() %>% #mengubah objek Tensof menjadi array
as.factor() #untuk masukin ke confusionMatrix()confusionMatrix(data = pred3,
reference = as.factor(data_test$label))#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1 2 3 4 5 6 7 8 9
#> 0 797 0 2 1 1 6 5 0 9 6
#> 1 0 891 0 0 1 1 1 5 7 0
#> 2 2 7 721 20 3 4 6 7 6 1
#> 3 1 5 30 768 1 62 2 37 50 23
#> 4 3 0 5 1 765 2 8 8 5 63
#> 5 5 0 3 6 3 532 8 2 3 2
#> 6 10 0 10 1 7 11 808 0 12 1
#> 7 1 3 2 21 8 8 0 767 14 59
#> 8 31 28 41 59 4 106 19 6 667 18
#> 9 0 0 1 4 11 2 0 44 3 702
#>
#> Overall Statistics
#>
#> Accuracy : 0.8829
#> 95% CI : (0.8758, 0.8897)
#> No Information Rate : 0.1112
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.8698
#>
#> Mcnemar's Test P-Value : NA
#>
#> Statistics by Class:
#>
#> Class: 0 Class: 1 Class: 2 Class: 3 Class: 4 Class: 5
#> Sensitivity 0.93765 0.9540 0.88466 0.87174 0.95149 0.72480
#> Specificity 0.99603 0.9980 0.99262 0.97195 0.98750 0.99583
#> Pos Pred Value 0.96372 0.9834 0.92793 0.78447 0.88953 0.94326
#> Neg Pred Value 0.99300 0.9943 0.98767 0.98478 0.99483 0.97423
#> Prevalence 0.10117 0.1112 0.09700 0.10486 0.09569 0.08736
#> Detection Rate 0.09486 0.1060 0.08581 0.09141 0.09105 0.06332
#> Detection Prevalence 0.09843 0.1078 0.09248 0.11652 0.10236 0.06713
#> Balanced Accuracy 0.96684 0.9760 0.93864 0.92184 0.96949 0.86031
#> Class: 6 Class: 7 Class: 8 Class: 9
#> Sensitivity 0.94282 0.87557 0.85954 0.80229
#> Specificity 0.99311 0.98459 0.95909 0.99136
#> Pos Pred Value 0.93953 0.86863 0.68131 0.91525
#> Neg Pred Value 0.99350 0.98550 0.98532 0.97734
#> Prevalence 0.10200 0.10426 0.09236 0.10414
#> Detection Rate 0.09617 0.09129 0.07939 0.08355
#> Detection Prevalence 0.10236 0.10509 0.11652 0.09129
#> Balanced Accuracy 0.96797 0.93008 0.90931 0.89683
Hasil :
dari hasil yang didapat menunjukan model ke 2 yang terbaik dari 3 model yang dibuat, model ke 3 merupakan model yang nilai accuracy-nya paling kecil diantara model lain.
dari hasil pembuatan model menunjukan bahwa penambahan hidden layaer yang sebelumnya 2 menjadi 3 mempengaruhi performasi dari model tersebut serta jumlah node yang di design juga dapat mempengaruhi performasi, akan tetapi jika data yang kita miliki tidak begitu kompleks ada baiknya menggunakan hidden atau node yang tidak terlalu banyak karena akan tidak sesuai dengan kebutuhan prediksi data kita yang mana nantinya akan mengurangi accuracy pada model. untuk pemilihan optimizer pada saat model fitting juga harus diperhatikan bisa saja malah mengurangi performasi pada model seperti yang terjadi pada model ke 3.