Neural Network untuk Klasifikasi Multikelas dengan Keras

Neural Network Klasifikasi Multikelas dengan Keras

Neural network adalah model matematika yang terinspirasi oleh struktur dan fungsi otak manusia. Proses pembelajaran neural network melibatkan pelatihan model dari dataset yang diberikan, di mana bobot koneksi antar neuron disesuaikan dan diperbarui untuk menghasilkan prediksi yang lebih akurat. Dalam beberapa tahun terakhir, neural network telah menghasilkan kemajuan signifikan di berbagai bidang, termasuk pengenalan gambar, pemrosesan bahasa alami, dan prediksi data.

Terdapat berbagai pustaka yang dapat digunakan untuk membangun model neural network, salah satunya adalah Keras (dan TensorFlow). Pertama kali diluncurkan, Keras dibuat sebagai backend Theano, namun sejak versi 2.0, Keras juga mendukung backend TensorFlow. Pada versi 2.3.0, Keras telah terintegrasi dengan TensorFlow dan menjadi bagian dari paket TensorFlow. Keras menyediakan antarmuka yang lebih sederhana dan mudah digunakan daripada TensorFlow atau Theano yang lebih low-level, sehingga memungkinkan pengguna lebih mudah dan cepat dalam membangun model deep learning.

Instalasi Keras dan Tensorflow

Seperti yang sudah disampaikan sebelumnya, Keras saat ini sudah terintegrasi dengan TensorFlow sehingga dengan menginstal Tensorflow maka Keras akan otomatis ikut terinstal. Jika anda menggunakan pip maka untuk menginstal tensorflow dapat dilakukan dengan sintaks seperti berikut:

# jika mengunakan jupyter notebook (tambahkan simbol % sebelum pip)

# instalasi tensorflow
# pip install tensorflow

# instalasi paket pendukung lainnya
# pip install pandas numpy scikit-learn

Jika perangkat mendukung GPU maka anda dapat menginstall tensorflow dengan dukungan GPU. Panduan lengkap instalasi dapat dilihat pada tautan berikut https://www.tensorflow.org/install/pip.

Pustaka lainnya yang diperlukan dalam tutorial ini adalah pandas, numpy dan scikit-learn. Ketiganya dapat diinstal menggunakan pip seperti contoh di atas.

Penyiapan Data

Data yang digunakan pada tutorial ini dapat diunduh di sini yang merupakan versi modifikasi dari data obesity level. Pada data asli kelas target memiliki 7 kategori, sedangkan yang digunakan di sini, sudah dikelompokkan menjadi 4 kategori saja.

Data set ini terdiri dari 2.111 amatan dengan 16 fitur. Terdapat 9 fitur bertipe kategorik dan 8 fitur numerik. Peubah Nobeyesdad merupakan peubah target bertipe kategorik dengan 4 kelas yaitu Insufficient, Normal, Overweight, Obesity. Sementara untuk fitur-fitur kategorik memiliki kategori dari 2 hingga 5 kategori. Tidak terdapat missing value sehingga proses dapat dilanjutkan ke tahap berikutnya.

Python

import pandas as pd

# memuat data CSV
data = pd.read_csv("obesitas.csv")

# menampilkan info data
print(data.info())

# menampilkan label dari kelas target
print(data["NObeyesdad"].unique())

Output

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2111 entries, 0 to 2110
Data columns (total 17 columns):
 #   Column                          Non-Null Count  Dtype  
---  ------                          --------------  -----  
 0   Gender                          2111 non-null   object 
 1   Age                             2111 non-null   float64
 2   Height                          2111 non-null   float64
 3   Weight                          2111 non-null   float64
 4   family_history_with_overweight  2111 non-null   object 
 5   FAVC                            2111 non-null   object 
 6   FCVC                            2111 non-null   float64
 7   NCP                             2111 non-null   float64
 8   CAEC                            2111 non-null   object 
 9   SMOKE                           2111 non-null   object 
 10  CH2O                            2111 non-null   float64
 11  SCC                             2111 non-null   object 
 12  FAF                             2111 non-null   float64
 13  TUE                             2111 non-null   float64
 14  CALC                            2111 non-null   object 
 15  MTRANS                          2111 non-null   object 
 16  NObeyesdad                      2111 non-null   object 
dtypes: float64(8), object(9)
memory usage: 280.5+ KB
None


['Normal' 'Overweight' 'Obesity' 'Insufficient']

Praproses Data

Ada beberapa proses yang harus dilakukan agar data dapat digunakan dalam pemodelan neural network dengan keras yaitu:

  1. Menentukan Kolom-kolom fitur dan kolom target
  2. Merubah fitur bertipe kategorik menjadi numerik. Hal ini penting karena proses pemodelan hanya bekerja pada data numerik sehingga data kategorik harus diubah terlebih dahulu. Salah satu cara yang paling mudah yaitu merubah fitur menjadi One Hot Encoding (OHE) menggunakan fungsi get_dummies dari pandas.
  3. Menggabungkan kembali fitur numerik dengan fitur kategorik yang sudah di-encoding.
  4. Membagi data latih dan data uji. Data latih akan menjadi dasar untuk pelatihan model dan menentukan model yang optimal. Data uji digunakan untuk mengevaluasi kinerja model pada data yang belum pernah dilihat. Di sini kita membagi data 75% sebagai data latih dan 25% sebagai data uji. Proses ini dapat dilakukan menggunakan fungsi train_test_split dari modul sklearn.model_selection.
  5. Merubah peubah target menjadi numerik. Kita akan menggunakan fungsi LabelEncoder dari modul sklearn.preprocessing, dimana dari 4 kelas respon dirubah menjadi numerik dengan nilai 0, 1, 2, dan 3.
  6. Features scaling, langkah ini untuk membuat semua fitur yang ada memiliki skala nilai yang sama. Beberapa teknik yang dapat digunakan yaitu Standardize (merubah skala sehingga memiliki rata-rata 0 dan standar deviasi 1) dan Normalize (Min Max Scaling, merubah skala sehingga berada pada rentang nilai tertentu, misal (0 sampai 1) atau (-1 sampai 1). Kita akan menggunakan fungsi StandardScaler dari modul sklearn.preprocessing untuk proses standardize.

Python

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder


# menentukan kolom fitur dan target
X = data.drop(["NObeyesdad"], axis=1)
y = data["NObeyesdad"]

# list kolom kategorik
cat_features = [
    "Gender",
    "family_history_with_overweight",
    "FAVC",
    "CAEC",
    "SMOKE",
    "SCC",
    "CALC",
    "MTRANS",
]


# list kolom numerik
num_features = X.columns[~X.columns.isin(cat_features)]

# merubah fitur kategorik menjadi One Hot Encoding
X_cat = pd.get_dummies(X[cat_features], drop_first=True)

# mengabungkan kembali fitur numerik dan OHE
X_final = pd.concat([X[num_features], X_cat], axis=1)

# membagi data train dan test
X_train, X_test, y_train, y_test = train_test_split(
    X_final, y, test_size=0.25, random_state=123
)


# merubah kelas label menjadi numerik
lenc = LabelEncoder()
lenc.fit(y_train)
y_train = lenc.transform(y_train)
y_test = lenc.transform(y_test)


# merubah skala fitur (menggunakan standardisasi)
scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

Model Neural Network (1 Hidden Layer)

Langkah-langkah pembuatan model neural network dengan 1 hidden layer:

  1. Menginisiasi model menggunakan fungsi Sequential dari modul keras.models.
  2. Menambah sebuah hidden layer pada model dengan fungsi Dense dari modul keras.layers. Beberapa parameter yang dapat diatur:
    • units : banyaknya neuron pada layer tersebut
    • activation : fungsi aktivasi yang digunakan misalkan "relu".
    • input_dim : Jika kita tidak menentukan input layer secara eksplisit, maka pada hidden layer yang pertama, kita dapat menentukan dimensi dari input layer tersebut melalui parameter ini yang menunjukkan jumlah fitur yang digunakan. Contoh data yang kita gunakan terdapat 16 fitur (sebanyak jumlah kolom pada variabel X_train).
  3. Menambah output layer menggunakan fungsi Dense.
    • units : jumlah neuron pada output layer harus sesuai dengan banyaknya kelas dari peubah target, dalam hal ini adalah 4 kelas.
    • activation : fungsi aktivasi yang dapat digunakn untuk klasifikasi multikelas adalah softmax.
  4. Mengompilasi model dengan memanggil method compile pada model. Beberapa parameter yang dapat diatur :
    • optimizer : algoritma yang digunakan untuk mencari solusi optimum. Optimizer yang sering digunakan karena memiliki performa efisien, stabil serta adaptif yaitu "adam". Contoh lainya SGD, Adamax dan sebagainya.
    • loss : Loss function yang sesuai untuk data multikelas yaitu categorical_crossentropy atau sparse_categorical_crossentropy. Jika label data dalam bentuk integer biasa gunakan sparse_categorical_crossentropy namun jika label tersimpan dalam bentuk OHE gunakan categorical_cross_entropy.
    • metrics : Ukuran untuk menghitung performa model. Pada model klasifikasi, metrik yang umum digunakan adalah accuracy. Kita dapat menggunakan beberapa metrik sekaligus dengan menambahkan metrik lainnya ke dalam list.
  5. Melatih model dengan memanggil method fit. Selain menentukan data fitur dan target, kita dapat mengatur beberapa parameter lainnya antara lain:
    • epochs : Parameter ini mengatur banyaknya proses iterasi pembaruan bobot pada neural network. Satu epoch merujuk pada satu kali proses pelatihan yang melibatkan penyebaran seluruh data latih pada neural network untuk menghitung gradien dan memperbarui bobot jaringan.
    • validation_split : jika parameter ini ditentukan (maka pada setiap epoch data latih akan dibagi, dimana sebagiannya digunakan sebagai validasi. Misal : 0.2)
  6. Evaluasi model pada data uji

Python

from keras.models import Sequential
from keras.layers import Dense


# Membangun model neural network
model_1 = Sequential()

# hidden layer
model_1.add(Dense(units=64, input_dim=X_train.shape[1], activation="relu"))

# output layar : unit=4 (sebanyak kelas output)
model_1.add(Dense(units=4, activation="softmax"))


# Mengompilasi model
model_1.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)


# Melatih model
model_1.fit(
    X_train,
    y_train,
    epochs=10,
    validation_split=0.2,
)

print(model_1.summary())


# Evaluasi model pada data test
loss, accuracy = model_1.evaluate(X_test, y_test)

print("Loss:", loss)
print("Accuracy:", accuracy)

Output

Epoch 1/10
40/40 [==============================] - 1s 6ms/step - loss: 1.2502 - accuracy: 0.4621 - val_loss: 1.0602 - val_accuracy: 0.5615
Epoch 2/10
40/40 [==============================] - 0s 2ms/step - loss: 0.9558 - accuracy: 0.5940 - val_loss: 0.8803 - val_accuracy: 0.6215
Epoch 3/10
40/40 [==============================] - 0s 2ms/step - loss: 0.8065 - accuracy: 0.6485 - val_loss: 0.7714 - val_accuracy: 0.6593
Epoch 4/10
40/40 [==============================] - 0s 2ms/step - loss: 0.7110 - accuracy: 0.6967 - val_loss: 0.6930 - val_accuracy: 0.6877
Epoch 5/10
40/40 [==============================] - 0s 2ms/step - loss: 0.6420 - accuracy: 0.7275 - val_loss: 0.6345 - val_accuracy: 0.7161

...

Epoch 9/10
40/40 [==============================] - 0s 2ms/step - loss: 0.4710 - accuracy: 0.8357 - val_loss: 0.4921 - val_accuracy: 0.8265
Epoch 10/10
40/40 [==============================] - 0s 2ms/step - loss: 0.4408 - accuracy: 0.8483 - val_loss: 0.4679 - val_accuracy: 0.8517


Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 64)                1536      
                                                                 
 dense_1 (Dense)             (None, 4)                 260       
                                                                 
=================================================================
Total params: 1,796
Trainable params: 1,796
Non-trainable params: 0
_________________________________________________________________
None


17/17 [==============================] - 0s 1ms/step - loss: 0.4855 - accuracy: 0.8258

Loss: 0.4855416715145111
Accuracy: 0.8257575631141663

Hasil pelatihan pada model_1 setelah 10 epoch dapat dilihat pada output di atas. Terdapat 4 nilai yang ditampilkan yaitu loss, accuracy, val_loss, dan val_accuracy. Dua nilai terakhir tersedia karena kita mengatur parameter validation_split saat memanggil method fit. Nilai akurasi model saat pelatihan pada epoch ke-10 sebesar 0.8483 dengan nilai akurasi pada porsi data validasi sebesar 0.8517.

Selanjutnya model_1 kita evaluasi menggunakan data uji dimana diperoleh nilai akurasi sebesar 0.8257. Nilai ini relatif tinggi, namun kita akan coba barangkali performa model lebih meningkat lagi.

Model Neural Network (2 Hidden Layer)

Beberapa cara yang dapat kita lakukan untuk memperbaiki performa model yaitu dengan mengatur jumlah hidden layer serta jumlah units pada setiap hidden layer. Tidak ada aturan tegas mengenai banyaknya hidden layer maupun units yang tepat. Semua sangat tergantung dengan kondisi data. Hal terpenting adalah memastikan model tidak terlalu rumit sehingga dapat mengakibatkan overfitting.

Kode di bawah ini pada dasarnya mirip dengan kode untuk model_1. Perbedaannya adalah pada model ini (model_2) kita menambahkan 1 hidden layer lagi. Adapun struktur neural network yang kita bangun yaitu pada hidden layer pertama terdiri dari 64 neuron (units) dan pada hidden layer ke-2 memiliki 32 neuron. Pada hidden layer ke-2, kita tidak perlu menentukan parameter input_dim karena input yang masuk adalah sebanyak units pada layer sebelumnya.

Satu hal lain yang juga kita ubah adalah jumlah epoch. Jika sebelumnya kita set sebanyak 10, pada model_2 dibuat menjadi 50. Silahkan untuk mencoba jumlah lainnya misal 100, 200 ataupun yang lainnya.

Python

from keras.models import Sequential
from keras.layers import Dense


# Membangun model neural network
model_2 = Sequential()

# hidden layer ke-1
model_2.add(Dense(units=64, input_dim=X_train.shape[1], activation="relu"))

# hidden layer ke-2
model_2.add(Dense(units=32, activation="relu"))

# output layar : unit=4 (sebanyak kelas output)
model_2.add(Dense(units=4, activation="softmax"))


# Mengompilasi model
model_2.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)


# Melatih model
model_2.fit(
    X_train,
    y_train,
    epochs=50,
    validation_split=0.2,
)

print(model_2.summary())


# Evaluasi model pada data test
loss, accuracy = model_2.evaluate(X_test, y_test)

print("Loss:", loss)
print("Accuracy:", accuracy)

Output

Epoch 1/50
40/40 [==============================] - 1s 5ms/step - loss: 1.2077 - accuracy: 0.4463 - val_loss: 0.9441 - val_accuracy: 0.5868
Epoch 2/50
40/40 [==============================] - 0s 2ms/step - loss: 0.8241 - accuracy: 0.6517 - val_loss: 0.7424 - val_accuracy: 0.6498
Epoch 3/50
40/40 [==============================] - 0s 3ms/step - loss: 0.6641 - accuracy: 0.7291 - val_loss: 0.6245 - val_accuracy: 0.7129
Epoch 4/50
40/40 [==============================] - 0s 4ms/step - loss: 0.5578 - accuracy: 0.7915 - val_loss: 0.5448 - val_accuracy: 0.7823
Epoch 5/50
40/40 [==============================] - 0s 3ms/step - loss: 0.4728 - accuracy: 0.8357 - val_loss: 0.4767 - val_accuracy: 0.8328

...

Epoch 48/50
40/40 [==============================] - 0s 3ms/step - loss: 0.0115 - accuracy: 0.9976 - val_loss: 0.1255 - val_accuracy: 0.9495
Epoch 49/50
40/40 [==============================] - 0s 3ms/step - loss: 0.0092 - accuracy: 1.0000 - val_loss: 0.1320 - val_accuracy: 0.9527
Epoch 50/50
40/40 [==============================] - 0s 3ms/step - loss: 0.0085 - accuracy: 0.9992 - val_loss: 0.1256 - val_accuracy: 0.9527


Model: "sequential_5"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_14 (Dense)            (None, 64)                1536      
                                                                 
 dense_15 (Dense)            (None, 32)                2080      
                                                                 
 dense_16 (Dense)            (None, 4)                 132       
                                                                 
=================================================================
Total params: 3,748
Trainable params: 3,748
Non-trainable params: 0
_________________________________________________________________
None


17/17 [==============================] - 0s 1ms/step - loss: 0.1217 - accuracy: 0.9602

Loss: 0.1217188686132431
Accuracy: 0.9602272510528564

Hasil pelatihan pada model_2 menunjukkan nilai yang jauh lebih tinggi dari model_1. pada proses sampai epoch ke-2\50, terlihat nilai akurasi data validasi val_accuracy adalah sebesar 0.9527. Demikian pula ketika dievaluasi menggunakan data uji, akurasi model_2 adalah sebesar 0,9602. Nilai ini bermakna model_2 mampu mengklasifikasikan dengan benar sebanyak 96,02 persen dari data uji.

Menambah Layer Dropout

Layer Dropout adalah salah satu teknik regularisasi yang digunakan dalam neural network untuk mencegah overfitting. Dropout bekerja dengan cara secara acak menonaktifkan (menghapus) sejumlah neuron pada layer di dalam proses pelatihan.

Berikut adalah cara kerja layer Dropout:

  1. Selama pelatihan, dalam setiap iterasi atau batch data, layer Dropout secara acak memilih sejumlah neuron untuk dihapus dengan probabilitas p. Probabilitas ini dapat diatur sebagai parameter. Nilai p=0.1 menunjukkan bahwa setiap neuron memiliki peluang sebesar 0.1 untuk dinonaktifkan pada iterasi tersebut.
  2. Setelah pemilihan acak, unit-unit yang dihapus ditandai sebagai tidak aktif atau tidak berkontribusi dalam perhitungan selama iterasi tersebut. Dalam arti, output dari unit-unit ini tidak dikirim ke layer berikutnya dan gradien tidak dihitung untuk unit-unit ini.
  3. Proses penghapusan unit secara acak ini memiliki efek samping yaitu membuat setiap unit harus menjadi lebih tangguh dan independen dari unit-unit lain dalam jaringan. Ini dapat mendorong jaringan untuk mengembangkan fitur-fitur yang lebih robust dan tidak tergantung pada unit-unit tertentu.
  4. Ketika fase prediksi atau pengujian, semua unit dalam layer Dropout diaktifkan kembali. Namun, bobot dari unit-unit yang dihapus selama pelatihan akan dikurangi dengan faktor (1 – p) untuk menjaga konsistensi antara fase pelatihan dan fase prediksi.

Dengan menggunakan Dropout, neural network cenderung menjadi lebih tahan terhadap overfitting karena unit-unit yang dihapus secara acak memaksa jaringan untuk tidak bergantung terlalu banyak pada unit-unit tertentu. Ini membantu meningkatkan generalisasi pada data yang belum pernah dilihat sebelumnya.

Perlu dicatat bahwa layer Dropout harus digunakan secara bijak dengan pertimbangan yang tepat tergantung pada kompleksitas model serta data yang digunakan.

Python

from keras.models import Sequential
from keras.layers import Dense, Dropout


# Membangun model neural network
model_3 = Sequential()

# hidden layer ke-1
model_3.add(Dense(units=64, input_dim=X_train.shape[1], activation="relu"))

# dropout layer 
model_3.add(Dropout(0.1))

# hidden layer ke-2
model_3.add(Dense(units=32, activation="relu"))

# dropout layer
model_3.add(Dropout(0.1))

# output layar : unit=4 (sebanyak kelas output)
model_3.add(Dense(units=4, activation="softmax"))


# Mengompilasi model
model_3.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)


# Melatih model
model_3.fit(
    X_train,
    y_train,
    epochs=50,
    validation_split=0.2,
)

print(model_3.summary())


# Evaluasi model pada data test
loss, accuracy = model_3.evaluate(X_test, y_test)

print("Loss:", loss)
print("Accuracy:", accuracy)

Output

Epoch 1/50
40/40 [==============================] - 1s 6ms/step - loss: 1.2839 - accuracy: 0.4439 - val_loss: 1.0820 - val_accuracy: 0.5584
Epoch 2/50
40/40 [==============================] - 0s 3ms/step - loss: 0.9724 - accuracy: 0.5995 - val_loss: 0.8513 - val_accuracy: 0.5931
Epoch 3/50
40/40 [==============================] - 0s 3ms/step - loss: 0.7985 - accuracy: 0.6572 - val_loss: 0.7075 - val_accuracy: 0.6688
Epoch 4/50
40/40 [==============================] - 0s 3ms/step - loss: 0.6664 - accuracy: 0.7188 - val_loss: 0.6010 - val_accuracy: 0.7476
Epoch 5/50
40/40 [==============================] - 0s 3ms/step - loss: 0.5720 - accuracy: 0.7709 - val_loss: 0.5269 - val_accuracy: 0.7950

...

Epoch 48/50
40/40 [==============================] - 0s 3ms/step - loss: 0.0503 - accuracy: 0.9842 - val_loss: 0.1017 - val_accuracy: 0.9621
Epoch 49/50
40/40 [==============================] - 0s 3ms/step - loss: 0.0433 - accuracy: 0.9874 - val_loss: 0.0991 - val_accuracy: 0.9590
Epoch 50/50
40/40 [==============================] - 0s 3ms/step - loss: 0.0426 - accuracy: 0.9850 - val_loss: 0.0829 - val_accuracy: 0.9653


Model: "sequential_6"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_17 (Dense)            (None, 64)                1536      
                                                                 
 dropout_6 (Dropout)         (None, 64)                0         
                                                                 
 dense_18 (Dense)            (None, 32)                2080      
                                                                 
 dropout_7 (Dropout)         (None, 32)                0         
                                                                 
 dense_19 (Dense)            (None, 4)                 132       
                                                                 
=================================================================
Total params: 3,748
Trainable params: 3,748
Non-trainable params: 0
_________________________________________________________________
None

17/17 [==============================] - 0s 3ms/step - loss: 0.1163 - accuracy: 0.9489

Loss: 0.11632095277309418
Accuracy: 0.9488636255264282

Dari output di atas, nilai akurasi model_3 pada saat epoch ke-50 untuk data validasi mencapai 0.9563. Evaluasi dengan data uji juga memberikan nilai akurasi yang tinggi yaitu mencapai 0.9489.

Checkpoint dan Early Stopping

Checkpoint adalah fitur untuk menyimpan model ke dalam file selama proses pelatihan berlangsung. Kita dapat menentukan kriteria bagaimana checpoint dilakukan. beberapa parameter pada ModelCheckpoint adalah sebagai berikut:

  • filepath : path dan nama file untuk menyimpan model
  • monitor : menunjukkan nilai apa yang digunakan untuk membuat checkpoint
  • mode : menunjukkan nilai mana yang menjadi indikator untuk dimonitor. Misal, jika monitor menggunakan val_accuracy maka tentu saja nilai yang lebih tinggi adalah yang lebih baik sehingga kita menggunakan max. Sebaliknya jika monitor mengunakan loss tentu nilai yang lebih kecil lebih baik dan kita dapat mengatur mode="min". Nilai default mode adalah "auto" dimana keras akan menentukan nilai yang tetap sesuai monitor.
  • save_best_only : ketika parameter ini diset True maka setiap epoch, akan dicek nilai yang dimonitor, jika nilai pada epoch sekarang lebih baik dari sebelumnya, maka file sebelumnya akan ditimpa dengan model berdasarkan epoch yang sekarang.

Early Stoping dilakukan menggunakan fungsi EarlyStopping. Terdapat dua parameter utama yaitu monitor dan patience. Pada dasarnya, fungsi ini memonitor hasil setiap epoch berdasarkan parameter monitor. Misal diset monitor=val_accuracy dan patience=10, maka fungsi akan mengecek nilai val_accuracy pada setiap epoch dan seandainya hingga 10 epoch berikutnya nilai ini tidak meningkat maka proses pelatihan akan dihentikan tanpa menunggu seluruh epoch selesai.

Untuk menerapkan kedua fungsi ini ke dalam model yang akan dilatih, kita harus mengatur parameter callbacks pada method fit.

Python

from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.callbacks import ModelCheckpoint, EarlyStopping
from keras.optimizers import Adam


# menentukan nama dan path file untuk penyimpanan model
filepath = "model_check.h5"

# mengatur kriteria checkpoint
checkpoint = ModelCheckpoint(
    filepath=filepath,
    monitor="val_accuracy",
    save_best_only=True,
    mode="max",
    verbose=1,
)

# mengatur kondisi untuk early stopping
early_stopping = EarlyStopping(
    monitor="val_accuracy",
    patience=10,
    verbose=1,
)


# Membangun model neural network
model_4 = Sequential()

# hidden layer ke-1
model_4.add(Dense(units=64, input_dim=X_train.shape[1], activation="relu"))

# dropout layer 
model_4.add(Dropout(0.1))

# hidden layer ke-2
model_4.add(Dense(units=32, activation="relu"))

# dropout layer
model_4.add(Dropout(0.1))

# output layar : unit=4 (sebanyak kelas output)
model_4.add(Dense(units=4, activation="softmax"))


# Mengompilasi model
model_4.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)


# Melatih model
model_4.fit(
    X_train,
    y_train,
    epochs=50,
    validation_split=0.2,
    callbacks=[checkpoint, early_stopping],  # mengatur checkpoint dan early stopping
)

Output

Epoch 1/50
33/40 [=======================>......] - ETA: 0s - loss: 1.2333 - accuracy: 0.4640 
Epoch 1: val_accuracy improved from -inf to 0.58360, saving model to model_check.h5
40/40 [==============================] - 1s 8ms/step - loss: 1.2094 - accuracy: 0.4810 - val_loss: 0.9926 - val_accuracy: 0.5836
Epoch 2/50
36/40 [==========================>...] - ETA: 0s - loss: 0.9047 - accuracy: 0.6207
Epoch 2: val_accuracy improved from 0.58360 to 0.65300, saving model to model_check.h5
40/40 [==============================] - 0s 5ms/step - loss: 0.8899 - accuracy: 0.6256 - val_loss: 0.7686 - val_accuracy: 0.6530
Epoch 3/50
21/40 [==============>...............] - ETA: 0s - loss: 0.7519 - accuracy: 0.6711
Epoch 3: val_accuracy improved from 0.65300 to 0.70978, saving model to model_check.h5
40/40 [==============================] - 0s 5ms/step - loss: 0.7259 - accuracy: 0.6809 - val_loss: 0.6274 - val_accuracy: 0.7098
Epoch 4/50
22/40 [===============>..............] - ETA: 0s - loss: 0.6607 - accuracy: 0.7287
Epoch 4: val_accuracy improved from 0.70978 to 0.76656, saving model to model_check.h5
40/40 [==============================] - 0s 5ms/step - loss: 0.6125 - accuracy: 0.7551 - val_loss: 0.5441 - val_accuracy: 0.7666
Epoch 5/50
21/40 [==============>...............] - ETA: 0s - loss: 0.5415 - accuracy: 0.7917
Epoch 5: val_accuracy improved from 0.76656 to 0.79495, saving model to model_check.h5
40/40 [==============================] - 0s 5ms/step - loss: 0.5395 - accuracy: 0.7907 - val_loss: 0.4789 - val_accuracy: 0.7950

...

Epoch 44/50
32/40 [=======================>......] - ETA: 0s - loss: 0.0563 - accuracy: 0.9844
Epoch 44: val_accuracy did not improve from 0.96845
40/40 [==============================] - 0s 3ms/step - loss: 0.0566 - accuracy: 0.9842 - val_loss: 0.1029 - val_accuracy: 0.9621
Epoch 45/50
33/40 [=======================>......] - ETA: 0s - loss: 0.0687 - accuracy: 0.9811
Epoch 45: val_accuracy did not improve from 0.96845
40/40 [==============================] - 0s 3ms/step - loss: 0.0661 - accuracy: 0.9818 - val_loss: 0.1076 - val_accuracy: 0.9621
Epoch 45: early stopping

Pada output di atas, dapat kita lihat saat nilai val_accuracy meningkat maka model akan disimpan dalam file "model_check.h5". Selanjutnya dapat dilihat juga, pada epoch ke-45, tampak nilai val_accuracy tidak meningkat dibandingkan 10 epoch sebelumnya. Oleh karena itu, proses pelatihan otomatis berhenti tanpa menunggu sampai epoch ke-50.

Masih dari kode di atas, kita dapat menggunakan model_4 untuk melakukan evaluasi atau prediksi. Namun kita dapat juga memuat model yang sudah tersimpan. Model dapat kita akses menggunakan fungsi load_model dari modul keras.models. Setelah model dimuat, kita dapat melakukan prediksi, evaluasi ataupun melakukan pelatihan kembali (penambahan epoch).

Python

from keras.models import load_model

# Memuat model yang disimpan dalam file
model_from_file = load_model("model_check.keras")

# model dapat digunakan kembali untuk prediksi, evaluasi atau pelatihan

loss, accuracy = model_from_file.evaluate(X_test, y_test)

print("Loss:", loss)
print("Accuracy:", accuracy)

Output

17/17 [==============================] - 0s 1ms/step - loss: 0.1190 - accuracy: 0.9527

Loss: 0.11901430785655975
Accuracy: 0.9526515007019043

Prediksi Data

Sebelumnya kita sudah menggunakan data uji sebagai dasar evaluasi model, namun kita belum pernah benar-benar melihat hasil prediksi model pada data uji. Memprediksi data uji dapat dilakukan memanggil method predict. Output dari method predict berupa nilai probabilitas setiap amatan untuk masuk ke kelas.

Setiap amatan akan masuk ke dalam kelas yang mana peluangnya masuk kelas tersebut adalah tertinggi dibandingkan masuk kelas lainnya. Agar daapt menentukan kelas prediksinya, kita dapat menggunakan bantuan funsgi argmax dari pustaka numpy . Dengan mengatur parameter axis=1, fungsi argmax akan mengembalikan indeks kolom yang memilki nilai tertinggi.

Hasil prediksi juga dapat ditampilkan dalam bentuk confusion matrix. Kita dapat menampilkan confusion matrix menggunakan fungsi confusion_matrix dari modul sklearn.metrics. Jika ingin menampilkan dalam bentuk visual maka dapat menggunakan ConfussionMatrixDisplay dengan tambahan pustaka matplotlib.

Python

import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

# ingat variabel lenc (encoding peubah target)
# label asli dapat diakses pada atribut classes_
print(lenc.classes_)

# Evaluasi model pada data test
loss, accuracy = model_5.evaluate(X_test, y_test)

# melihat prediksi pada data test
y_pred = model_4.predict(X_test)

# Mengkonversi prediksi menjadi label kelas
y_pred_class = np.argmax(y_pred, axis=1)

# Menampilkan hasil prediksi
print(y_pred_class)

# memvisualisasikan confusion matrix
disp = ConfusionMatrixDisplay(
    confusion_matrix(y_pred_class, y_test), display_labels=lenc.classes_
)

disp.plot()
plt.show()

Output

['Insufficient' 'Normal' 'Obesity' 'Overweight']

17/17 [==============================] - 0s 1ms/step - loss: 0.1190 - accuracy: 0.9527

17/17 [==============================] - 0s 1ms/step

# output dalam bentuk peluang
[[1.18677307e-22 6.68677624e-13 9.99999642e-01 3.28039988e-07]
 [1.32066503e-04 5.14231980e-01 6.05750689e-03 4.79578465e-01]
 [7.84581403e-07 4.64998605e-03 9.22671519e-03 9.86122549e-01]
 ...
 [3.23932694e-13 5.31596129e-07 9.97674882e-01 2.32454971e-03]
 [1.51934853e-06 1.29436925e-02 2.20790016e-03 9.84846950e-01]
 [2.35353610e-07 3.05640721e-03 1.25635946e-02 9.84379768e-01]]

# merubah output menjadi kelas dengan peluang tertinggi
[2 1 3 2 2 2 3 2 2 2 2 3 2 3 1 2 3 2 3 3 3 2 3 2 3 2 3 0 2 3 2 2 2 2 0 3 2
 1 2 2 3 3 3 2 1 2 2 2 0 0 2 2 3 2 3 2 0 2 2 2 3 3 3 2 3 2 3 0 3 2 2 2 1 0
 2 1 2 2 0 2 0 2 2 0 3 3 3 0 2 0 2 2 2 2 2 2 3 2 3 2 1 3 1 2 2 3 2 2 3 3 3
 3 1 2 3 2 0 3 1 2 2 2 2 3 1 2 3 1 1 3 3 1 0 2 2 1 0 2 2 2 2 2 0 3 2 2 0 0
 2 0 2 1 3 0 2 2 2 3 2 3 0 3 2 2 2 1 2 2 1 1 3 2 2 3 3 3 3 2 2 0 2 3 2 1 3
 3 2 2 0 2 3 2 3 1 3 3 3 0 2 1 0 1 0 2 3 2 2 3 1 3 2 2 2 3 2 2 2 0 2 2 2 2
 3 0 3 2 0 2 0 0 2 3 1 2 2 2 1 2 2 3 3 2 2 2 1 2 3 2 2 2 2 3 2 2 0 3 2 3 2
 2 3 3 3 2 1 2 2 2 3 1 3 2 3 3 2 1 2 0 2 3 2 2 3 3 1 0 1 0 2 2 1 2 2 3 0 3
 2 2 2 3 3 2 2 2 3 1 2 2 3 3 0 3 3 3 0 2 0 2 0 2 3 3 1 3 2 3 2 0 2 2 2 3 3
 2 1 3 3 3 3 3 2 3 2 2 2 3 2 2 2 2 2 2 1 2 3 2 1 2 1 2 2 3 2 2 0 3 0 3 0 2
 2 0 3 2 2 3 3 3 3 2 1 0 3 3 3 2 0 2 2 2 1 0 3 0 0 1 2 1 2 1 1 3 1 2 2 3 3
 3 2 3 3 3 1 3 2 3 2 3 2 0 3 3 3 0 2 1 0 2 0 2 3 2 1 2 3 3 1 2 2 0 1 2 1 3
 2 1 3 2 3 2 2 3 3 3 3 1 1 1 0 2 1 2 2 2 2 0 1 0 2 2 2 2 2 3 2 2 2 2 3 3 2
 1 0 2 1 3 2 2 2 2 3 3 0 3 2 1 2 2 2 0 2 2 1 0 3 2 1 2 2 3 2 0 2 3 2 0 1 2
 0 2 2 3 1 3 0 2 3 3]
Confusion Matrix

Confusion matrix di atas menunjukkan hasil prediksi data uji. Sebagai contoh, dari 65 amatan yang memiliki label Normal, 56 nya diprediksi benar, sementara 2 salah prediksi menjadi "Insufficient" dan 7 salah prediksi menjadi "Overweight". Adapun dari 242 amatan yang memiliki label "Obesity", hanya 3 yang dipredisi salah masuk sebagai "Overweight".

Menyimpan dan Memuat Model

Di bagian sebelumnya, sudah ditunjukkan bagaimana model dapat disimpan ke dalam file melalui mekanisme checkpoint. Juga sudah dibahas bagaimana memuat kembali model yang tersimpan.

Selain kedua hal tersebut, kita juga dapat menyimpan model secara langsung tanpa melalui checkpoint. Penyimpanan model dilakukan dengan memanggil method save pada model. Model yang sudah disimpan, dapat diakses kembali dengan fungsi load_model. Selanjutnya, model yang dimuat dapat digunakan seperti sebelumnya, misal untuk melakukan prediksi, malakukan penambahan pelatihan dan lain sebagainya.

Python

from keras.models import load_model

# menyimpan model_1
model_1.save("model_10_epoch.keras")

# memuat model
model = load_model("model_10_epoch.keras")

Tulisan Lainnya

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

Daftar Isi