मुख्य सामग्री पर जाएँ

मल्टी-डिकोडर फ़्रेमवर्क ट्यूटोरियल के साथ इमेज सुपर-रिज़ॉल्यूशन

इस ट्यूटोरियल में, आप Keras में Python के साथ डीप लर्निंग मेडिकल इमेजिंग पेपर को इम्प्लीमेंट करेंगे।
· 15 मि॰ पढ़ें

AI के साथ खोजें

Training Script खंड में, आप एक नई डीप लर्निंग आर्किटेक्चर का उपयोग करते हुए इमेज सुपर-रिज़ॉल्यूशन समस्या पर काम करेंगे। यहाँ कार्य कम-फ़ील्ड 3-टेस्ला ब्रेन MR इमेज से उच्च-फ़ील्ड 7-टेस्ला ब्रेन MR इमेज तक एक नॉन-लीनियर मैपिंग करना है। Testing Script खंड में, आप Part-1 में प्रशिक्षित वेट्स का उपयोग करेंगे और अनदेखे डेटा पर प्रेडिक्शन करेंगे। आप यह भी सीखेंगे कि अंततः 2D इमेज को एक संयुक्त वॉल्यूम के रूप में कैसे सेव करें।

यह ट्यूटोरियल दो भागों में बँटा है—पहला भाग आपको ट्रेनिंग प्रक्रिया से ले चलेगा और दूसरा भाग टेस्टिंग प्रक्रिया को कवर करेगा।

नोट: यदि आप पेपर पढ़ने में रुचि रखते हैं, तो लेख आपको यहाँ मिल जाएगा।

Training Script

संक्षेप में, आप इस ट्यूटोरियल के Part-1 में निम्नलिखित विषयों को कवर करेंगे:

Python मॉड्यूल डिपेंडेंसीज़

इस ट्यूटोरियल के साथ आगे बढ़ने से पहले सुनिश्चित करें कि आपके पास नीचे दिए गए मॉड्यूल संस्करण बिल्कुल यही हैं:

  • Keras==2.0.4
  • tensorflow==1.8.0
  • scipy==0.19.0
  • numpy==1.14.5
  • Pillow==4.1.1
  • nibabel==2.1.0
  • scikit_learn==0.18.1

नोट: शुरू करने से पहले ध्यान दें कि मॉडल को Nvidia 1080 Ti GPU Xeon e5 GeForce प्रोसेसर और 32GB RAM वाले सिस्टम पर ट्रेन किया जाएगा। यदि आप Jupyter Notebook का उपयोग कर रहे हैं, तो आपको तीन और लाइनें जोड़ने की आवश्यकता होगी, जिनमें आप os मॉड्यूल का उपयोग करके CUDA device order और CUDA visible devices निर्दिष्ट करेंगे।

नीचे दिए गए कोड में, आप os.environ का उपयोग करके नोटबुक में environment variables सेट करते हैं। Keras इनिशियलाइज़ करने से पहले यह करना अच्छा है ताकि Keras बैकएंड TensorFlow पहले GPU का उपयोग करे। यदि जिस मशीन पर आप ट्रेन कर रहे हैं उस पर GPU 0 पर है, तो 1 की जगह 0 का उपयोग करें। इसे आप टर्मिनल पर एक सरल कमांड चलाकर जाँच सकते हैं: उदाहरण के लिए, nvidia-smi

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

मॉड्यूल इम्पोर्ट करना

सबसे पहले, आप सभी आवश्यक मॉड्यूल जैसे tensorflow, numpy, और सबसे महत्वपूर्ण keras, तथा आवश्यक फ़ंक्शंस या लेयर्स जैसे Input, Conv2D, MaxPooling2D आदि इम्पोर्ट करेंगे क्योंकि आप मॉडल को ट्रेन करने के लिए इन सभी फ़्रेमवर्क्स का उपयोग करेंगे!
nifti फॉर्मैट इमेज पढ़ने के लिए आपको nibabel नामक मॉड्यूल भी इम्पोर्ट करना होगा।

import os
import numpy as np
import math
import tensorflow as tf
import nibabel as nib
import numpy as np
from keras.layers import Input,Dense,merge,Reshape,Conv2D,MaxPooling2D,UpSampling2D
from keras.layers.normalization import BatchNormalization
from keras.models import Model,Sequential
from keras.callbacks import ModelCheckpoint
from keras.optimizers import RMSprop
from keras import backend as K
import scipy.misc
from sklearn.utils import shuffle
from sklearn.cross_validation import train_test_split
import matplotlib.pyplot as plt
from keras.models import model_from_json
Using TensorFlow backend.
/usr/local/lib/python3.5/dist-packages/sklearn/cross_validation.py:41: 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 is different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)

Brain MRI 3T और 7T डेटासेट को समझना

ब्रेन MRI 3T और 7T डेटासेट 3D वॉल्यूम्स का बना है, प्रत्येक वॉल्यूम में कुल 207 स्लाइस/इमेज होती हैं जो मस्तिष्क के अलग-अलग स्लाइसों पर ली जाती हैं। हर स्लाइस का आयाम 173 x 173 है। इमेज सिंगल-चैनल ग्रेस्केल हैं। कुल 39 सब्जेक्ट्स हैं, प्रत्येक सब्जेक्ट में एक मरीज का MRI स्कैन है। इमेज फॉर्मैट jpeg, png आदि नहीं है बल्कि nifti फॉर्मैट है। आगे चलकर आप देखेंगे कि nifti फॉर्मैट इमेज कैसे पढ़ी जाती हैं।

डेटासेट में T1 मॉडैलिटी MR इमेज शामिल हैं; T1 सीक्वेंस आमतौर पर एनाटोमिक संरचनाओं के आकलन के लिए अच्छे माने जाते हैं। आज जिस डेटासेट पर आप काम करेंगे उसमें 3T और 7T ब्रेन MRI शामिल हैं।

यह डेटासेट सार्वजनिक है और इस स्रोत से डाउनलोड के लिए उपलब्ध है।

ट्रेनिंग के लिए 28 सब्जेक्ट्स और टेस्टिंग के लिए शेष 11 सब्जेक्ट्स का उपयोग किया जाता है।

इनिशियलाइज़र्स परिभाषित करना

पहले डेटा के आयाम परिभाषित करते हैं। आप डेटा पढ़ने वाले भाग में इमेज का आयाम 173x173 से 176x176 में बदलेंगे। यहाँ आप डेटा डायरेक्टरी, मॉडल ट्रेन करने के लिए बैच साइज़, चैनल्स की संख्या, एक Input() लेयर, train और test मैट्रिक्स को लिस्ट के रूप में और अंत में रीस्केलिंग के लिए उस टेक्स्ट फ़ाइल को भी परिभाषित करेंगे जिसमें MRI डेटासेट के न्यूनतम और अधिकतम मान हैं।

नोट: रीस्केलिंग के लिए, आप डेटासेट के अधिकतम और न्यूनतम मान भी स्वयं निकाल सकते हैं क्योंकि आपके पास maxANDmin.txt फ़ाइल नहीं होगी।

x,y = 173,173
full_z = 207
resizeTo=176
batch_size = 32
inChannel = outChannel = 1
input_shape=(x,y,inChannel)
input_img = Input(shape = (resizeTo, resizeTo, inChannel))
inp = "ground3T"
out = "ground7T"     
train_matrix = []
test_matrix = []
min_max = np.loadtxt('maxANDmin.txt')

डेटा लोड करना

इसके बाद, आप nibabel लाइब्रेरी का उपयोग करके MRI डेटा लोड करेंगे और इमेज को 173 x 173 से 176 x 176 में x और y आयाम में ज़ीरो पैडिंग करके बदलेंगे।

ध्यान दें कि जब आप Nifti फॉर्मैट वॉल्यूम लोड करते हैं, तो Nibabel इमेज एरे को तुरंत लोड नहीं करता। यह तब तक प्रतीक्षा करता है जब तक आप एरे डेटा नहीं माँगते। एरे डेटा माँगने का मानक तरीका get_data() मेथड को कॉल करना है।

क्योंकि आपको 3D की बजाय 2D स्लाइस चाहिए, आप पहले से इनिशियलाइज़ की गई train और test लिस्ट का उपयोग करेंगे; हर बार जब आप एक वॉल्यूम पढ़ते हैं, तो आप 3D वॉल्यूम की सभी 207 स्लाइसों पर इटरेट करेंगे और हर स्लाइस को एक-एक करके लिस्ट में जोड़ेंगे।

folder = os.listdir(inp)

पहले 3T डेटा लोड करते हैं।

for f in folder:
    temp = np.zeros([resizeTo,full_z,resizeTo])
    a = nib.load(inp + f)
    a = a.get_data()
    temp[3:,:,3:] = a
    a = temp
    for j in range(full_z):
        train_matrix.append(a[:,j,:])

फिर 7T डेटा लोड करें, और आप 7T डेटा लोड करने के लिए भी वही folder वेरिएबल उपयोग करेंगे क्योंकि 3T और 7T MR वॉल्यूम्स की संख्या बराबर है।

for f in folder:
    temp = np.zeros([resizeTo,full_z,resizeTo])
    b = nib.load(out + f)
    b = b.get_data()
    temp[3:,:,3:] = b
    b = temp
    for j in range(full_z):
        test_matrix.append(b[:,j,:])

डेटा प्रीप्रोसेसिंग

क्योंकि train और test मैट्रिक्स एक लिस्ट हैं, आप numpy मॉड्यूल का उपयोग करके लिस्ट को numpy एरे में बदलेंगे।

आगे, आप numpy एरे के type को float32 में बदलेंगे और साथ ही input तथा ground truth दोनों को रीस्केल करेंगे।

train_matrix = np.asarray(train_matrix)
train_matrix = train_matrix.astype('float32')
m = min_max[0]
mi = min_max[1]
train_matrix = (train_matrix - mi) / (m - mi)

test_matrix = np.asarray(test_matrix)
test_matrix = test_matrix.astype('float32')
test_matrix = (test_matrix - mi) / (m - mi)

आइए जल्दी से train_matrix (3T) और test_matrix (7T) के शेप को प्रिंट करें। इनमें कुल 28 x 207 = 5796 इमेज होनी चाहिए, प्रत्येक का आयाम 176 x 176 होगा।

train_matrix.shape
(5796, 176, 176)
test_matrix.shape
(5796, 176, 176)

इसके बाद, आप दो नए वेरिएबल augmented_images (3T/इनपुट) और Haugmented_images (7T/ग्राउंड ट्रुथ) बनाएँगे जिनका शेप train और test मैट्रिक्स के अनुरूप होगा। यह 4D मैट्रिक्स होगा जिसमें पहला आयाम इमेज की कुल संख्या, दूसरा और तीसरा हर इमेज का आयाम और अंतिम आयाम चैनलों की संख्या (यहाँ एक) होगा।"

augmented_images=np.zeros(shape=[(train_matrix.shape[0]),(train_matrix.shape[1]),(train_matrix.shape[2]),(1)])
Haugmented_images=np.zeros(shape=[(train_matrix.shape[0]),(train_matrix.shape[1]),(train_matrix.shape[2]),(1)])

फिर आप सभी इमेजों पर एक-एक करके इटरेट करेंगे; हर बार आप train और test मैट्रिक्स को 176 x 176 में रीशेप करेंगे और क्रमशः augmented_images (3T/इनपुट) और Haugmented_images (7T/ग्राउंड ट्रुथ) में जोड़ेंगे।

for i in range(train_matrix.shape[0]):
    augmented_images[i,:,:,0] = train_matrix[i,:,:].reshape(resizeTo,resizeTo)
    Haugmented_images[i,:,:,0] = test_matrix[i,:,:].reshape(resizeTo,resizeTo)

इन सबके बाद, डेटा को विभाजित करना महत्वपूर्ण है। ताकि आपका मॉडल अच्छी तरह जनरलाइज़ करे, आप डेटा को दो भागों में बाँटते हैं: ट्रेनिंग और वैलिडेशन सेट। आप अपने मॉडल को 80% डेटा पर ट्रेन करेंगे और शेष 20% ट्रेनिंग डेटा पर वैलिडेट करेंगे।

यह ओवरफ़िटिंग की संभावना को कम करने में भी मदद करेगा, क्योंकि आप अपने मॉडल को ऐसे डेटा पर वैलिडेट करेंगे जिसे उसने ट्रेनिंग चरण में नहीं देखा होगा।

डेटा को ठीक से बाँटने के लिए आप ट्यूटोरियल की शुरुआत में परिभाषित किए गए scikit-learn के train_test_split मॉड्यूल का उपयोग कर सकते हैं:

data,Label = shuffle(augmented_images,Haugmented_images, random_state=2)
X_train, X_test, y_train, y_test = train_test_split(data, Label, test_size=0.2, random_state=2)
X_test = np.array(X_test)
y_test = np.array(y_test)
X_test = X_test.astype('float32')
y_test = y_test.astype('float32')
X_train = np.array(X_train)
y_train = np.array(y_train)
X_train = X_train.astype('float32')
y_train = y_train.astype('float32')

मॉडल: 1-Encoder-3-Decoders!

model
चित्र: Selective Auto-Encoder Backpropagation
चित्र इस पेपर से लिया गया है।

Merge कनेक्शन

इसके बाद, आप एन्कोडर सेक्शन में क्रमिक फ़िल्टर लेयरों के ब्लॉक्स के साथ प्रस्तावित आर्किटेक्चर परिभाषित करेंगे जिनके बाद एक मैक्स पूलिंग लेयर होगी, जैसा कि अगले सेल में दिखाया गया है। आउटपुट पर इमेज का मूल आकार पुनर्निर्मित करने के लिए, प्रत्येक डिकोडर ब्लॉक में एक अपसैंपलिंग लेयर जोड़ी जाती है। अपसैंपलिंग के दौरान, डिकोडर के डाउनसैम्पल्ड इनपुट में विवरण की कमी के कारण कुछ आर्टिफैक्ट आ सकते हैं। इसलिए, आप डिकोडर के इनपुट को एन्कोडर से उसके अपस्केल्ड संस्करण के साथ कंकैटनेट करते हैं ताकि अपसैंपलिंग के दौरान बेहतर पुनर्निर्माण के लिए अपस्केल्ड विवरण की प्रकृति उपलब्ध रहे। वास्तव में, merge कनेक्शन जोड़ने से PSNR में उल्लेखनीय सुधार (लगभग 5dB के क्रम का) मिलता है। हमारे आर्किटेक्चर की यह सेटिंग इस पेपर से प्रेरित है।

मल्टी डिकोडर्स

प्रस्तावित विधि एक सिंगल एन्कोडर और मल्टीपल डिकोडर आर्किटेक्चर अपनाती है, जिसमें सिंगल-चैनल इनपुट होता है। एन्कोडर और सभी तीन डिकोडर्स के प्रत्येक ब्लॉक में तीन-तीन कन्वोल्यूशनल लेयर्स का उपयोग किया जाता है, जिनके बाद संख्यात्मक स्थिरता बनाए रखने के लिए एक बैच नॉर्मलाइज़ेशन लेयर होती है।

एन्कोडर के पहले कन्वोल्यूशनल ब्लॉक में 32 फ़िल्टर्स हैं, और प्रत्येक कन्वोल्यूशनल ब्लॉक के बाद फ़िल्टर्स की संख्या दोगुनी हो जाती है। सभी डिकोडर्स में पहले कन्वोल्यूशनल ब्लॉक में 256 फ़िल्टर्स हैं, और प्रत्येक ब्लॉक के बाद फ़िल्टर्स की संख्या आधी हो जाती है। आप सभी कन्वोल्यूशनल ब्लॉक्स में 3-बाई-3 फ़िल्टर साइज़ का उपयोग करेंगे।

सभी लेयर्स में, अंतिम लेयर को छोड़कर, एक्टिवेशन फ़ंक्शन के रूप में Rectified Linear Unit (ReLU) का उपयोग किया जाएगा। चूँकि डेटा 0 और 1 के बीच सामान्यीकृत है, अंतिम लेयर में Sigmoid एक्टिवेशन फ़ंक्शन का उपयोग किया जाता है।

यह सर्वज्ञात है कि विभिन्न स्केल्स पर स्थानीय इमेज विवरण इमेज रिकंस्ट्रक्शन में महत्वपूर्ण भूमिका निभाते हैं। प्रस्तावित आर्किटेक्चर एन्कोडर और डिकोडर्स में क्रमशः डाउनसैम्पलिंग (मैक्सपूलिंग) और अपसैम्पलिंग (प्रत्येक के लिए फैक्टर 2) हेतु पदानुक्रमित लेयरों का उपयोग करते हुए विभिन्न स्केल पर इमेज पर विचार करता है। तीन डाउनसैम्पलिंग ऑपरेशन्स के बाद प्राप्त एन्कोडेड रिप्रेज़ेंटेशन डेटा को उच्च-आयाम इनपुट से एक लैटेंट स्पेस रिप्रेज़ेंटेशन में लाता है।

Encoder

def encoder(input_img):
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img)
    conv1 = BatchNormalization()(conv1)
    conv1 = Conv2D(32, (3,3), activation='relu', padding='same')(conv1)
    conv1 = BatchNormalization()(conv1)
    conv1 = Conv2D(32, (3,3), activation='relu', padding='same')(conv1)
    conv1 = BatchNormalization()(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)
    conv2 = BatchNormalization()(conv2)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    conv2 = BatchNormalization()(conv2)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    conv2 = BatchNormalization()(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)
    conv3 = BatchNormalization()(conv3)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    conv3 = BatchNormalization()(conv3)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    conv3 = BatchNormalization()(conv3)
    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)
    conv4 = BatchNormalization()(conv4)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
    conv4 = BatchNormalization()(conv4)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
    conv4 = BatchNormalization()(conv4)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv4)
    conv5 = BatchNormalization()(conv5)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)
    conv5 = BatchNormalization()(conv5)
    conv5 = Conv2D(512, (3, 3), activation='sigmoid', padding='same')(conv5)
    conv5 = BatchNormalization()(conv5)
    return conv5,conv4,conv3,conv2,conv1

Decoder 1

def decoder_1(conv5,conv4,conv3,conv2,conv1):
    up6 = merge([conv5, conv4], mode='concat', concat_axis=3)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    up7 = UpSampling2D((2,2))(conv6)
    up7 = merge([up7, conv3], mode='concat', concat_axis=3)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    up8 = UpSampling2D((2,2))(conv7)
    up8 = merge([up8, conv2], mode='concat', concat_axis=3)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    up9 = UpSampling2D((2,2))(conv8)
    up9 = merge([up9, conv1], mode='concat', concat_axis=3)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    decoded_1 = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(conv9)
    return decoded_1

Decoder 2

def decoder_2(conv5,conv4,conv3,conv2,conv1):
    up6 = merge([conv5, conv4], mode='concat', concat_axis=3)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    up7 = UpSampling2D((2,2))(conv6)
    up7 = merge([up7, conv3], mode='concat', concat_axis=3)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    up8 = UpSampling2D((2,2))(conv7)
    up8 = merge([up8, conv2], mode='concat', concat_axis=3)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    up9 = UpSampling2D((2,2))(conv8)
    up9 = merge([up9, conv1], mode='concat', concat_axis=3)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    decoded_2 = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(conv9)
    return decoded_2

Decoder 3

def decoder_3(conv5,conv4,conv3,conv2,conv1):
    up6 = merge([conv5, conv4], mode='concat', concat_axis=3)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    up7 = UpSampling2D((2,2))(conv6)
    up7 = merge([up7, conv3], mode='concat', concat_axis=3)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    up8 = UpSampling2D((2,2))(conv7)
    up8 = merge([up8, conv2], mode='concat', concat_axis=3)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    up9 = UpSampling2D((2,2))(conv8)
    up9 = merge([up9, conv1], mode='concat', concat_axis=3)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    decoded_3 = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(conv9)
    return decoded_3

ऊपर दिए गए 4 सेल्स में, आपने चार फ़ंक्शन परिभाषित किए। एक एन्कोडर के लिए और शेष तीन डिकोडर्स के लिए। चूँकि ये फ़ंक्शंस हैं, आप decoder() फ़ंक्शन एक बार परिभाषित कर उसे तीन बार कॉल कर सकते थे, लेकिन बेहतर समझ के लिए आप इसे तीन बार परिभाषित करेंगे और तीनों डिकोडर्स में रैंडमनेस की समस्या से बचेंगे।

लॉस फ़ंक्शन

अगले चरण में, आप mean square error का उपयोग करेंगे जिसमें आप ग्राउंड ट्रुथ y_t और y_p दोनों के वे मान (पिक्सेल) जो शून्य के बराबर हैं, उन्हें बाहर कर देंगे।

def root_mean_sq_GxGy(y_t, y_p):
    a1=1
    where = tf.not_equal(y_t, 0)
    a_t=tf.boolean_mask(y_t,where,name='boolean_mask')
    a_p=tf.boolean_mask(y_p,where,name='boolean_mask')
    return a1*(K.sqrt(K.mean((K.square(a_t-a_p)))))

मॉडल परिभाषा और कॉम्पिलेशन

सबसे पहले, आप encoder फ़ंक्शन को इनपुट पास करके कॉल करेंगे। चूँकि आप अपनी आर्किटेक्चर में merge कनेक्शन का उपयोग कर रहे हैं, इसलिए encoder फ़ंक्शन पाँच convolution लेयर्स का आउटपुट लौटाएगा जिन्हें आप तीनों डिकोडर्स के आउटपुट के साथ अलग-अलग merge करेंगे।

conv5,conv4,conv3,conv2,conv1 = encoder(input_img)
autoencoder_1 = Model(input_img, decoder_1(conv5,conv4,conv3,conv2,conv1))
autoencoder_1.compile(loss=root_mean_sq_GxGy, optimizer = RMSprop())

autoencoder_2 = Model(input_img, decoder_2(conv5,conv4,conv3,conv2,conv1))
autoencoder_2.compile(loss=root_mean_sq_GxGy, optimizer = RMSprop())

autoencoder_3 = Model(input_img, decoder_3(conv5,conv4,conv3,conv2,conv1))
autoencoder_3.compile(loss=root_mean_sq_GxGy, optimizer = RMSprop())
/usr/local/lib/python3.5/dist-packages/ipykernel_launcher.py:2: UserWarning: The `merge` function is deprecated and will be removed after 08/2017. Use instead layers from `keras.layers.merge`, e.g. `add`, `concatenate`, etc.

/usr/local/lib/python3.5/dist-packages/keras/legacy/layers.py:460: UserWarning: The `Merge` layer is deprecated and will be removed after 08/2017. Use instead layers from `keras.layers.merge`, e.g. `add`, `concatenate`, etc.
  name=name)
/usr/local/lib/python3.5/dist-packages/ipykernel_launcher.py:10: UserWarning: The `merge` function is deprecated and will be removed after 08/2017. Use instead layers from `keras.layers.merge`, e.g. `add`, `concatenate`, etc.
  # Remove the CWD from sys.path while we load stuff.
/usr/local/lib/python3.5/dist-packages/ipykernel_launcher.py:18: UserWarning: The `merge` function is deprecated and will be removed after 08/2017. Use instead layers from `keras.layers.merge`, e.g. `add`, `concatenate`, etc.
/usr/local/lib/python3.5/dist-packages/ipykernel_launcher.py:26: UserWarning: The `merge` function is deprecated and will be removed after 08/2017. Use instead layers from `keras.layers.merge`, e.g. `add`, `concatenate`, etc.


WARNING:tensorflow:From /usr/local/lib/python3.5/dist-packages/keras/backend/tensorflow_backend.py:1257: calling reduce_mean (from tensorflow.python.ops.math_ops) with keep_dims is deprecated and will be removed in a future version.
Instructions for updating:
keep_dims is deprecated, use keepdims instead

मॉडल को ट्रेन करें

आप वेट्स तभी सेव करेंगे जब वैलिडेशन डेटा पर peak signal-to-noise ratio में सुधार होगा। इसके लिए आप psnr_gray_channel नाम की एक लिस्ट परिभाषित करेंगे जिसमें आप डिफ़ॉल्ट वैल्यू के रूप में 1 जोड़ेंगे; आप 1 इसलिए जोड़ते हैं क्योंकि आपको लिस्ट को किसी रैंडम नंबर से इनिशियलाइज़ करना है और PSNR ट्रेनिंग के शुरुआती चरणों में भी इससे कहीं अधिक होगा—यह केवल एक डमी नंबर की तरह काम करेगा।

आप सीखने की दर (learning rate) 1e-3 से प्रारंभ करेंगे और एक learning rate decay रणनीति अपनाएँगे जिसमें हर 20 epochs के बाद आप अपनी learning rate को वर्तमान मान से 10% घटाएँगे!

psnr_gray_channel = []
psnr_gray_channel.append(1)
learning_rate = 0.001
j=0

नोट: अगला पूरा कोड एक ही सेल में चलना चाहिए, लेकिन ट्रेनिंग प्रक्रिया की बेहतर समझ के लिए इसे छोटे सेल्स में विभाजित किया जाएगा।

मॉडल को 500 epochs के लिए ट्रेन किया जाता है। प्रारंभिक learning rate पिछली सेल में 1e-3 परिभाषित है। आप हर epoch के बाद 7T और प्रेडिक्टेड के PSNR, MSE मान भी सेव करेंगे। आप K.set_value फ़ंक्शन का उपयोग करके हर 20 epochs के बाद तीनों मॉडलों की learning rate को 10% कम करेंगे।

for jj in range(500):
    myfile_valid_psnr_7T = open('../1_encoder_3_decoders_complete_slices_single_channel/validation_psnr7T_1encoder_3decoders.txt', 'a')
    myfile_valid_mse_7T = open('../1_encoder_3_decoders_complete_slices_single_channel/validation_mse7T_1encoder_3decoders.txt', 'a')

    K.set_value(autoencoder_1.optimizer.lr, learning_rate)
    K.set_value(autoencoder_2.optimizer.lr, learning_rate)
    K.set_value(autoencoder_3.optimizer.lr, learning_rate)

इसके बाद, आप इनपुट 3T और ग्राउंड ट्रुथ 7T इमेज को शफ़ल करेंगे ताकि नेटवर्क ओवरफ़िट न हो, क्योंकि शफ़ल न करने पर मॉडल हर epoch के बाद सैम्पल्स को उसी क्रम में देखेगा। फिर आप पहले से परिभाषित batch_size के आधार पर बनने वाले बैचों की संख्या निकालेंगे। अंततः, आप num_batches पर इटरेट करना शुरू करेंगे।

train_X,train_Y = shuffle(X_train,y_train)
print ("Epoch is: %d\n" % j)
print ("Number of batches: %d\n" % int(len(train_X)/batch_size))
num_batches = int(len(train_X)/batch_size)
for batch in range(num_batches):

PSNR मानों को स्टोर करने के अलावा आप तीनों ऑटोएन्कोडर्स और तीनों डिकोडर्स के लॉसेज़ भी स्टोर करेंगे।

myfile_ae1_loss = open('../1_encoder_3_decoders_complete_slices_single_channel/ae1_train_loss_1encoder_3decoders.txt', 'a')
myfile_ae2_loss = open('../1_encoder_3_decoders_complete_slices_single_channel/ae2_train_loss_1encoder_3decoders.txt', 'a')
myfile_ae3_loss = open('../1_encoder_3_decoders_complete_slices_single_channel/ae3_train_loss_1encoder_3decoders.txt', 'a')
myfile_dec1_loss = open('../1_encoder_3_decoders_complete_slices_single_channel/dec1_train_loss_1encoder_3decoders.txt', 'a')
myfile_dec2_loss = open('../1_encoder_3_decoders_complete_slices_single_channel/dec2_train_loss_1encoder_3decoders.txt', 'a')
myfile_dec3_loss = open('../1_encoder_3_decoders_complete_slices_single_channel/dec3_train_loss_1encoder_3decoders.txt', 'a')

क्योंकि हर बैच में आप अगले 32 (batch_size) सैम्पल्स मॉडल को दिखाना चाहते हैं, अगला सेल यह कार्य करता है!

batch_train_X = train_X[batch*batch_size:min((batch+1)*batch_size,len(train_X)),:]
batch_train_Y = train_Y[batch*batch_size:min((batch+1)*batch_size,len(train_Y)),:]

हमारी Minimum autoencoder रणनीति के काम करने के लिए, हर epoch के बाद आप Keras के test_on_batch फ़ंक्शन का उपयोग करके ट्रेनिंग डेटा पर टेस्ट करेंगे जो क्रमशः आपको तीन लॉसेज़ देगा, और अंत में आप उन्हें प्रिंट करेंगे।

loss_1 = autoencoder_1.test_on_batch(batch_train_X,batch_train_Y)
loss_2 = autoencoder_2.test_on_batch(batch_train_X,batch_train_Y)
loss_3 = autoencoder_3.test_on_batch(batch_train_X,batch_train_Y)
print ('epoch_num: %d batch_num: %d Test_loss_1: %f\n' % (j,batch,loss_1))
print ('epoch_num: %d batch_num: %d Test_loss_2: %f\n' % (j,batch,loss_2))
print ('epoch_num: %d batch_num: %d Test_loss_3: %f\n' % (j,batch,loss_3))

आपके नेटवर्क में छह संभावित स्थितियाँ हो सकती हैं:
loss_1: Autoencoder 1 का लॉस
loss_2: Autoencoder 2 का लॉस
loss_3: Autoencoder 3 का लॉस

    • loss_1, loss_2 और loss_3 से बड़ा हो सकता है। यदि यह सत्य है, तो आप केवल Autoencoder 1 का उपयोग करके ट्रेन करेंगे। आप Autoencoder 2 और Autoencoder 3 के Encoder भागों को False करेंगे और केवल उनके डिकोडर्स को ट्रेन करेंगे, और अंत में आप सभी लॉसेज़ को टेक्स्ट फ़ाइलों में लिखेंगे।
    • loss_2, loss_1 और loss_3 से बड़ा हो सकता है। यदि यह सत्य है, तो आप केवल Autoencoder 2 का उपयोग करके ट्रेन करेंगे। आप Autoencoder 1 और Autoencoder 3 के Encoder भागों को False करेंगे और केवल उनके डिकोडर्स को ट्रेन करेंगे, और अंत में आप सभी लॉसेज़ को टेक्स्ट फ़ाइलों में लिखेंगे।
    • loss_3, loss_1 और loss_2 से बड़ा हो सकता है। यदि यह सत्य है, तो आप केवल Autoencoder 3 का उपयोग करके ट्रेन करेंगे। आप Autoencoder 1 और Autoencoder 2 के Encoder भागों को False करेंगे और केवल उनके डिकोडर्स को ट्रेन करेंगे, और अंत में आप सभी लॉसेज़ को टेक्स्ट फ़ाइलों में लिखेंगे।
    • loss_1, loss_2 के बराबर हो सकता है। यदि यह सत्य है, तो आप Autoencoder 1 या 2 में से किसी एक का उपयोग करके ट्रेन करेंगे। आप Autoencoder 3 के Encoder भाग को False करेंगे, साथ ही 1 और 2 में से जिसे आपने नहीं चुना, और केवल उनके डिकोडर्स को ट्रेन करेंगे, और अंत में आप सभी लॉसेज़ को टेक्स्ट फ़ाइलों में लिखेंगे।
    • loss_2, loss_3 के बराबर हो सकता है। यदि यह सत्य है, तो आप Autoencoder 2 या 3 में से किसी एक का उपयोग करके ट्रेन करेंगे। आप Autoencoder 1 के Encoder भाग को False करेंगे, साथ ही 2 और 3 में से जिसे आपने नहीं चुना, और केवल उनके डिकोडर्स को ट्रेन करेंगे, और अंत में आप सभी लॉसेज़ को टेक्स्ट फ़ाइलों में लिखेंगे।
    • loss_3, loss_1 के बराबर हो सकता है। यदि यह सत्य है, तो आप Autoencoder 3 या 1 में से किसी एक का उपयोग करके ट्रेन करेंगे। आप Autoencoder 2 के Encoder भाग को False करेंगे, साथ ही 3 और 1 में से जिसे आपने नहीं चुना, और केवल उनके डिकोडर्स को ट्रेन करेंगे, और अंत में आप सभी लॉसेज़ को टेक्स्ट फ़ाइलों में लिखेंगे।
model
चित्र: मॉडल की आर्किटेक्चर
चित्र इस पेपर से लिया गया है।
if loss_1 < loss_2 and loss_1 < loss_3:
    train_1 = autoencoder_1.train_on_batch(batch_train_X,batch_train_Y)
    myfile_ae1_loss.write("%f \n" % (train_1))
    print ('epoch_num: %d batch_num: %d AE_Train_loss_1: %f\n' % (j,batch,train_1))
    #myfile.write('epoch_num: %d batch_num: %d AE_Train_loss_1: %f\n' % (j,batch,train_1))
    for layer in autoencoder_2.layers[:34]:
        layer.trainable = False
    for layer in autoencoder_3.layers[:34]:
        layer.trainable = False
    #autoencoder_2.summary()
    #autoencoder_3.summary()
    train_2 = autoencoder_2.train_on_batch(batch_train_X,batch_train_Y)
    train_3 = autoencoder_3.train_on_batch(batch_train_X,batch_train_Y)
    myfile_dec2_loss.write("%f \n" % (train_2))
    myfile_dec3_loss.write("%f \n" % (train_3))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_2: %f\n' % (j,batch,train_2))
    print ('epoch_num: %d batch_num: %d Decoder_loss_3: %f\n' % (j,batch,train_3))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_2: %f\n' % (j,batch,train_2))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_loss_3: %f\n' % (j,batch,train_3))
elif loss_2 < loss_1 and loss_2 < loss_3:
    train_2 = autoencoder_2.train_on_batch(batch_train_X,batch_train_Y)
    myfile_ae2_loss.write("%f \n" % (train_2))
    print ('epoch_num: %d batch_num: %d AE_Train_loss_2: %f\n' % (j,batch,train_2))
    #myfile.write('epoch_num: %d batch_num: %d AE_Train_loss_2: %f\n' % (j,batch,train_2))
    for layer in autoencoder_1.layers[:34]:
        layer.trainable = False
    for layer in autoencoder_3.layers[:34]:
        layer.trainable = False
    #autoencoder_1.summary()
    #autoencoder_3.summary()
    train_1 = autoencoder_1.train_on_batch(batch_train_X,batch_train_Y)
    train_3 = autoencoder_3.train_on_batch(batch_train_X,batch_train_Y)
    myfile_dec1_loss.write("%f \n" % (train_1))
    myfile_dec3_loss.write("%f \n" % (train_3))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_1: %f\n' % (j,batch,train_1))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_3: %f\n' % (j,batch,train_3))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_1: %f\n' % (j,batch,train_1))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_3: %f\n' % (j,batch,train_3))
elif loss_3 < loss_1 and loss_3 < loss_2:
    train_3 = autoencoder_3.train_on_batch(batch_train_X,batch_train_Y)
    myfile_ae3_loss.write("%f \n" % (train_3))
    print ('epoch_num: %d batch_num: %d AE_Train_loss_3: %f\n' % (j,batch,train_3))
    #myfile.write('epoch_num: %d batch_num: %d AE_Train_loss_3: %f\n' % (j,batch,train_3))
    for layer in autoencoder_1.layers[:34]:
        layer.trainable = False
    for layer in autoencoder_2.layers[:34]:
        layer.trainable = False
    #autoencoder_1.summary()
    #autoencoder_2.summary()
    train_1 = autoencoder_1.train_on_batch(batch_train_X,batch_train_Y)
    train_2 = autoencoder_2.train_on_batch(batch_train_X,batch_train_Y)
    myfile_dec1_loss.write("%f \n" %(train_1))
    myfile_dec2_loss.write("%f \n" % (train_2))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_1: %f\n' % (j,batch,train_1))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_2: %f\n' % (j,batch,train_2))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_1: %f\n' % (j,batch,train_1))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_2: %f\n' % (j,batch,train_2))
elif loss_1 == loss_2:
    train_1 = autoencoder_1.train_on_batch(batch_train_X,batch_train_Y)
    myfile_ae1_loss.write("%f \n" % (train_1))
    print ('epoch_num: %d batch_num: %d AE_Train_loss_1_equal_state: %f\n' % (j,batch,train_1))
    #myfile.write('epoch_num: %d batch_num: %d AE_Train_loss_1_equal_state: %f\n' % (j,batch,train_1))
    for layer in autoencoder_3.layers[:34]:
        layer.trainable = False
    for layer in autoencoder_2.layers[:34]:
        layer.trainable = False
    #autoencoder_2.summary()
    #autoencoder_3.summary()
    train_2 = autoencoder_2.train_on_batch(batch_train_X,batch_train_Y)
    train_3 = autoencoder_3.train_on_batch(batch_train_X,batch_train_Y)
    myfile_dec2_loss.write("%f \n" % (train_2))
    myfile_dec3_loss.write("%f \n" % (train_3))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_2_equal_state: %f\n' % (j,batch,train_2))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_3_equal_state: %f\n' % (j,batch,train_3))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_2_equal_state: %f\n' % (j,batch,train_2))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_3_equal_state: %f\n' % (j,batch,train_3))
elif loss_2 == loss_3:
    train_2 = autoencoder_2.train_on_batch(batch_train_X,batch_train_Y)
    myfile_ae2_loss.write("%f \n" % (train_2))
    print ('epoch_num: %d batch_num: %d AE_Train_loss_2_equal_state: %f\n' % (j,batch,train_2))
    #myfile.write('epoch_num: %d batch_num: %d AE_Train_loss_2_equal_state: %f\n' % (j,batch,train_2))
    for layer in autoencoder_1.layers[:34]:
        layer.trainable = False
    for layer in autoencoder_3.layers[:34]:
        layer.trainable = False

    #autoencoder_2.summary()
    #autoencoder_3.summary()
    train_1 = autoencoder_1.train_on_batch(batch_train_X,batch_train_Y)
    train_3 = autoencoder_3.train_on_batch(batch_train_X,batch_train_Y)
    myfile_dec1_loss.write("%f \n" % (train_1))
    myfile_dec3_loss.write("%f \n" % (train_3))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_1_equal_state: %f\n' % (j,batch,train_1))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_3_equal_state: %f\n' % (j,batch,train_3))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_1_equal_state: %f\n' % (j,batch,train_1))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_3_equal_state: %f\n' % (j,batch,train_3))
elif loss_3 == loss_1:
    train_1 = autoencoder_1.train_on_batch(batch_train_X,batch_train_Y)
    myfile_ae1_loss.write("%f \n" % (train_1))
    print ('epoch_num: %d batch_num: %d AE_Train_loss_1_equal_state: %f\n' % (j,batch,train_1))
    #myfile.write('epoch_num: %d batch_num: %d AE_Train_loss_1_equal_state: %f\n' % (j,batch,train_1))
    for layer in autoencoder_2.layers[:34]:
        layer.trainable = False
    for layer in autoencoder_3.layers[:34]:
        layer.trainable = False
    #autoencoder_2.summary()
    #autoencoder_3.summary()
    train_2 = autoencoder_2.train_on_batch(batch_train_X,batch_train_Y)
    train_3 = autoencoder_3.train_on_batch(batch_train_X,batch_train_Y)
    myfile_dec2_loss.write("%f \n" % (train_2))
    myfile_dec3_loss.write("%f \n" % (train_3))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_2_equal_state: %f\n' % (j,batch,train_2))
    print ('epoch_num: %d batch_num: %d Decoder_Train_loss_3_equal_state: %f\n' % (j,batch,train_3))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_2_equal_state: %f\n' % (j,batch,train_2))
    #myfile.write('epoch_num: %d batch_num: %d Decoder_Train_loss_3_equal_state: %f\n' % (j,batch,train_3))


    myfile_ae1_loss.close()
    myfile_ae2_loss.close()
    myfile_ae3_loss.close()
    myfile_dec1_loss.close()
    myfile_dec2_loss.close()
    myfile_dec3_loss.close()

यह एक आवश्यक चरण है क्योंकि आपने ऊपर दी गई स्थितियों में कुछ लेयरों को False किया था; अब आपको उन लेयरों को True करना होगा ताकि सभी ऑटोएन्कोडर लेयर्स test_on_batch फ़ंक्शन के लिए इस्तेमाल हो सकें और वे पूरे ट्रेनिंग के दौरान False न रह जाएँ।

for layer in autoencoder_1.layers[:34]:
            layer.trainable = True
for layer in autoencoder_2.layers[:34]:
            layer.trainable = True
for layer in autoencoder_3.layers[:34]:
            layer.trainable = True

आप तीन अलग-अलग तरीकों से वेट्स सेव करेंगे, नीचे उनमें से दो दिए गए हैं। पहला—आप हर 100 epochs के बाद वेट्स सेव करेंगे; दूसरा—आप हर epoch के बाद वेट्स सेव करेंगे। मूलतः, वे हर epoch के बाद ओवरराइट हो जाते हैं।

if jj % 100 ==0:
            autoencoder_1.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE1_" + str(jj)+".h5")
            autoencoder_2.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE2_" + str(jj)+".h5")
            autoencoder_3.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE3_" + str(jj)+".h5")


autoencoder_1.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE1.h5")
autoencoder_2.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE2.h5")
autoencoder_3.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE3.h5")

वैलिडेशन डेटा पर टेस्टिंग

आप पहले वैलिडेशन डेटा को शफ़ल करेंगे और फिर ऊपर परिभाषित वही 6 संभावित स्थितियों का उपयोग करेंगे। अतः जो भी स्थिति सत्य होगी, आप उसी विशेष ऑटोएन्कोडर का उपयोग करके अपने मॉडल को test करेंगे।

फिर आप decoded_imgs (प्रेडिक्टेड) और ग्राउंड ट्रुथ के बीच दो मैट्रिक्स MSE और PSNR की गणना करेंगे। अंत में, आप उन्हें टेक्स्ट फ़ाइलों में सेव करेंगे।

X_test,y_test = shuffle(X_test,y_test)
if loss_1 < loss_2 and loss_1 < loss_3:
    decoded_imgs = autoencoder_1.predict(X_test)
    mse_7T=  np.mean((y_test[:,:,:,0] - decoded_imgs[:,:,:,0]) ** 2)
    check_7T = math.sqrt(mse_7T)
    psnr_7T = 20 * math.log10( 1.0 / check_7T)


    myfile_valid_psnr_7T.write("%f \n" % (psnr_7T))
    myfile_valid_mse_7T.write("%f \n" % (mse_7T))

    #print (check)
elif loss_2 < loss_1 and loss_2 < loss_3:
    decoded_imgs = autoencoder_2.predict(X_test)
    mse_7T=  np.mean((y_test[:,:,:,0] - decoded_imgs[:,:,:,0]) ** 2)
    check_7T = math.sqrt(mse_7T)
    psnr_7T = 20 * math.log10( 1.0 / check_7T)

    myfile_valid_psnr_7T.write("%f \n" % (psnr_7T))
    myfile_valid_mse_7T.write("%f \n" % (mse_7T))

    #print (check)
elif loss_3 < loss_2 and loss_3 < loss_1:
    decoded_imgs = autoencoder_3.predict(X_test)
    mse_7T=  np.mean((y_test[:,:,:,0] - decoded_imgs[:,:,:,0]) ** 2)
    check_7T = math.sqrt(mse_7T)
    psnr_7T = 20 * math.log10( 1.0 / check_7T)

    myfile_valid_psnr_7T.write("%f \n" % (psnr_7T))
    myfile_valid_mse_7T.write("%f \n" % (mse_7T))
    #print (check)

elif loss_1 == loss_2:
    decoded_imgs = autoencoder_1.predict(X_test)
    mse_7T=  np.mean((y_test[:,:,:,0] - decoded_imgs[:,:,:,0]) ** 2)
    check_7T = math.sqrt(mse_7T)
    psnr_7T = 20 * math.log10( 1.0 / check_7T)

    myfile_valid_psnr_7T.write("%f \n" % (psnr_7T))
    myfile_valid_mse_7T.write("%f \n" % (mse_7T))


elif loss_2 == loss_3:
    decoded_imgs = autoencoder_2.predict(X_test)
    mse_7T=  np.mean((y_test[:,:,:,0] - decoded_imgs[:,:,:,0]) ** 2)
    check_7T = math.sqrt(mse_7T)
    psnr_7T = 20 * math.log10( 1.0 / check_7T)

    myfile_valid_psnr_7T.write("%f \n" % (psnr_7T))
    myfile_valid_mse_7T.write("%f \n" % (mse_7T))


elif loss_3 == loss_1:
    decoded_imgs = autoencoder_3.predict(X_test)
    mse_7T=  np.mean((y_test[:,:,:,0] - decoded_imgs[:,:,:,0]) ** 2)
    check_7T = math.sqrt(mse_7T)
    psnr_7T = 20 * math.log10( 1.0 / check_7T)

    myfile_valid_psnr_7T.write("%f \n" % (psnr_7T))
    myfile_valid_mse_7T.write("%f \n" % (mse_7T))

यहाँ आप वेट्स तभी सेव करते हैं जब प्रेडिक्टेड 7T और ग्राउंड ट्रुथ (7T) के बीच का PSNR, psnr_gray_channel लिस्ट में पहले से सेव मानों की तुलना में अधिकतम हो।

if max(psnr_gray_channel) < psnr_7T:
            autoencoder_1.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE1_" + str(jj)+".h5")
            autoencoder_2.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE2_" + str(jj)+".h5")
            autoencoder_3.save_weights("../Model/CROSSVAL1/CROSSVAL1_AE3_" + str(jj)+".h5")

    psnr_gray_channel.append(psnr_7T)

इनपुट, ग्राउंड ट्रुथ और डिकोडेड सेव करना: मात्रात्मक परिणाम

आप एक numpy मैट्रिक्स temp परिभाषित करेंगे जिसका आकार 176 x 528 होगा क्योंकि एक पंक्ति में 3 इमेज सेव होंगी, प्रत्येक 176 x 176 के आयाम की। आप सभी वैलिडेशन 3T, 7T और प्रेडिक्टेड में से किसी एक इमेज को सेव करेंगे और मैट्रिक्स को 255 से गुणा करेंगे क्योंकि इमेज 0 और 1 के बीच स्केल की गई थीं।

अंत में scipy फ़ंक्शन का उपयोग करते हुए आप इमेज सेव करेंगे।

temp = np.zeros([resizeTo,resizeTo*3])
temp[:resizeTo,:resizeTo] = X_test[0,:,:,0]
temp[:resizeTo,resizeTo:resizeTo*2] = y_test[0,:,:,0]
temp[:resizeTo,2*resizeTo:] = decoded_imgs[0,:,:,0]
temp = temp*255
scipy.misc.imsave('../Results/1_encoder_3_decoders_complete_slices_single_channel/' + str(j) + '.jpg', temp)
j +=1

आइए अंत में PSNR और MSE फ़ाइलें बंद कर दें।

myfile_valid_psnr_7T.close()
myfile_valid_mse_7T.close()

अंततः, हर 20 epochs के बाद आप learning rate को उसके वर्तमान मान के 10% से घटा देंगे।

if jj % 20 ==0:
        learning_rate = learning_rate - learning_rate * 0.10

Testing Script

इस ट्यूटोरियल के भाग-2 में आप निम्नलिखित विषयों को कवर करेंगे:

  • आप आवश्यक मॉड्यूल इम्पोर्ट करके शुरू करेंगे जिनकी आपको अपना डीप लर्निंग मॉडल ट्रेन करने के लिए आवश्यकता होगी,
  • फिर आपको 3T और 7T MRI डेटासेट के बारे में बताया जाएगा,
  • उसके बाद आप इनिशियलाइज़र्स परिभाषित करेंगे और 3T तथा 7T टेस्ट डेटासेट को लोड करेंगे; डेटा लोड करते समय आप इमेज का आकार ऑन-द-फ़्लाइ बदलेंगे,
  • अगला चरण होगा लोड किए गए डेटा का प्रीप्रोसेस करना: ट्रेन और टेस्ट लिस्ट को numpy मैट्रिक्स में बदलना, मैट्रिक्स का प्रकार float32 में बदलना, मैक्स-मिन स्ट्रैटेजी से रीस्केल करना, एरेज़ को रीशेप करना और अंत में डेटा को 80% ट्रेनिंग और शेष 20% वैलिडेशन सेट में बाँटना,
  • फिर, आप 1-Encoder-3-Decoder आर्किटेक्चर बनाएँगे: जिसमें merge कनेक्शन और मल्टी-डिकोडर्स शामिल होंगे,
  • इसके बाद, आप परिभाषित करेंगे: लॉस फ़ंक्शन, तीन अलग-अलग मॉडल और अंत में प्रशिक्षित वेट्स लोड करेंगे,
  • अंत में, समय है कि आप अपने merge और मल्टी-डिकोडर मॉडल का उपयोग करके अनदेखे डेटा पर प्रेडिक्ट करें और मात्रात्मक तथा गुणात्मक दोनों तरह के परिणाम सेव करें। आप nibabel का उपयोग करके 2D इमेज को एक संयुक्त वॉल्यूम के रूप में सेव करना भी सीखेंगे।

Python मॉड्यूल डिपेंडेंसीज़

इस ट्यूटोरियल के साथ आगे बढ़ने से पहले सुनिश्चित करें कि आपके पास नीचे दिए गए मॉड्यूल संस्करण बिल्कुल यही हैं:

  • Keras==2.0.4
  • tensorflow==1.8.0
  • scipy==0.19.0
  • numpy==1.14.5
  • Pillow==4.1.1
  • nibabel==2.1.0
  • scikit_learn==0.18.1

नोट: शुरू करने से पहले ध्यान दें कि मॉडल को Nvidia 1080 Ti GPU Xeon e5 GeForce प्रोसेसर और 32GB RAM वाले सिस्टम पर ट्रेन किया जाएगा। यदि आप Jupyter Notebook का उपयोग कर रहे हैं, तो आपको os नामक मॉड्यूल का उपयोग करके CUDA device order और CUDA visible devices निर्दिष्ट करने वाली तीन और कोड लाइनों को जोड़ने की आवश्यकता होगी।

नीचे दिए गए कोड में, आप मूलतः os.environ का उपयोग करके नोटबुक में environment variables सेट करते हैं। Keras इनिशियलाइज़ करने से पहले यह करना अच्छा है ताकि Keras बैकएंड TensorFlow पहले GPU का उपयोग करे। यदि जिस मशीन पर आप ट्रेन कर रहे हैं उस पर GPU 0 पर है, तो 1 की जगह 0 का उपयोग करें। इसे आप टर्मिनल पर एक सरल कमांड चलाकर जाँच सकते हैं: उदाहरण के लिए, nvidia-smi

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

मॉड्यूल इम्पोर्ट करना

सबसे पहले, आप सभी आवश्यक मॉड्यूल जैसे tensorflow, numpy, और सबसे महत्वपूर्ण keras, तथा आवश्यक फ़ंक्शंस या लेयर्स जैसे Input, Conv2D, MaxPooling2D आदि इम्पोर्ट करेंगे क्योंकि आप मॉडल को ट्रेन करने के लिए इन सभी फ़्रेमवर्क्स का उपयोग करेंगे!
nifti फॉर्मैट इमेज पढ़ने के लिए आपको nibabel नामक मॉड्यूल भी इम्पोर्ट करना होगा।

import os
from keras.layers import Input,Dense,Flatten,Dropout,merge,Reshape,Conv2D,MaxPooling2D,UpSampling2D
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
import numpy as np
import scipy.misc
import numpy.random as rng
from sklearn.utils import shuffle
import nibabel as nib
from sklearn.cross_validation import train_test_split
import math

Brain MRI 3T और 7T डेटासेट को समझना

ब्रेन MRI 3T और 7T डेटासेट 3D वॉल्यूम्स का बना है, प्रत्येक वॉल्यूम में कुल 207 स्लाइस/इमेज होती हैं जो मस्तिष्क के अलग-अलग स्लाइसों पर ली जाती हैं। हर स्लाइस का आयाम 173 x 173 है। इमेज सिंगल-चैनल ग्रेस्केल हैं। कुल 39 सब्जेक्ट्स हैं, प्रत्येक सब्जेक्ट में एक मरीज का MRI स्कैन है। इमेज फॉर्मैट jpeg, png आदि नहीं है बल्कि nifti फॉर्मैट है। आगे चलकर आप देखेंगे कि nifti फॉर्मैट इमेज कैसे पढ़ी जाती हैं।

डेटासेट में T1 मॉडैलिटी MR इमेज शामिल हैं; T1 सीक्वेंस पारंपरिक रूप से एनाटोमिक संरचनाओं के आकलन के लिए अच्छे माने जाते हैं। आज जिस डेटासेट पर आप काम करेंगे उसमें 3T और 7T ब्रेन MRI शामिल हैं।

यह डेटासेट सार्वजनिक है और इस स्रोत से डाउनलोड के लिए उपलब्ध है।

इनिशियलाइज़र्स परिभाषित करना

पहले डेटा के आयाम परिभाषित करें। डेटा पढ़ने वाले भाग में आप इमेज का आयाम 173x173 से 176x176 में बदलेंगे। यहाँ हम डेटा डायरेक्टरी, मॉडल ट्रेन करने के लिए बैच साइज़, चैनलों की संख्या, एक Input() लेयर, train और test मैट्रिक्स को लिस्ट के रूप में और अंत में रीस्केलिंग के लिए MRI डेटासेट के न्यूनतम और अधिकतम मानों वाली टेक्स्ट फ़ाइल लोड करना भी परिभाषित करते हैं।

x,y = 173,173
full_z = 207
resizeTo=176
inChannel = outChannel = 1
input_shape=(x,y,inChannel)
input_img = Input(shape = (resizeTo, resizeTo, inChannel))
train_matrix = []
test_matrix = []
ff = os.listdir("../test_crossval1")
save = "../Result_nii_crossval1"
folder_ground = os.listdir("../test_g_crossval1")
ToPredict_images=[]
predict_matrix=[]
ground_images=[]
ground_matrix=[]
min_max=np.loadtxt('../maxANDmin.txt')

टेस्टिंग वॉल्यूम्स लोड करें

इसके बाद, हम nibabel लाइब्रेरी का उपयोग करके MRI डेटा लोड करेंगे और इमेज को 173 x 173 से 176 x 176 में x और y आयाम में ज़ीरो पैडिंग करके बदलेंगे।

ध्यान दें कि जब आप Nifti फॉर्मैट वॉल्यूम लोड करते हैं, तो Nibabel इमेज एरे को तुरंत लोड नहीं करता। यह तब तक प्रतीक्षा करता है जब तक आप एरे डेटा नहीं माँगते। एरे डेटा माँगने का मानक तरीका get_data() मेथड को कॉल करना है।

क्योंकि आपको 3D की बजाय 2D स्लाइस चाहिए, आप पहले से इनिशियलाइज़ की गई train और test लिस्ट का उपयोग करेंगे; हर बार जब आप एक वॉल्यूम पढ़ते हैं, तो आप 3D वॉल्यूम की सभी 207 स्लाइसों पर इटरेट करेंगे और हर स्लाइस को एक-एक करके लिस्ट में जोड़ेंगे।

for f in ff:
    temp = np.zeros([resizeTo,full_z,resizeTo])
    a = nib.load("../test_crossval1" + f)
    affine = a.affine
    a = a.get_data()
    temp[3:,:,3:] = a
    a = temp
    for j in range(full_z):
        predict_matrix.append(a[:,j,:])
for f in ff:
    temp = np.zeros([resizeTo,full_z,resizeTo])
    a = nib.load("../test_g_crossval1" + f)
    affine = a.affine
    a = a.get_data()
    temp[3:,:,3:] = a
    a = temp
    for j in range(full_z):
        ground_matrix.append(a[:,j,:])

डेटा प्रीप्रोसेसिंग

क्योंकि 3T और 7T टेस्ट मैट्रिक्स लिस्ट हैं, आप numpy मॉड्यूल का उपयोग करके इन्हें numpy एरे में बदलेंगे।

आगे, आप numpy एरे के type को float32 में बदलेंगे और साथ ही input तथा ground truth दोनों को रीस्केल करेंगे।

ToPredict_images = np.asarray(predict_matrix)
ToPredict_images = ToPredict_images.astype('float32')
mx = min_max[0]
mn = min_max[1]
ToPredict_images[:,:,:,0] = (ToPredict_images[:,:,:,0] - mn ) / (mx - mn)
ground_images = np.asarray(ground_matrix)
ground_images = ground_images.astype('float32')
ground_images[:,:,:,0] = (ground_images[:,:,:,0] - mn ) / (mx - mn)

इसके बाद, आप दो नए वेरिएबल ToPredict_images (3T टेस्ट/इनपुट) और ground_images (7T टेस्ट/ग्राउंड ट्रुथ) बनाएँगे जिनका शेप train और test मैट्रिक्स के अनुरूप होगा। यह 4D मैट्रिक्स होगा जिसमें पहला आयाम इमेज की कुल संख्या, दूसरा और तीसरा हर इमेज का आयाम और अंतिम आयाम चैनलों की संख्या (यहाँ एक) होगा।"

ToPredict_images=np.zeros(shape=[(ToPredict_images.shape[0]),(ToPredict_images.shape[1]),(ToPredict_images.shape[2]),(1)])
ground_images=np.zeros(shape=[(ground_images.shape[0]),(ground_images.shape[1]),(ground_images.shape[2]),(1)])

फिर आप सभी इमेजों पर एक-एक करके इटरेट करेंगे; हर बार आप train और test मैट्रिक्स को 176 x 176 में रीशेप करेंगे और क्रमशः ToPredict_images (3T टेस्ट/इनपुट) और ground_images (7T टेस्ट/ग्राउंड ट्रुथ) में जोड़ेंगे।

for i in range(ToPredict_images.shape[0]):
    ToPredict_images[i,:,:,0] = ToPredict_images[i,:,:].reshape(resizeTo,resizeTo)
for i in range(ground_images.shape[0]):
    ground_images[i,:,:,0] = ground_images[i,:,:].reshape(resizeTo,resizeTo)

मॉडल!

model
चित्र: मॉडल की आर्किटेक्चर
चित्र इस पेपर से लिया गया है।

Encoder

def encoder(input_img):
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img)
    conv1 = BatchNormalization()(conv1)
    conv1 = Conv2D(32, (3,3), activation='relu', padding='same')(conv1)
    conv1 = BatchNormalization()(conv1)
    conv1 = Conv2D(32, (3,3), activation='relu', padding='same')(conv1)
    conv1 = BatchNormalization()(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)
    conv2 = BatchNormalization()(conv2)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    conv2 = BatchNormalization()(conv2)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    conv2 = BatchNormalization()(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)
    conv3 = BatchNormalization()(conv3)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    conv3 = BatchNormalization()(conv3)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    conv3 = BatchNormalization()(conv3)
    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)
    conv4 = BatchNormalization()(conv4)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
    conv4 = BatchNormalization()(conv4)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
    conv4 = BatchNormalization()(conv4)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv4)
    conv5 = BatchNormalization()(conv5)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)
    conv5 = BatchNormalization()(conv5)
    conv5 = Conv2D(512, (3, 3), activation='sigmoid', padding='same')(conv5)
    conv5 = BatchNormalization()(conv5)
    return conv5,conv4,conv3,conv2,conv1

Decoder

def decoder(conv5,conv4,conv3,conv2,conv1):
    up6 = merge([conv5, conv4], mode='concat', concat_axis=3)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    up7 = UpSampling2D((2,2))(conv6)
    up7 = merge([up7, conv3], mode='concat', concat_axis=3)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    up8 = UpSampling2D((2,2))(conv7)
    up8 = merge([up8, conv2], mode='concat', concat_axis=3)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)
    conv8 = BatchNormalization()(conv8)
    up9 = UpSampling2D((2,2))(conv8)
    up9 = merge([up9, conv1], mode='concat', concat_axis=3)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)
    conv9 = BatchNormalization()(conv9)
    decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(conv9)
    return decoded

लॉस फ़ंक्शन

अगले चरण में, आप mean square error का उपयोग करेंगे जिसमें आप ग्राउंड ट्रुथ y_t और y_p दोनों के वे मान (पिक्सेल) जो शून्य के बराबर हैं, उन्हें बाहर कर देंगे।

def root_mean_sq_GxGy(y_t, y_p):
    a1=1
    zero = tf.constant(0, dtype=tf.float32)
    where = tf.not_equal(y_t, zero)
    a_t=tf.boolean_mask(y_t,where,name='boolean_mask')
    a_p=tf.boolean_mask(y_p,where,name='boolean_mask')
    return a1*(K.sqrt(K.mean((K.square(a_t-a_p)))))

मॉडल परिभाषा और तीनों ऑटोएन्कोडर्स में वेट्स लोड करें!

सबसे पहले, encoder फ़ंक्शन को इनपुट पास करके कॉल करें। चूँकि आप अपनी आर्किटेक्चर में merge कनेक्शन का उपयोग कर रहे हैं, इसलिए encoder फ़ंक्शन पाँच convolution लेयर्स का आउटपुट लौटाएगा जिन्हें आप तीनों डिकोडर्स के आउटपुट के साथ अलग-अलग merge करेंगे।

conv5,conv4,conv3,conv2,conv1 = encoder(input_img)

अब तीन अलग-अलग मॉडल बनाते हैं और उन पर प्रशिक्षित मॉडल वेट्स लोड करते हैं।

autoencoder_1 = Model(input_img, decoder(conv5,conv4,conv3,conv2,conv1))

autoencoder_1.load_weights("../Model/CROSSVAL1/CROSSVAL1_AE1.h5")
autoencoder_2 = Model(input_img, decoder(conv5,conv4,conv3,conv2,conv1))

autoencoder_2.load_weights("../Model/CROSSVAL1/CROSSVAL1_AE2.h5")
autoencoder_3 = Model(input_img, decoder(conv5,conv4,conv3,conv2,conv1))

autoencoder_3.load_weights("../Model/CROSSVAL1/CROSSVAL1_AE3.h5")

टेस्ट वॉल्यूम्स पर मॉडल प्रेडिक्शन: मात्रात्मक और गुणात्मक परिणाम!

आइए जल्दी से दो numpy एरे इनिशियलाइज़ करें, प्रत्येक का आकार 11 x 3 x 1 होगा जहाँ पहला आयाम उन वॉल्यूम्स की संख्या को दर्शाएगा जिनका आप अपने मॉडल की टेस्टिंग के लिए उपयोग करेंगे। दूसरा आयाम MSE और PSNR को दर्शाएगा—तीन मामलों के बीच: प्रेडिक्टेड आउटपुट 7T MR इमेज और ग्राउंड ट्रुथ 7T MR इमेज, प्रेडिक्टेड आउटपुट और इनपुट 3T MR इमेज, इनपुट 3T MR इमेज और ग्राउंड ट्रुथ 7T MR इमेज; तीसरा आयाम उन चैनलों की संख्या को दर्शाएगा जिन्हें आप अपने मॉडल में इनपुट देंगे!

mse= np.zeros([11,3,1])
psnr= np.zeros([11,3,1])
i=0 #for iterating over the slices of all the 11 volumes

अगले भाग में, आप 11 वॉल्यूम्स पर एक-एक करके इटरेट करेंगे। प्रत्येक इटरेशन में, आप तीनों ऑटोएन्कोडर्स का उपयोग करके प्रत्येक वॉल्यूम का प्रेडिक्शन करेंगे और अंत में प्रेडिक्शंस का औसत लेंगे।

हर वॉल्यूम में, आप उस वॉल्यूम के चैनलों की संख्या पर इटरेट करेंगे और ऊपर चर्चा किए गए तीन अलग-अलग मामलों के लिए PSNR और MSE की गणना करेंगे।

फिर nibabel लाइब्रेरी का उपयोग करके, आप प्रेडिक्टेड आउटपुट, इनपुट (3T) और ग्राउंड ट्रुथ (7T) को .nii फॉर्मैट फ़ाइलों के रूप में सेव करेंगे: प्रत्येक 11 वॉल्यूम में 207 स्लाइस शामिल होंगी।

अंत में, आप numpy लाइब्रेरी का उपयोग करके PSNR मैट्रिक्स को एक टेक्स्ट फ़ाइल में सेव करेंगे।

जैसा कि पेपर में कहा गया है, प्रेडिक्टेड आउटपुट्स का एवरेज लेना शोर के प्रभाव को कम करने में मदद करता है लेकिन रिकंस्ट्रक्टेड इमेज में स्थानीय फीचर्स को संरक्षित रखता है, जिसके कारण व्यक्तिगत डिकोडर आउटपुट्स की तुलना में PSNR बेहतर होता है।

for j in range(11):
    decoded_imgs_1 = autoencoder_1.predict(ToPredict_images[i:i+207,:,:,:])
    decoded_imgs_2 = autoencoder_2.predict(ToPredict_images[i:i+207,:,:,:])
    decoded_imgs_3 = autoencoder_3.predict(ToPredict_images[i:i+207,:,:,:])
    decoded_imgs = np.mean( np.array([ decoded_imgs_1, decoded_imgs_2,decoded_imgs_3 ]), axis=0 )
    for channel in range(1):
        mse[j,0,channel]=  np.mean((ground_images[i:i+207,:,:,channel] - decoded_imgs[:,:,:,channel]) ** 2)
        psnr[j,0,channel] = 20 * math.log10( 1.0 / math.sqrt(mse[j,0,channel]))
        mse[j,1,channel]=  np.mean((ground_images[i:i+207,:,:,channel] - ToPredict_images[i:i+207,:,:,channel])** 2)
        psnr[j,1,channel] = 20 * math.log10( 1.0 / math.sqrt(mse[j,1,channel]))
        mse[j,2,channel] =  np.mean((ToPredict_images[i:i+207,:,:,channel] - decoded_imgs[:,:,:,channel]) ** 2)
        checklt = math.sqrt(mse[j,2,channel])
        psnr[j,2,channel] = 20 * math.log10( 1.0 / math.sqrt(mse[j,2,channel]))
    obj = nib.Nifti1Image(decoded_imgs, affine)
    string =str(j)+'_crossval1.nii'
    nib.save(obj, save + string)
    obj = nib.Nifti1Image(ground_images[i:i+207,:,:,:], affine)
    string =str(j)+'_ground_images_crossval1.nii'
    nib.save(obj, save + string)
    obj = nib.Nifti1Image(ToPredict_images[i:i+207,:,:,:], affine)
    string =str(j)+'_ToPredict_images_crossval1.nii'
    nib.save(obj, save + string)
    i=i+207


np.savetxt('psnr_all_slices.txt',psnr[:,:,0])

यदि आप Python के बारे में और सीखना चाहते हैं, तो DataCamp का Introduction to Data Visualization with Matplotlib कोर्स देखें।

Keras ट्यूटोरियल: Python में डीप लर्निंग देखें।

विषय