I am trying to predict 3D medical brain images based on their assessment score using CNN, however the accuracy scores I have received were within a range of numbers (ex: there are 7 possible test scores: 1, 1.5, 2, 2.5, 3, 4, 5 and the output only gives predictions within 1-1.5 range)
I have resized, normalized, and separated the images into train (66 imgs), test (22 imgs), and validation (22 imgs) sets. Because there are so few images, I have added a custom 3D image augmentation (from github) so the total number of images increased to 10x what I originally had.
I have tried changing most, if not all, the parameters (batch size, optimizer, learning rate, simpler/complex nn's, activation, loss, etc) within my network to no avail. I have also looked online for similar problems in hope that someone has had the same issue and solved it.
Here is an example image that I am using:
the size of this image is (96, 96, 96) and a strip of its array value is (after normalizing them):
[0.54124768 0.59549533 0.61464823 0.59833751 0.50441322 0.33578409
0.40528049 0.4359369 0.39544678 0.32074109 0.20008253 0.28538722
0.27870766 0.37098099 0.13504691 0.2372147 0.4171059 0.56398624
0.38187722 0.71896363 0.44387385 0.41523819 0.31195372 0.10586056
0.12634818 0.13454185 0.57811427 0.6465261 0.61814963 0.61493715]
After preprocessing steps, I fed this into my CNN model:
batch_size = 3
model = Sequential()
model.add(Conv3D(32, [3, 3, 3], padding='same', activation='relu',
input_shape=input_size))
model.add(Conv3D(32, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))
model.add(Conv3D(64, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(64, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))
model.add(Dropout(0.5))
model.add(Conv3D(128, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(128, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(128, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))
model.add(Conv3D(256, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(256, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(256, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='linear'))
opt = optimizers.Adam(lr=1e-6)
model.compile(loss='mean_squared_logarithmic_error', optimizer=opt, metrics=['accuracy'])
train_datagen = customImageDataGenerator(shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
val_datagen = customImageDataGenerator()
test_datagen = customImageDataGenerator()
training_set = train_datagen.flow(x_train, y_train, batch_size=batch_size, shuffle=True)
validation_set = val_datagen.flow(x_val, y_val, batch_size=batch_size, shuffle=False)
testing_set = test_datagen.flow(x_test, y_test, batch_size=batch_size, shuffle=False)
earlystop = EarlyStopping(monitor='val_loss', patience=30)
history = model.fit(
training_set,
steps_per_epoch = len(x_train)//batch_size,
epochs = 50,
#callbacks = [earlystop],
validation_data = validation_set,
validation_steps = len(x_val)//batch_size
)
I created a custom accuracy check to visualize the outputs which are:
Predicted score: [1.8405123] True score: 3.0
Predicted score: [1.4033222] True score: 3.0
Predicted score: [1.4690828] True score: 1.0
Predicted score: [1.5127727] True score: 3.0
Predicted score: [1.6159409] True score: 1.0
Predicted score: [1.4333361] True score: 1.5
Predicted score: [1.7470968] True score: 3.0
Predicted score: [1.2196972] True score: 1.5
Predicted score: [1.5940914] True score: 4.0
Predicted score: [1.4052064] True score: 1.0
Predicted score: [1.5127727] True score: 1.0
Predicted score: [1.4584785] True score: 1.0
Predicted score: [1.7860543] True score: 3.0
Predicted score: [1.4752649] True score: 2.5
Predicted score: [1.8568267] True score: 1.0
Predicted score: [1.4793051] True score: 3.0
Predicted score: [1.395096] True score: 2.5
Predicted score: [1.6011616] True score: 4.0
Predicted score: [1.9094267] True score: 1.0
Predicted score: [1.6322718] True score: 1.0
Predicted score: [1.7284409] True score: 4.0
Predicted score: [1.5262214] True score: 1.5
Out: 0.09090909090909091
As you can see, the predicted values fall within the 1-2 range even though there are test scores at the 2.5, 3, 4, and 5 range.
print(y_pred.min(), y_pred.max())
1.2196972 1.9094267
Finally, here are my graphs:
As you can see, the loss decreases beautifully, but the accuracy freezes midway and I am not sure what the cause may be.
Sorry for the long post, but I would appreciate any answers, thank you!


