dan*_*jar 12 regression derivative backpropagation neural-network softmax
对于神经网络库,我实现了一些激活函数和损失函数及其衍生物.它们可以任意组合,输出层的导数只是损耗导数和激活导数的乘积.
但是,我没有独立于任何损失函数实现Softmax激活函数的导数.由于归一化即等式中的分母,改变单个输入激活会改变所有输出激活而不仅仅是一个.
这是我的Softmax实现,其衍生物未通过梯度检查约1%.如何实现Softmax衍生产品以便与任何损耗功能相结合?
import numpy as np
class Softmax:
def compute(self, incoming):
exps = np.exp(incoming)
return exps / exps.sum()
def delta(self, incoming, outgoing):
exps = np.exp(incoming)
others = exps.sum() - exps
return 1 / (2 + exps / others + others / exps)
activation = Softmax()
cost = SquaredError()
outgoing = activation.compute(incoming)
delta_output_layer = activation.delta(incoming) * cost.delta(outgoing)
Run Code Online (Sandbox Code Playgroud)
tic*_*cky 10
它应该是这样的:(x是softmax层的输入,dy是来自它上面的损失的delta)
dx = y * dy
s = dx.sum(axis=dx.ndim - 1, keepdims=True)
dx -= y * s
return dx
Run Code Online (Sandbox Code Playgroud)
但是你计算错误的方式应该是:
yact = activation.compute(x)
ycost = cost.compute(yact)
dsoftmax = activation.delta(x, cost.delta(yact, ycost, ytrue))
Run Code Online (Sandbox Code Playgroud)
说明:因为delta
函数是反向传播算法的一部分,所以它的职责是将向量dy
(在我的代码中,outgoing
在你的例子中)乘以在其中compute(x)
计算的函数的雅可比行列式x
.如果你弄清楚这个Jacobian对于softmax [1]看起来是什么样的,然后将它从左边乘以一个向量dy
,经过一些代数后你就会发现你得到了与我的Python代码相对应的东西.
[1] https://stats.stackexchange.com/questions/79454/softmax-layer-in-a-neural-network
数学上,Softmaxσ(j)相对于logit Zi的导数(例如,Wi*X)是
其中红色三角洲是克罗内克三角洲.
如果迭代实现:
def softmax_grad(s):
# input s is softmax value of the original input x. Its shape is (1,n)
# i.e. 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
Run Code Online (Sandbox Code Playgroud)
测试:
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]])
Run Code Online (Sandbox Code Playgroud)
如果您在矢量化版本中实现:
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]])
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
12671 次 |
最近记录: |