我使用keras.applications包中的VGG16创建了我的模型图,并使用顺序建模在其上添加了密集和平均的池图层。我不知道如何从这个复合模型中访问类激活映射。这是我的模型定义。
def VGGCAM(nb_classes):
input_tensor = Input(shape=(224,224,3))
model_vgg16_conv =VGG16(weights='imagenet',include_top=False,input_tensor=input_tensor)
model_vgg16_conv.summary()
my_model = Sequential()
inp = model_vgg16_conv.output_shape[1:]
my_model.add(Convolution2D(77, 7,7, activation='relu',border_mode="same",input_shape=inp))
my_model.add(AveragePooling2D((5, 5)))
my_model.add(Flatten())
my_model.add(Dense(nb_classes, activation='softmax'))
my_model.compile(optimizer="sgd", loss='categorical_crossentropy')
my_model = Model(input=[model_vgg16_conv.input], output=[my_model(model_vgg16_conv.output)])
my_model.summary()
return my_model
我的最终模型摘要是
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 224, 224, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
sequential_1 (Sequential) (None, 10) 1932633
答案 0 :(得分:0)
您可以可视化类激活图(CAM)使用Keras。 但是,网络应该具有全局平均池层以获得CAM。 请按照以下示例:
https://jacobgil.github.io/deeplearning/class-activation-maps
答案 1 :(得分:0)
这是一种急切执行的方法,在tensorflow 2中效果很好,与禁用急切执行相比,它工作更快且错误更少。
gmodel= VGG16()
input_tensor_shape = gmodel.layers[0].input.shape
image_shape = (input_tensor_shape[1],input_tensor_shape[2])
for layer in gmodel.layers[::-1]:
if isinstance(layer,tensorflow.keras.layers.Conv2D):
convolution_shape = layer.output[-1]
convolution_name = layer.name
break
heatmap_model = Model(
[gmodel.inputs], [gmodel.get_layer(convolution_name).output, gmodel.output])
img = cv2.imread(str(gimg_path))
if img.shape[2] ==1:
img = np.dstack([img, img, img])
img = cv2.resize(img, image_shape)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_norm = img.astype(np.float32)/255.0
img_norm = np.expand_dims(img_norm,axis=0)
last_conv = gmodel.get_layer(str(convolution_name))
with tensorflow.GradientTape() as tape:
inputs = tensorflow.cast(img_norm, tensorflow.float32)
(conv_output, predictions) = heatmap_model(inputs)
loss = predictions[:, np.argmax(predictions[0])]
grads = tape.gradient(loss, conv_output)
castConvOutputs = tensorflow.cast(conv_output > 0, "float32")
castGrads = tensorflow.cast(grads > 0, "float32")
guidedGrads = castConvOutputs * castGrads * grads
convOutputs = conv_output[0]
guidedGrads = guidedGrads[0]
weights = tensorflow.reduce_mean(guidedGrads, axis=(0, 1))
cam = tensorflow.reduce_sum(tensorflow.multiply(weights, convOutputs), axis=-1)
(w, h) = (img_norm.shape[2], img_norm.shape[1])
heatmap = cv2.resize(cam.numpy(), (w, h))
heatmap0 = heatmap
numer = heatmap0 - np.min(heatmap0)
denom = (heatmap0.max() - heatmap0.min()) + 1e-100
heatmap0 = numer / denom
heatmap0 = (heatmap0 * 255).astype("uint8")
heatmap1 = cv2.applyColorMap(heatmap0, cv2.COLORMAP_COOL)
output = cv2.addWeighted(img, 0.5, heatmap1, 0.5, 0)
信用:基于Adrian Rosebrock的代码