python - 我应该使用什么激活函数来强制执行舍入行为
问题描述
我需要一个激活函数来舍入我的张量。
函数 round() 的导数(梯度)为 0(或在 tensorflow 中为 None),这使得它无法用作激活函数。
我正在寻找一个强制执行类似舍入行为的函数,以便我的模型的结果不只是近似一个数字。(因为我的标签是整数)
我知道公式: tanh ○ sigmoid 用于强制 {-1, 0, 1} 数字仅流经模型,所以是否有一些可导出的函数组合来模拟舍入行为?
解决方案
如果您想在实线上进行近似舍入,可以执行以下操作:
def approx_round(x, steepness=1):
floor_part = tf.floor(x)
remainder = tf.mod(x, 1)
return floor_part + tf.sigmoid(steepness*(remainder - 0.5))
事实上,有一些方法可以在 Tensorflow 中注册您自己的梯度(例如,参见这个问题)。但是,我对实现这部分并不熟悉,因为我不经常使用 Keras/TensorFlow。
就可以为您提供此近似值梯度的函数而言,它将如下所示:
def approx_round_grad(x, steepness=1):
remainder = tf.mod(x, 1)
sig = tf.sigmoid(steepness*(remainder - 0.5))
return sig*(1 - sig)
需要明确的是,这个近似假设您使用的是“足够陡峭”的steepness
参数,因为 sigmoid 函数不会精确到 0 或 1,除非在大参数的限制下。
要执行半正弦近似值之类的操作,您可以使用以下命令:
def approx_round_sin(x, width=0.1):
if width > 1 or width <= 0:
raise ValueError('Width must be between zero (exclusive) and one (inclusive)')
floor_part = tf.floor(x)
remainder = tf.mod(x, 1)
return (floor_part + clipped_sin(remainder, width))
def clipped_sin(x, width):
half_width = width/2
sin_part = (1 + tf.sin(np.pi*((x-0.5)/width)))/2
whole = sin_part*tf.cast(tf.abs(x - 0.5) < half_width, tf.float32)
whole += tf.cast(x > 0.5 + half_width, tf.float32)
return whole
def approx_round_grad_sin(x, width=0.1):
if width > 1 or width <= 0:
raise ValueError('Width must be between zero (exclusive) and one (inclusive)')
remainder = tf.mod(x, 1)
return clipped_cos(remainder, width)
def clipped_cos(x, width):
half_width = width/2
cos_part = np.pi*tf.cos(np.pi*((x-0.5)/width))/(2*width)
return cos_part*tf.cast(tf.abs(x - 0.5) < half_width, dtype=tf.float32)