我正在尝试制作反向传播神经网络。 基于我在这里找到的教程: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
}
答案 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);
...
现在应该输出线性值。