这是代码。
public class Adaline{ private int _layer; public int Layer { get { return _layer; } } private int _epoch; public int Epoch { get { return _epoch; } } private double _error; public double Error { get { return _error; } } private double[] _weights; public Adaline(int layer) { _layer = layer; _weights = new double[layer]; Reset(); } public void Reset() { Random r = new Random(); for (int i = 0; i < _layer; i++) _weights[i] = r.NextDouble() - 0.5; _error = 1; } public void Train(BasicTrainSet<double> trainset, double learnRate) { double ers = 0; for(int p = 0; p < trainset.DataCount; p++) { double result = Compute(trainset.Input[p], true); double error = trainset.Output[p] - result; for (int i = 0; i < _weights.Length; i++) { _weights[i] += error * trainset.Input[p][i] * learnRate; } ers += Math.Abs(error); } _epoch++; _error = ers; } public double Compute(double[] input, bool quan) { double result = 0; for (int i = 0; i < _layer; i++) result += Math.Tanh(_weights[i] * input[i]); //double result = _weights.Zip(input, (a, b) => Math.Tanh(a * b)).Sum(); return quan ? (result >= 0 ? 1 : 0) : result; }}
当我尝试训练AND门时,表现如下。上面的四个结果来自此代码这很奇怪,因为算法本身没有问题。权重越来越大。我哪里出错了?
回答:
在你的代码中,计算每个神经元输出的方式不对。你需要先计算权重和输入的点积,然后再应用激活函数。你现在是在每次加权累加后就应用激活函数,这是不正确的。
应该先累加,再应用激活函数:
public double Compute(double[] input, bool quan){ double result = 0; for (int i = 0; i < _layer; i++) result += _weights[i] * input[i]; // 修改 - 先累加 result = Math.Tanh(result); // 修改 - 现在应用激活函数 return quan ? (result >= 0 ? 1 : 0) : result;}