所以我试图在c#中实现反向传播神经网络。而且我遇到了一个打嗝。训练网络时,所有输出都是0.49 ??? ...或0.51 ??? ...
这是我的网络课程
namespace BackPropNetwork
{
public class Network
{
public double[][] Values { get; set; }
public double[][] Deltas { get; set; }
public double[][][] Weights { get; set; }
public Network(params int[] size)
{
Values = new double[size.Length][];
Weights = new double[size.Length][][];
Deltas = new double[size.Length][];
Random r = new Random();
for(int i = 0; i < size.Length; i++)
{
Values[i] = new double[size[i]];
Weights[i] = new double[size[i]][];
Deltas[i] = new double[size[i]];
if (i != size.Length - 1) {
for (int j = 0; j < size[i]; j++)
{
Weights[i][j] = new double[size[i + 1]];
for(int k= 0; k < size[i + 1]; k++)
{
Weights[i][j][k] = r.NextDouble() ;
}
}
}
}
}
public double[] FeedThrough (double[] input)
{
if(input.Length!= Values[0].Length)
{
throw new InvalidOperationException();
}
Values[0] = input;
for(int i = 0; i < Values.Length-1; i++)
{
for(int j = 0; j < Values[i + 1].Length; j++)
{
Values[i + 1][j] = Sigmoid(GetPassValue(i, j),false);
}
}
return Values[Values.Length - 1];
}
double GetPassValue(int layer,int neuron)
{
double sum = 0;
for(int i = 0; i < Values[layer].Length; i++)
{
sum += Values[layer][i] * Weights[layer][i][neuron];
}
return sum;
}
public double Sigmoid(double d, bool dir)
{
if (dir)
{
return d * (1 - d);
}else
{
return 1 / (1 + Math.Exp(d));
}
}
public void CorrectError(double[] error)
{
for(int i = Values.Length - 1; i >= 0; i--)
{
if (i !=Values.Length - 1)
{
error = new double[Values[i].Length];
for(int j = 0; j < Values[i].Length; j++)
{
error[j] = 0;
for(int k = 0; k < Values[i + 1].Length; k++)
{
error[j] += Weights[i][j][k] * Deltas[i + 1][k];
}
}
}
for(int j = 0; j < Values[i].Length; j++)
{
Deltas[i][j] = error[j] * Sigmoid(Values[i][j],true);
}
}
}
public void ApplyCorrection(double rate)
{
for(int i = 0; i < Values.Length-1; i++)
{
for(int j = 0; j < Values[i].Length; j++)
{
for(int k = 0; k < Values[i + 1].Length; k++)
{
Weights[i][j][k] = rate * Deltas[i + 1][k] * Values[i][j];
}
}
}
}
}
}
这是我的测试人员课程:
namespace BackPropagationTest
{
class Program
{
static void Main(string[] args)
{
Network n = new Network(3, 5, 5, 1);
double[][] input = new double[][] { new double[] { 1, 0, 1 }, new double[] { 1, 1, 1 }, new double[] { 0, 0, 0 }, new double[] {0, 1, 0 } };
double[][] output = new double[][] { new double[] { 0 },new double[] { 1 }, new double[] { 0 }, new double[] { 0 } };
for (int i = 0; i < 10; i++)
{
for(int j = 0; j < input.Length; j++)
{
var x = n.FeedThrough(input[j]);
double[] error = new double[output[0].Length];
for(int k= 0; k < x.Length; k++)
{
error[k] = output[j][k] - x[k];
}
n.CorrectError(error);
n.ApplyCorrection(0.01);
for(int k = 0; k < x.Length; k++)
{
Console.Write($"Expected: {output[j][k]} Got: {x[k]} ");
}
Console.WriteLine();
}
Console.WriteLine();
}
}
}
}
这是我的输出:
Expected: 0 Got: 0.270673949003643
Expected: 1 Got: 0.500116517554687
Expected: 0 Got: 0.499609458404919
Expected: 0 Got: 0.50039031963377
Expected: 0 Got: 0.500390929619276
Expected: 1 Got: 0.500390929999612
Expected: 0 Got: 0.499609680732027
Expected: 0 Got: 0.500390319841144
Expected: 0 Got: 0.50039092961941
Expected: 1 Got: 0.500390929999612
Expected: 0 Got: 0.499609680732027
Expected: 0 Got: 0.500390319841144
Expected: 0 Got: 0.50039092961941
Expected: 1 Got: 0.500390929999612
Expected: 0 Got: 0.499609680732027
Expected: 0 Got: 0.500390319841144
它会永远这样下去。
编辑1:
我在ApplyCorrection()函数中进行了更改,我已将其替换为
Weights[i][j][k] = rate * Deltas[i + 1][k] * Values[i][j];
与`
Weights[i][j][k] += rate * Deltas[i + 1][k] * Values[i][j];
现在权重似乎更新了。但我仍然质疑这种实施的正确性。 A.k.a仍然需要帮助:))
编辑2:
我没有总结输出层的总误差,而是单独反向传播每个样本错误。现在我,但输出非常混乱:
我还尝试将输出对从(0,1)更改为(-1,1),以使计算出的误差值更大。 这是在1000000个时期之后,学习率为0.1:
Expected: -1 Got: 0.999998429209274
Expected: 1 Got: 0.999997843901661
Expected: -1 Got: 0.687098308461306
Expected: -1 Got: 0.788960893508226
Expected: -1 Got: 0.999998429209274
Expected: -1 Got: 0.863022549216158
Expected: -1 Got: 0.788960893508226
Expected: -1 Got: 0.999998474717769
答案 0 :(得分:0)
尝试使用下面的内容进行播放,并检查错误是否正在减少或仍然相同。
public double Sigmoid(double d, bool dir)
{
if (dir)
{
return d * (1 - d);
}else
{
if (d < -45.0) return 0.0;
else if (d > 45.0) return 1.0;
else return 1.0 / (1.0 + Math.Exp(-d));
}
}