Ana içeriğe geç

Derin Öğrenme (Evrişimli Otomatik Kodlayıcı) Kullanarak Beyin MRG Görüntülerini Yeniden Oluşturma

Bu eğitimde, nifti formatındaki beyin manyetik rezonans görüntüleme (MRG) görüntülerini nasıl okuyacağınızı ve bunları evrişimli otomatik kodlayıcı kullanarak nasıl yeniden oluşturacağınızı öğrenecek ve anlayacaksınız.
· 13 dk. oku

Yapay Zeka ile Keşfedin

Ağınınızı eğitmek için 3T beyin MRG veri kümesini kullanacaksınız. Modelinizin etkinliğini gözlemlemek için modelinizi şu üzerinde test edeceksiniz:

  • Görülmemiş 3T MRG görüntüleri,
  • Gürültülü 3T MRG görüntüleri ve
  • Yeniden oluşturulan görüntülerin performansını değerlendirmek için nitel bir metrik: Tepe sinyal-gürültü oranı (PSNR).

Bu eğitim tıpta görüntülemenin inceliklerine girmeyecek, derin öğrenme tarafına odaklanacak! Not : Bu eğitim büyük ölçüde evrişimli otomatik kodlayıcıların pratik uygulamasını kapsar. Dolayısıyla, henüz evrişimli sinir ağı (CNN) ve otomatik kodlayıcı hakkında bilgi sahibi değilseniz, CNN ve Otomatik Kodlayıcı eğitimine göz atmak isteyebilirsiniz. Bu eğitimin en güzel yanı, 3B hacimleri 2B görüntüler olarak yükleyip bunları modele verecek olmanız. Kısaca, bugün şu konuları ele alacaksınız:

  • Başlangıçta Manyetik Rezonans Görüntüleme (MRG) hakkında kısa bir bilgilendirme alacaksınız,
  • Ardından Beyin MRG veri kümesini anlayacaksınız: ne tür görüntüler içeriyor, modüllerin içe aktarılması, görüntülerin nasıl okunacağı, görüntülerden bir dizi oluşturma, beyin MRG görüntülerini modele besleyebilecek şekilde ön işleme ve son olarak beyin MRG görüntülerini keşfetme.
  • Evrişimli otomatik kodlayıcının uygulanmasında: ön işlenmiş veriyi modele oturtacak, eğitim ve doğrulama kayıp grafiğini görselleştirecek, eğitilmiş modeli kaydedecek ve son olarak test kümesi üzerinde tahmin yapacaksınız.
  • Sonraki adımda, test görüntülerine gürültü ekleyerek önceden eğitilmiş modelinizin sağlamlığını test edecek ve modelin nicel olarak ne kadar iyi performans gösterdiğini göreceksiniz.
  • Son olarak, tahminlerinizi nicel bir metrik olan tepe sinyal-gürültü oranı (PSNR) kullanarak test edecek ve modelinizin performansını ölçeceksiniz.

MR Görüntülerine Kısa Bir Giriş

Tıpta görüntülemede, manyetik alan gücü 0,3 Tesla (T) olan açık MRG ünitelerinden, alan gücü 1,0 T'a kadar çıkan ekstremite MRG sistemlerine ve klinik kullanımda alan gücü 3,0 T'a kadar çıkan tüm vücut tarayıcılarına kadar çeşitli sistemler kullanılır. Tesla, MR görüntülerinin manyetik alanının nicel gücünü ölçen birimdir. Yüksek alanlı MR tarayıcılar (7T, 11,5T), daha küçük voksel (3 boyutlu yama veya ızgara) boyutlarında bile daha yüksek S/G (sinyal-gürültü oranı) sunar ve bu nedenle daha doğru tanı için tercih edilir.

Daha küçük voksel boyutu daha iyi bir çözünürlük sağlar; bu da klinik tanıya yardımcı olabilir. Ancak, MR tarayıcısında kullanılan manyetik alanın gücü, MR görüntü ayrıntılarını korumak için iyi bir sinyal-gürültü oranını (SNR) muhafaza edecek şekilde voksel boyutuna alt sınır koyar.
7T ve 11,5T’nin üstün görüntü kalitesine rağmen, maliyet kısıtları nedeniyle üretimde nadiren kullanılırlar.

Yakın tarihli makalelere göre, bildirilen 3T tarayıcı sayısı ~20.000 iken 7T tarayıcı sayısı yalnızca ~40’tır.

Beyin MRG 3T Veri Kümesini Anlamak

Beyin MRG veri kümesi 3B hacimlerden oluşur; her hacim, beynin farklı kesitlerinden alınmış toplam 207 beyin MRG dilimi/görüntüsü içerir. Her dilim 173 x 173 boyutundadır. Görüntüler tek kanallı gri tonlamalıdır. Toplamda 30 denek vardır; her denek bir hastanın MRG taramasını içerir. Görüntü formatı jpeg,png vb. değil, nifti formatıdır. İlerleyen bölümde nifti formatındaki görüntülerin nasıl okunacağını göreceksiniz.

Veri kümesi T1 modalite MRG görüntülerinden oluşur; T1 sekansları geleneksel olarak anatomik yapıları değerlendirmede iyidir. Bugün üzerinde çalışacağınız veri kümesi 3T Beyin MRG’lerinden oluşur.

Veri kümesi herkese açıktır ve bu kaynaktan indirilebilir.

İpucu: MNIST veri kümesiyle sınıflandırma görevleri için Çok Katmanlı Algılayıcı (MLP) nasıl uygulanır öğrenmek istiyorsanız, bu eğitime göz atın.

Not : Başlamadan önce, modelin Nvidia 1080 Ti GPU Xeon e5 GeForce işlemcili ve 32GB RAM’li bir sistemde eğitileceğini lütfen not edin. Jupyter Notebook kullanıyorsanız, os adlı bir modül kullanarak CUDA aygıt sırasını ve CUDA görünür aygıtlarını belirttiğiniz üç satır kod daha eklemeniz gerekecek.

Aşağıdaki kodda, temel olarak os.environ kullanarak not defterinde ortam değişkenlerini ayarlarsınız. Keras’ı başlatmadan önce bunu yapmak, Keras arka ucu TensorFlow’un ilk GPU’yu kullanmasını sınırlamak için iyidir. Eğittiğiniz makinede GPU 0’daysa, 1 yerine 0 kullandığınızdan emin olun. Bunu terminalinizde basit bir komut çalıştırarak kontrol edebilirsiniz: örneğin, nvidia-smi

import os
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]="1" #model will be trained on GPU 1

Modüllerin İçe Aktarılması

Önce, bugün bu eğitimde kullanacağınız çerçeve Keras olduğundan, cv2, numpy, matplotlib ve en önemlisi keras gibi gerekli tüm modülleri içe aktarın!
nifti formatındaki görüntüleri okumak için, nibabel adlı bir modülü de içe aktarmanız gerekir.

import os
import cv2
from keras.layers import Input,Dense,Flatten,Dropout,merge,Reshape,Conv2D,MaxPooling2D,UpSampling2D,Conv2DTranspose
from keras.layers.normalization import BatchNormalization
from keras.models import Model,Sequential
from keras.callbacks import ModelCheckpoint
from keras.optimizers import Adadelta, RMSprop,SGD,Adam
from keras import regularizers
from keras import backend as K
Using TensorFlow backend.
import numpy as np
import scipy.misc
import numpy.random as rng
from PIL import Image, ImageDraw, ImageFont
from sklearn.utils import shuffle
import nibabel as nib #reading MR images
from sklearn.cross_validation import train_test_split
import math
import glob
from matplotlib import pyplot as plt
%matplotlib inline
/usr/local/lib/python3.5/dist-packages/sklearn/cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)

Verilerin Yüklenmesi

Belirttiğiniz klasördeki tüm hacimlerden oluşan bir liste döndürecek glob modülünü kullanacaksınız!

ff = glob.glob('ground3T/*')

Listenin ilk öğesini yazdıralım ve uzunluğunu kontrol edelim: bizim durumumuzda 30 olmalı.

ff[0]
'ground3T/181232.nii.gz'
len(ff)
30

Artık nibabel kullanarak 3B hacimleri yüklemeye hazırsınız. Nifti formatında bir hacim yüklediğinizde, Nibabel’ın görüntü dizisini yüklemediğine dikkat edin. Dizi verisini siz talep edene kadar bekler. Dizi verisini istemenin normal yolu get_data() yöntemini çağırmaktır.

3B yerine 2B dilimler istediğiniz için bir liste başlatacaksınız; her hacmi okuduğunuzda, 3B hacmin tüm 207 dilimi üzerinde yineleme yapacak ve her bir dilimi tek tek listeye ekleyeceksiniz.

images = []

3B hacimlerden birinin şeklini de yazdıralım, 173 x 207 x 173 (x, y, z; koordinatları) şeklinde olmalı.

Not : Tüm 207 dilimi değil, yalnızca beynin orta 51 dilimini kullanacaksınız. O halde, yalnızca merkez dilimlerin nasıl seçilip yükleneceğini de görelim.

for f in range(len(ff)):
    a = nib.load(ff[f])
    a = a.get_data()
    a = a[:,78:129,:]
    for i in range(a.shape[1]):
        images.append((a[:,i,:]))
print (a.shape)
(173, 51, 173)

207 dilimden birinin şeklini analiz edelim.

a[:,0,:].shape
(173, 173)

Veri Ön İşleme

images bir liste olduğundan, listeyi bir numpy dizisine dönüştürmek için numpy modülünü kullanacaksınız.

images = np.asarray(images)

Şimdi numpy dizisinin şeklini kontrol etme zamanı; dizinin ilk boyutu sırasıyla 207 x 30 = 6210 ve kalan iki boyut 173 x 173 olacaktır.

images.shape
(1530, 173, 173)

Veri kümesindeki görüntüler gerçekten 173 x 173 boyutunda gri tonlamalıdır; bu nedenle verileri modele vermeden önce ön işlemden geçirmek çok önemlidir. Önce her 173 x 173 görüntüyü ağa besleyebileceğiniz 173 x 173 x 1 boyutunda bir matrise dönüştüreceksiniz:

images = images.reshape(-1, 173,173,1)
images.shape
(1530, 173, 173, 1)

Sonraki adımda verileri maks-min normalizasyon tekniği ile yeniden ölçeklendirin:

m = np.max(images)
mi = np.min(images)
m, mi
(3599.0959, -341.83853)
images = (images - mi) / (m - mi)

Yeniden ölçeklendirmeden sonra verinin minimum ve maksimum değerinin 0,0 ve 1,0 olduğunu doğrulayalım!

np.min(images), np.max(images)
(0.0, 1.0)

Bu önemli bir adımdır; burada görüntülerin boyutları çift sayı olsun ve modelden geçirirken ikiye bölerek aşağı örneklemek kolay olsun diye görüntülerin sınırlarına sıfırlarla dolgu yapacaksınız. Boyutu 176 x 176 yapmak için üç satır ve üç sütuna sıfır ekleyelim

temp = np.zeros([1530,176,176,1])
temp[:,3:,3:,:] = images
images = temp

Tüm bunlardan sonra veriyi bölmek önemlidir. Modelinizin iyi genelleşmesi için veriyi ikiye ayırırsınız: bir eğitim ve bir doğrulama kümesi. Verilerin %80’i üzerinde modelinizi eğitecek ve kalan verilerin %20’si üzerinde doğrulayacaksınız.

Bu aynı zamanda aşırı öğrenme ihtimalini azaltmanıza yardımcı olur; çünkü modelinizi eğitim aşamasında görmediği veriler üzerinde doğrulamış olursunuz.

Veriyi düzgün bir şekilde bölmek için scikit-learn’ün train_test_split modülünü kullanabilirsiniz:

from sklearn.model_selection import train_test_split
train_X,valid_X,train_ground,valid_ground = train_test_split(images,
                                                             images,
                                                             test_size=0.2,
                                                             random_state=13)

Not bu görev için eğitim ve test etiketlerine ihtiyacınız yok. Bu yüzden eğitim görüntülerini iki kez geçeceksiniz. Eğitim görüntüleriniz tıpkı sınıflandırma görevindeki etiketlere benzer şekilde hem girdi hem de yer gerçeği (ground truth) görevi görecektir.

Veri Keşfi

Şimdi veri kümesindeki görüntülerin nasıl göründüğünü analiz edelim ve NumPy dizi özelliği .shape yardımıyla görüntülere üçer satır ve sütun ekledikten sonraki boyutlarını bir kez daha görelim:

# Shapes of training set
print("Dataset (images) shape: {shape}".format(shape=images.shape))
Dataset (images) shape: (1530, 176, 176, 1)

Yukarıdaki çıktıda görebileceğiniz gibi verinin şekli 6210 x 176 x 176’dır; çünkü 176 x 176 x 1 boyutlu matristen 6210 örnek vardır.

Şimdi, veri kümenizdeki birkaç eğitim ve doğrulama görüntüsüne göz atalım:

plt.figure(figsize=[5,5])

# Display the first image in training data
plt.subplot(121)
curr_img = np.reshape(train_X[0], (176,176))
plt.imshow(curr_img, cmap='gray')

# Display the first image in testing data
plt.subplot(122)
curr_img = np.reshape(valid_X[0], (176,176))
plt.imshow(curr_img, cmap='gray')
<matplotlib.image.AxesImage at 0x7ff67d5d59b0>
görüntüler

Yukarıdaki iki grafiğin çıktıları eğitim ve doğrulama setlerinden alınmıştır. Hem eğitim hem de doğrulama görüntülerinin farklı olduğunu görüyorsunuz; evrişimli otomatik kodlayıcının özellikleri öğrenip bu görüntüleri doğru şekilde yeniden oluşturup oluşturamayacağını görmek ilginç olacaktır.

Artık ağı tanımlamak ve veriyi ağa beslemek için hazırsınız. O halde daha fazla uzatmadan bir sonraki adıma geçelim!

Evrişimli Otomatik Kodlayıcı!

Görüntüler 176 x 176 x 1 boyutunda veya 30976 boyutlu bir vektördür. Görüntü matrisini diziye çevirir, 0 ile 1 arasına yeniden ölçeklendirir, 176 x 176 x 1 boyutuna yeniden şekillendirir ve bunu ağa girdi olarak verirsiniz.

Ayrıca, 128’lik bir yığın boyutu kullanacaksınız; 256 veya 512 gibi daha yüksek bir yığın boyutu da tercih edilebilir, tamamen modeli eğittiğiniz sisteme bağlıdır. Öğrenme parametrelerinin belirlenmesine büyük katkı sağlar ve tahmin doğruluğunu etkiler. Ağınızı 50 dönem boyunca eğiteceksiniz.

batch_size = 128
epochs = 300
inChannel = 1
x, y = 176, 176
input_img = Input(shape = (x, y, inChannel))

Muhtemelen bildiğiniz gibi otomatik kodlayıcı iki parçaya ayrılır: bir kodlayıcı ve bir kod çözücü vardır.

Kodlayıcı: 3 Evrişim bloğu vardır; her blokta bir evrişim katmanı ve ardından bir yığın normalizasyon katmanı bulunur. Birinci ve ikinci evrişim bloklarından sonra maksimum havuzlama katmanı kullanılır.

  • İlk evrişim bloğu 3 x 3 boyutunda 32 filtreye sahip olacak, ardından aşağı örnekleme (maksimum havuzlama) katmanı gelecek,
  • İkinci blok 3 x 3 boyutunda 64 filtreye sahip olacak, ardından bir başka aşağı örnekleme katmanı gelecek,
  • Kodlayıcının son bloğu 3 x 3 boyutunda 128 filtreye sahip olacak.

Kod çözücü: 2 Evrişim bloğu vardır; her blokta bir evrişim katmanı ve ardından bir yığın normalizasyon katmanı bulunur. Birinci ve ikinci evrişim bloklarından sonra yukarı örnekleme katmanı kullanılır.

  • İlk blok 3 x 3 boyutunda 128 filtreye ve ardından bir yukarı örnekleme katmanına sahip olacak,
  • İkinci blok 3 x 3 boyutunda 64 filtreye ve ardından bir başka yukarı örnekleme katmanına sahip olacak,
  • Kodlayıcının son katmanı 3 x 3 boyutunda 1 filtreye sahip olacak ve tek kanallı girdiyi geri yeniden oluşturacaktır.

Maksimum havuzlama katmanı her kullanımda girdiyi iki kat aşağı örneklerken, yukarı örnekleme katmanı her kullanımda girdiyi iki kat yukarı örnekler.

Not: Filtre sayısı, filtre boyutu, katman sayısı, modeli eğittiğiniz dönem sayısı gibi unsurların tümü hiperparametrelerdir ve kendi sezginize göre belirlenmelidir; bu hiperparametreleri değiştirerek yeni deneyler yapma ve modelinizin performansını ölçme konusunda özgürsünüz. Derin öğrenme sanatını yavaş yavaş böyle öğreneceksiniz!

def autoencoder(input_img):
    #encoder
    #input = 28 x 28 x 1 (wide and thin)
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img) #28 x 28 x 32
    conv1 = BatchNormalization()(conv1)
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
    conv1 = BatchNormalization()(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1) #14 x 14 x 32
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1) #14 x 14 x 64
    conv2 = BatchNormalization()(conv2)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    conv2 = BatchNormalization()(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2) #7 x 7 x 64
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2) #7 x 7 x 128 (small and thick)
    conv3 = BatchNormalization()(conv3)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    conv3 = BatchNormalization()(conv3)


    #decoder
    conv4 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv3) #7 x 7 x 128
    conv4 = BatchNormalization()(conv4)
    conv4 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv4)
    conv4 = BatchNormalization()(conv4)
    up1 = UpSampling2D((2,2))(conv4) # 14 x 14 x 128
    conv5 = Conv2D(32, (3, 3), activation='relu', padding='same')(up1) # 14 x 14 x 64
    conv5 = BatchNormalization()(conv5)
    conv5 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv5)
    conv5 = BatchNormalization()(conv5)
    up2 = UpSampling2D((2,2))(conv5) # 28 x 28 x 64
    decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up2) # 28 x 28 x 1
    return decoded

Model oluşturulduktan sonra, optimize edici olarak RMSProp’u kullanarak derlemeniz gerekir.

Ayrıca loss bağımsız değişkeni aracılığıyla kayıp türünü de belirtmeniz gerekir. Bu durumda, piksel piksel, tahmin edilen çıktı yığınları ve yer gerçeği arasındaki kaybı ortalama karesel hata ile hesapladığınız için kayıp türü ortalama karesel hatadır:

autoencoder = Model(input_img, autoencoder(input_img))
autoencoder.compile(loss='mean_squared_error', optimizer = RMSprop())

Yukarıdaki adımda oluşturduğunuz katmanları summary işlevini kullanarak görselleştirelim; bu, her katmandaki parametre (ağırlık ve sapmalar) sayısını ve ayrıca modelinizdeki toplam parametreleri gösterecektir.

autoencoder.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         (None, 176, 176, 1)       0         
_________________________________________________________________
conv2d_18 (Conv2D)           (None, 176, 176, 32)      320       
_________________________________________________________________
batch_normalization_11 (Batc (None, 176, 176, 32)      128       
_________________________________________________________________
conv2d_19 (Conv2D)           (None, 176, 176, 32)      9248      
_________________________________________________________________
batch_normalization_12 (Batc (None, 176, 176, 32)      128       
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 88, 88, 32)        0         
_________________________________________________________________
conv2d_20 (Conv2D)           (None, 88, 88, 64)        18496     
_________________________________________________________________
batch_normalization_13 (Batc (None, 88, 88, 64)        256       
_________________________________________________________________
conv2d_21 (Conv2D)           (None, 88, 88, 64)        36928     
_________________________________________________________________
batch_normalization_14 (Batc (None, 88, 88, 64)        256       
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 44, 44, 64)        0         
_________________________________________________________________
conv2d_22 (Conv2D)           (None, 44, 44, 128)       73856     
_________________________________________________________________
batch_normalization_15 (Batc (None, 44, 44, 128)       512       
_________________________________________________________________
conv2d_23 (Conv2D)           (None, 44, 44, 128)       147584    
_________________________________________________________________
batch_normalization_16 (Batc (None, 44, 44, 128)       512       
_________________________________________________________________
conv2d_24 (Conv2D)           (None, 44, 44, 64)        73792     
_________________________________________________________________
batch_normalization_17 (Batc (None, 44, 44, 64)        256       
_________________________________________________________________
conv2d_25 (Conv2D)           (None, 44, 44, 64)        36928     
_________________________________________________________________
batch_normalization_18 (Batc (None, 44, 44, 64)        256       
_________________________________________________________________
up_sampling2d_5 (UpSampling2 (None, 88, 88, 64)        0         
_________________________________________________________________
conv2d_26 (Conv2D)           (None, 88, 88, 32)        18464     
_________________________________________________________________
batch_normalization_19 (Batc (None, 88, 88, 32)        128       
_________________________________________________________________
conv2d_27 (Conv2D)           (None, 88, 88, 32)        9248      
_________________________________________________________________
batch_normalization_20 (Batc (None, 88, 88, 32)        128       
_________________________________________________________________
up_sampling2d_6 (UpSampling2 (None, 176, 176, 32)      0         
_________________________________________________________________
conv2d_28 (Conv2D)           (None, 176, 176, 1)       289       
=================================================================
Total params: 427,713
Trainable params: 426,433
Non-trainable params: 1,280
_________________________________________________________________

Artık modeli Keras’ın fit() işleviyle eğitme zamanı! Model 50 dönem boyunca eğitilir. fit() işlevi bir geçmiş (history) nesnesi döndürür; bu işlevin sonucunu fashion_train içinde saklayarak, daha sonra eğitim ve doğrulama arasındaki kayıp fonksiyonu grafiğini çizmek için kullanabilir ve modelinizin performansını görsel olarak analiz edebilirsiniz.

Modeli Eğitin

autoencoder_train = autoencoder.fit(train_X, train_ground, batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(valid_X, valid_ground))
Train on 1224 samples, validate on 306 samples
Epoch 1/300
1224/1224 [==============================] - 7s - loss: 0.1201 - val_loss: 0.0838
Epoch 2/300
1224/1224 [==============================] - 7s - loss: 0.0492 - val_loss: 0.0534
...
Epoch 299/300
1224/1224 [==============================] - 7s - loss: 1.3101e-04 - val_loss: 6.1086e-04
Epoch 300/300
1224/1224 [==============================] - 7s - loss: 1.0711e-04 - val_loss: 3.9641e-04

Nihayet! Modeli parmak izi veri kümesi üzerinde 200 dönem boyunca eğittiniz. Şimdi model performansını görselleştirmek için eğitim ve doğrulama verileri arasındaki kayıp grafiğini çizelim.

loss = autoencoder_train.history['loss']
val_loss = autoencoder_train.history['val_loss']
epochs = range(300)
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
eğitim ve doğrulama kaybı

Son olarak, doğrulama kaybı ile eğitim kaybının birbiriyle uyumlu olduğunu görebilirsiniz. Bu, modelinizin aşırı öğrenmediğini gösterir: doğrulama kaybı artmıyor, azalıyor ve eğitim boyunca eğitim ve doğrulama kaybı arasında nadiren bir boşluk oluşuyor.

Dolayısıyla, modelinizin genelleme yeteneğinin iyi olduğu söylenebilir.

Son olarak, Keras’ın predict() işlevini kullanarak test görüntülerini yeniden oluşturma ve modelinizin test verisi üzerinde ne kadar iyi yeniden oluşturabildiğini görme zamanı.

Modeli Kaydedin

Şimdi eğitilmiş modeli kaydedelim. Derin Öğrenme ile çalışırken bu önemli bir adımdır. Zira, üzerinde çalıştığınız sorunun çözümünün kalbi ağırlıklardır!

Kaydedilmiş ağırlıkları istediğiniz zaman aynı modele yükleyebilir ve eğitimi kaldığı yerden sürdürebilirsiniz. Örneğin: Yukarıdaki model tekrar eğitilirse, ağırlıklar, sapmalar, kayıp fonksiyonu vb. gibi parametreler baştan başlamaz ve eğitim artık sıfırdan olmaz.

Sadece tek bir kod satırıyla ağırlıkları kaydedip tekrar modele yükleyebilirsiniz.

autoencoder = autoencoder.save_weights('autoencoder_mri.h5')
autoencoder = Model(input_img, autoencoder(input_img))
autoencoder.load_weights('autoencoder_mri.h5')

Doğrulama Verisi Üzerinde Tahmin

Burada ayrı bir test veriniz olmadığı için, az önce eğittiğiniz model üzerinde tahmin yapmak üzere doğrulama verisini kullanalım.

Eğitilmiş modeli kalan 306 doğrulama görüntüsü üzerinde tahmin edecek ve modelinizin doğrulama görüntülerini ne kadar iyi yeniden oluşturabildiğini görselleştirmek için birkaç yeniden oluşturulmuş görüntüyü çizeceksiniz.

pred = autoencoder.predict(valid_X)
plt.figure(figsize=(20, 4))
print("Test Images")
for i in range(5):
    plt.subplot(1, 5, i+1)
    plt.imshow(valid_ground[i, ..., 0], cmap='gray')
plt.show()    
plt.figure(figsize=(20, 4))
print("Reconstruction of Test Images")
for i in range(5):
    plt.subplot(1, 5, i+1)
    plt.imshow(pred[i, ..., 0], cmap='gray')  
plt.show()
Test Images
Test Images
Reconstruction of Test Images
Test Images'in Yeniden Oluşturulması

Yukarıdaki şekillerden, modelinizin model kullanılarak tahmin ettiğiniz test görüntülerini yeniden oluşturmada harika bir iş çıkardığını gözlemleyebilirsiniz. En azından nitel olarak, test ve yeniden oluşturulmuş görüntüler neredeyse birebir benzer görünüyor.

Belki orijinal 3T görüntülerdeki bazı yerel ayrıntıları yeniden oluşturmada biraz daha iyi iş çıkarabilir.

Gürültülü 3T Görüntüler Üzerinde Tahmin

Önce, ortalaması sıfır ve standart sapması 0,03 olan biraz gürültüyü doğrulama görüntülerine ekleyelim.

[a,b,c,d]= np.shape(valid_X)
mean = 0
sigma = 0.03
gauss = np.random.normal(mean,sigma,(a,b,c,d))
noisy_images = valid_X + gauss

Sıra gürültülü doğrulama görüntüleri üzerinde tahmin yapmaya geldi. Modeliniz eğitilirken gürültülü görüntüleri hiç görmemiş olmasına rağmen, gürültülü görüntüler üzerinde ne kadar iyi iş çıkardığına bakalım.

pred_noisy = autoencoder.predict(noisy_images)
plt.figure(figsize=(20, 4))
print("Noisy Test Images")
for i in range(5):
    plt.subplot(1, 5, i+1)
    plt.imshow(noisy_images[i, ..., 0], cmap='gray')
plt.show()    
plt.figure(figsize=(20, 4))
print("Reconstruction of Noisy Test Images")
for i in range(5):
    plt.subplot(1, 5, i+1)
    plt.imshow(pred_noisy[i, ..., 0], cmap='gray')  
plt.show()
Noisy Test Images
gürültülü test görüntüleri
Reconstruction of Noisy Test Images
Gürültülü Test Görüntülerinin Yeniden Oluşturulması

Görünüşe göre model oldukça iyi iş çıkardı. Öyle değil mi? Sonuçta, yeniden oluşturulan görüntüler gürültülü görüntülerden daha iyi görünüyor. Üstelik model eğitim sırasında gürültülü görüntüleri hiç görmemişti.

Nicel Metrik: Tepe Sinyal-Gürültü Oranı (PSNR)

PSNR bloğu, iki görüntü arasındaki tepe sinyal-gürültü oranını desibel (dB) cinsinden hesaplar. Bu oran genellikle orijinal görüntü ile yeniden oluşturulmuş görüntü arasındaki kalite ölçümü olarak kullanılır. PSNR ne kadar yüksekse, yeniden oluşturulmuş görüntünün kalitesi o kadar iyidir.

Öyleyse, önce doğrulama görüntüleri ile yeniden oluşturulmuş doğrulama görüntülerinin performansını hesaplayalım.

valid_pred = autoencoder.predict(valid_X)
mse =  np.mean((valid_X - valid_pred) ** 2)
psnr = 20 * math.log10( 1.0 / math.sqrt(mse))
print('PSNR of reconstructed validation images: {psnr}dB'.format(psnr=np.round(psnr,2)))
PSNR of reconstructed validation images: 34.02dB

Şimdi de orijinal doğrulama görüntüleri ile tahmin edilen gürültülü görüntüler arasındaki PSNR’yi hesaplayalım

noisy_pred = autoencoder.predict(noisy_images)
mse =  np.mean((valid_X - noisy_pred) ** 2)
psnr_noisy = 20 * math.log10( 1.0 / math.sqrt(mse))
print('PSNR of reconstructed validation images: {psnr}dB'.format(psnr=np.round(psnr_noisy,2)))
PSNR of reconstructed validation images: 32.48dB

Görünen o ki nicel olarak, gürültüsüz yeniden oluşturmalardaki PSNR ile gürültülü yeniden oluşturmalardaki PSNR arasında yalnızca 1,54 dB’lik bir fark var. Üstelik modelinizi gürültüyle başa çıkacak şekilde eğitmediniz. Harika değil mi?

Daha İleri Gidin!

Bu eğitim, MRG nifti formatındaki görüntülerin nasıl okunacağını, analiz edileceğini, ön işleneceğini ve bir beyin MRG 3T veri kümesi kullanarak modele nasıl besleneceğini anlamak için iyi bir başlangıç oldu. Otomatik kodlayıcıların pratikteki güzel bir uygulamasını gösterdi. Kolayca ya da biraz daha fazla çabayla takip edebildiyseniz, tebrikler!

Mimaride oynayıp hem nicel hem de nitel olarak tahminleri iyileştirmeyi deneyebilirsiniz. Belki daha fazla katman ekleyerek, belki daha uzun süre eğiterek? Bu kombinasyonları deneyin ve yardımcı olup olmadığını görün.

Hâlâ kapsanacak çok şey var; o halde neden DataCamp’in Python ile Derin Öğrenmeye Giriş kursunu almıyorsunuz? Henüz almadıysanız. Temellerden başlayacak ve yavaş yavaş derin öğrenme alanında ustalaşmaya ilerleyeceksiniz; Python’da evrişimli sinir ağlarıyla nasıl çalışılacağını, yüzleri, nesneleri vb. nasıl tespit edeceğinizi öğrenirken kuşkusuz vazgeçilmez bir kaynak olacaktır.

Konular

İlgili