提问者:小点点

如何在Keras中加速循环内的Grad-CAM计算?


我正在编写一个手工编制的解决方案,用于计算给定数据集中包含的每个图像的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在每次迭代之后都会继续向它的图中添加新的节点。 经过几百次迭代后,代码变得慢得令人尴尬。 如何应对这种情况? 提前非常感谢!


共1个答案

匿名用户

您应该拆分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...