我正在编写一个手工编制的解决方案,用于计算给定数据集中包含的每个图像的Grad-CAM。 下面是代码:
def grad_cam(model, image, _class, layer_name, channel_index):
class_output = model.output[:, _class]
conv_output_layer = model.get_layer(layer_name).output
gradients = K.gradients(class_output, conv_output_layer)[0]
grad_function = K.function([model.input], [conv_output_layer, gradients])
output, grad_val = grad_function([image]) # <== Execution time bottleneck
#code...
return grad_cam
给定一幅图像,一个卷积层和一个通道索引,目的是了解CNN分类器正在查看的位置,以及为什么必须为所有数据集的图像计算Grad-CAM表示的原因。 由于数据集提供了数万张图像,因此在循环中调用grad_cam()
函数:
def visual_attention(df):
#code...
for i in range(0, len(df)):
#code...
heatmap = grad_cam(model, df[i], _class, layer_name, channel_index)
#code...
#code...
其中df
代表整个数据集。 即使前面提到的代码工作得很好,我也注意到grad_cam()
函数的速度减慢,因为每次调用k.gradients()
都会构建一个新的反向传播图。 我做了很多尝试来管理这种情况,但是TensorFlow在每次迭代之后都会继续向它的图中添加新的节点。 经过几百次迭代后,代码变得慢得令人尴尬。 如何应对这种情况? 提前非常感谢!
您应该拆分grad_function
函数的创建并独立使用它,例如:
def grad_cam(model, _class, layer_name, channel_index):
class_output = model.output[:, _class]
conv_output_layer = model.get_layer(layer_name).output
gradients = K.gradients(class_output, conv_output_layer)[0]
grad_function = K.function([model.input], [conv_output_layer, gradients])
return return grad_function
然后只创建一次grad函数的实例:
grad_fn = grad_cam(model, _class, layer_name, channel_index)
然后在循环中调用此函数:
def visual_attention(df):
#code...
for i in range(0, len(df)):
#code...
heatmap = grad_fn(df[i])
#code...
#code...