我正在尝试实现softmax函数的导数矩阵(Softmax的雅可比矩阵)。
我在数学上知道Softmax(Xi)相对于Xj的导数是:
其中红色三角洲是Kronecker delta。
到目前为止,我所实施的是:
def softmax_grad(s):
# input s is softmax value of the original input x. Its shape is (1,n)
# e.i. s = np.array([0.3,0.7]), x = np.array([0,1])
# make the matrix whose size is n^2.
jacobian_m = np.diag(s)
for i in range(len(jacobian_m)):
for j in range(len(jacobian_m)):
if i == j:
jacobian_m[i][j] = s[i] * (1-s[i])
else:
jacobian_m[i][j] = -s[i]*s[j]
return jacobian_m
当我测试时:
In [95]: x
Out[95]: array([1, 2])
In [96]: softmax(x)
Out[96]: array([ 0.26894142, 0.73105858])
In [97]: softmax_grad(softmax(x))
Out[97]:
array([[ 0.19661193, -0.19661193],
[-0.19661193, 0.19661193]])
你们是如何实施雅可比人的?我想知道是否有更好的方法来做到这一点。任何对网站/教程的引用也将受到赞赏。
答案 0 :(得分:2)
您可以像以下一样对softmax_grad
进行矢量化;
soft_max = softmax(x)
# reshape softmax to 2d so np.dot gives matrix multiplication
def softmax_grad(softmax):
s = softmax.reshape(-1,1)
return np.diagflat(s) - np.dot(s, s.T)
softmax_grad(soft_max)
#array([[ 0.19661193, -0.19661193],
# [-0.19661193, 0.19661193]])
详细信息:sigma(j) * delta(ij)
是一个对角矩阵,sigma(j)
为对角元素,您可以使用np.diagflat(s)
创建; sigma(j) * sigma(i)
是softmax的矩阵乘法(或外积),可以使用np.dot
计算:
答案 1 :(得分:0)
我一直在修补这个,这就是我想出来的。也许你会发现它很有用。我认为它比Psidom提供的解决方案更明确。
def softmax_grad(probs):
n_elements = probs.shape[0]
jacobian = probs[:, np.newaxis] * (np.eye(n_elements) - probs[np.newaxis, :])
return jacobian