让神经网络输出介于-1.0和1.0之间的任何东西

时间:2017-06-02 07:33:07

标签: c# neural-network

我正在尝试制作反向传播神经网络。 基于我在这里找到的教程:James McCaffrey的MSDN article。他提供了许多例子,但他所有的网络都是基于同样的问题来解决。所以他的网络看起来像4:7:3>> 4输入 - 7隐藏 - 3输出。

他的输出总是二进制0或1,一个输出得1,将爱尔兰花分类为三个类别之一。

我想用神经网络解决另一个问题,这需要我2个神经网络,其中需要在0..255之间的输出和0到2倍Pi之间的另一个输出。 (一个完整的转弯,圆圈)。基本上我认为我需要一个范围从0.0到1.0或-1到1以及介于两者之间的任何输出,以便我可以将它乘以becomme 0..255或0..2Pi

我认为他的网络确实有行为,就像他的computeOutputs一样 我将在下面展示:

public void actionPerformed(AnActionEvent anActionEvent)

网络使用下面的hyperTan函数

  private double[] ComputeOutputs(double[] xValues)
    {

    if (xValues.Length != numInput)
            throw new Exception("Bad xValues array length");

        double[] hSums = new double[numHidden]; // hidden nodes sums scratch array
        double[] oSums = new double[numOutput]; // output nodes sums

        for (int i = 0; i < xValues.Length; ++i) // copy x-values to inputs
            this.inputs[i] = xValues[i];

        for (int j = 0; j < numHidden; ++j)  // compute i-h sum of weights * inputs
            for (int i = 0; i < numInput; ++i)
                hSums[j] += this.inputs[i] * this.ihWeights[i][j]; // note +=

        for (int i = 0; i < numHidden; ++i)  // add biases to input-to-hidden sums
            hSums[i] += this.hBiases[i];

        for (int i = 0; i < numHidden; ++i)   // apply activation
            this.hOutputs[i] = HyperTanFunction(hSums[i]); // hard-coded

        for (int j = 0; j < numOutput; ++j)   // compute h-o sum of weights * hOutputs
            for (int i = 0; i < numHidden; ++i)
                oSums[j] += hOutputs[i] * hoWeights[i][j];

        for (int i = 0; i < numOutput; ++i)  // add biases to input-to-hidden sums
            oSums[i] += oBiases[i];

        double[] softOut = Softmax(oSums); // softmax activation does all outputs at once for efficiency
        Array.Copy(softOut, outputs, softOut.Length);

        double[] retResult = new double[numOutput]; // could define a GetOutputs method instead
        Array.Copy(this.outputs, retResult, retResult.Length);
        return retResult;

在上面一个函数使得Softmax()的输出层使用,我觉得这里的问题至关重要。在那里我认为它使他的输出全部为二进制,它看起来像这样:

      private static double HyperTanFunction(double x)
      {
        if (x < -20.0) return -1.0; // approximation is correct to 30 decimals
        else if (x > 20.0) return 1.0;
        else return Math.Tanh(x);
      }

如何重写softmax? 那么网络能够提供非二进制答案吗?

请注意,网络的完整代码是here。如果你想尝试一下。

另外,为了测试网络,使用了以下精度函数,可能会出现二进制行为

     private static double[] Softmax(double[] oSums)
    {
        // determine max output sum
        // does all output nodes at once so scale doesn't have to be re-computed each time
        double max = oSums[0];
        for (int i = 0; i < oSums.Length; ++i)
            if (oSums[i] > max) max = oSums[i];

        // determine scaling factor -- sum of exp(each val - max)
        double scale = 0.0;
        for (int i = 0; i < oSums.Length; ++i)
            scale += Math.Exp(oSums[i] - max);

        double[] result = new double[oSums.Length];
        for (int i = 0; i < oSums.Length; ++i)
            result[i] = Math.Exp(oSums[i] - max) / scale;

        return result; // now scaled so that xi sum to 1.0
    }

2 个答案:

答案 0 :(得分:6)

以防有人遇到同样的情况。 如果您需要一些神经网络回归的示例代码 (一个NNR)这就是它们的召唤方式。

以下是C#中示例code的链接,此处为a good article。请注意,那家伙在那里写了更多的文章,你找不到所有东西,但那里有很多东西。尽管我跟踪了这​​个人有一段时间我错过了这篇特定的文章,因为我不知道他们在哪里调用,当我在这里询问有关堆栈溢出的问题时。

答案 1 :(得分:1)

我对Neural Netowrks有点生疏,但我认为,如果你想从你的输出中获得一系列值,那么你需要确保输出层上的激活函数是线性的(或类似的东西)效果)。

尝试添加此方法:

private static double[] Linear(double[] oSums)
{
    double sum = oSums.Sum(d => Math.Abs(d));

    double[] result = new double[oSums.Length];
    for (int i = 0; i < oSums.Length; ++i)
        result[i] = Math.Abs(oSums[i]) / sum;

    // scaled so that xi sum to 1.0
    return result;
}

然后在ComputeOutputs方法中,你需要为输出使用这个新的激活函数(而不是Softmax):

...
//double[] softOut = Softmax(oSums); // all outputs at once for efficiency
double[] softOut = Linear(oSums); // all outputs at once for efficiency
Array.Copy(softOut, outputs, softOut.Length);
...

现在应该输出线性值。