Python numpy:计算softmax函数的导数

Python numpy:计算softmax函数的导数,python,numpy,neural-network,backpropagation,softmax,Python,Numpy,Neural Network,Backpropagation,Softmax,我正试图用MNIST在一个简单的三层神经网络中理解backpropagation 输入层具有权重和偏差。标签是MNIST,因此它是10类向量 第二层是线性变换。第三层是softmax激活,以获得作为概率的输出 反向传播计算每一步的导数,并将其称为梯度 上一层将全局或上一个渐变添加到局部渐变。我在计算softmax 一些在线资源对softmax及其衍生物进行了解释,甚至给出了softmax本身的代码示例 def softmax(x): """Compute the softmax of v

我正试图用
MNIST
在一个简单的三层神经网络中理解
backpropagation

输入层具有
权重
偏差
。标签是
MNIST
,因此它是
10
类向量

第二层是
线性变换
。第三层是
softmax激活
,以获得作为概率的输出

反向传播
计算每一步的导数,并将其称为梯度

上一层将
全局
上一个
渐变添加到
局部渐变
。我在计算
softmax

一些在线资源对softmax及其衍生物进行了解释,甚至给出了softmax本身的代码示例

def softmax(x):
    """Compute the softmax of vector x."""
    exps = np.exp(x)
    return exps / np.sum(exps)
i=j
i!=j
。这是我想到的一个简单的代码片段,希望验证我的理解:

def softmax(self, x):
    """Compute the softmax of vector x."""
    exps = np.exp(x)
    return exps / np.sum(exps)

def forward(self):
    # self.input is a vector of length 10
    # and is the output of 
    # (w * x) + b
    self.value = self.softmax(self.input)

def backward(self):
    for i in range(len(self.value)):
        for j in range(len(self.input)):
            if i == j:
                self.gradient[i] = self.value[i] * (1-self.input[i))
            else: 
                 self.gradient[i] = -self.value[i]*self.input[j]

然后
self.gradient
localgradient
,它是一个向量。这是正确的吗?有更好的方法写这个吗?

就像我说的,你有
n^2
偏导数

如果你计算一下,你会发现
dSM[i]/dx[k]
SM[i]*(dx[i]/dx[k]-SM[i])
,所以你应该:

if i == j:
    self.gradient[i,j] = self.value[i] * (1-self.value[i])
else: 
    self.gradient[i,j] = -self.value[i] * self.value[j]
而不是

if i == j:
    self.gradient[i] = self.value[i] * (1-self.input[i])
else: 
     self.gradient[i] = -self.value[i]*self.input[j]
顺便说一下,这可以像这样更简洁地计算(矢量化):


我假设你有一个带有
W1
b1
的三层NN,for与从输入层到隐藏层的线性变换相关联,
W2
b2
与从隐藏层到输出层的线性变换相关联
Z1
Z2
是隐藏层和输出层的输入向量
a1
a2
表示隐藏层和输出层的输出
a2
是您的预测输出
delta3
delta2
是错误(反向传播),您可以看到损失函数相对于模型参数的梯度


这是3层NN(输入层,只有一个隐藏层和一个输出层)的一般场景。您可以按照上面描述的过程来计算梯度,这应该很容易计算!因为这篇文章的另一个答案已经指出了代码中的问题,所以我不再重复相同的内容。

np.exp
不稳定,因为它有Inf。 因此,您应该减去
x
中的最大值

def softmax(x):
    """Compute the softmax of vector x."""
    exps = np.exp(x - x.max())
    return exps / np.sum(exps)

如果
x
是矩阵,请检查中的softmax函数。

这太不清楚了。。。你到底想计算什么梯度?SM是从R^n到R^n的映射,所以你可以定义n^2个偏导数dSM[i]/dx[k]…@JulienBernu我已经更新了这个问题。有什么想法吗?好吧,这就是雅各比?我想我还有另一个想法。@wasi答案中的线性变换是隐藏层吗?我想是的。请注意,大多数人认为最后一个线性变换+ SM仅为一个层。通常,层是一个线性变换,然后是一个非线性(sigmoid、tanh、SM、relu或其他…)在我看到的一些实现中,前向传播中的softmax的输出值也被使用。在您的版本中,情况并非如此,仅使用损失函数梯度的输入。我是否遗漏了什么,或者这是完整的公式?再澄清一件事。如果我们从z2开始,即z1从未存在过,这会使它成为2层NN吗?线性变换发生两次,使其成为3层NN?你能解释方程中各层的名称吗?您的案例中的输入层是z1?有多少隐藏层?它们是什么?太棒了!非常感谢你!上帝保佑你,祝你博士学习好运!我将更新这个库,使之与上述内容相匹配。完成后将编辑问题这里的损失函数是什么?
def softmax(x):
    """Compute the softmax of vector x."""
    exps = np.exp(x - x.max())
    return exps / np.sum(exps)