Как вы предложили, вы можете искусственно прикрепить градиент к операции маскирования, которая не будет дифференцируемой.Вот пример, где градиент всегда один:
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)
Конечно, вы можете выбрать другой градиент, например, градиент сигмовидной.Это действительно зависит от того, что вы хотите сделать;любой выбор будет неправильным, так как пороговое значение не дифференцируемо, но, надеюсь, один из вариантов будет вам полезен.
Подводным камнем такого рода техники является то, что теперь используемый вами градиент не является градиентом потери, которую высводятся к минимуму.Вот почему люди обычно используют мягкие пороги, а не жесткие пороги.Например, если вы намереваетесь использовать градиент сигмоиды, потому что чувствуете, что вам нужен порог в обратной связи, то почему бы не использовать саму сигмоиду в качестве маски?