Seperti kebanyakan orang, saya sendiri merasa deg-deg-an dengan wabah virus corona ini, pilek dikit takut corona, padahal biasanya juga sering pilek santai aja, tetapi sekarang pilek itu rasanya beda gitu.... Jujur saya, sebagai manusia hal yang paling menakutkan untuk saat ini adalah kurang nya informasi yang benar tentang virus corona, banyak informasi yang simpang siur dan tidak jelas sumbernya.
san-king seringnya mondar-mandir digoogle mencari tentang informasi virus corona hingga saya sampai di sebuah repository github milik dokter Dr.Joseph Cohen, seorang dokter dari Universitas Monteral. Sekitar semingguan yang lalu Pak Joseph Cohen mengumpulkan hasil x-ray pasien yang terinfeksi virus corona, hingga terbesit di kepala saya untuk mencoba menggunakan X-rays tersebut untuk project kurang kerjaan ini.
pada tulisan kali ini saya tidak akan menjelaskan panjang lebar tentang deep-learning, karena saya yakin banyak tutorial yang bisa teman-teman temui di google yang menjelaskan lebih rinci tentang pembahasan deep-learning,tensorflow
,keras
dan kawan-kawan-nya.
Discalimer
Tulisan tentang mendeteksi virus corona ini hanya bertujuan untuk pembelajaran semata, tidak digunakan untuk menentukan hasil diagnosis ataupun terinfeksinya seseorang.
tujuan tulisan ini cukup simple, saya hanya ingin berbagi bagaiman memanfaatkan computer vision dan deep learning pada bidang kesehatan, siapa tau kedepanya bisa benar-benar dimanfaatkan.
Mendeteksi Corona Melalui Gambar X-Rays
Hingga saat ini hasil test tentang virus corona super sangat susah untuk didapatkan, saya berterima kasih kepada pak dokter Joseph Cohen untuk Gambarnya. Dari informasi yang saya rangkum, Virus corona akan menyerang sel Epitel yang melapisi saluran pernapasan kita, sejujurnya saya juga tidak mengerti akan hal ini, pengetahuan saya tentang ilmu kedokteran adalah Nol Besar.
Tetapi ada satu hal yang membuat saya antusias, prinsip Sederhana Deep Learning adalah melakukan train data dengan dataset yang tersedia, dataset disini maksudnya kita mengumpulkan sebanyak mungkin sample gambar x-rays dari pasien yang terinfeksi virus corona(Positif
), dan sample gambar x-rays dari pasien yang sehat (Negatif
), kedua sample gambar itu akan ditraining menggunakan metode tertentu sehingga kita mendapatkan model dari kasus negatif dan kasus positif, tentu saja banyaknya data sample akan sangat mempengaruhi tingkat akurasi yang kita dapatkan.
Seperti yang saya utarakan sebelumnya, disini kita akan menggunakan dataset dari repository github milik Dr.Joseph Cohen, Didalam repository tersebut ada beberapa hasil x-rays seperti Virus Corona, MERS, SARS dan ARDS, karena kita hanya membutuhkan gambar x-rays virus corona jadi kita harus memilah-milah gambar yang sesuai, didalam repositorynya juga Pak Dokter menyertkan sebuah file metadata.csv yang menerangkan data gambar yang tersedia.
Sample gambar X-Rays Positif Virus Corona sudah kita dapatkan, sekarang kita butuh gambar X-Rays dari orang/pasien yang Negatif virus Corona, untuk itu saya menggunakan Data Kaggle's Chest X-Ray Image (Pneumonia), data tersebut memiliki hasil x-rays Orang yang terkena Pneunomia dan Hasil X-Rays orang Normal/Sehat, karena kita butuhnya x-rays Orang sehat maka kita cukup mengambil data x-rays orang sehat.
sejauh ini kita memiliki 25 Gambar x-rays positif Corona
dan 25 Gambar x-rays Negatif Corona
, saatnya kita menentukan struktur folder dan project.
Implementasi
pada tulisan ini saya menggunakan python
dan virtual environtment
dengan python
package yang tersintall
numpy
tensorflow
opencv-contrib-python
scikit-image
pillow
imutils
scikit-learn
progressbar2
berikut versi open-cv
dan tensorflow
yang saya gunakan
kita sudah menyiapkan gambar sample, struktur folder dan package yang dibutuhkan, sekarang kita coba koding dikit-dikit. Buka file train_model.py
dan kita coba masukan kode berikut:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import AveragePooling2D
from tensorflow.keras.layers import Dropout
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Input
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.utils import to_categorical
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import argparse
import cv2
import os
kode diatas memperlihatkan bahwa kita akan menggunakan tensorflow.keras
, scikit-learn
sebagain library machine learning
dan OpenCV
untuk pengolahan citra/gambar.
coba teman-teman jalankan script diatas, jika tidak ada error berarti semua library sudah terinstall, jika masih ada error sebaiknya teman-teman install dulu library-libray yang kurang.
tahap selanjutnya kita akan membuat terminal interaktif, dengan menggunakan ArgumenParser()
dari python
, sebenarnya ini tidak wajib, hanya saja bisa menjadi lebih interaktif.
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
help="folder dataset")
ap.add_argument("-p", "--plot", type=str, default="plot.png",
help="Output Gambar Plot")
ap.add_argument("-m", "--model", type=str, default="corona.model",
help="Nama Model")
args = vars(ap.parse_args())
INIT_LR = 1e-3 # Learning Rate
EPOCHS = 25 # Epoch
BS = 8 # Batch Size
sekarang kita coba untuk membaca gambar dataset yang kita punya dengan OpenCV
dan kemudian merubahnya menjadi numpy array
agar kita memiliki gambar dalam bentuk key:value
print("[INFO] loading Gambar Dataset...")
imagePaths = list(paths.list_images(args["dataset"]))
data = []
labels = []
# loop sebanyak gambar dalam folder
for imagePath in imagePaths:
# ambil nama folder sebagai label
label = imagePath.split(os.path.sep)[-2]
# load Gambar, swap color channels, dan resize gambar jadi 224x224 pixels
image = cv2.imread(imagePath)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (224, 224))
data.append(image)
labels.append(label)
# convert data dan labels ke NumPy arrays
# dengan intensities dalam range [0, 255]
data = np.array(data) / 255.0
labels = np.array(labels)
saya rasa potongan kode diatas cukup mudah untuk dipahami, mulai dari baca semua isi folder dataset kemudian loop
semua sub folder yang ditemukan, load gambar dengan OpenCV
, Konversi warnanya menjadi RGB Channels
, resize
gambar kedalam ukuran 224x224 pixel
(untuk kebutuhan CNN
=Convolutional Neural Network
) kemudian append/tambah data dan label kedalam list
.
langkah selanjutnya, kita akan menggunakan one-hot encoding
pada labels
dan membuat trainig split
-nya.
# one-hot encoding pada labels
lb = LabelBinarizer()
labels = lb.fit_transform(labels)
labels = to_categorical(labels); print(labels)
# partisi data menjadi data training dan testing
# 80% training dan 20% untuk testing
(trainX, testX, trainY, testY) = train_test_split(data, labels,
test_size=0.20, stratify=labels, random_state=42)
#inisialisasi training data menggunakan augmentation object
trainAug = ImageDataGenerator(
rotation_range=15,
fill_mode="nearest")
mungkin teman-teman banyak yang bingung dengan istilah-istilah pada Machine
/Deep learning
, One-Hot Encoding
maksudnya merubah format label menjadi kira-kira seperti ini
[[0.,1.]
[0.,1.]]
Setiap hasil encoded
pada label memiliki 2 elemen array
yang mana 1 disebut sebagai Hot
dan 0 Sebagai Not
, kemudian ada istilah data augmentation
, maksudnya kita membuat semua gambar dirotasi se-arah dan berlawanan arah jarum jam secara random
dengan harapan hasil modeling nantinya bisa lebih akurat, karena pada realita nya gambar itu bentuk dan ukuranya macam-macam.
pada tahap ini, saatnya kita menggunakan VGGNet Model
pada data yang akan kita training.bingung dengan maksud VGGNet Model
? teman-teman bisa membacanya disini
# VGG16 network
baseModel = VGG16(weights="imagenet", include_top=False,
input_tensor=Input(shape=(224, 224, 3)))
headModel = baseModel.output
headModel = AveragePooling2D(pool_size=(4, 4))(headModel)
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(64, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(2, activation="softmax")(headModel)
model = Model(inputs=baseModel.input, outputs=headModel)
# loop semua layer pada base model kemudian set freeze
# agar tidak ikut terupdate pada proses training pertama
for layer in baseModel.layers:
layer.trainable = False
pada kode diatas, kita membentuk full-connected layer
menggunakan POOL=>FC = SOFTMAX
dan menginsert hasilnya pada VGG16
, dengan begitu kita siap untuk melakukan training model pada data
# Kompail Model
print("[INFO] Memproses Training Model...")
opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)
model.compile(loss="binary_crossentropy", optimizer=opt,
metrics=["accuracy"])
print("[INFO] Sedang Memproses Model...")
H = model.fit_generator(
trainAug.flow(trainX, trainY, batch_size=BS),
steps_per_epoch=len(trainX) // BS,
validation_data=(testX, testY),
validation_steps=len(testX) // BS,
epochs=EPOCHS)
pada kode diatas, kita melakukan model training dengan model rate decay
dan Adam Optimizer
, dengan begitu sekarang kita memiliki 2 Klasifikasi
, disini saya menggunakan metode binary_crossentropy
dan tidak menggunakan categorical_cronssentropy
.
sekarang kita akan menggunakan Keras fit_generator
untuk melakukan training sebelumnya dan melakukan testing
pada 20%
data yang kita split sebelumnya.
# Testing Prediksi
print("[INFO] Evaluasi network...")
predIdxs = model.predict(testX, batch_size=BS)
# Temukan index semua image yang di test
# Tentukan label dari nilai predicted probability tertinggi
predIdxs = np.argmax(predIdxs, axis=1)
print(classification_report(testY.argmax(axis=1), predIdxs,
target_names=lb.classes_))
pada tahap ini seharusnya model sudah bisa digunakan, tetapi biasanya jika kita melakukan training model pada deep-learning
tidak afdol rasanya jika tidak menyertakan classification
report
# Hitung confusion matrix
# accuracy, sensitivity, dan specificity
cm = confusion_matrix(testY.argmax(axis=1), predIdxs)
total = sum(sum(cm))
acc = (cm[0, 0] + cm[1, 1]) / total
sensitivity = cm[0, 0] / (cm[0, 0] + cm[0, 1])
specificity = cm[1, 1] / (cm[1, 0] + cm[1, 1])
print(cm)
print("acc: {:.4f}".format(acc))
print("sensitivity: {:.4f}".format(sensitivity))
print("specificity: {:.4f}".format(specificity))
kemudian saatnya kita simpan model hasil traning dalam format h5
print("[INFO] Menyimpan Model...")
model.save(args["model"], save_format="h5")
sekarang mari kita coba menjalankan train_model.py
, perhatian, Komputer atau CPU teman-teman akan sedikit menjerit pada saat menjalankan model Training, karena proses ini membutuhkan CPU yang besar (Laptop saya tidak menggunakan Kartu Grafis)
python train_model.py --dataset dataset
setelah model training selesai dilalukan, (Laptop saya butuh waktu sekitar 15 Menit untuk melakukan training) saatnya kita mencoba model hasil training kita, berikut script sederhana untuk melakukan prediksi
dengan menggunakan model yang telah kita training sebelumnya
import cv2
import tensorflow as tf
import numpy as np
import argparse
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
ap = argparse.ArgumentParser()
ap.add_argument("-g", "--gambar", required=True,help="Gambar yang akan dites")
ap.add_argument("-m", "--model", type=str, default="corona.model",help="Nama Model")
args = vars(ap.parse_args())
labels=['Negatif','Positif']
data = []
def prepare(filepath):
image = cv2.imread(filepath)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (224, 224))
data.append(image)
prepare(args['gambar'])
data = np.array(data) / 255.0
model = tf.keras.models.load_model(args['model'])
prediksi = model.predict(data)
prediksi_index = np.argmax(prediksi, axis=1)
max_val = int(np.amax(prediksi)*100)
print("Prediksi Hasil {persen}% {hasil} Covid-19".format(hasil=labels[int(prediksi_index[0])],persen=max_val))
karena kebijakan Google tidak bisa menayangkan video dengan content virus corona di website, teman-teman bisa melihat videonya di alamat berikut https://drive.google.com/file/d/1G7IAuMenpovHcuP_X01JbDu0Qj9dEIue/view
hasil diatas tidak bisa diklaim sebagai hasil final, ini hanya sekedar pembelajaran, dibutuhkan expert tentang virus serta dokter-dokter yang profesional untuk menentuk apakah seseorang terinfeksi corona atau tidak.
dari video dan gambar diatas, kita bisa melihat bahwa tingkat akurasi untuk mendeteksi infeksi virus corona melalui gambar x-rays mencapai 90-92%
dengan menggunakan sample data yang ada pada folder dataset, tingkat akurasi sangat-sangat ditentukan dengan jumlah sample data yang masuk dalam model train, hasil prediksi bisa saja salah (false positive)
karena kualitas gambar dari x-rays
dan banyaknya sample sangat mempengaruhi hasil dari prediksi itu sendiri.
dengan hanya menggunakan 25 sample
data dari Positif dan Negatif hasil dari prediksi ini belum bisa kita katakan benar-benar akurat, sejatinya dibutuhkan ribuan hingga ratusan ribu gambar dataset untuk bisa mendapatkan tingkat akurasi yang mungkin mendekati akurat.
saya harus memperingatkan teman-teman dan semua yang membaca tulisan ini, saya bukan seorang yang ahli dalam per-virusan, sekali lagi tulisan ini hanya untuk tujuan pembelajaran semata.
Sources Code Tersedia DiGithub, silahkan teman-teman download dan coba https://github.com/khairu-aqsara/covid19