|
a |
|
b/scripts/cv_analysis/miscnn_k3.py |
|
|
1 |
#==============================================================================# |
|
|
2 |
# Author: Dominik Müller # |
|
|
3 |
# Copyright: 2020 IT-Infrastructure for Translational Medical Research, # |
|
|
4 |
# University of Augsburg # |
|
|
5 |
# # |
|
|
6 |
# This program is free software: you can redistribute it and/or modify # |
|
|
7 |
# it under the terms of the GNU General Public License as published by # |
|
|
8 |
# the Free Software Foundation, either version 3 of the License, or # |
|
|
9 |
# (at your option) any later version. # |
|
|
10 |
# # |
|
|
11 |
# This program is distributed in the hope that it will be useful, # |
|
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of # |
|
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # |
|
|
14 |
# GNU General Public License for more details. # |
|
|
15 |
# # |
|
|
16 |
# You should have received a copy of the GNU General Public License # |
|
|
17 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. # |
|
|
18 |
#==============================================================================# |
|
|
19 |
#-----------------------------------------------------# |
|
|
20 |
# Library imports # |
|
|
21 |
#-----------------------------------------------------# |
|
|
22 |
import tensorflow as tf |
|
|
23 |
from miscnn.data_loading.interfaces import NIFTI_interface |
|
|
24 |
from miscnn import Data_IO, Preprocessor, Data_Augmentation, Neural_Network |
|
|
25 |
from miscnn.processing.subfunctions import Normalization, Clipping, Resampling |
|
|
26 |
from miscnn.neural_network.architecture.unet.standard import Architecture |
|
|
27 |
from miscnn.neural_network.metrics import tversky_crossentropy, dice_soft, \ |
|
|
28 |
dice_crossentropy, tversky_loss |
|
|
29 |
from miscnn.evaluation.cross_validation import cross_validation |
|
|
30 |
from tensorflow.keras.callbacks import ReduceLROnPlateau, TensorBoard, \ |
|
|
31 |
EarlyStopping, CSVLogger, ModelCheckpoint |
|
|
32 |
from miscnn.evaluation.cross_validation import run_fold, load_disk2fold |
|
|
33 |
import argparse |
|
|
34 |
import os |
|
|
35 |
|
|
|
36 |
#-----------------------------------------------------# |
|
|
37 |
# Argparser # |
|
|
38 |
#-----------------------------------------------------# |
|
|
39 |
parser = argparse.ArgumentParser(description="Automated COVID-19 Segmentation") |
|
|
40 |
parser.add_argument("-f", "--fold", help="Cross-validation fold. Range: [0:5]", |
|
|
41 |
required=True, type=int, dest="fold") |
|
|
42 |
parser.add_argument("-g", "--gpu", help="GPU ID selection for multi cluster", |
|
|
43 |
required=False, type=int, dest="gpu", default=0) |
|
|
44 |
|
|
|
45 |
path_eval = "evaluation.cv3" |
|
|
46 |
path_preds = "predictions.cv3" |
|
|
47 |
|
|
|
48 |
args = parser.parse_args() |
|
|
49 |
fold = args.fold |
|
|
50 |
fold_subdir = os.path.join(path_eval, "fold_" + str(fold)) |
|
|
51 |
|
|
|
52 |
#-----------------------------------------------------# |
|
|
53 |
# Tensorflow Configuration for GPU Cluster # |
|
|
54 |
#-----------------------------------------------------# |
|
|
55 |
os.environ["CUDA_VISIBLE_DEVICES"] = str(int(args.gpu)) |
|
|
56 |
|
|
|
57 |
#-----------------------------------------------------# |
|
|
58 |
# Setup of MIScnn Pipeline # |
|
|
59 |
#-----------------------------------------------------# |
|
|
60 |
# Initialize Data IO Interface for NIfTI data |
|
|
61 |
## We are using 4 classes due to [background, lung_left, lung_right, covid-19] |
|
|
62 |
interface = NIFTI_interface(channels=1, classes=4) |
|
|
63 |
|
|
|
64 |
# Create Data IO object to load and write samples in the file structure |
|
|
65 |
data_io = Data_IO(interface, input_path="data", output_path=path_preds, |
|
|
66 |
delete_batchDir=False) |
|
|
67 |
|
|
|
68 |
# Access all available samples in our file structure |
|
|
69 |
sample_list = data_io.get_indiceslist() |
|
|
70 |
sample_list.sort() |
|
|
71 |
|
|
|
72 |
# Create and configure the Data Augmentation class |
|
|
73 |
data_aug = Data_Augmentation(cycles=1, scaling=True, rotations=True, |
|
|
74 |
elastic_deform=True, mirror=True, |
|
|
75 |
brightness=True, contrast=True, gamma=True, |
|
|
76 |
gaussian_noise=True) |
|
|
77 |
|
|
|
78 |
# Create a clipping Subfunction to the lung window of CTs (-1250 and 250) |
|
|
79 |
sf_clipping = Clipping(min=-1250, max=250) |
|
|
80 |
# Create a pixel value normalization Subfunction to scale between 0-255 |
|
|
81 |
sf_normalize = Normalization(mode="grayscale") |
|
|
82 |
# Create a resampling Subfunction to voxel spacing 1.58 x 1.58 x 2.70 |
|
|
83 |
sf_resample = Resampling((1.58, 1.58, 2.70)) |
|
|
84 |
# Create a pixel value normalization Subfunction for z-score scaling |
|
|
85 |
sf_zscore = Normalization(mode="z-score") |
|
|
86 |
|
|
|
87 |
# Assemble Subfunction classes into a list |
|
|
88 |
sf = [sf_clipping, sf_normalize, sf_resample, sf_zscore] |
|
|
89 |
|
|
|
90 |
# Create and configure the Preprocessor class |
|
|
91 |
pp = Preprocessor(data_io, data_aug=data_aug, batch_size=2, subfunctions=sf, |
|
|
92 |
prepare_subfunctions=True, prepare_batches=False, |
|
|
93 |
analysis="patchwise-crop", patch_shape=(160, 160, 80), |
|
|
94 |
use_multiprocessing=True) |
|
|
95 |
# Adjust the patch overlap for predictions |
|
|
96 |
pp.patchwise_overlap = (80, 80, 30) |
|
|
97 |
|
|
|
98 |
# Initialize the Architecture |
|
|
99 |
unet_standard = Architecture(depth=4, activation="softmax", |
|
|
100 |
batch_normalization=True) |
|
|
101 |
|
|
|
102 |
# Create the Neural Network model |
|
|
103 |
model = Neural_Network(preprocessor=pp, architecture=unet_standard, |
|
|
104 |
loss=tversky_crossentropy, |
|
|
105 |
metrics=[tversky_loss, dice_soft, dice_crossentropy], |
|
|
106 |
batch_queue_size=3, workers=3, learninig_rate=0.001) |
|
|
107 |
|
|
|
108 |
# Define Callbacks |
|
|
109 |
cb_lr = ReduceLROnPlateau(monitor='loss', factor=0.1, patience=15, |
|
|
110 |
verbose=1, mode='min', min_delta=0.0001, cooldown=1, |
|
|
111 |
min_lr=0.00001) |
|
|
112 |
cb_es = EarlyStopping(monitor="loss", patience=100) |
|
|
113 |
cb_tb = TensorBoard(log_dir=os.path.join(fold_subdir, "tensorboard"), |
|
|
114 |
histogram_freq=0, write_graph=True, write_images=True) |
|
|
115 |
cb_cl = CSVLogger(os.path.join(fold_subdir, "logs.csv"), separator=',', |
|
|
116 |
append=True) |
|
|
117 |
cb_mc = ModelCheckpoint(os.path.join(fold_subdir, "model.best.hdf5"), |
|
|
118 |
monitor="loss", verbose=1, |
|
|
119 |
save_best_only=True, mode="min") |
|
|
120 |
|
|
|
121 |
#-----------------------------------------------------# |
|
|
122 |
# Run Pipeline for provided CV Fold # |
|
|
123 |
#-----------------------------------------------------# |
|
|
124 |
# Run pipeline for cross-validation fold |
|
|
125 |
run_fold(fold, model, epochs=1000, iterations=150, evaluation_path=path_eval, |
|
|
126 |
draw_figures=True, callbacks=[cb_lr, cb_es, cb_tb, cb_cl, cb_mc], |
|
|
127 |
save_models=False) |
|
|
128 |
|
|
|
129 |
# Dump latest model to disk |
|
|
130 |
model.dump(os.path.join(fold_subdir, "model.latest.hdf5")) |
|
|
131 |
|
|
|
132 |
#-----------------------------------------------------# |
|
|
133 |
# Inference for provided CV Fold # |
|
|
134 |
#-----------------------------------------------------# |
|
|
135 |
# Load best model weights during fitting |
|
|
136 |
model.load(os.path.join(fold_subdir, "model.best.hdf5")) |
|
|
137 |
|
|
|
138 |
# Obtain training and validation data set |
|
|
139 |
training, validation = load_disk2fold(os.path.join(fold_subdir, |
|
|
140 |
"sample_list.json")) |
|
|
141 |
|
|
|
142 |
# Compute predictions |
|
|
143 |
model.predict(validation, return_output=False) |