簡體   English   中英

如何正確訓練我的神經網絡

[英]How to correctly train my Neural Network

我正在嘗試教一個神經網絡,根據輸入的生命水平決定去哪里。 神經網絡將始終接收三個輸入[x, y, life] 如果life => 0.2 ,它應該輸出從[x, y](1, 1) 如果life < 0.2 ,則應輸出從[x, y](0, 0)

由於神經元的輸入和輸出應該在01之間,我將角度除以2 *Math.PI

這是代碼:

var network = new synaptic.Architect.Perceptron(3,4,1);

for(var i = 0; i < 50000; i++){
  var x = Math.random();
  var y = Math.random();
  var angle1 = angleToPoint(x, y, 0, 0) / (2 * Math.PI);
  var angle2 = angleToPoint(x, y, 1, 1) / (2 * Math.PI);
  for(var j = 0; j < 100; j++){
    network.activate([x,y,j/100]);
    if(j < 20){
      network.propagate(0.3, [angle1]);
    } else {
      network.propagate(0.3, [angle2]);
    }
  }
}

在這里嘗試一下: jsfiddle

因此,當我輸入以下輸入[0, 1, 0.19] 1.5PI / 2PI [0, 1, 0.19] ,我希望神經網絡輸出接近[0.75]1.5PI / 2PI )的1.5PI / 2PI 但是我的結果完全不一致,並且與任何輸入都沒有任何關聯。

我在教授神經網絡時犯了什么錯誤?

我已成功地教神經網絡來輸出1時輸入[a, b, c]c => 0.20時輸入[a, b, c]c < 0.2 我還設法教它根據[x, y]輸入將角度輸出到某個位置,但是我似乎無法將它們組合起來


根據要求,我編寫了一些代碼,使用2個神經網絡來獲得所需的輸出。 第一神經網絡將生命水平轉換為0或1,並且第二神經網絡根據從第一神經網絡輸出的0或1輸出角度。 這是代碼:

// This network outputs 1 when life => 0.2, otherwise 0
var network1 = new synaptic.Architect.Perceptron(3,3,1);
// This network outputs the angle to a certain point based on life
var network2 = new synaptic.Architect.Perceptron(3,3,1);

for (var i = 0; i < 50000; i++){
  var x = Math.random();
  var y = Math.random();
  var angle1 = angleToPoint(x, y, 0, 0) / (2 * Math.PI);
  var angle2 = angleToPoint(x, y, 1, 1) / (2 * Math.PI);

  for(var j = 0; j < 100; j++){
    network1.activate([x,y,j/100]);
    if(j < 20){
      network1.propagate(0.1, [0]);
    } else {
      network1.propagate(0.1, [1]);
    }
     network2.activate([x,y,0]);
    network2.propagate(0.1, [angle1]);
    network2.activate([x,y,1]);
    network2.propagate(0.1, [angle2]);
  }
}

在這里嘗試一下: jsfiddle

正如您在此示例中看到的那樣。 它設法非常接近地達到期望的輸出,通過添加更多迭代它將更加接近。

意見

  1. 傾斜分布作為訓練集采樣

    你的訓練集是選擇里面的life參數for(var j = 0; j < 100; j++) ,它高度偏向於j>20 ,因此life>0.2 它為該子集提供了4倍的訓練數據,這使您的訓練功能優先。

  2. 非混亂的訓練數據

    您正在按life參數順序訓練,這可能是有害的。 你的網絡將最終關注更大的j s,因為它是網絡傳播的最新原因。 你應該改變你的訓練集以避免這種偏見。

    這將與前一點疊加,因為您再次關注life值的某些子集。

  3. 您還應該衡量您的訓練表現

    盡管以前有過觀察,你的網絡並不是那么糟糕。 您的訓練錯誤不如您的測試那么大。 這種差異通常意味着您正在對不同的樣本分布進行培訓和測試。

    你可以說你有兩類數據點: life>0.2而其他數據點不是。 但是因為你在angleToPoint函數中引入了一個不連續性,我建議你將它分成三個類:保持一個life<0.2life<0.2 (因為函數連續運行)並在“above(1,1)”中拆分life>0.2和“下面(1,1)。”

  4. 網絡復雜性

    您可以分別為每個任務成功訓練網絡。 現在你想要堆疊它們。 這是深度學習的目的:每一層都建立在前一層感知的概念之上,因此增加了它可以學習的概念的復雜性。

    因此,我建議您使用2層10個節點,而不是在單個層中使用20個節點。 這與我在前一點中提到的類層次結構相匹配。

代碼

運行此代碼我的訓練/測試誤差為0.0004 / 0.0002

https://jsfiddle.net/hekqj5jq/11/

var network = new synaptic.Architect.Perceptron(3,10,10,1);
var trainer = new synaptic.Trainer(network);
var trainingSet = [];

for(var i = 0; i < 50000; i++){
  // 1st category: above vector (1,1), measure against (1,1)
  var x = getRandom(0.0, 1.0);
  var y = getRandom(x, 1.0);
  var z = getRandom(0.2, 1);
  var angle = angleToPoint(x, y, 1, 1) / (2 * Math.PI);
  trainingSet.push({input: [x,y,z], output: [angle]});
  // 2nd category: below vector (1,1), measure against (1,1)
  var x = getRandom(0.0, 1.0);
  var y = getRandom(0.0, x);
  var z = getRandom(0.2, 1);
  var angle = angleToPoint(x, y, 1, 1) / (2 * Math.PI);
  trainingSet.push({input: [x,y,z], output: [angle]});
  // 3rd category: above/below vector (1,1), measure against (0,0)
  var x = getRandom(0.0, 1.0);
  var y = getRandom(0.0, 1.0);
  var z = getRandom(0.0, 0.2);
  var angle = angleToPoint(x, y, 0, 0) / (2 * Math.PI);
  trainingSet.push({input: [x,y,z], output: [angle]});
}

trainer.train(trainingSet, {
    rate: 0.1,
    error: 0.0001,
    iterations: 50,
    shuffle: true,
    log: 1,
    cost: synaptic.Trainer.cost.MSE
});

testSet = [
    {input: [0,1,0.25], output: [angleToPoint(0, 1, 1, 1) / (2 * Math.PI)]},
    {input: [1,0,0.35], output: [angleToPoint(1, 0, 1, 1) / (2 * Math.PI)]},
    {input: [0,1,0.10], output: [angleToPoint(0, 1, 0, 0) / (2 * Math.PI)]},
    {input: [1,0,0.15], output: [angleToPoint(1, 0, 0, 0) / (2 * Math.PI)]}
];

$('html').append('<p>Train:</p> ' + JSON.stringify(trainer.test(trainingSet)));
$('html').append('<p>Tests:</p> ' + JSON.stringify(trainer.test(testSet)));

$('html').append('<p>1st:</p> ')
$('html').append('<p>Expect:</p> ' + angleToPoint(0, 1, 1, 1) / (2 * Math.PI));
$('html').append('<p>Received: </p> ' + network.activate([0, 1, 0.25]));

$('html').append('<p>2nd:</p> ')
$('html').append('<p>Expect:</p> ' + angleToPoint(1, 0, 1, 1) / (2 * Math.PI));
$('html').append('<p>Received: </p> ' + network.activate([1, 0, 0.25]));

$('html').append('<p>3rd:</p> ')
$('html').append('<p>Expect:</p> ' + angleToPoint(0, 1, 0, 0) / (2 * Math.PI));
$('html').append('<p>Received: </p> ' + network.activate([0, 1, 0.15]));

$('html').append('<p>4th:</p> ')
$('html').append('<p>Expect:</p> ' + angleToPoint(1, 0, 0, 0) / (2 * Math.PI));
$('html').append('<p>Received: </p> ' + network.activate([1, 0, 0.15]));

function angleToPoint(x1, y1, x2, y2){
  var angle = Math.atan2(y2 - y1, x2 - x1);
  if(angle < 0){
    angle += 2 * Math.PI;
  }
  return angle;
}

function getRandom (min, max) {
    return Math.random() * (max - min) + min;
}

進一步的評論

正如我在評論和聊天中提到的,沒有“(x,y)和(0,0)之間的角度”,因為矢量之間的角度概念通常被視為它們的方向和(0,0)沒有方向。

您的函數angleToPoint(p1, p2)返回(p1-p2)的方向。 對於p2 = (0,0) ,這意味着p1和x軸之間的角度正好。 但是對於p1 = (1,1)和p2 = (1,0)它不會返回45度。 對於p1 = p2,它是未定義的而不是零。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM