I am training a neural network when in the forward pass, randomly half of the time a non-differentiable activation is used which rounds activation to either 0 or 1 (binary), and the other half it uses a differentiable function similar to Sigmoid (saturated-Sigmoid to be exact) In the backward pass however, we use the gradient with regard to the differentiable function, even when we have used the non-differentiable discrete one for forward pass. The code I have so far is:
diff_active = tf.math.maximum(sat_sigmoid_term1(feature), sat_sigmoid_term2(feature))
binary_masks = diff_active
rand_cond = tf.random.uniform([1,])
cond = tf.constant(rand_cond, shape=[1,])
if cond <0.5:
with tf.GradientTape() as tape:
non_diff_active = tf.grad_pass_through(tf.keras.layers.Lambda(lambda x: tf.where(tf.math.greater(x,0), x, tf.zeros_like(x))))(feature)
grads = tape.gradient(non_diff_active , feature)
binary_masks = non_diff_active
tf.math.multiply(binary_masks, feature)
My intuition is that this way, the differentiable activation is always applied (and hopefully gradient of it is always included in bacl-prop) and with tf.grad_pass_through() I can apply the non-differentiable activation while replacing it's back-propagation with identity matrix. However, I am not sure if my use of tf.grad_pass_through() or the way I condition of my random variable is correct aand if the behaviour is as intended?