numpy 在Python中从头开始计算雅可比矩阵

os8fio9y  于 2023-04-12  发布在  Python
关注(0)|答案(3)|浏览(136)

我正在尝试实现softmax函数的导数矩阵(Softmax的雅可比矩阵)。
我从数学上知道Softmax(Xi)对Xj的导数是:

其中红色的δ是克罗内克δ。
到目前为止,我实现的是:

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]])

你们是如何实现雅可比的?我想知道是否有更好的方法来做到这一点。任何参考网站/教程将不胜感激。

9jyewag0

9jyewag01#

您可以像下面这样对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计算:
q5lcpyga

q5lcpyga2#

我一直在修补这个,这就是我提出的。也许你会发现它很有用。我认为它比Psidom提供的解决方案更明确。

def softmax_grad(probs):
    n_elements = probs.shape[0]
    jacobian = probs[:, np.newaxis] * (np.eye(n_elements) - probs[np.newaxis, :])
    return jacobian
vcudknz3

vcudknz33#

这里有一个比公认的答案更容易阅读的版本,它假设输入概率是(rows,n)而不是(1,n)。

def softmax_grad(probs):
   # probs has shape (rows, n)
   # output has shape (rows, n, n) giving the jacobian for each row of probabilities
   eye = np.eye(probs.shape[-1])
   return probs[:, None, :] * (eye[None, :, :] - probs[:, :, None])

相关问题