我对在Tensorflow中构建Softmax的衍生产品感兴趣,并且作为新用户我感到困惑。
我能找到的最接近的代码是NumPy版本Softmax derivative in NumPy approaches 0 (implementation)。代码如下。我能够轻松地将softmax部分转换为张量流,但我仍然坚持如何将导数部分应用于张量流 - 在"以及"如果衍生"给我带来麻烦。您将如何构建衍生部分的三条线?
谢谢。
if derivative:
J = - signal[..., None] * signal[:, None, :] # off-diagonal Jacobian
iy, ix = np.diag_indices_from(J[0])
J[:, iy, ix] = signal * (1. - signal) # diagonal
return J.sum(axis=1)
以下是上述链接的完整代码。
def softmax_function( signal, derivative=False ):
# Calculate activation signal
e_x = np.exp( signal )
signal = e_x / np.sum( e_x, axis = 1, keepdims = True )
if derivative:
J = - signal[..., None] * signal[:, None, :] # off-diagonal Jacobian
iy, ix = np.diag_indices_from(J[0])
J[:, iy, ix] = signal * (1. - signal) # diagonal
return J.sum(axis=1)
else:
# Return the activation signal
return signal
答案 0 :(得分:1)
我最近处于这种情况并且找不到多少帮助,特别是在提取对角线元素以更新i = j场景时。
一个可能的原因可能是缺乏像tensorflow中的多功能性那样的numpy。
看看下面两个替代方案是否适合您,
在图表中定义占位符
derivative = tf.placeholder(tf.float32,[None,num_features])
考虑到你的softmax概率存储在一个名为'output'的变量中
然后在你的会话中你可以这样做,
session.run(train,feed_dict {derivative:softmax(output.eval(),deriv = True)})
注意:此方法的计算成本可能很高。
损失函数,
L= -1/N ∑ yk.log(pk)
根据连锁规则,
∂L/∂W2 = ∂L/dpi .∂pi/∂a2 .∂a2/dW2
其中L是损失函数 p是概率输出
通过计算两个案例的链规则中的前两个项,k = i和k!= i,将其简化为下面的术语,
∂L/dpi . ∂pi/∂a2 = pi-yi --- > delta value for the output layer.
所以你可以简单地通过从前传播的softmax输出中减去你的目标而不是复杂的雅可比矩阵方法来计算你的l2_delta。
查看这些链接,了解有关此背后数学的更多信息,
为什么softmax衍生物不像任何其他激活那样简单的优秀解释 - > Derivative of a softmax function
PDF解释答案PDF
中描述的简化步骤答案 1 :(得分:1)
我的代码有几个注释:
Tensorflow基于计算图,因此无需手动计算梯度。在纯粹的numpy中做这件事是完全没问题的,只是为了让你知道。
您的softmax
正向计算是正确的,但可能在数值上不稳定。简而言之,划分非常大的值会导致精度损失,因此在计算指数之前最好减去signal
的最大值:
stable_signal = signal - np.max(signal)
e_x = np.exp(stable_signal)
signal = e_x / np.sum(e_x, axis=1, keepdims=True)
有关详细信息,请参阅this post中的“实际问题:数字稳定性”部分。
Softmax衍生物本身有点毛茸茸。计算来自softmax层的后向信号更有效(也更容易),即信号的交叉熵损失的导数。为此,您需要将正确的标签y
传递给softmax_function
。然后计算如下:
sums_per_row = np.sum(exponents, axis=1, keepdims=True) # can also reuse with the forward pass
all_softmax_matrix = (e_x.T / sums_per_row).T
grad_coeff = np.zeros_like(signal)
grad_coeff[np.arange(num_train), y] = -1
grad_coeff += all_softmax_matrix
return grad_coeff
如果您不确定为何如此容易,请查看these brilliant notes。
答案 2 :(得分:0)
您可以直接在 tensorflow 中编写您的导数部分,如下所示:
#Assuming signal is a tensor created in tensorflow.
if derivative:
J = - signal[..., None] * signal[:, None, :] # off-diagonal Jacobian
J = tf.linalg.set_diag(J, signal * (1. - signal))# diagonal
return tf.reduce_sum(J,1)