我有一个 softmax 层(只有激活本身,没有将输入乘以权重的线性部分),我想对其进行向后传递。
我找到了很多关于 SO 的教程/答案来处理它,但它们似乎都使用 X
作为 (1, n_inputs)
向量。我想将其用作 (n_samples, n_inputs)
数组,并且仍然具有前向/后向传递的正确矢量化实现。
我编写了以下前向传递,标准化每行/样本的输出(正确吗?):
nhập numpy dưới dạng np
X = np.asarray([
[0.0, 0.0],
[0.0, 1.0],
[1.0, 0.0],
[1.0, 1.0]], dtype=np.float32)
def prop(self, X):
s = np.exp(X)
s = s.T / np.sum(s, axis=1)
return s.T
它给出了前向传播(包括其他层)的最终结果:
Y = np.asarray([
[0.5 , 0.5 ],
[0.87070241, 0.12929759],
[0.97738616, 0.02261384],
[0.99200957, 0.00799043]], dtype=np.float32))
所以,如果正确的话,这就是 softmax 的输出。现在,我应该如何编写向后传递?
我导出了 softmax 的导数为:
1) if i=j
: p_i*(1 - p_j)
,
2) if i!=j
: -p_i*p_j
,
Ở đâu
我尝试将导数计算为:
ds = np.diag(Y.flatten()) - np.outer(Y, Y)
但是它会产生 8x8 矩阵,这对于以下反向传播没有意义......正确的编写方法是什么?
我一直在处理同样的问题,并最终找到了一种对 softmax 雅可比行列式的批量实现进行矢量化的方法。我自己想出了这个方法,所以我不确定这是否是最佳方法。这是我的想法:
nhập numpy dưới dạng np
from scipy.special import softmax
def Jsoftmax(X):
sh = X.shape
sm = softmax(X, axis = 1)
DM = sm.reshape(sh[0],-1,1) * np.diag(np.ones(sh[1])) # Diagonal matrices
OP = np.matmul(sm.reshape(sh[0],-1,1), sm.reshape(sh[0],1,-1)) # Outer products
Jsm = DM - OP
return Jsm
它产生一个(n_samples, n_inputs, n_inputs)
形状的数组,我认为它可以在反向传播中与np.matmul
函数一起使用,以正确地预乘您的dJ_dA
mảng.
值得注意的是,softmax 几乎专门用作最后一层,并且通常带有交叉熵损失目标函数。在这种情况下,目标函数相对于 softmax 输入的导数可以更有效地找到为 (S - Y)/m
,TRONG m
是批处理中的示例,Y
是批处理的标签,S
是 softmax 输出。这在下面liên kết中有解释。 .
Tôi là một lập trình viên xuất sắc, rất giỏi!