Home > Mobile >  Class map activation with transfer learning
Class map activation with transfer learning

Time:11-01

I am building a CNN model using Resnet50 to identify to classify 5 objects. The images of the objects were taken on my desk so there is a portion of my desk in every object. The code to initialize the model is, like so,

model = Sequential()

pretrained_model= tf.keras.applications.ResNet50(include_top=False,
                   input_shape=(180,180,3),
                   pooling='avg',classes=5,
                   weights='imagenet')
for layer in pretrained_model.layers:
        layer.trainable=False

model.add(pretrained_model)
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dense(2, activation='softmax'))

I compiled the model and fit it and it works as expected.

The model isn't working great, the predictions are not very accurate. I suspect that the model is being trained on the portions of my desk and I would like to use class activation maps to know if that's true.

The tutorials I have seen have class activation maps code for a model that has been built from scratch. I understand that we need to add a global average pooling layer followed by a dense layer with softmax activation to enable class activations.

The Resnet50 model ends with a global average pooling layer which I found out by running,

pretrained_model.layers

so I simply had to add the dense layer which I added by running,

model.add(pretrained_model)
model.add(Dense(2, activation='softmax'))

but when I print out the summary of this model, I get,

Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
resnet50 (Functional)        (None, 2048)              23587712  
_________________________________________________________________
dense_3 (Dense)              (None, 2)                 4098      
=================================================================
Total params: 23,591,810
Trainable params: 4,098
Non-trainable params: 23,587,712

I am following Laurence Moroney's example and he says we have to extract weights from the global average pooling layer and the dense layer which I am not able to do with the model I just created.

Is there a way to expand the resnet50 (Functional) layer to access the global average pooling layer?

Edit

I am continuing my queries here since it is part of the my actual question, i.e enabling class activation maps with transfer learning.

As mentioned in the comments, I can obtain the last convolution layer by providing,

model.layers[0].layers[-5]

After obtaining the weights of the dense layer and the last conv layer, I tried creating the cam_model, like so,

cam_model  = Model(inputs=(model.layers[0].layers[0].input), outputs=(model.layers[0].layers[-5].output, model.layers[1].output))

which results in this error,

ValueError: Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 180, 180, 3), dtype=tf.float32, name='resnet50_input'), name='resnet50_input', description="created by layer 'resnet50_input'") at layer "resnet50". The following previous layers were accessed without issue: ['conv1_pad', 'conv1_conv', 'conv1_bn', 'conv1_relu', 'pool1_pad', 'pool1_pool', 'conv2_block1_1_conv', 'conv2_block1_1_bn', 'conv2_block1_1_relu', 'conv2_block1_2_conv', 'conv2_block1_2_bn', 'conv2_block1_2_relu', 'conv2_block1_3_conv', 'conv2_block1_0_conv', 'conv2_block1_0_bn', 'conv2_block1_3_bn', 'conv2_block1_add', 'conv2_block1_out', 'conv2_block2_1_conv', 'conv2_block2_1_bn', 'conv2_block2_1_relu', 'conv2_block2_2_conv', 'conv2_block2_2_bn', 'conv2_block2_2_relu', 'conv2_block2_3_conv', 'conv2_block2_3_bn', 'conv2_block2_add', 'conv2_block2_out', 'conv2_block3_1_conv', 'conv2_block3_1_bn', 'conv2_block3_1_relu', 'conv2_block3_2_conv', 'conv2_block3_2_bn', 'conv2_block3_2_relu', 'conv2_block3_3_conv', 'conv2_block3_3_bn', 'conv2_block3_add', 'conv2_block3_out', 'conv3_block1_1_conv', 'conv3_block1_1_bn', 'conv3_block1_1_relu', 'conv3_block1_2_conv', 'conv3_block1_2_bn', 'conv3_block1_2_relu', 'conv3_block1_3_conv', 'conv3_block1_0_conv', 'conv3_block1_0_bn', 'conv3_block1_3_bn', 'conv3_block1_add', 'conv3_block1_out', 'conv3_block2_1_conv', 'conv3_block2_1_bn', 'conv3_block2_1_relu', 'conv3_block2_2_conv', 'conv3_block2_2_bn', 'conv3_block2_2_r...

My model.summary looks like this,

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
resnet50 (Functional)        (None, 2048)              23587712  
_________________________________________________________________
dense (Dense)                (None, 5)                 10245     
=================================================================
Total params: 23,597,957
Trainable params: 10,245
Non-trainable params: 23,587,712

and the first few layers of my model.layers[0].summary() looks like this,

Model: "resnet50"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_2 (InputLayer)            [(None, 180, 180, 3) 0                                            
__________________________________________________________________________________________________
conv1_pad (ZeroPadding2D)       (None, 186, 186, 3)  0           input_2[0][0]                    
__________________________________________________________________________________________________
conv1_conv (Conv2D)             (None, 90, 90, 64)   9472        conv1_pad[0][0]                  
__________________________________________________________________________________________________

I think the graph is getting disconnected at the resnet50 layer but I have no idea where to find it. Can someone please help.

CodePudding user response:

To print out the layers of the resnet model try this: model.layers[0].summary(). If you want to access the GlobalAveragePooling layer, which happens to be the last layer of the model, then try this: global_max_pooling = model.layers[0].layers[-1]. Note, however, that the GlobalAveragePooling layer itself does not have any weights.

  • Related