I am trying to implement a Machine Learning Model for MRI scan diagnosis. I have Inputs of shape (x, 256, 256, 3), where we have 3 color channels and where x is the number of slices in a sequence. I read the MRNet paper and I want to implement a similar architecture in TensorFlow Keras. Instead of using the AlexNet feature extractor, I'd like to use VGG16.
The model architecture in the paper:
The primary building block of our prediction system is MRNet, a convolutional neural network (CNN) mapping a 3-dimensional MRI series to a probability [15] (Fig 2). The input to MRNet has dimensions s × 3 × 256 × 256, where s is the number of images in the MRI series (3 is the number of color channels). First, each 2-dimensional MRI image slice was passed through a feature extractor based on AlexNet to obtain a s × 256 × 7 × 7 tensor containing features for each slice. A global average pooling layer was then applied to reduce these features to s × 256. We then applied max pooling across slices to obtain a 256-dimensional vector, which was passed to a fully connected layer and sigmoid activation function to obtain a prediction in the 0 to 1 range.
So far so good. I have a sequential model, added the feature extractor as the first step, then apply a GlobalAveragePooling2D() to reduce features to shape (x, 512). Then I must MaxPool across the slices but I have no approach for this problem.
feature_extractor = VGG16(weights='imagenet', include_top=False, input_shape=(256, 256, 3))
model = Sequential()
model.add(feature_extractor) #output shape: (x, 8, 8, 512)
model.add(GlobalAveragePooling2D()) #output shape: (x, 512)
# Here i have to add a Layer witch Pools over the slices.
model.add( ) #output shape(1, 512)
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
The example Scan has a shape of (44, 256, 256, 3). When it runs through the VGG16 its features have the Dimension of (44, 8, 8, 512). After GlobalAverage Pooling I got (44, 512). This 2-D Array must then somehow be transformed into the shape of (1, 512). I mean if I do the operation on a simple 2-D NumPy array I need a function like np.max over the 0-axis
np.max(x, axis=0)
Maybe you can give me a hint or have an approach for this. Thanks a lot for your help :)
################################################################################ Edit: 01.05.2021
I played around with your approach @Aaron Keesing, but fitting the model does not train it at all somehow. Ater 25 epochs i still have the same accuracy. And the accuracy is the distribution over my 2 classes (i was just training on coronal plane and abnormal)
In this case for example i have 500 cases, and 80% of the cases do have an abnormality and 20% doesn't.
# Dataset train, overall 500 cases
Absolute:
abnormal acl meniscus
1 0 0 184
1 118
0 0 0 100
1 1 1 63
0 35
dtype: int64
Relative:
abnormal acl meniscus
1 0 0 0.368
1 0.236
0 0 0 0.200
1 1 1 0.126
0 0.070
###########################################################
# Dataset valid, overall 100 cases
Absolute:
abnormal acl meniscus
1 1 1 27
0 0 0 25
1 1 0 23
0 0 20
1 5
dtype: int64
Relative:
abnormal acl meniscus
1 1 1 0.27
0 0 0 0.25
1 1 0 0.23
0 0 0.20
1 0.05
