因此,我是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的导数?
如果可以,我该如何实施?

最佳答案

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

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

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

但是,由于您将softmax用于最后一层,因此很有可能在训练神经网络时将优化交叉熵代价函数,即:

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

其中tj是目标值,aj是类别j的softmax结果。

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

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

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

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

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

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

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

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

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

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

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP
java - 我如何在反向传播中采用softmax输出的导数-LMLPHP
java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

因此,在这种特定情况下,事实证明,计算的最终结果非常简洁,并且代表了网络输出与目标值之间的简单差异,仅此而已,即,您需要计算部分和的总和衍生品只是:

java - 我如何在反向传播中采用softmax输出的导数-LMLPHP

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

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


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

关于java - 我如何在反向传播中采用softmax输出的导数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57631507/

10-12 22:05