我想从张量生成掩码。例如:
import numpy as np
import tensorflow as tf
input = tf.Variable(np.array([[0, 0.1], [0.9, 1.0]]))
然后从输入
,我想得到一个具有值的掩码张量:
[[0, 1.0], [1.0, 1.0]]
一种方法是:
output = tf.cast(tf.cast(input, dtype=tf.bool), dtype=tf.float32)
然而,tf.cast
是不可微的,梯度不能反向传播,而我希望这个操作是可微的。我还搜索了其他方法,例如 tf.floor
、tf.where
但它们都是不可区分的。
一种可能的方法是使用这些不可微的方法并为它们定义梯度。但是,我想知道它们的梯度应该是多少才能使反向传播可行(也许只是将梯度设置为 1?),为什么?
正如您所建议的,您可以人为地将梯度粘贴到不可微分的掩码操作中。这是一个示例,其中梯度始终为一个:
import tensorflow as tf
def my_mask(x):
return tf.to_float(tf.greater(x, 0))
def diff_mask(mask_op):
@tf.custom_gradient
def _diff_mask(x):
def grad(dy):
return dy * tf.ones_like(x)
return mask_op(x), grad
return _diff_mask
x = tf.random_normal((5,))
w = tf.random_normal((5,))
m = diff_mask(my_mask)(w)
loss = x * m
g = tf.gradients([loss], [x, w])
sess = tf.InteractiveSession()
sess.run([x, loss] + g)
您当然可以选择其他梯度,例如 sigmoid 的梯度。这真的取决于你想做什么;任何选择都是错误的,因为阈值不可微分,但希望其中一个选择对您有用。
这种技术的一个缺陷是,现在您使用的梯度不是您正在最小化的损失的梯度。这就是为什么人们通常倾向于使用软阈值,而不是硬阈值。例如,如果您打算使用 sigmoid 的梯度,因为您觉得在反馈中需要一个阈值,那么为什么不使用 sigmoid 本身作为掩码呢?
我是一名优秀的程序员,十分优秀!