0
$\begingroup$

I have used a 3D CNN architecture, for detecting the presence of a particular promoter (MGMT), by using FLAIR brain scans. (64 slices per patient). The output is supposed to be binary (0/1).

I have gone through the pre-processing properly, and used stratification after splitting the "train" dataset into train and validation sets, (80-20 ratio). My model initialisation and training kernels look like this:

def get_model(width=128, height=128, depth=64):
"""Build a 3D convolutional neural network model."""

inputs = keras.Input((width, height, depth, 1))

x = layers.Conv3D(filters=64, kernel_size=3, activation="relu")(inputs)
x = layers.MaxPool3D(pool_size=2)(x)
x = layers.BatchNormalization()(x)

x = layers.Conv3D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPool3D(pool_size=2)(x)
x = layers.BatchNormalization()(x)

x = layers.Conv3D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPool3D(pool_size=2)(x)
x = layers.BatchNormalization()(x)

x = layers.Conv3D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPool3D(pool_size=2)(x)
x = layers.BatchNormalization()(x)

x = layers.GlobalAveragePooling3D()(x)
x = layers.Dense(units=512, activation="relu")(x)
x = layers.Dropout(0.3)(x)

outputs = layers.Dense(units=1, activation="sigmoid")(x)

# Define the model.
model = keras.Model(inputs, outputs, name="3dcnn")
return model


# Build model.
model = get_model(width=128, height=128, depth=64)
model.summary()

Compile model:

initial_learning_rate = 0.0001
lr_schedule = keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate, decay_steps=100000, decay_rate=0.96, staircase=True
)
model.compile(
    loss="binary_crossentropy",
    optimizer=keras.optimizers.Adam(learning_rate=lr_schedule),
    metrics=["acc"],
)

# Define callbacks.
checkpoint_cb = keras.callbacks.ModelCheckpoint(
    "Brain_3d_classification.h5", save_best_only=True,monitor = 'val_acc', 
                             mode = 'max', verbose = 1
)
early_stopping_cb = keras.callbacks.EarlyStopping(monitor="val_acc", patience=20,mode = 'max', verbose = 1,
                           restore_best_weights = True)

# Train the model, doing validation at the end of each epoch
epochs = 60
model.fit(
    train_dataset,
    validation_data=valid_dataset,
    epochs=epochs,
    shuffle=True,
    verbose=2,
    callbacks=[checkpoint_cb, early_stopping_cb],
)

This is my first time ever working with a 3D CNN, and I used this keras webpage for the format:https://keras.io/examples/vision/3D_image_classification/

The (max) validation accuracy in my case was about 54%. I tried reducing the initial learning rate , and for 0.00001 I got to a max of 66.7%. For learning rates of 0.00005, 0.00002, I got max accuracy of about 60 and 62%.

Accuracy vs epoch plots for learning rates 0.0001, 0.00005,0.00002 and 0.00001:

0.0001 enter image description here enter image description here enter image description here

It does seem like reducing the initial learning rate has a positive effect on accuracy, although the accuracy is still very low.

What other parameters can I tune to expect a better accuracy? And is it okay to just keep reducing the initial learning rate until we achieve a targeted accuracy?

I know this is a rather broad question, but I am quite confused as to how we should approach increasing the accuracy in the case of CNNs, (that too 3D), where there just seems to be a lot of stuff going on. Do I change something in my initialisations? Add more layers? Or change the parameters? Do I decrease or increase them? With so many things going on, I don't think trying every combination and just keep repeating the training process is an efficient idea...

Full notebook (including pre-processing steps): https://www.kaggle.com/shivamee682003/3d-image-preprocessing-17cd03/edit

$\endgroup$
1
  • $\begingroup$ maybe more dropout layers, in general tuning architecture itself, via hyper-parameter search is possible $\endgroup$
    – Nikos M.
    Commented Oct 11, 2021 at 15:53

1 Answer 1

0
$\begingroup$

Adding more FC layers is also helpful for small data and small image sizes for example after flattening layer as below:

flatten_layer = layers.Flatten()(x)

dense_layer1 = layers.Dense(units=512, activation='relu')(flatten_layer)
dense_layer1 = layers.Dropout(0.4)(dense_layer1)


dense_layer2 = layers.Dense(units=512, activation='relu')(dense_layer1)
dense_layer2 = layers.Dropout(0.4)(dense_layer2)

dense_layer3 = layers.Dense(units=256, activation='relu')(dense_layer2)
dense_layer3 = layers.Dropout(0.4)(dense_layer3)

dense_layer4 = layers.Dense(units=128, activation='relu')(dense_layer3)
dense_layer4 = layers.Dropout(0.4)(dense_layer4)

You can play with dropout rate and the number of neurons in the Dense layer as there is no rule of thumb for them. The following paper might be helpful

https://arxiv.org/pdf/1902.02771.pdf#:~:text=The%20output%20(FC)%20layer%20has,%2C%20and%20CRCHistoPhenotypes%20datasets%2C%20respectively.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.