了解 softmax 的反向传播

问题描述 投票:0回答:2

如果这是一个愚蠢的问题,我很抱歉,但我就是无法理解这个问题。 我正在尝试创建我的第一个神经网络,它采用 MNIST 数据 (28x28),其中手绘数字 0-9 并输出神经网络认为是哪个数字。在最后一层,我需要做一个softmax函数,它可以输出这些数字的所有概率,然后总和为1。

def softmax(z):
    exps = np.exp(z - z.max())

    return exps/np.sum(exps), z

到目前为止,一切都应该没问题。 但现在我们进入反向传播部分 => 我在互联网上找到了这个用于反向传播的 softmax 函数。

def softmax_backward(dA, Z):
    x, _ =softmax(dA)
    s=x.reshape(-1,1)

    return (np.diagflat(s) - np.dot(s, s.T))

问题1:这个softmax导数函数适合我的神经网络吗?

如果合适,那么我在其他地方有错误。 这是我的错误:

--------------------------------------------------------------------------- ValueError                                Traceback (most recent call
last) <ipython-input-21-b0721d5dd18f> in <module>
---> 26 parameters = model(x_testone, y_testone, layer_dims)

<ipython-input-20-0653ba2ad7e6> in model(X, y, layer_dims,
learning_rate, epochs, print_cots, activation)
     10         zCache = zCaches[l+1]
     11 
---> 12         grads = L_model_backward(Al, y, linCaches, zCaches, activation)
     13 
     14         parameters = update_parameters(parameters, grads, learning_rate)

<ipython-input-18-8b76528a319a> in L_model_backward(Al, y, linCaches,
zCaches, activation)
---> 11     grads["dA" + str(L-1)], grads["dW" + str(L)], grads["db" + str(L)] = liner_activ_backward(dAl, zCaches[L-1], linCaches[L-1],
"softmax")
     12 

<ipython-input-17-6e9b3ba31571> in liner_activ_backward(dA, zCache,
linCache, activation)
     20         dZ = softmax_backward(dA, Z)
---> 21         dA_prev, dW, db = linear_backward(dZ, linCache)
     22         return dA_prev, dW, db
     23 

<ipython-input-16-4b15b65d0522> in linear_backward(dZ, linCache)
----> 7     dW = (1/m) * np.dot(dZ, A_prev.T)
      8     db = (1/m) * np.sum(dZ, axis=1, keepdims=True)
      9     dA_prev = np.dot(W.T, dZ)

ValueError: shapes (10000,10000) and (20,1000) not aligned: 10000 (dim
1) != 20 (dim 0) ```

现在我认为我的错误在于

liner_backward
方法,因为它与softmax不兼容。我的观点是正确的还是完全错误的?

问题2:我应该使用什么方法来代替

linear_backward
方法?

非常感谢您的帮助!

python neural-network softmax
2个回答
0
投票

Softmax接受一个向量作为输入并给出一个向量作为输出,因此为softmax定义“梯度”是没有意义的。 softmax 的导数由其雅可比矩阵给出,这只是编写输出相对于所有输入的导数的所有组合的一种简洁方式。

softmax 的一个用例是在基于分类的顺序网络的输出层中,它与分类交叉熵损失函数一起使用。防止计算 softmax 雅可比行列式的通常解决方法是简单地对传递给 softmax 的输入(而不是 softmax 传递的输出)的损失函数求导。

因此,你可以简单地编写softmax后向函数,将从“下一层”(损失函数)获得的输出梯度传递到“上一层”。

def softmax_backward(dA):
    return dA

请注意,当给定损失函数的梯度时,softmax 之前的层的职责是实现后向函数来计算损失函数相对于该层参数所需的导数。

富有洞察力的资源:

https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi

https://www.youtube.com/watch?v=pauPCy_s0好的

https://towardsdatascience.com/derivative-of-the-softmax-function-and-the-categorical-cross-entropy-loss-ffceefc081d1

https://eli.thegreenplace.net/2016/the-softmax-function-and-its-derivative/

https://www.youtube.com/playlist?list=PLQVvvaa0QuDcjD5BAw2DxE6OF2tius3V3


0
投票

首先,2D张量和1D向量的softmax计算存在一些差异; // 您需要确定您的输入是 2D 矩阵还是 1D 向量。

其次,softmax-backward和损失函数经常一起使用,所以最好将它们融合在一起。

sotfmax-forward:

def softmax(x):
    '''
    :param x: maybe 2D matrix, or 1D array.
    :return:
    '''
    if x.ndim == 2:  # if x is 2D matrix
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T
    # if x is 1D array
    x = x - np.max(x)
    return np.exp(x) / np.sum(np.exp(x))

参考:https://github.com/zli2014/python_deep_learning/blob/master/src/common/functions.py#L61-L75

softmax-向后:

https://github.com/zli2014/python_deep_learning/blob/master/src/common/layers.py#L82-L104


我猜你想写一个神经网络推理框架(使用python和numpy)并训练在mnist数据集上识别手写体,你可以参考它:

https://github.com/zli2014/python_deep_learning/blob/master/src/test/train_neuralnet_v2.py

© www.soinside.com 2019 - 2024. All rights reserved.