避免局部最佳训练XOR

时间:2017-03-14 10:52:41

标签: javascript neural-network genetic-algorithm

我使用 Neataptic 训练神经网络,用遗传算法解决XOR问题。适合度定义如下:

// max score = 0
score -= Math.abs(0 - network.activate([0, 0])) * 5000;
score -= Math.abs(1 - network.activate([1, 0])) * 5000;
score -= Math.abs(1 - network.activate([0, 1])) * 5000;
score -= Math.abs(0 - network.activate([1, 1])) * 5000;

有时它运行得很好。但我认为它只是运气好。但很多时候,它甚至无法达到-6000。它会在-8000附近徘徊。

这些是我的设置:

  GNN = new Evolution({
    size: 100,
    elitism: 10,
    mutationRate: 0.3,
    networkSize : [2,3,1],
    mutationMethod: [
      Methods.Mutate.MODIFY_RANDOM_BIAS,
      Methods.Mutate.MODIFY_RANDOM_WEIGHT,
      Methods.Mutate.SWAP_BIAS,
      Methods.Mutate.SWAP_WEIGHT,
      Methods.Mutate.MODIFY_SQUASH
    ],
    crossOverMethod: [
      Methods.Crossover.UNIFORM,
      Methods.Crossover.AVERAGE,
      Methods.Crossover.SINGLE_POINT,
      Methods.Crossover.TWO_POINT
    ],
    selectionMethod: [
      Methods.Selection.FITNESS_PROPORTIONATE
    ],
    generationMethod: [
      Methods.Generation.POINTS
    ],
    fitnessFunction: function(network){
      var score = 0;

      score -= Math.abs(0 - network.activate([0, 0])) * 5000;
      score -= Math.abs(1 - network.activate([1, 0])) * 5000;
      score -= Math.abs(1 - network.activate([0, 1])) * 5000;
      score -= Math.abs(0 - network.activate([1, 1])) * 5000;

      return Math.round(score);
    }
  });

(view the JSFiddle here and press train)

您建议我更改哪些设置? (请提供证明)

P.S。我知道通过反向传播训练XOR会更容易,但这仅用于实验目的。

1 个答案:

答案 0 :(得分:1)

我改变了:

fitnessFunction: function(network){
  var score = 0;

  score -= Math.abs(0 - network.activate([0, 0])) * 5000;
  score -= Math.abs(1 - network.activate([1, 0])) * 5000;
  score -= Math.abs(1 - network.activate([0, 1])) * 5000;
  score -= Math.abs(0 - network.activate([1, 1])) * 5000;

  return Math.round(score);
}

fitnessFunction: function(network){
  var score = 0;

  score -= Methods.Cost.MSE([0], network.activate([0, 0])) * 5000;
  score -= Methods.Cost.MSE([1], network.activate([1, 0])) * 5000;
  score -= Methods.Cost.MSE([1], network.activate([0, 1])) * 5000;
  score -= Methods.Cost.MSE([0], network.activate([1, 1])) * 5000;

  return Math.round(score);
}

这在逻辑上是正确的,因为平方误差有助于增加输出完全错误的机会。 Read about it here