Pembelajaran Mendalam

Masalah

Lebih dari 700.000 orang Amerika hidup dengan tumor otak saat ini dan penelitian menunjukkan bahwa lebih dari 84.000 orang akan didiagnosis menderita tumor otak primer pada tahun 2021 [1]. Mendiagnosis tumor otak biasanya dimulai dengan pemindaian Magnetic Resonance Imaging (MRI). Hasilnya kemudian ditinjau oleh dokter saraf untuk melihat apakah terdapat tumor di otak.

Menggunakan kecerdasan buatan untuk mendeteksi tumor otak dari pemindaian MRI akan menghemat uang dan yang terpenting waktu. Tak hanya itu, hal ini juga kemungkinan bisa mengurangi human error dalam pendeteksian tumor. Dengan populasi yang terus bertambah saat ini, dokter harus menggunakan teknologi untuk menentukan hasil pemindaian otak secara tepat waktu. Pada artikel ini, kami akan membuat model Convolutional Neural Network (CNN) untuk mengklasifikasikan pemindaian otak MRI.

Analisis

Himpunan data

Untuk tugas yang ada, kami memilih untuk menggunakan kumpulan data Gambar MRI Otak untuk Deteksi Tumor Otak dari Kaggle. Dataset ini berisi 155 gambar hasil scan MRI dengan tumor otak dan 98 gambar tanpa tumor. Pemindaian tumor otak ada di folder berlabel “ya” dan gambar otak yang sehat ada di folder “tidak”.

Di bawah ini adalah contoh pemindaian yang menunjukkan otak tanpa tumor (kiri) dan otak dengan tumor (kanan).

Pemrosesan Awal Data

Semua gambar berwarna abu-abu, sehingga ketika diimpor akan memiliki nilai yang sama untuk saluran R, G dan B. Kita dapat menggunakan salah satu saluran untuk model kita. Namun, semua gambar tidak memiliki dimensi yang sama sehingga harus diubah ukurannya atau diisi sebelum meneruskannya ke model jaringan saraf. Selain itu, kami menormalkan gambar dengan menskalakan nilai piksel mulai dari 0 hingga 255 hingga rentang 0 hingga 1.

Fitur dan Label

Gambar data masukan akan digunakan untuk melatih model dalam mengklasifikasikan gambar pemindaian MRI apakah memiliki tumor atau tidak. Gambar dalam hal ini akan menjadi fitur untuk algoritma dan label, baik 0 atau 1 akan digunakan untuk mengklasifikasikan masing-masing gambar tanpa tumor dan tumor.

Kami mendefinisikan fungsi preprocess_data yang mengambil jalur penyimpanan gambar dan bentuk yang diinginkan untuk mengubah ukuran gambar. Setelah membaca, mengubah ukuran dan menskalakan gambar, ia menyimpannya dalam array X (fitur) dan label yang sesuai dalam array y (label).

def preprocess_data(path, img_size):
'''
Reads in images classified into folders, resizes and scales them. Returns
those processed images as features and their associated labels as well.
Arguments:
path (str) - path to classified image folders
img_size (tuple) - tuple containing resized image height and width
Returns:
X (array) - features (brain scan images)
y (array) - feature labels (0 - no tumor, 1 - tumor)
'''
unsuccessful_files = {}
X = []
y = []
for folder_name in os.listdir(path):
if folder_name == 'no':
label = 0
else:
label = 1
folder_path = os.path.join(path, folder_name)
for fname in os.listdir(folder_path):
fpath = os.path.join(folder_path, fname)
try:
img = cv2.imread(fpath)
img = cv2.resize(img, img_size)
img = img / 255.0
X.append(img)
y.append(label)
except Exception as e:
unsuccessful_files[fname] = e
if unsuccessful_files:
print(f'Error processing the following files:\n')
for index, key in enumerate(unsuccessful_files, 1):
print(f'{index}. {key} - {unsuccessful_files[key]}')
else:
print('Successfully processed all images.')
X = np.array(X)
y = np.array(y)
return X, y

Algoritma

Tujuan dari proyek ini adalah untuk membangun model Convolutional Neural Network (CNN) yang secara akurat mengklasifikasikan pemindaian otak MRI apakah memiliki tumor atau tidak. Sebagai tolok ukur, kami akan membandingkan kinerja model jaringan saraf kami dengan pengklasifikasi gambar Support Vector Machine. Kontributor kumpulan data ini di Kaggle tidak menentukan sumber datanya sehingga kami tidak dapat membandingkan performa model kami dengan tolok ukur yang dipublikasikan.

Perpecahan Tes Kereta Api

Kami menggunakan pemisahan pengujian kereta sklearn untuk membagi data menjadi set pelatihan (75%), validasi (12,5%) dan pengujian (12,5%).

# split data into train, validation and test sets
from sklearn.model_selection import train_test_split

X_train, X_test_val, y_train, y_test_val = train_test_split(X, y, test_size=0.25, random_state=42)
X_test, X_val, y_test, y_val = train_test_split(X_test_val, y_test_val, test_size=0.5, random_state=42)

Memvisualisasikan 9 gambar pertama di set pelatihan kami beserta labelnya:

Penerapan

Jaringan Neural Konvolusional

  • Bangun Modelnya

Kami membangun model sekuensial yang terdiri dari tiga blok konvolusi (16, 32, dan 64 unit resp.) dengan lapisan kumpulan maksimal di masing-masing blok. Lapisan ini bertindak sebagai ekstraktor fitur. Output dari lapisan-lapisan ini setelah melewati lapisan dropout diratakan dan kemudian dilewatkan melalui lapisan yang terhubung penuh dengan 128 unit yang diaktifkan oleh fungsi aktivasi relu. Terakhir, kami memiliki lapisan padat dengan aktivasi sigmoid yang menghasilkan kemungkinan mendeteksi tumor.

# create the model
model = Sequential([
layers.Input((img_height, img_width, 3)),
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Dropout(0.2),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(1, activation='sigmoid')
])
  • Kompilasi Modelnya

Kami kemudian mengkompilasi model menggunakan pengoptimal adam, kehilangan entropi silang biner, dan akurasi sebagai metrik.

# compile the model
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(),
metrics=['accuracy'])
  • Latih Modelnya

Kami menggunakan ukuran batch 32 dan 20 epoch untuk melatih model. Kami menambahkan callback penghentian awal untuk mencegah overfitting pada data. Selain itu, lapisan dropout dalam model sekuensial kita juga akan membantu mencegah overfitting.

# train the model
early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=4)
history = model.fit(
X_train,
y_train,
batch_size=32,
validation_data=(X_val, y_val),
epochs=20,
callbacks=[early_stop]
)

  • Uji Modelnya

Kami menguji model dengan membuat prediksi pada set pengujian kami. Perhatikan bahwa model mengeluarkan probabilitas dari 0 hingga 1, oleh karena itu kami membulatkan nilai ini untuk mendapatkan label klasifikasi untuk setiap prediksi.

# make predictions on the test set
y_pred = model.predict(X_test)
y_pred = np.squeeze(y_pred).round().astype(int)
# classification report
from sklearn.metrics import classification_report , confusion_matrix
print(classification_report(y_test, y_pred))

Melihat laporan klasifikasi, model kami memberi kami akurasi 75% dan rata-rata perolehan tertimbang 75%. Performanya bukan yang terbaik, terutama karena kami tidak memiliki cukup sampel dalam kumpulan data kami. Kumpulan data kami memiliki total 253 gambar.

  • Augmentasi Data

Untuk meningkatkan performa model, kami menggunakan augmentasi data untuk meningkatkan ukuran sampel. Kita mulai dengan mendefinisikan lapisan augmentasi data yang menambahkan pembalikan, rotasi, dan zoom acak pada gambar.

# define augmentation layer
data_augmentation = tf.keras.Sequential([
layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
layers.experimental.preprocessing.RandomRotation(0.2),
layers.experimental.preprocessing.RandomZoom(0.1)])

Kami kemudian mendefinisikan fungsi augment_image yang mengambil gambar input dan mengembalikan daftar sejumlah gambar augmented tertentu.

def augment_image(image, n_augmented_images):
'''
Returns a list of augmented images for the given input image
Arguments:
image (array) - input image
number_of_images (int) - number of augmented images to return
Returns:
images (list) - list of augmented images
'''
image = tf.expand_dims(image, 0)
images = []
for i in range(n_augmented_images):
augmented_image = data_augmentation(image)
images.append(np.array(augmented_image[0]))
return images

Kami menghasilkan 12 gambar yang diperbesar untuk setiap gambar dalam kumpulan data kami, sehingga menghasilkan jumlah total 3289 sampel gambar. Itu jauh lebih banyak daripada yang kami miliki di kumpulan data asli kami. Dengan memvisualisasikan 9 gambar pertama di set pelatihan kita, kita dapat melihat perpaduan gambar asli dan gambar tambahan.

Setelah melatih dan menguji model menggunakan kumpulan data augmented, kami mendapatkan akurasi sebesar 86% dan rata-rata tertimbang perolehan sebesar 86%. Itu berarti peningkatan performa model sebesar 15%.

  • Penyetelan Hiperparameter

Kami mencoba menyempurnakan model dasar CNN dengan mengevaluasi rentang nilai dalam ruang hyperparameter menggunakan validasi silang. Untuk ini, kami menggunakan tuner hyperband Keras dan mendapatkan hyperparameter terbaik berikut:

Setelah membuat, melatih, dan menguji model menggunakan hyperparameter terbaik, kami memperoleh akurasi 91% dan perolehan 91%. Itu merupakan peningkatan ~6% dibandingkan model kami sebelumnya.

Mendukung Pengklasifikasi Vektor

Kami akan membandingkan performa model kami dengan pengklasifikasi Support Vector Machine (SVM) sebagai tolok ukur. Kami menggunakan kumpulan data tambahan di sini. Bentuk fiturnya perlu sedikit diubah agar kita dapat menggunakan SVM. Gambar berukuran (128, 128, 3) perlu diratakan sebelum dipasang ke SVM.

Setelah selesai, kami membuat pengklasifikasi SVM dan melatihnya.

from sklearn import svm
# Create a classifier: a support vector classifier
clf = svm.SVC(gamma=0.001)
# Learn the digits on the train subset
clf.fit(X_train, y_train)

Pengujian klasifikasi SVM pada pengujian kami menghasilkan akurasi dan rata-rata tertimbang recall sebesar 79%.

Hasil

Untuk meringkas pekerjaan kami, kami memulai dengan kumpulan data asli dan melatih model CNN untuk mengklasifikasikan pemindaian otak dengan dan tanpa tumor. Kami segera menyadari bahwa performa modelnya bukanlah yang terbaik. Hal ini disebabkan oleh kecilnya ukuran sampel dari kumpulan data asli. Kami kemudian menggunakan augmentasi gambar untuk menghasilkan gambar yang diperbesar untuk setiap gambar di kumpulan data asli yang menghasilkan 3289 sampel dibandingkan dengan 253 gambar yang kami miliki di kumpulan data asli kami.

Kami kemudian mengoptimalkan kinerja model kami lebih lanjut menggunakan penyetelan hyperparameter untuk menemukan hyperparameter terbaik.

Terakhir, kami membuat dan melatih pengklasifikasi SVM sebagai tolok ukur. Karena kami tidak menggunakan penelusuran grid untuk menyetel hyperparameter pengklasifikasi SVM, kami akan membandingkan performanya dengan model CNN sebelum melakukan penyetelan hyperparameter. Perhatikan bahwa augmentasi data digunakan dalam kedua kasus.

Meskipun kami mendapatkan akurasi dan perolehan yang baik sebesar 91% dengan model CNN yang telah kami sesuaikan, masih ada ruang untuk perbaikan. Berikut beberapa saran untuk meningkatkan kinerja:

  1. Pangkas gambar yang diperbesar untuk menghapus artefak yang tidak kita inginkan. Kita dapat menggunakan OpenCV untuk menemukan kontur terbesar dan memotong sisanya.
  2. Gunakan kumpulan data yang lebih baik dengan lebih banyak gambar pemindaian otak sehingga kita tidak terlalu bergantung pada augmentasi data.
  3. Kami hanya menjalankan pencarian untuk menemukan jumlah unit optimal di setiap lapisan. Dapatkan jumlah epoch, ukuran batch, dan jumlah lapisan konvolusi yang optimal serta menggunakan penyetelan hyperparameter.

Secara keseluruhan, ini adalah proyek yang menyenangkan dan saya harap Anda menikmati alur kerja bersama saya. Jika Anda memiliki saran tentang cara lain untuk meningkatkan kinerja model, beri tahu saya. Kode untuk pekerjaan ini dapat ditemukan di sini.

Referensi

  1. Porter KR, McCarthy BJ, Freels S,Kim Y, Davis FG. Perkiraan prevalensi tumor otak primer di Amerika Serikat berdasarkan usia, jenis kelamin, perilaku, dan histologi. Neuro-Onkologi 12(6):520–527, 2010.

Ada 'bisa' dalam Cancer karena kita BISA mengalahkannya!