【问题标题】:how can i take the derivative of the softmax output in back-prop我如何在 back-prop 中获取 softmax 输出的导数
【发布时间】:2019-12-29 02:04:54
【问题描述】:

所以我是 ML 新手,并尝试制作一个简单的“库”,以便了解更多关于神经网络的信息。

我的问题: 根据我的理解,我必须根据它们的激活函数对每一层进行导数,这样我就可以计算它们的增量并调整它们的权重等......

对于 ReLU、sigmoid、tanh,用 Java(这是我使用的语言 BTW)实现它们非常简单

但是要从输出到输入,我必须(显然)从具有 softmax 激活函数的输出开始。

那么我是否也必须采用输出层的导数,还是只适用于所有其他层?

如果我必须得到派生,我如何在 Java 中实现派生? 谢谢。

我已经阅读了很多关于 softmax 算法导数的解释的页面,但它们对我来说真的很复杂,正如我所说,我刚开始学习 ML,我不想使用现成的库所以我来了。

这是我存储激活函数的类。

public class ActivationFunction {

    public static double tanh(double val) {
        return Math.tanh(val);
    }

    public static double sigmoid(double val) {
        return 1 / 1 + Math.exp(-val);
    }

    public static double relu(double val) {
        return Math.max(val, 0);
    }

    public static double leaky_relu(double val) {
        double result = 0;
        if (val > 0) result = val;
        else result = val * 0.01;
        return result;
    }

    public static double[] softmax(double[] array) {
        double max = max(array);
        for (int i = 0; i < array.length; i++) {
            array[i] = array[i] - max;
        }

        double sum = 0;
        double[] result = new double[array.length];
        for (int i = 0; i < array.length; i++) {
            sum += Math.exp(array[i]);
        }
        for (int i = 0; i < result.length; i++) {
            result[i] = Math.exp(array[i]) / sum;
        }
        return result;
    }

    public static double dTanh(double x) {
        double tan = Math.tanh(x);
        return (1 / tan) - tan;
    }

    public static double dSigmoid(double x) {
        return x * (1 - x);
    }

    public static double dRelu(double x) {
        double result;
        if (x > 0) result = 1;
        else result = 0;
        return result;
    }

    public static double dLeaky_Relu(double x) {
        double result;
        if (x > 0) result = 1;
        else if (x < 0) result = 0.01;
        else result = 0;
        return result;
    }

    private static double max(double[] array) {
        double result = Double.MIN_VALUE;
        for (int i = 0; i < array.length; i++) {
            if (array[i] > result) result = array[i];
        }
        return result;
    }
}

我期待得到这个问题的答案:我是否需要 softmax 的导数? 如果可以,我该如何实现?

【问题讨论】:

    标签: java machine-learning backpropagation derivative softmax


    【解决方案1】:

    您的第一个问题的简短回答是,您需要计算softmax 的导数。

    较长的版本将涉及一些计算,因为为了实现反向传播,您需要通过一阶优化算法来训练您的网络,该算法需要计算成本函数 w.r.t 权重的偏导数,即:

             

    然而,由于您在最后一层使用 softmax,因此您很可能会在训练神经网络时优化交叉熵成本函数网络,即:

             

    其中 tj 是目标值,ajj 类的 softmax 结果。

    Softmax 本身代表 n 个类别的概率分布:

             

    其中所有 z 都是前一层激活函数的结果乘以相应权重的简单总和:

             

    其中n是层数,i是前一层的神经元个数, j 是我们的 softmax 层中神经元的数量。

    因此,为了对这些权重中的任何一个进行偏导,应该计算:

             

    其中二阶偏导∂ak/∂zj确实是softmax导数,可以是计算方式如下:

             

    但是如果您尝试计算上述成本函数 w.r.t 的导数的总和项。权重,你会得到:

             

    所以在这种特殊情况下,计算的最终结果非常简洁,代表了网络输出和目标值之间的简单差异,就是这样,即,您只需要计算这个总和偏导数就是:

             

    因此,要回答您的第二个问题,您可以将交叉熵成本函数 w.r.t 输出激活(即 softmax)的偏导数的计算与输出激活 w.r.t 的偏导数结合起来。 zj 会产生简短而清晰的实现,如果您使用的是非矢量化形式,它将如下所示:

    for (int i = 0; i < lenOfClasses; ++i)
    {
        dCdz[i] = t[i] - a[i];
    }
    

    随后您可以使用 dCdz 反向传播到神经网络的其余层。

    【讨论】:

    • 解释得很好。向你致敬。
    • @Michael Glazunov,你会用细节扩展 ∂ak/∂zj 的计算吗?谢谢!
    猜你喜欢
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 2020-07-07
    • 1970-01-01
    • 2017-05-15
    • 2023-03-15
    相关资源
    最近更新 更多