@ -11,6 +11,7 @@ from metrics import *
from tensorflow . keras . models import load_model
from tqdm import tqdm
import json
from sklearn . metrics import f1_score
def configuration ( ) :
@ -73,6 +74,8 @@ def config_params():
is_loss_soft_dice = False # Use soft dice as loss function. When set to true, "weighted_loss" must be false.
weighted_loss = False # Use weighted categorical cross entropy as loss fucntion. When set to true, "is_loss_soft_dice" must be false.
data_is_provided = False # Only set this to true when you have already provided the input data and the train and eval data are in "dir_output".
task = " segmentation " # This parameter defines task of model which can be segmentation, enhancement or classification.
f1_threshold_classification = None # This threshold is used to consider models with an evaluation f1 scores bigger than it. The selected model weights undergo a weights ensembling. And avreage ensembled model will be written to output.
@ex.automain
@ -86,162 +89,239 @@ def run(_config, n_classes, n_epochs, input_height,
scaling_brightness , scaling_binarization , rotation , rotation_not_90 ,
thetha , scaling_flip , continue_training , transformer_patchsize ,
num_patches_xy , model_name , flip_index , dir_eval , dir_output ,
pretraining , learning_rate ):
pretraining , learning_rate , task , f1_threshold_classification ):
num_patches = num_patches_xy [ 0 ] * num_patches_xy [ 1 ]
if data_is_provided :
dir_train_flowing = os . path . join ( dir_output , ' train ' )
dir_eval_flowing = os . path . join ( dir_output , ' eval ' )
if task == " segmentation " :
dir_flow_train_imgs = os . path . join ( dir_train_flowing , ' images ' )
dir_flow_train_labels = os . path . join ( dir_train_flowing , ' labels ' )
num_patches = num_patches_xy [ 0 ] * num_patches_xy [ 1 ]
if data_is_provided :
dir_train_flowing = os . path . join ( dir_output , ' train ' )
dir_eval_flowing = os . path . join ( dir_output , ' eval ' )
dir_flow_train_imgs = os . path . join ( dir_train_flowing , ' images ' )
dir_flow_train_labels = os . path . join ( dir_train_flowing , ' labels ' )
dir_flow_eval_imgs = os . path . join ( dir_eval_flowing , ' images ' )
dir_flow_eval_labels = os . path . join ( dir_eval_flowing , ' labels ' )
dir_flow_eval_imgs = os . path . join ( dir_eval_flowing , ' images ' )
dir_flow_eval_labels = os . path . join ( dir_eval_flowing , ' labels ' )
configuration ( )
else :
dir_img , dir_seg = get_dirs_or_files ( dir_train )
dir_img_val , dir_seg_val = get_dirs_or_files ( dir_eval )
# make first a directory in output for both training and evaluations in order to flow data from these directories.
dir_train_flowing = os . path . join ( dir_output , ' train ' )
dir_eval_flowing = os . path . join ( dir_output , ' eval ' )
dir_flow_train_imgs = os . path . join ( dir_train_flowing , ' images/ ' )
dir_flow_train_labels = os . path . join ( dir_train_flowing , ' labels/ ' )
dir_flow_eval_imgs = os . path . join ( dir_eval_flowing , ' images/ ' )
dir_flow_eval_labels = os . path . join ( dir_eval_flowing , ' labels/ ' )
if os . path . isdir ( dir_train_flowing ) :
os . system ( ' rm -rf ' + dir_train_flowing )
os . makedirs ( dir_train_flowing )
else :
os . makedirs ( dir_train_flowing )
if os . path . isdir ( dir_eval_flowing ) :
os . system ( ' rm -rf ' + dir_eval_flowing )
os . makedirs ( dir_eval_flowing )
else :
os . makedirs ( dir_eval_flowing )
os . mkdir ( dir_flow_train_imgs )
os . mkdir ( dir_flow_train_labels )
os . mkdir ( dir_flow_eval_imgs )
os . mkdir ( dir_flow_eval_labels )
# set the gpu configuration
configuration ( )
imgs_list = np . array ( os . listdir ( dir_img ) )
segs_list = np . array ( os . listdir ( dir_seg ) )
imgs_list_test = np . array ( os . listdir ( dir_img_val ) )
segs_list_test = np . array ( os . listdir ( dir_seg_val ) )
# writing patches into a sub-folder in order to be flowed from directory.
provide_patches ( imgs_list , segs_list , dir_img , dir_seg , dir_flow_train_imgs ,
dir_flow_train_labels , input_height , input_width , blur_k ,
blur_aug , padding_white , padding_black , flip_aug , binarization ,
scaling , degrading , brightening , scales , degrade_scales , brightness ,
flip_index , scaling_bluring , scaling_brightness , scaling_binarization ,
rotation , rotation_not_90 , thetha , scaling_flip , augmentation = augmentation ,
patches = patches )
provide_patches ( imgs_list_test , segs_list_test , dir_img_val , dir_seg_val ,
dir_flow_eval_imgs , dir_flow_eval_labels , input_height , input_width ,
blur_k , blur_aug , padding_white , padding_black , flip_aug , binarization ,
scaling , degrading , brightening , scales , degrade_scales , brightness ,
flip_index , scaling_bluring , scaling_brightness , scaling_binarization ,
rotation , rotation_not_90 , thetha , scaling_flip , augmentation = False , patches = patches )
if weighted_loss :
weights = np . zeros ( n_classes )
if data_is_provided :
for obj in os . listdir ( dir_flow_train_labels ) :
try :
label_obj = cv2 . imread ( dir_flow_train_labels + ' / ' + obj )
label_obj_one_hot = get_one_hot ( label_obj , label_obj . shape [ 0 ] , label_obj . shape [ 1 ] , n_classes )
weights + = ( label_obj_one_hot . sum ( axis = 0 ) ) . sum ( axis = 0 )
except :
pass
else :
for obj in os . listdir ( dir_seg ) :
try :
label_obj = cv2 . imread ( dir_seg + ' / ' + obj )
label_obj_one_hot = get_one_hot ( label_obj , label_obj . shape [ 0 ] , label_obj . shape [ 1 ] , n_classes )
weights + = ( label_obj_one_hot . sum ( axis = 0 ) ) . sum ( axis = 0 )
except :
pass
weights = 1.00 / weights
weights = weights / float ( np . sum ( weights ) )
weights = weights / float ( np . min ( weights ) )
weights = weights / float ( np . sum ( weights ) )
if continue_training :
if model_name == ' resnet50_unet ' :
if is_loss_soft_dice :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { ' soft_dice_loss ' : soft_dice_loss } )
if weighted_loss :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { ' loss ' : weighted_categorical_crossentropy ( weights ) } )
if not is_loss_soft_dice and not weighted_loss :
model = load_model ( dir_of_start_model , compile = True )
elif model_name == ' hybrid_transformer_cnn ' :
if is_loss_soft_dice :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { " PatchEncoder " : PatchEncoder , " Patches " : Patches , ' soft_dice_loss ' : soft_dice_loss } )
if weighted_loss :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { ' loss ' : weighted_categorical_crossentropy ( weights ) } )
if not is_loss_soft_dice and not weighted_loss :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { " PatchEncoder " : PatchEncoder , " Patches " : Patches } )
else :
index_start = 0
if model_name == ' resnet50_unet ' :
model = resnet50_unet ( n_classes , input_height , input_width , weight_decay , pretraining )
elif model_name == ' hybrid_transformer_cnn ' :
model = vit_resnet50_unet ( n_classes , transformer_patchsize , num_patches , input_height , input_width , weight_decay , pretraining )
#if you want to see the model structure just uncomment model summary.
#model.summary()
if not is_loss_soft_dice and not weighted_loss :
model . compile ( loss = ' categorical_crossentropy ' ,
optimizer = Adam ( lr = learning_rate ) , metrics = [ ' accuracy ' ] )
if is_loss_soft_dice :
model . compile ( loss = soft_dice_loss ,
optimizer = Adam ( lr = learning_rate ) , metrics = [ ' accuracy ' ] )
if weighted_loss :
model . compile ( loss = weighted_categorical_crossentropy ( weights ) ,
optimizer = Adam ( lr = learning_rate ) , metrics = [ ' accuracy ' ] )
# generating train and evaluation data
train_gen = data_gen ( dir_flow_train_imgs , dir_flow_train_labels , batch_size = n_batch ,
input_height = input_height , input_width = input_width , n_classes = n_classes )
val_gen = data_gen ( dir_flow_eval_imgs , dir_flow_eval_labels , batch_size = n_batch ,
input_height = input_height , input_width = input_width , n_classes = n_classes )
##img_validation_patches = os.listdir(dir_flow_eval_imgs)
##score_best=[]
##score_best.append(0)
for i in tqdm ( range ( index_start , n_epochs + index_start ) ) :
model . fit_generator (
train_gen ,
steps_per_epoch = int ( len ( os . listdir ( dir_flow_train_imgs ) ) / n_batch ) - 1 ,
validation_data = val_gen ,
validation_steps = 1 ,
epochs = 1 )
model . save ( dir_output + ' / ' + ' model_ ' + str ( i ) )
with open ( dir_output + ' / ' + ' model_ ' + str ( i ) + ' / ' + " config.json " , " w " ) as fp :
json . dump ( _config , fp ) # encode dict into JSON
#os.system('rm -rf '+dir_train_flowing)
#os.system('rm -rf '+dir_eval_flowing)
#model.save(dir_output+'/'+'model'+'.h5')
elif task == ' classification ' :
configuration ( )
model = resnet50_classifier ( n_classes , input_height , input_width , weight_decay , pretraining )
else :
dir_img , dir_seg = get_dirs_or_files ( dir_train )
dir_img_val , dir_seg_val = get_dirs_or_files ( dir_eval )
opt_adam = Adam ( learning_rate = 0.001 )
model. compile ( loss = ' categorical_crossentropy ' ,
optimizer = opt_adam , metrics = [ ' accuracy ' ] )
# make first a directory in output for both training and evaluations in order to flow data from these directories.
dir_train_flowing = os . path . join ( dir_output , ' train ' )
dir_eval_flowing = os . path . join ( dir_output , ' eval ' )
dir_flow_train_imgs = os . path . join ( dir_train_flowing , ' images/ ' )
dir_flow_train_labels = os . path . join ( dir_train_flowing , ' labels/ ' )
testX , testY = generate_data_from_folder_evaluation ( dir_eval , input_height , input_width , n_classes )
dir_flow_eval_imgs = os . path . join ( dir_eval_flowing , ' images/ ' )
dir_flow_eval_labels = os . path . join ( dir_eval_flowing , ' labels/ ' )
#print(testY.shape, testY)
if os . path . isdir ( dir_train_flowing ) :
os . system ( ' rm -rf ' + dir_train_flowing )
os . makedirs ( dir_train_flowing )
else :
os . makedirs ( dir_train_flowing )
y_tot = np . zeros ( ( testX . shape [ 0 ] , n_classes ) )
indexer = 0
if os . path . isdir ( dir_eval_flowing ) :
os . system ( ' rm -rf ' + dir_eval_flowing )
os . makedirs ( dir_eval_flowing )
else :
os . makedirs ( dir_eval_flowing )
score_best = [ ]
score_best . append ( 0 )
os . mkdir ( dir_flow_train_imgs )
os . mkdir ( dir_flow_train_labels )
num_rows = return_number_of_total_training_data ( dir_train )
os . mkdir ( dir_flow_eval_imgs )
os . mkdir ( dir_flow_eval_labels )
weights = [ ]
# set the gpu configuration
configuration ( )
for i in range ( n_epochs ) :
#history = model.fit(trainX, trainY, epochs=1, batch_size=n_batch, validation_data=(testX, testY), verbose=2)#,class_weight=weights)
history = model . fit ( generate_data_from_folder_training ( dir_train , n_batch , input_height , input_width , n_classes ) , steps_per_epoch = num_rows / n_batch , verbose = 0 ) #,class_weight=weights)
imgs_list = np . array ( os . listdir ( dir_img ) )
segs_list = np . array ( os . listdir ( dir_seg ) )
imgs_list_test = np . array ( os . listdir ( dir_img_val ) )
segs_list_test = np . array ( os . listdir ( dir_seg_val ) )
# writing patches into a sub-folder in order to be flowed from directory.
provide_patches ( imgs_list , segs_list , dir_img , dir_seg , dir_flow_train_imgs ,
dir_flow_train_labels , input_height , input_width , blur_k ,
blur_aug , padding_white , padding_black , flip_aug , binarization ,
scaling , degrading , brightening , scales , degrade_scales , brightness ,
flip_index , scaling_bluring , scaling_brightness , scaling_binarization ,
rotation , rotation_not_90 , thetha , scaling_flip , augmentation = augmentation ,
patches = patches )
provide_patches ( imgs_list_test , segs_list_test , dir_img_val , dir_seg_val ,
dir_flow_eval_imgs , dir_flow_eval_labels , input_height , input_width ,
blur_k , blur_aug , padding_white , padding_black , flip_aug , binarization ,
scaling , degrading , brightening , scales , degrade_scales , brightness ,
flip_index , scaling_bluring , scaling_brightness , scaling_binarization ,
rotation , rotation_not_90 , thetha , scaling_flip , augmentation = False , patches = patches )
if weighted_loss :
weights = np . zeros ( n_classes )
if data_is_provided :
for obj in os . listdir ( dir_flow_train_labels ) :
try :
label_obj = cv2 . imread ( dir_flow_train_labels + ' / ' + obj )
label_obj_one_hot = get_one_hot ( label_obj , label_obj . shape [ 0 ] , label_obj . shape [ 1 ] , n_classes )
weights + = ( label_obj_one_hot . sum ( axis = 0 ) ) . sum ( axis = 0 )
except :
pass
else :
y_pr_class = [ ]
for jj in range ( testY . shape [ 0 ] ) :
y_pr = model . predict ( testX [ jj , : , : , : ] . reshape ( 1 , input_height , input_width , 3 ) , verbose = 0 )
y_pr_ind = np . argmax ( y_pr , axis = 1 )
#print(y_pr_ind, 'y_pr_ind')
y_pr_class . append ( y_pr_ind )
y_pr_class = np . array ( y_pr_class )
#model.save('./models_save/model_'+str(i)+'.h5')
#y_pr_class=np.argmax(y_pr,axis=1)
f1score = f1_score ( np . argmax ( testY , axis = 1 ) , y_pr_class , average = ' macro ' )
print ( i , f1score )
if f1score > score_best [ 0 ] :
score_best [ 0 ] = f1score
model . save ( os . path . join ( dir_output , ' model_best ' ) )
##best_model=keras.models.clone_model(model)
##best_model.build()
##best_model.set_weights(model.get_weights())
if f1score > f1_threshold_classification :
weights . append ( model . get_weights ( ) )
y_tot = y_tot + y_pr
indexer + = 1
y_tot = y_tot / float ( indexer )
new_weights = list ( )
for weights_list_tuple in zip ( * weights ) :
new_weights . append ( [ np . array ( weights_ ) . mean ( axis = 0 ) for weights_ in zip ( * weights_list_tuple ) ] )
new_weights = [ np . array ( x ) for x in new_weights ]
model_weight_averaged = tf . keras . models . clone_model ( model )
model_weight_averaged . set_weights ( new_weights )
#y_tot_end=np.argmax(y_tot,axis=1)
#print(f1_score(np.argmax(testY,axis=1), y_tot_end, average='macro'))
##best_model.save('model_taza.h5')
model_weight_averaged . save ( os . path . join ( dir_output , ' model_ens_avg ' ) )
for obj in os . listdir ( dir_seg ) :
try :
label_obj = cv2 . imread ( dir_seg + ' / ' + obj )
label_obj_one_hot = get_one_hot ( label_obj , label_obj . shape [ 0 ] , label_obj . shape [ 1 ] , n_classes )
weights + = ( label_obj_one_hot . sum ( axis = 0 ) ) . sum ( axis = 0 )
except :
pass
weights = 1.00 / weights
weights = weights / float ( np . sum ( weights ) )
weights = weights / float ( np . min ( weights ) )
weights = weights / float ( np . sum ( weights ) )
if continue_training :
if model_name == ' resnet50_unet ' :
if is_loss_soft_dice :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { ' soft_dice_loss ' : soft_dice_loss } )
if weighted_loss :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { ' loss ' : weighted_categorical_crossentropy ( weights ) } )
if not is_loss_soft_dice and not weighted_loss :
model = load_model ( dir_of_start_model , compile = True )
elif model_name == ' hybrid_transformer_cnn ' :
if is_loss_soft_dice :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { " PatchEncoder " : PatchEncoder , " Patches " : Patches , ' soft_dice_loss ' : soft_dice_loss } )
if weighted_loss :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { ' loss ' : weighted_categorical_crossentropy ( weights ) } )
if not is_loss_soft_dice and not weighted_loss :
model = load_model ( dir_of_start_model , compile = True , custom_objects = { " PatchEncoder " : PatchEncoder , " Patches " : Patches } )
else :
index_start = 0
if model_name == ' resnet50_unet ' :
model = resnet50_unet ( n_classes , input_height , input_width , weight_decay , pretraining )
elif model_name == ' hybrid_transformer_cnn ' :
model = vit_resnet50_unet ( n_classes , transformer_patchsize , num_patches , input_height , input_width , weight_decay , pretraining )
#if you want to see the model structure just uncomment model summary.
#model.summary()
if not is_loss_soft_dice and not weighted_loss :
model . compile ( loss = ' categorical_crossentropy ' ,
optimizer = Adam ( lr = learning_rate ) , metrics = [ ' accuracy ' ] )
if is_loss_soft_dice :
model . compile ( loss = soft_dice_loss ,
optimizer = Adam ( lr = learning_rate ) , metrics = [ ' accuracy ' ] )
if weighted_loss :
model . compile ( loss = weighted_categorical_crossentropy ( weights ) ,
optimizer = Adam ( lr = learning_rate ) , metrics = [ ' accuracy ' ] )
# generating train and evaluation data
train_gen = data_gen ( dir_flow_train_imgs , dir_flow_train_labels , batch_size = n_batch ,
input_height = input_height , input_width = input_width , n_classes = n_classes )
val_gen = data_gen ( dir_flow_eval_imgs , dir_flow_eval_labels , batch_size = n_batch ,
input_height = input_height , input_width = input_width , n_classes = n_classes )
##img_validation_patches = os.listdir(dir_flow_eval_imgs)
##score_best=[]
##score_best.append(0)
for i in tqdm ( range ( index_start , n_epochs + index_start ) ) :
model . fit_generator (
train_gen ,
steps_per_epoch = int ( len ( os . listdir ( dir_flow_train_imgs ) ) / n_batch ) - 1 ,
validation_data = val_gen ,
validation_steps = 1 ,
epochs = 1 )
model . save ( dir_output + ' / ' + ' model_ ' + str ( i ) )
with open ( dir_output + ' / ' + ' model_ ' + str ( i ) + ' / ' + " config.json " , " w " ) as fp :
json . dump ( _config , fp ) # encode dict into JSON
#os.system('rm -rf '+dir_train_flowing)
#os.system('rm -rf '+dir_eval_flowing)
#model.save(dir_output+'/'+'model'+'.h5')