Deteksi Pneumonia dengan Convolutional Neural Network (CNN)

Rizkynindra
11 min readJul 16, 2023

--

Part #01: Introduction

Pneumonia adalah peradangan paru-paru yang disebabkan oleh infeksi. Pneumonia bisa menimbulkan gejala yang ringan hingga berat. Beberapa gejala yang umum dialami penderita pneumonia adalah batuk berdahak, demam dan sesak nafas. Penyakit ini menjadi salah satu penyebab kematian tertinggi pada anak-anak di seluruh dunia menurut WHO tahun 2019. Pada sesi kali ini, kita akan mempelajari cara memprediksi gejala pneumonia berdasarkan data hasil rontgen pasien.

Dataset pada studi kasus ini berisikan kumpulan gambar rontgen pasien yang sudah dibedakan antara yang normal dan terkena pneumonia. Tugas kita adalah membuat model deep learning yang bisa memprediksi apakah seseorang terindikasi pneumonia atau tidak. So, mari kita masuk ke tahap selanjutnya.

Part #02: Load Dataset

Dataset yang kita gunakan bisa kalian akses melalui link berikut ini: https://www.kaggle.com/datasets/paultimothymooney/chest-xray-pneumonia. Silakan didownload dulu untuk bisa ke langkah berikutnya atau langsung dikerjakan di kaggle. Langkah awal yang bisa kalian lakukan adalah mengimport seluruh library yang diperlukan.

figure 1. import libraries

Project ini saya kerjakan langsung di kaggle, jika kalian mengerjakannya di jupyter notebook disarankan untuk mendownload library — library tersebut agar bisa diimport.

Selanjutnya kita buat fungsi untuk membaca gambar yang ada pada dataset. Script pada figure 2 berfungsi untuk membaca direktori tempat kita menyimpan dataset dan membaca gambar yang ada didalamnya. Untuk membaca gambar sendiri prosesnya dimulai dari baris ke 4–12. Baris ke 7 berfungsi untuk membaca gambar sedangkan baris ke 9 berfungsi untuk me-resize gambar menjadi 200 x 200px. Perlu diketahui bahwa ukuran asli gambar pada dataset ini sebesar 2.000 x 1858 px yang dimana jika tidak di resize maka akan memberatkan mesin kita kedepannya. Oleh karena itu filenya kita perkecil agar sedikit meringankan beban kerja laptop kalian.

figure 2. fungsi load images

Setelah fungsi dibuat, selanjutnya kita sudah bisa memasukkan dataset yang kita punya. Disini kita sudah langsung punya 2 folder train dan test dan di masing — masing folder terdapat folder lagi yang berisikan NORMAL dan PNEUMONIA.

figure 3. load dataset
figure 4. shape dataset

Bila kalian jalankan code pada figure 3 dan figure 4. Hasilnya tidak akan jauh berbeda. Keduanya menampilkan jumlah data yang kita miliki dari masing — masing folder. Namun pada figure 4, informasi yang kita dapat lebih lengkap karena menampilkan dimensi(200,200) dan juga warna dari gambar tersebut (3). Angka 3 pada warna disini maksudnya adalah mencerminkan symbol RGB. Detail hasilnya bisa kalian lihat pada figure 5.

figure 5. hasil shape

Selanjutnya kita bisa melihat sampel gambar dari orang normal dan yang terkena pneumonia dengan mengetik code dari figure 6 dan figure 7.

figure 6. X-ray normal
figure 7. X-ray pneumonia

Hasil dari code diatas akan menampilkan 8 gambar x-ray orang normal dan 8 gambar x-ray orang yang terkena pneumonia. Karena saya pribadi kurang paham dunia kesehatan, jadi saya hanya bisa mengambil sedikit kesimpulan dari hasil pengamatan saya bahwa orang yang terkena pneumonia hasil x-raynya akan cenderung lebih kabur (blur) dibandingkan dengan orang normal (x-ray orang normal terlihat lebih jelas). Untuk detailnya bisa kalian lihat di figure 8 dan figure 9.

figure 8. Penampakan X-ray orang normal
figure 9. Penampakan X-ray orang pneumonia

Part #03: Data Preprocessing

Setelah kita menemukan sedikit informasi dari dataset yang kita miliki, langkah selanjutnya kita buat training data dan testing data. Disini kita menggunakan fungsi vstack untuk menggabungkan gambar NORMAL dan PNEUMONIA. Jadi, untuk training data, x_train akan berisi gambar — gambar dari subfolder NORMAL dan PNEUMONIA di folder train. Sedangkan x_test akan berisikan gambar — gambar dari subfolder NORMAL dan PNEUMONIA di folder test.

figure 10. X_train & X_test
figure 11. y_train & y_test

Setelah code diatas dijalankan, terlihat bahwa shape untuk training data menjadi 5216 (1341 (normal) + 3875 (pneumonia)) dan testing data menjadi 624 (234 (normal) + 390 (pneumonia)). Selanjutnya training data dan testing data kita acak dengan fungsi shuffle dan kemudian kita pisahkan lagi datanya untuk pembagian x dan y. untuk codenya bisa dicek pada figure 12.

figure 12. shuffle training data & testing data

Selanjutnya kita gunakan fungsi ImageDataGenerator untuk melakukan sedikit modifikasi terhadap gambar yang kita miliki. ImageDataGenerator merupakan library dari “Keras” yang menyediakan cara cepat dan mudah untuk memodifikasi gambar. Tekniknya berupa standarization, rotation, shifts, flips, brightness change, dan lain-lain. Teknik ini kita gunakan agar dataset mempunyai banyak variasi gambar. bila kalian perhatikan, dataset yang kita miliki kebanyakan berada pada posisi tampak depan dan posisi tegak. Namun pernahkah kalian membayangkan jika kalian memiliki dataset dengan posisi yang tidak beraturan apakah mesin bisa belajar dengan baik? Jadi, untuk mengantisipasi hal-hal tersebut digunakanlah fungsi ImageDataGenerator agar algoritma deep learning nantinya dapat mempelajari data dengan berbagai kondisi. Pada project ini, fungsi yang akan kita gunakan adalah rotation, zoom, dan shift.

figure 13. image data generator

untuk pengaturan angka pada tiap fungsi (baris 2–5) tidak ada ketentuan. Jadi, kalian bisa mengubahnya sesuai dengan selera kalian. Selanjutnya kita fit-kan datagennya.

figure 14. fit datagen

Part #04: Create Model

Setelah di fit-kan. Selanjutnya kita bisa masuk ke tahap pembuatan model. Langkah awal adalah mendefinisikan input. Karena diawal kita me-resize gambarnya menjadi 200x200 pixel, maka untuk input shapenya kali ini kita juga buat dengan ukuran 200x200 pixel.

figure 15. input definition

Selanjutnya kita definisikan untuk convolutional layernya. Sebelum kita masuk ke codenya, disini akan saya jelaskan sedikit mengenai cara kerja dari Convolutional Neural Network (CNN). Metode CNN adalah salah satu metode AI yang diterapkan khusus untuk data berbentuk visual atau citra. CNN umum digunakan untuk mendeteksi dan mengenali object pada sebuah image. CNN terdiri dari convolutional layer, activation function, pooling layer dan fully connected layer. secara garis besarnya, CNN memanfaatkan proses konvolusi dengan menggerakkan sebuah kernel konvolusi (filter) berukuran tertentu ke sebuah gambar, computer mendapatkan informasi representative baru dari hasil perkalian bagian gambar tersebut dengan filter yang digunakan.

figure 16. Arsitektur CNN

Kembali ke code, convolutional layernya bisa kita buat dengan code dari figure 17 dibawah ini.

figure 17. Convolutional layer

Disini kita menggunakan aktivasi relu karena secara sederhana aktivasi ini hanya membuat pembatas pada bilangan 0 yang artinya jika x ≤ 0 maka x = 0 dan jika x > 0 maka x = x. Secara garis besar, baris ke-1 menjelaskan bahwa convolutional layer memiliki ukuran kernel sebesar 3x3 dan diterapkan pada gambar inputan berukuran 200x200 yang memiliki 3 channel warna (RGB) dan menghasilkan output layer dengan 16 channels. Baris ke-2 kurang lebih sama dengan baris ke-1 hanya saja untuk channelnya menjadi lebih besar sebanyak 32 channels. Layer pertama (baris 1) diawali dengan ukuran kecil (16) karena layer pertama digunakan untuk mengekstrak pola — pola yang sifatnya masih general. Selanjutnya, baru dibutuhkan layer lebih besar (32) untuk mengekstrak pola — pola agar lebih detail.

Bagian berikutnya, untuk pooling layer (baris ke-3) digunakan untuk mereduksi input secara spasial (mengurangi jumlah parameter). Umumnya metode yang digunakan adalah max pooling. Namun tidak menutup kemungkinan kalian juga bisa menggunakan metode lain seperti average pooling atau L2-norm pooling.

figure 18. ilustrasi cara kerja max pooling layer

Selanjutnya layer Flatten digunakan untuk meng-convert data gambar multidimensi menjadi array 1 dimensi sebelum disambungkan ke fully-connected layer (Dense()).

figure 19. dense layer

Untuk dense layer, diawali dengan 100 neuron dan kemudian turun menjadi 50 neuron. Untuk jumlah neuronnya sendiri sebenarnya tidak ada ketentuan baku, tapi umumnya diawali dengan jumlah neuron yang banyak lalu kemudian berkurang seterusnya. Untuk outputnya sendiri memiliki 1 neuron dan menggunakan activation sigmoid. Berbeda dengan relu, cara kerja sigmoid adalah ia akan menerima angka tunggal dan mengubah nilai x menjadi sebuah nilai yang memiliki range 0 sampai 1.

figure 20. sigmoid function

Untuk dropout rate digunakan 0.5 yang artinya jika nilai output yang dihasilkan diatas 0.5 maka akan dibulatkan menjadi 1 yang dalam kasus ini dinyatakan sebagai positif terkena pneumonia. Sebaliknya, jika nilai output dibawah 0.5 maka akan dibulatkan menjadi 0 yang artinya data dinyatakan sebagai orang sehat (tidak terkena pneumonia).

Selanjutnya kita buat modelnya sekaligus menentukan input dan outputnya. Dan jangan lupa tampilkan summarynya untuk mengetahui detail dari model kita.

figure 21. create model

Seperti yang terlihat pada figure 22. Model yang kita buat terdiri dari 32 juta param. Cukup banyak param yang kita miliki, oleh karena itu saya sarankan kalian dapat menggunakan Kaggle atau google colab supaya bisa memanfaatkan GPU nya.

figure 22. model summary & hasilnya

Selanjutnya model kita compile sebelum di-train. Disini kita akan gunakan loss function binary_crossentropy karena klasifikasi kita berupa binary (0 atau 1). Kemudian optimizer kita gunakan adam dan berfokus pada metric akurasi.

figure 23. model compile

Setelah di compile, kita bisa buat sebuah checkpoint yang berfungsi untuk menyimpan model terbaik dari hasil training nantinya. Checkpoint ini juga bertujuan untuk mengurangi waktu kalian dalam training ulang. Seringkali dengan mengulang proses training hasil yang didapatkan tidak konsisten. Jadi untuk menghindari hal itu ada baiknya kita simpan hasil terbaik yang didapat oleh model kita. Untuk scriptnya bisa dilihat di figure 24.

figure 24. checkpoint

Langkah selanjutnya adalah kita training untuk modelnya. Untuk settingannya disini saya gunakan epochs sebanyak 30 dan batch_size 32. Untuk jumlah epochs tidak ada ketentuan baku, namun disarankan jangan terlalu sedikit supaya model lebih banyak mempelajari polanya.

figure 25. training model

Bagi kalian yang tidak menggunakan GPU proses ini akan memakan waktu yang lama, jadi harap bersabar aja #haha. Jika sudah selesai, kalian bisa ketik code pada figure 26 untuk menyimpan hasil training modelnya.

figure 26. save model

Part #05: Evaluate Model

Akhirnya kita masuk pada tahapan terakhir dari project ini. Jadi, setelah model selesai di training, kita lanjutkan dengan mengevaluasi model tersebut untuk mengetahui performanya. Langkah pertama yang bisa kita lakukan adalah melihat nilai loss dan akurasi yang diterima dari seluruh epochs.

figure 27. cek nilai loss
figure 28. hasil nilai loss
figure 29. cek nilai akurasi
figure 30. hasil nilai akurasi

Berdasarkan figure 28, terlihat bahwa nilai loss pada validation data sudah rendah sejak awal. Hal ini bertolak belakang dengan nilai akurasinya. Seperti yang terlihat pada figure 30, nilai akurasi sangat beragam dari epoch 1 sampai 30. Titik tertinggi yang diraih sebesar 0.83 dan titik terendah berada pada nilai 0.77. Selanjutnya kita dapat memastikan jumlah data yang terprediksi dengan menggunakan confusion matrix. Sebelumnya, kita dapat memanggil kembali model terbaik yang pernah kita buat dengan code dibawah ini:

figure 31. Load model

Dilanjutkan dengan membuat fungsi untuk memanggil confusion matrixnya. Kemudian menampilkan hasil confusion matrix untuk training data dan validation data.

figure 32. create confusion matrix
figure 33. hasil confusion matrix data training

Confusion matrix tersusun atas 4 komponen penilaian yaitu true positive (TP), true negative (TN), false positive (FP) dan false negative (FN). Data disebut true positive apabila data positif juga diprediksi positif oleh model. Pada kasus ini contohnya apabila data yang sesungguhnya menyebutkan bahwa pasien terkena pneumonia dan model memprediksi pasien tersebut juga terkena pneumonia. False negative menyatakan sebaliknya, jika pasien menderita pneumonia namun model memprediksi pasien tersebut tidak menderita pneumonia. Lalu true negative adalah data negatif yang terprediksi negative oleh model. Misalkan ketika data menyebutkan pasien tidak terkena pneumonia dan model juga memprediksi hal yang sama. Dan false positive adalah data negatif yang terprediksi sebagai data positif oleh model.

figure 34. ilustrasi konsep confusion matrix

Kita dapat menghitung evaluation metric berdasarkan hasil confusion matrix pada data training. Untuk perhitungannya sendiri menggunakan rumus — rumus sebagai berikut:

Accuracy = (TP+TN)/(TP+FP+TN+FN)
Precision = TP/(TP+FP)
Recall = TP/(TP+FN)
F1 Score = 2x (Precision x Recall)/(Precision+Recall)

Adapun keterangan dari masing — masing parameter yaitu:

· Accuracy: menggambarkan seberapa akurat model dalam mengklasifikasi dengan benar.

· Precision: menggambarkan akurasi antara data yang diminta dengan hasil prediksi yang diberikan oleh model.

· Recall: menggambarkan keberhasilan model dalam menemukan Kembali sebuah informasi.

· F1 Score: menggambarkan perbandingan rata-rata precision dan recall yang dibobotkan.

Accuracy tepat kita gunakan sebagai acuan performansi algoritma jika dataset memiliki jumlah data false negative dan false positive yang sangat mendekati. Namun jika jumlahnya tidak mendekati, maka sebaiknya menggunakan F1 Score sebagai acuan.

Bercermin dari figure 34, maka hasil dari perhitungan evaluation metric untuk training data adalah:

Accuracy : 0.92

Precision : 0.95

Recall : 0.94

F1 Score : 0.94

Terlihat bahwa kita memiliki nilai evaluation metric yang tinggi untuk training data. Selanjutnya, kita lakukan hal yang sama terhadap testing data yaitu membuat confusion matrix dan mencari hasil evaluation metricnya.

figure 35. hasil confusion matrix testing data

Accuracy : 0.77

Precision : 0.75

Recall : 0.95

F1 Score : 0.83

Jika melihat hasil dari table 1 dan 2, terlihat bahwa nilai dari masing — masing parameter evaluation metric berbeda cukup jauh. Dalam kondisi inipun nilai akurasi tidak bisa digunakan mengingat jumlah data orang yang normal dan terkena pneumonia tidak seimbang. Maka dari itu kita dapat berfokus pada nilai lain yaitu F1 score. Disini terlihat bahwa nilai F1 score untuk data testing sebesar 0.83. nilai ini sudah lumayan bagus untuk dalam permasalahan ini karena hampir mencapai 0.90 atau 90%.

Dan tibalah kita pada tahap terakhir dari project ini. Disini kita akan mencoba melakukan prediksi untuk data yang ada pada folder val. Langkah pertama kita load terlebih dahulu untuk datanya dengan code dibawah ini.

figure 36. load data apda folder val

Lalu kita prediksi datanya menggunakan perintah “predict”.

figure 37. prediksi data val

Selanjutnya kita visualisasikan hasil prediksinya dengan menggunakan code dibawah ini. Data yang akan kita visualisasikan adalah data pada subfolder Normal dan Pneumonia.

figure 38. code dan hasil prediksi dari subfolder normal
figure 39. code dan hasil prediksi dari subfolder pneumonia

Berdasarkan hasil dari figure 38 dan 39, kesimpulan yang bisa kita dapatkan adalah model masih keliru dalam memprediksi data normal (terlihat pada figure 38, banyak data normal terprediksi sebagai pneumonia (1). Sedangkan pada data pneumonia model suskes memprediksi semua data dengan benar. Jika kita melihat hipotesis yang kita buat sebelumnya bahwa x-ray orang yang terkena pneumonia cenderung terlihat lebih buram (blur) daripada yang normal, kita bisa katakan bahwa model kita telah sukses memprediksi orang yang terindikasi terkena pneumonia (meskipun ada sedikit error yang ditemukan).

--

--

Rizkynindra

Programmer Jarang Coding || Editor jarang ngedit || Musisi jarang nyanyi. Pokoknya hampir semua saya garap