python_for_microscopists icon indicating copy to clipboard operation
python_for_microscopists copied to clipboard

Binary focal loss

Open sehreen1234 opened this issue 3 years ago • 0 comments

the loss starts at 0.03 and the Jaccard coefficient does not increase and stays 0.018 what could possibly be wrong The code: model: def conv_block(x, filter_size, size, dropout=0.6, batch_norm=True):

conv = layers.Conv2D(size, (filter_size, filter_size), padding="same")(x)
if batch_norm is True:
    conv = layers.BatchNormalization(axis=3)(conv)
conv = layers.Activation("relu")(conv)

conv = layers.Conv2D(size, (filter_size, filter_size), padding="same")(conv)
if batch_norm is True:
    conv = layers.BatchNormalization(axis=3)(conv)
conv = layers.Activation("relu")(conv)

if dropout > 0:
    conv = layers.Dropout(dropout)(conv)

return conv

def repeat_elem(tensor, rep): # lambda function to repeat Repeats the elements of a tensor along an axis #by a factor of rep. # If tensor has shape (None, 256,256,3), lambda will return a tensor of shape #(None, 256,256,6), if specified axis=3 and rep=2.

 return layers.Lambda(lambda x, repnum: K.repeat_elements(x, repnum, axis=3),
                      arguments={'repnum': rep})(tensor)

def res_conv_block(x, filter_size, size, dropout, batch_norm=True): ''' Residual convolutional layer. Two variants.... Either put activation function before the addition with shortcut or after the addition (which would be as proposed in the original resNet).

1. conv - BN - Activation - conv - BN - Activation 
                                      - shortcut  - BN - shortcut+BN
                                      
2. conv - BN - Activation - conv - BN   
                                 - shortcut  - BN - shortcut+BN - Activation                                     

Check fig 4 in https://arxiv.org/ftp/arxiv/papers/1802/1802.06955.pdf
'''

conv = layers.Conv2D(size, (filter_size, filter_size), padding='same')(x)
if batch_norm is True:
    conv = layers.BatchNormalization(axis=3)(conv)
conv = layers.Activation('relu')(conv)

conv = layers.Conv2D(size, (filter_size, filter_size), padding='same')(conv)
if batch_norm is True:
    conv = layers.BatchNormalization(axis=3)(conv)
#conv = layers.Activation('relu')(conv)    #Activation before addition with shortcut
if dropout > 0:
    conv = layers.Dropout(dropout)(conv)

shortcut = layers.Conv2D(size, kernel_size=(1, 1), padding='same')(x)
if batch_norm is True:
    shortcut = layers.BatchNormalization(axis=3)(shortcut)

res_path = layers.add([shortcut, conv])
res_path = layers.Activation('relu')(res_path)    #Activation after addition with shortcut (Original residual block)
return res_path

def gating_signal(input, out_size, batch_norm=True): """ resize the down layer feature map into the same dimension as the up layer feature map using 1x1 conv :return: the gating feature map with the same dimension of the up layer feature map """ x = layers.Conv2D(out_size, (1, 1), padding='same')(input) if batch_norm: x = layers.BatchNormalization()(x) x = layers.Activation('relu')(x) return x

def attention_block(x, gating, inter_shape): shape_x = K.int_shape(x) shape_g = K.int_shape(gating)

Getting the x signal to the same shape as the gating signal

theta_x = layers.Conv2D(inter_shape, (2, 2), strides=(2, 2), padding='same')(x)  # 16
shape_theta_x = K.int_shape(theta_x)

Getting the gating signal to the same number of filters as the inter_shape

phi_g = layers.Conv2D(inter_shape, (1, 1), padding='same')(gating)
upsample_g = layers.Conv2DTranspose(inter_shape, (3, 3),
                             strides=(shape_theta_x[1] // shape_g[1], shape_theta_x[2] // shape_g[2]),
                             padding='same')(phi_g)  # 16

concat_xg = layers.add([upsample_g, theta_x])
act_xg = layers.Activation('relu')(concat_xg)
psi = layers.Conv2D(1, (1, 1), padding='same')(act_xg)
sigmoid_xg = layers.Activation('sigmoid')(psi)
shape_sigmoid = K.int_shape(sigmoid_xg)
upsample_psi = layers.UpSampling2D(size=(shape_x[1] // shape_sigmoid[1], shape_x[2] // shape_sigmoid[2]))(sigmoid_xg)  # 32

#upsample_psi = repeat_elem(upsample_psi, shape_x[3])

y = layers.multiply([upsample_psi, x])

result = layers.Conv2D(shape_x[3], (1, 1), padding='same')(y)
result_bn = layers.BatchNormalization()(result)
return result_bn

def Attention_ResUNet(input_shape, NUM_CLASSES=1, dropout_rate=0.8, batch_norm=True): ''' Rsidual UNet, with attention

'''
# network structure
FILTER_NUM = 64 # number of basic filters for the first layer
FILTER_SIZE = 3 # size of the convolutional filter
UP_SAMP_SIZE = 2 # size of upsampling filters
# input data
# dimension of the image depth
inputs = layers.Input(input_shape, dtype=tf.float32)
axis = 3

# Downsampling layers
# DownRes 1, double residual convolution + pooling
conv_128 = res_conv_block(inputs, FILTER_SIZE, FILTER_NUM, dropout_rate, batch_norm)
pool_64 = layers.MaxPooling2D(pool_size=(2,2))(conv_128)
# DownRes 2
conv_64 = res_conv_block(pool_64, FILTER_SIZE, 2*FILTER_NUM, dropout_rate, batch_norm)
pool_32 = layers.MaxPooling2D(pool_size=(2,2))(conv_64)
# DownRes 3
conv_32 = res_conv_block(pool_32, FILTER_SIZE, 4*FILTER_NUM, dropout_rate, batch_norm)
pool_16 = layers.MaxPooling2D(pool_size=(2,2))(conv_32)
# DownRes 4
conv_16 = res_conv_block(pool_16, FILTER_SIZE, 8*FILTER_NUM, dropout_rate, batch_norm)
pool_8 = layers.MaxPooling2D(pool_size=(2,2))(conv_16)
# DownRes 5, convolution only
conv_8 = res_conv_block(pool_8, FILTER_SIZE, 16*FILTER_NUM, dropout_rate, batch_norm)

# Upsampling layers
# UpRes 6, attention gated concatenation + upsampling + double residual convolution
gating_16 = gating_signal(conv_8, 8*FILTER_NUM, batch_norm)
att_16 = attention_block(conv_16, gating_16, 8*FILTER_NUM)
up_16 = layers.UpSampling2D(size=(UP_SAMP_SIZE, UP_SAMP_SIZE), data_format="channels_last")(conv_8)
up_16 = layers.concatenate([up_16, att_16], axis=axis)
up_conv_16 = res_conv_block(up_16, FILTER_SIZE, 8*FILTER_NUM, dropout_rate, batch_norm)
# UpRes 7
gating_32 = gating_signal(up_conv_16, 4*FILTER_NUM, batch_norm)
att_32 = attention_block(conv_32, gating_32, 4*FILTER_NUM)
up_32 = layers.UpSampling2D(size=(UP_SAMP_SIZE, UP_SAMP_SIZE), data_format="channels_last")(up_conv_16)
up_32 = layers.concatenate([up_32, att_32], axis=axis)
up_conv_32 = res_conv_block(up_32, FILTER_SIZE, 4*FILTER_NUM, dropout_rate, batch_norm)
# UpRes 8
gating_64 = gating_signal(up_conv_32, 2*FILTER_NUM, batch_norm)
att_64 = attention_block(conv_64, gating_64, 2*FILTER_NUM)
up_64 = layers.UpSampling2D(size=(UP_SAMP_SIZE, UP_SAMP_SIZE), data_format="channels_last")(up_conv_32)
up_64 = layers.concatenate([up_64, att_64], axis=axis)
up_conv_64 = res_conv_block(up_64, FILTER_SIZE, 2*FILTER_NUM, dropout_rate, batch_norm)
# UpRes 9
gating_128 = gating_signal(up_conv_64, FILTER_NUM, batch_norm)
att_128 = attention_block(conv_128, gating_128, FILTER_NUM)
up_128 = layers.UpSampling2D(size=(UP_SAMP_SIZE, UP_SAMP_SIZE), data_format="channels_last")(up_conv_64)
up_128 = layers.concatenate([up_128, att_128], axis=axis)
up_conv_128 = res_conv_block(up_128, FILTER_SIZE, FILTER_NUM, dropout_rate, batch_norm)

# 1*1 convolutional layers

conv_final = layers.Conv2D(NUM_CLASSES, kernel_size=(1,1))(up_conv_128)
conv_final = layers.BatchNormalization(axis=axis)(conv_final)
conv_final = layers.Activation('sigmoid')(conv_final)  #Change to softmax for multichannel

# Model integration
model = models.Model(inputs, conv_final, name="AttentionResUNet")
return model

input_shape = (256,256,1) model=Attention_ResUNet(input_shape, NUM_CLASSES=1, dropout_rate=0.6, batch_norm=True) #model.summary()

DATA:

image_directory = '/content/drive/MyDrive/MRA/new/train/images/' mask_directory = '/content/drive/MyDrive/MRA/new/train/masks/'

SIZE = 256 image_dataset = [] #Many ways to handle data, you can use pandas. Here, we are using a list format.
mask_dataset = [] #Place holders to define add labels. We will add 0 to all parasitized images and 1 to uninfected.

images = sorted(os.listdir(image_directory)) for i, image_name in enumerate(images): #Remember enumerate method adds a counter and returns the enumerate object if (image_name.split('.')[1] == 'png'): #print(image_directory+image_name) image = cv2.imread(image_directory+image_name, 1) image = Image.fromarray(image) image = image.resize((SIZE, SIZE)) image_dataset.append(np.array(image))

#Iterate through all images in Uninfected folder, resize to 64 x 64 #Then save into the same numpy array 'dataset' but with label 1

masks = sorted(os.listdir(mask_directory)) for i, image_name in enumerate(masks): if (image_name.split('.')[1] == 'png'): image = cv2.imread(mask_directory+image_name, 0) image = Image.fromarray(image) image = image.resize((SIZE, SIZE)) mask_dataset.append(np.array(image))

#Normalize images image_dataset = np.array(image_dataset)/255. #D not normalize masks, just rescale to 0 to 1. mask_dataset = np.expand_dims((np.array(mask_dataset)),3) /255.

from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(image_dataset, mask_dataset, test_size = 0.05, random_state = 0)

#Sanity check, view few mages import random import numpy as np image_number = random.randint(0, len(X_train)) plt.figure(figsize=(12, 6)) plt.subplot(121) plt.imshow(np.reshape(X_train[image_number], (256, 256, 3)), cmap='gray') plt.subplot(122) plt.imshow(np.reshape(y_train[image_number], (256, 256)), cmap='gray') plt.show()

TRAINING: IMG_HEIGHT = X_train.shape[1] IMG_WIDTH = X_train.shape[2] IMG_CHANNELS = X_train.shape[3] num_labels = 1 #Binary input_shape = (IMG_HEIGHT,IMG_WIDTH,IMG_CHANNELS) batch_size = 16 #from focal_loss import BinaryFocalLoss

''' Attention Residual Unet ''' att_res_unet_model = Attention_ResUNet(input_shape)

att_res_unet_model.compile(optimizer=Adam(lr = 1e-2), loss=BinaryFocalLoss(gamma=2), metrics=['accuracy', jacard_coef])

#att_res_unet_model.compile(optimizer=Adam(lr = 1e-3), loss='binary_crossentropy',

metrics=['accuracy', jacard_coef])

#print(att_res_unet_model.summary())

start3 = datetime.now() att_res_unet_history = att_res_unet_model.fit(X_train, y_train, verbose=1, batch_size = batch_size, validation_data=(X_test, y_test ), shuffle=False, epochs=50) stop3 = datetime.now()

#Execution time of the model execution_time_AttResUnet = stop3-start3 #print("Attention ResUnet execution time is: ", execution_time_AttResUnet)

att_res_unet_model.save('AttResUnet.hdf5')

sehreen1234 avatar Nov 16 '21 18:11 sehreen1234