Skip to main content

Breast Histopathology Image Segmentation Part 3

Guangzhou, China

Github

Based on Breast Histopathology Images by Paul Mooney. Invasive Ductal Carcinoma (IDC) is the most common subtype of all breast cancers. To assign an aggressiveness grade to a whole mount sample, pathologists typically focus on the regions which contain the IDC. As a result, one of the common pre-processing steps for automatic aggressiveness grading is to delineate the exact regions of IDC inside of a whole mount slide. Can recurring breast cancer be spotted with AI tech? - BBC News

Model Creation - ResNet50

Start by loading the pre-trained model:

./train_ResNet50_32_20k.py

# Loading the ResNet50, ensuring the head Full Connected layers are left off / removed
baseModel = ResNet50(weights="imagenet", include_top=False, input_tensor=Input(shape=(48, 48, 3)))

Construct the head of the model that will be placed on top of the the base model:

## Flattening is converting the data into a 1-dimensional array for inputting it to the next layer. 
## We flatten the output of the convolutional layers to create a single long feature vector.
### Average pooling computes the average of the elements present in the region of feature map covered by the filter.
#### ReLU stands for Rectified Linear Unit.
#### The main advantage of using the ReLU function over other activation functions is that it does not activate all the neurons at the same time.
## Dropout is a technique where randomly selected neurons are ignored during training.

headModel = baseModel.output
headModel = AveragePooling2D(pool_size=(7, 7), padding="same")(headModel)
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(256, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)
headModel = Dense(len(config.CLASSES), activation="softmax")(headModel)

# Placing the head model on top of the base model
model = Model(inputs=baseModel.input, outputs=headModel)

# Loop over all the layers of the base model and freeze them so that they are
# not updated during the training process
for layer in baseModel.layers:
layer.trainable = False

Model Creation - Custom CNN Model

Construction

Instead of downloading a pre-trained model we can build our own. The layers of the Custom Model are constructed according to:

utils/conv_bc_model.py

class BC_Model:
@staticmethod
def build(width, height, depth, classes):

# Lets first initialize the model with input shape to be "channels last" and channel's dimension
model = Sequential()
inputShape = (height, width, depth)
chanDim = -1

# If we are using "channels first", then let's update the input shape and channel's dimension
if K.image_data_format() == "channels_first":
inputShape = (depth, height, width)
chanDim = 1

# (CONV2D => RELU => BatchNormalization ) * 1 => POOL => DROPOUT
model.add(Conv2D(32, (3, 3), padding="same", input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# (CONV2D => RELU => BatchNormalization ) * 2 => POOL => DROPOUT
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# (CONV2D => RELU => BatchNormalization ) * 3 => POOL => DROPOUT
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# (CONV2D => RELU => BatchNormalization ) * 4 => POOL => DROPOUT
model.add(Conv2D(256, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(256, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(256, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(256, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

# FC => RELU layers => BatchNormalization => DROPOUT
model.add(Flatten())
model.add(Dense(512))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))

# Dense layer and softmax classifier
model.add(Dense(classes))
model.add(Activation("softmax"))

# Returning the created network architecture
return model

We can use this function to build the model:

./train_CustomModel_32_conv_20k.py

# Building the model
print("Building the model")
model = BC_Model.build(width=48, height=48, depth=3, classes=2)