I work on medical images of kidneys scans. My goal would be to differentiate normal ones from pathologic ones (binary problem). Normal images have regular bilateral kidney contours, whereas abnormal cases can be patchy with foci of decreased intensity or defects.
Here are examples :
- Normal kidney scan, with regular bilateral kidney contours
- Pathologic right kidney, with irregular contours
I tried to train a convolutional neural network to differentiate normal and pathologic scans. I have 824 images for my training set (552 normal, 272 pathologic).
The best results I get is by pre-treating images like this :
- Cropping to have, from 1 picture, 2 pictures of unique kidney
- Flipping right kidneys to only have "left" kidneys
- Gaussian filter to limit noise and smooth the contours
- Otsu threshold to binarise my pictures.
This is the kind of pictures I get after this :
Unfortunately, the best results I get in validation is like ~ 85 % of accuracy. I'd like to reach at least 90-95 %.
Here is my code, with tensorflow :
model = Sequential()
model.add(Conv2D(filters=16, kernel_size=(3, 3), padding='same', activation='relu', input_shape = [x_train.shape[1], x_train.shape[2], x_train.shape[3]]))
model.add(MaxPool2D(pool_size=(2,2), strides=2, padding='valid'))
model.add(Conv2D(filters=16, kernel_size=(3, 3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2), strides=2, padding='valid'))
model.add(Conv2D(filters=16, kernel_size=(3, 3), padding='same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2), strides=2, padding='valid'))
model.add(Flatten())
model.add(Dense(units = 16, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(units = 1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
es = EarlyStopping(monitor = 'val_accuracy', mode = 'max', verbose = 1, patience = 6)
mc = ModelCheckpoint('best_model.h5', monitor='val_accuracy', mode='max', verbose=1, save_best_only=True)
history = model.fit(x_train, y_train, epochs=50, batch_size=128, verbose=1, validation_split=0.3, callbacks = [es, mc])
I get more or less the same results when I change number layers, of neurons by layer (from 16 to 128), dropout between each layer, batch size etc...
So I'm wondering if I am using the good method. I also tried anomaly detection algorithm with autoencoders but the pictures seemed to close to get appropriate detection...
So my question is :
- Do you see something I could do to improve my CNN algorithm ?
- Do you know another algorithm I should try ? Like a one that would be good on detection of irregular contours ?
Thank you very much for your help !