python - 替换 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 实现中实现引导式反向传播。
解决方案
推荐阅读
- arrays - 使用惰性 var 并且 Xcode 仍然说不能使用实例,属性初始化程序在“自我”之前运行?
- angular - 即使在尝试了多种方式之后,GitLab 管道也经常失败
- rabbitmq - 如何在 MQ 上捕获错误请求?
- regex - 设置正则表达式的优先级
- angular - 动态设置 scss 变量 angular ionic
- python - 如何使用 XPath 查找标题包含单引号和双引号的元素?
- intellij-idea - IntelliJ - 仅更改项目菜单的文本大小
- azure - 在 Azure 应用服务中更改系统日期?
- python - 重命名 groupby 的列名并使用 Pandas 计算结果
- android - 单击项目后,recyclerview 中的项目数量会自行增加