Tıbbi Teşhiste Yapay Zeka — I

Eren Bozarık
SMLR CENTER
Published in
6 min readMay 27, 2020

Merhabalar,

Bu yazıda tıbbi teşhiste yapay zekanın kullanımından bahsedeceğim. Bu yazı dizisi 2 yazıdan oluşacak. Bu yazımda akciğer görüntülerinden hastalık teşhisine odaklanacağız. Diğer yazımızda ise beyin MR görüntülerinin segmentastonu ile ilgili bir yazı yayınlayacağım.

Tıpta yapay zeka bir çok alanda kullanılmaktadır. Bunlardan bazılarını sıralayacak olursak. Bunlardan görüntü işleme üzerine olanlarını ele alalım.

Dermatoloji

Diyabetik Retinopati

Histopatoloji

Peki bu algoritma nedir?

Burada teşhis koymak için Evrişimli Sinir Ağlarından faydalanacağız. Temel hedefimiz X-Ray görüntülerinden hastalık teşhisi yapmak olduğu için X-Ray görüntülerinden oluşan bir veri setine ihtiyacımız var.

Bu projede ChestXray-NIHCC veri setini kullanacağız. Buradan veri setine erişim sağlayabilirsiniz. Veri setinde aşağıdaki görseldeki gibi görüntüler mevcut.

Bu X-Ray görüntüleri çeşitli sınıflara ayrılmaktadırlar. Bu sınıfların her biri bir hastalık çeşidine karşılık gelmektedir. Bunlar;

Atelectasis, Cardiomegaly, Consolidation, Edema, Effusion, Emphysema, Fibrosis, Hernia, Infiltration, Mass, Nodule

Bu sınıflar veri setimizde (1,0) şeklinde etiketli halde bulunmaktadır.

Veri setini inceleyelim.

# Egitim verisini iceren csv dosyasi okunuyor
train_df = pd.read_csv(“veriseti/train-small.csv”)
# Ilk 5 satir yazdiriliyor
print(f’{Bu veri kumesinde train_df.shape[0]} satir ve {train_df.shape[1]} kolon bulunmakta’)
train_df.head()

Çıktı : Bu veri kumesinde 1000 satir ve 16 kolon bulunmakta

Algoritmamızdan yapmasını istediğimiz temel şey, bu görüntülerin piksel değerlerini araştırıp, etiket değerlerini de baz alarak öğrenmesi.

Sinir ağımız kitle tespit edilmiş ve etiketlenmiş X-Ray görüntüsünüde normal X-Ray taramalarını da inceleyip bunlardan öz nitelik çıkarımı yaparak öğrenme işlemini gerçekleştirecek.

Kaybın Hesaplanması

Eğitim esnasında kaybı hesaplarken kullandığımız bu fonksiyon literatürde “binary cross entropy loss function” adıyla geçer. Fakat sınıflar arasında dengesizlik olması halinde bu fonksiyon çok kullanışlı değildir. Bu yüzden bu fonksiyona ağırlıklar dahil edilir.

Bu fonksiyondaki ağırlıkları pozitif ve negatif etiketlerin toplam etiket sayısına oranı ile hesaplanır.

Python’da Ağırlıklandırılmış Kayıp Fonksiyonu

def get_weighted_loss(pos_weights, neg_weights, epsilon=1e-7):

def weighted_loss(y_true, y_pred):

loss = 0.0
for i in range(len(pos_weights)):

loss += -(K.mean( pos_weights[i] * y_true[:,i] * K.log(y_pred[:,i] + epsilon) + \
neg_weights[i] * (1 - y_true[:,i]) * K.log(1 - y_pred[:,i] + epsilon), axis = 0))
return loss
return weighted_loss

Python’da Ağırlıkların Hesaplanması

def compute_class_freqs(labels):

N = labels.shape[0]

positive_frequencies = np.sum(labels, axis=0) / labels.shape[0]
negative_frequencies = 1 - positive_frequencies

return positive_frequencies, negative_frequencies
freq_pos, freq_neg = compute_class_freqs(train_generator.labels)

Pozitif ve negatif etiketlerin katkısını dengeliyoruz.

pos_weights = freq_neg
neg_weights = freq_pos
pos_contribution = freq_pos * pos_weights
neg_contribution = freq_neg * neg_weights

Değerlendirme Metrikleri

Özellikle tıp alanında yapılan projelerde en önemli kısım değerlendirmelerinizin doğruluk payıdır. Bu sebeple karmaşıklık matrisi oluştururken daha dikkatli olunması ve hesapların çok titizlikle yapılması gerekmektedir.

Kurduğunuz model ne kadar iyi?

Bu sorunun cevabını bize Doğruluk (Accuracy) metriği verebilir.

Yani doğruluk değerimiz, toplam örnek sayımızın, doğru sınıflandırılmış örneklerimizin birbirine oranı ile tanımlayabiliriz. Bu doğruluk değeri başka metriklerle daha detaylı bir şekilde tanımlanabilir. Burada karşımıza Duyarlılık (Sensitivity) ve Belirginlik (Specificity) kavramları çıkıyor. Tabi bu metriklerin hesaplanma yöntemleri var.

Duyarlılık (Sensitivity) : Modelimizin doğru bir şekilde tahmin ettiği hastalar ile gerçekten hasta olanların birbirine oranı şeklinde hesaplanır.

Belirginlik (Specificity) : Modelimizin doğru bir şekilde tahmin ettiği normal vakalar ile gerçekten normal olanların birbirine oranı şeklinde hesaplanır.

Hasta Vakaların Olasılığı : P(Disease)

Normal Vakaların Olasılığı : P(Normal) = 1 - P(Disease) (Kolmogorov Olasılık Aksiyomlarının bir kuralıdır.)

Sonuç Olarak: Modelimizin netliği aşağıdaki gibi hesaplanmış olur.

Karmaşıklık Matrisi (Confusion Matrix)

PREDICTED LABELS (Etiketlerin Tahmin Edilen Değerleri):
ACTUAL LABELS (Etiketlerin Gerçek Değerleri):

TP (TRUE — POSITIVE): Olumlu tahmin edilen etiket değeri ile olması gereken değeri uyuşması durumudur.
FP (FALSE — POSITIVE): Olumlu tahmin edilen bir etiketin asıl değerinin olumsuz olması durumu.
FN (FALSE — NEGATIVE) Type — II Error: Olumsuz tahmin edilen bir etiketin asıl değerinin olumlu olması durumu.
TN (TRUE — NEGATIVE) Type — I Error: Olumsuz tahmin edilen etiket değeri ile olması gereken değeri uyuşması durumudur.

False Negative ve True Negative değerlerini anlamak için bir meme :)

Kendi modelimiz için karmaşıklık matrisi oluşturalım

Karmaşıklık Matrisi ile PPV (Positive Predicted Values), NPV (Negative Predicted Values), Duyarlılık (Sensitivity) ve Belirginlik (Specificity) değerlerini hesaplayabiliriz.

Buraya kadar tıbbi teşhiste yapay zekanın daha çok istatistik boyutuna değinmeye çalıştım. Python üzerinde dikkat etmemiz gereken bazı önemli noktalar var bunlardan birisi ise veri sızıntısı (Leakage). Benzersiz hasta kimlik numaraları toplam kayit sayisindan fazla ise burada bir çakışma söz konusudur. Birden fazla kaydı olan hastalar için, veri sızıntısını önlemek amacıyla hem eğitim hem de test setlerinde görünmediğinden emin olmalısınız. Bu sorunu giderdiğimiz python fonksiyonu aşağıdaki gibidir.

def check_for_leakage(df1, df2, patient_col):

df1_patients_unique = set(df1[patient_col].unique().tolist())
df2_patients_unique = set(df2[patient_col].unique().tolist())

patients_in_both_groups = df1_patients_unique.intersection(df2_patients_unique)

leakage = len(patient_col)>0

return leakage
print("Egitim ve Test seti arasindaki sizintinin giderilme durumu: {}".format(check_for_leakage(train_df, test_df, 'PatientId')))
print("Dogrulama ve Test seti arasindaki sizintinin giderilme durumu: {}".format(check_for_leakage(valid_df, test_df, 'PatientId')))

Veri Artırma Yöntemi

Veri setimizin bazı sınıflarında örnek sayısı çok az olabilir. Örneğin bu veri seti için “mass” kitle barındıran X-Ray görüntü sayısı az miktardadır. Bunun için veri artırma yöntemi kullanılması uygun olacaktır.

Resim üzerinde bu şekillerde oynama yapılması herhangi bir sorun teşkil etmez. Fakat anatomik şekli bozacak şekilde bir yatay döndürme hareketi yapmak yanlış bir artırma yöntemi olacaktır.

Bu şekilde resimleri değiştirmek doğru sonuçlar almamıza engel teşkil edecektir. Bu işlemler için Python tarafında ImageDataGenerator kütüphanesini kullanacağız. Bu sınıf görüntülerin rastgele çevrilmesi gibi temel veri artırımı için destek sağlar. Ayrıca görüntüdeki değerleri tüm kanallarda tekrarlayarak tek kanallı X-ray görüntülerimizi (gri tonlamalı) üç kanallı bir formata dönüştürür.

Eğitim tarafı için Python’da bu fonksiyonun aşağıdaki gibidir.

def get_train_generator(df, image_dir, x_col, y_cols, shuffle=True, batch_size=8, seed=1, target_w = 320, target_h = 320):
print("getting train generator...")

image_generator = ImageDataGenerator(
samplewise_center=True,
samplewise_std_normalization= True)

generator = image_generator.flow_from_dataframe(
dataframe=df,
directory=image_dir,
x_col=x_col,
y_col=y_cols,
class_mode="raw",
batch_size=batch_size,
shuffle=shuffle,
seed=seed,
target_size=(target_w,target_h))

return generator

DenseNet

En nihayetinde bu bir resim sınıflandırma projesi bunun için Python tarafında önceden eğitilmiş bir DenseNet modeli kullanacağız. DenseNet modelinin detaylarını incelemek için buradaki makaleyi okuyabilirsiniz.

Modelin Entegrasyonu

from keras.applications.densenet import DenseNet121base_model = DenseNet121(weights=’./nih/densenet.hdf5', include_top=False);

GradCAM ile Öğrenmeyi Görselleştirme

Bu bölümde, patolojik durumu tahmin etmek için görüntüdeki önemli bölgeleri vurgulayan bir ısı haritası üretmek için GradCAM’in tekniğini kullanacağız.

İlk olarak, en yüksek performans gösteren AUC değerlerine sahip 4sınıfa bakmak için eğitim setini yükleyeceğiz.

df = pd.read_csv(root+"data_chest/train-small.csv")
IMAGE_DIR = root+"data_chest/images-small/"

labels_to_show = np.take(labels, np.argsort(auc_rocs)[::-1])[:4]
util.compute_gradcam(model, '00011355_002.png', IMAGE_DIR, df, labels, labels_to_show)

Sonuç:

Tıbbi teşhiste yapay zeka yazımın birincisinin burada sonuna geldik. Benzer bir çalışmayı beyin tümörünü MR görüntülerinden saptamak için segmentasyon çalışması yapacağız. Bu çalışmaya github üzerinden erişebilirsiniz. İyi çalışmalar dileklerimle :)

Bu makalede deeplearning.ai tarafından yayınlanan Tıbbi Teşhiste Yapay Zeka dersinden sıklıkla faydalanılmıştır.

--

--

Eren Bozarık
SMLR CENTER

Sr. Data Scientist & SWE | Galatasaray University