首页 > 解决方案 > 替换 Keras 层的反向传播功能

问题描述

我正在使用yolo v3 keras 实现,并希望添加一个引导反向传播模块来进一步分析网络的行为。

在 yolo.py 文件中,我添加了这个函数来尝试计算反向传播:

def propb_guided(self, image, layer_index):
    from tensorflow.python.ops import nn_ops, gen_nn_ops
    from tensorflow.python.framework import ops
    box_confidence = self.yolo_model.layers[layer_index].output[..., 4:5]
    box_class_probs = self.yolo_model.layers[layer_index].output[...,5:]

    #box_class_probs = tf.Print(box_class_probs, [tf.shape(box_class_probs)], message="box class probs")
    scores = tf.reduce_sum(box_class_probs[0] * box_confidence[0], axis=2)
    #scores = tf.contrib.layers.flatten(scores)
    print(self.yolo_model.input.get_shape(), "input blabal")
    scores = tf.Print(scores, [tf.shape(scores)], message="scores")
    #grads = tf.map_fn(lambda x: tf.gradients(x, image)[0], tf.contrib.layers.flatten(scores), dtype=tf.float32)
    # gradients are the 1,1,w,h,c shape, c = 3 because RGB

    grads = tf.reduce_mean(tf.gradients(scores, self.yolo_model.input)[0][0], axis=2)
    grads = tf.Print(grads, [tf.shape(grads)], message="grad shape")

    # prepare image for forward prop
    if self.model_image_size != (None, None):
        assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required'
        assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required'
        boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
    else:
        new_image_size = (image.width - (image.width % 32),
                          image.height - (image.height % 32))
        boxed_image = letterbox_image(image, new_image_size)
    image_data = np.array(boxed_image, dtype='float32')

    print(image_data.shape)
    image_data /= 255.
    image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

    # replace all relu layers with guided relu:
    # TODO replacing backprop layers doesn't work. The gradient override map doesnt work in this case
    @ops.RegisterGradient("GuidedReluBP")
    def _GuidedReluGrad(op, grad):
        #return tf.where(0. < grad, gen_nn_ops.relu_grad(grad, op.outputs[0]), tf.zeros(tf.shape(grad)))
        return 100000000

    tf_graph = K.get_session().graph
    layers = [op.name for op in tf_graph.get_operations() if op.type=="Maximum"]
    print(layers, "layers are")
    with tf_graph.gradient_override_map({'Maximum': 'GuidedReluBP'}):

        activation = sess.run(grads, feed_dict={
            self.yolo_model.input: image_data,
            self.input_image_shape: [image.size[1], image.size[0]], 
            K.learning_phase(): 0})

        return activation

现在,该函数获取最后一层(形状 (?, ?, 255)) ,并将第 5 个过滤器(框置信度)与类 logits(过滤器 6 到 80,称为 box_class_probs)相乘。然后它将所有过滤器的乘积相加并将其存储在分数张量中。

然后它根据分数计算每个像素的梯度,相对于一些输入图像,并将其存储在 grads 中(tf.Print 的 grads 具有形状 (416,416),即输入图像的宽度和高度)。

最后(评论是'用引导relu替换所有relu层),我想得到所有泄漏的relu keras层,并替换它的反向传播机制。我注意到 keras 泄漏的 relu 层最后有一个“最大”操作,所以我尝试用我所做的引导式 relu 操作替换每个最大操作。虽然这种方法行不通。相反,无论我是否实现 RegisterGradient 代码,此函数返回的激活变量都没有影响。

如何替换某些 keras 图中每个泄漏 relu 的反向传播机制?这样我就可以在 keras yolo v3 实现中实现引导式反向传播。

标签: pythontensorflowmachine-learningkerasconv-neural-network

解决方案


推荐阅读