Intro

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 :

    • Input layer : variabel input (x1, x2, …, xn)
    • Hidden layer : layer pemrosesan data
    • Output layer : target variabel
  • 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.

Data Preperation

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.

Load Data

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)

Inspect Data

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))

Cross-Validation

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

Data Preprocessing

Sebelum membuat model dengan Keras, ada beberapa hal yang perlu dilakukan untuk mempersiapkan data:

  1. Memisahkan prediktor dengan target variabel
  2. Mengubah prediktor menjadi matrix/array
  3. Melakukan one-hot encoding apabila target variabel adalah kategori
#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$label

kita 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)

Arsitektur Neural Network

Langkah selanjutnya adalah membangun arsitektur Neural Network. Beberapa ketentuan ketika membuat arsitektur Neural Network:

  1. Inisiasi objek model dengan fungsi keras_model_sequential()
  2. Layer pertama yang dibuat akan menjadi hidden layer pertama
  3. Input layer dibuat dengan memasukkan parameter input_shape pada layer pertama
  4. Layer terakhir yang dibuat akan menjadi output layer

Pertama, 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
  • pada layer hidden_2, jumlah parameter = 1040, ini didapatkan dari: 136 = 64 (node/neuron hidden_1) * 8 (hidden_2 neuron/node) + 8 (bias)
32 * 8 + 8
#> [1] 264

Model Fitting

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)

Model Evaluation & Tuning

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 :

  • Model ke 1 Hidden 2 jumlah node 32 dan 8 dengan optimizer sgd mendapatkan Accuracy overall 83%
  • Model ke 2 Hidden 3 jumlah node 128, 64 dan 32 dengan optimizer sgd mendapatkan Accuracy overall 88%
  • Model ke 3 Hidden 2 jumlah node 128 dan 32 dengan optimizer adam mendapatkan Accuracy overall 78%

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.

Conclusion

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.