我想将 Keras 的 Grad-CAM 与我自己的 CNN 模型结合使用。我遵循了这个 https://keras.io/examples/vision/grad_cam/ 函数 make_gradcam_heatmap 也来自其中。我是 CNN 新手,所以我可能会遗漏一些明显的东西,但为什么它在我运行模型时无法识别?
这是我的代码:
import numpy as np
import os
import tensorflow as tf
import keras
from tensorflow.keras.models import load_model
import cv2
from tensorflow.keras.models import Model
os.environ["KERAS_BACKEND"] = "tensorflow"
from IPython.display import Image, display
import matplotlib as mpl
import matplotlib.pyplot as plt
img_path = '/Users/.../image_1.npy'
model = load_model('/Users/.../particle_classifier_model.h5')
model_builder = keras.applications.xception.Xception
preprocess_input = keras.applications.xception.preprocess_input
decode_predictions = keras.applications.xception.decode_predictions
image = np.load(img_path)
img_size = image.shape # should be an array of shape (240, 146)
def make_gradcam_heatmap(img_array, model, last_conv_layer_name, pred_index=None):
# First, we create a model that maps the input image to the activations
# of the last conv layer as well as the output predictions
grad_model = keras.models.Model(
model.inputs, [model.get_layer(last_conv_layer_name).output, model.output]
)
# Then, we compute the gradient of the top predicted class for our input image
# with respect to the activations of the last conv layer
with tf.GradientTape() as tape:
last_conv_layer_output, preds = grad_model(img_array)
if pred_index is None:
pred_index = tf.argmax(preds[0])
class_channel = preds[:, pred_index]
# This is the gradient of the output neuron (top predicted or chosen)
# with regard to the output feature map of the last conv layer
grads = tape.gradient(class_channel, last_conv_layer_output)
# This is a vector where each entry is the mean intensity of the gradient
# over a specific feature map channel
pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))
# We multiply each channel in the feature map array
# by "how important this channel is" with regard to the top predicted class
# then sum all the channels to obtain the heatmap class activation
last_conv_layer_output = last_conv_layer_output[0]
heatmap = last_conv_layer_output @ pooled_grads[..., tf.newaxis]
heatmap = tf.squeeze(heatmap)
# For visualization purpose, we will also normalize the heatmap between 0 & 1
heatmap = tf.maximum(heatmap, 0) / tf.math.reduce_max(heatmap)
return heatmap.numpy()
last_conv_layer_name = "max_pooling2d_4"
image = image.reshape(1, 240, 146, 1)
preds = model.predict(image)
model.layers[-1].activation = None
heatmap = make_gradcam_heatmap(image, model, last_conv_layer_name)
plt.matshow(heatmap)
plt.show()
我的数据是维度为 (240, 146) 的 numpy 数组,CNN 将其作为输入。
想通了。添加
inputs = tf.keras.Input(shape=(240, 146, 1))
outputs = model(inputs)
并将
shape
替换为模型所采用的任何尺寸。