我怎样才能在 back-prop 中获取 softmax 输出的导数
how can i take the derivative of the softmax output in back-prop
所以我是 ML 的新手,正在尝试制作一个简单的 "library" 以便我可以了解有关神经网络的更多信息。
我的问题:
根据我的理解,我必须根据它们的激活函数对每一层进行导数,这样我就可以计算它们的增量并调整它们的权重等...
对于 ReLU、sigmoid、tanh,在 Java(这是我使用的语言 BTW)中实现它们非常简单
但是要从输出到输入,我必须(显然)从具有 softmax 激活函数的输出开始。
那么我是否也必须采用输出层的导数,或者它只适用于所有其他层?
如果我必须得到导数,我该如何实现 Java 中的导数?
谢谢
我已经阅读了很多解释 softmax 算法导数的页面,但它们对我来说真的很复杂,正如我所说,我刚刚开始学习 ML,我不想使用库架子所以我在这里。
这是我存储激活函数的 class。
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的导数。
较长的版本将涉及一些计算,因为为了实现反向传播,您通过一阶优化算法训练网络,该算法需要计算成本函数 w.r.t 权重的偏导数,即:
但是,因为你在最后一层使用softmax,所以很可能你要优化一个cross -训练神经网络时的熵成本函数,即:
其中tj是目标值,aj 是 class j[=95= 的 softmax 结果].
Softmax 本身表示 n classes:
上的概率分布
其中所有 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 反向传播到神经网络的其余层。
所以我是 ML 的新手,正在尝试制作一个简单的 "library" 以便我可以了解有关神经网络的更多信息。
我的问题: 根据我的理解,我必须根据它们的激活函数对每一层进行导数,这样我就可以计算它们的增量并调整它们的权重等...
对于 ReLU、sigmoid、tanh,在 Java(这是我使用的语言 BTW)中实现它们非常简单
但是要从输出到输入,我必须(显然)从具有 softmax 激活函数的输出开始。
那么我是否也必须采用输出层的导数,或者它只适用于所有其他层?
如果我必须得到导数,我该如何实现 Java 中的导数? 谢谢
我已经阅读了很多解释 softmax 算法导数的页面,但它们对我来说真的很复杂,正如我所说,我刚刚开始学习 ML,我不想使用库架子所以我在这里。
这是我存储激活函数的 class。
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的导数。
较长的版本将涉及一些计算,因为为了实现反向传播,您通过一阶优化算法训练网络,该算法需要计算成本函数 w.r.t 权重的偏导数,即:
但是,因为你在最后一层使用softmax,所以很可能你要优化一个cross -训练神经网络时的熵成本函数,即:
其中tj是目标值,aj 是 class j[=95= 的 softmax 结果].
Softmax 本身表示 n classes:
上的概率分布
其中所有 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 反向传播到神经网络的其余层。