2017-02-02 6 views
17

뉴럴 네트워크를 가르치 려하여 입력 된 값인 의 레벨을 기준으로을 결정하십시오. 뉴럴 네트워크는 항상 세 개의 입력을받습니다. [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]); 
    } 
    } 
} 

여기를보십시오 : 나는 다음과 같은 입력 [0, 1, 0.19]를 입력 할 때 jsfiddle

그래서, 내가 [0.75]에 가까운 출력 뭔가 신경망을 기대 여기

코드입니다 ( 1.5PI/2PI). 그러나 제 결과는 완전히 일치하지 않으며 주어진 입력과 상관 관계가 없습니다.

신경망을 가르치면서 어떤 실수를합니까?

I 출력 1에 신경망을 가르치는 데에 성공했으면 c => 0.20가 입력 될 때 c < 0.2[a, b, c][a, b, c]와 입력. 나는 또한 [x, y] 입력을 기반으로 특정 위치에 각도를 출력하도록 가르쳐 왔지만 나는 그것들을 조합 할 수 없다.. 요청으로


, 내가 원하는 출력을 얻기 위해 2 신경망을 사용하는 일부 코드를 작성했습니다. 첫 번째 뉴럴 네트워크는 라이프 레벨을 0 또는 1로 변환하고, 두 번째 뉴럴 네트워크는 첫 번째 뉴럴 네트워크에서 출력 된 0 또는 1에 따라 각도를 출력합니다. 이 예에서 볼 수 있듯이 jsfiddle

:

// 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]); 
    } 
} 

는 여기를보십시오 :이 코드입니다. 더 많은 반복을 추가함으로써 원하는 출력에 매우 근접하게 도달 할 수 있습니다. 교육으로 샘플링

+0

숨겨진 레이어에 더 많은 뉴런을 추가하는 것이 좋습니다. – cdm

+0

@cdm 시도했지만 차이는 없었습니다. 개별 레이어를 구성하여 내 네트워크를 만들려고합니다. –

+0

중 하나가 귀하의 레이어에 문제가 있거나 여러 신경망을 사용하는 것이 더 나은 해결책입니다. – Walfrat

답변

9

관찰

  1. 기울어 배포

    훈련 세트가 매우 j>20 결과적으로 life>0.2에 편중되어 for(var j = 0; j < 100; j++) 내부의 life 매개 변수를 선택하고있다 설정합니다. 해당 하위 집합에 대해 4 배 많은 교육 데이터가 있으므로 교육 기능의 우선 순위가 결정됩니다.

  2. 비 단행 훈련 데이터

    당신은 해가 될 수있는 life 매개 변수에 대해 순차적으로 훈련하고 있습니다. 네트워크는 네트워크 전파의 가장 최근의 이유이므로 더 큰 j에 더 많은주의를 기울일 것입니다. 이 편견을 피하기 위해 훈련 세트를 섞어 야합니다.

    life 값의 일부 하위 집합에 다시주의를 기울이기 때문에 이전 점과 중복됩니다.

  3. 당신은 이전의 관찰에도 불구하고, 정말 나쁘지 않았다, 당신의 훈련 성능뿐만 아니라

    네트워크를 측정한다. 귀하의 교육 오류가 귀하의 테스트만큼 큰 것은 아닙니다. 이러한 불일치는 대개 다른 샘플 배포에 대한 교육 및 테스트를 의미합니다.

    데이터 포인트의 클래스는 두 가지가 있습니다. 즉, life>0.2 인 데이터 클래스와 그렇지 않은 데이터 포인트가 있습니다. 하지만 angleToPoint 함수에서 불연속성을 도입 했으므로 다음과 같은 세 가지 클래스로 구분하는 것이 좋습니다. life<0.2 (함수가 계속 동작하기 때문에) 클래스를 유지하고 life>0.2을 "above (1,1)"및 "below 1,1). "

  4. 성공적 별도로 각 작업에 대한 네트워크를 훈련 할 수

    네트워크의 복잡성. 이제 더미 스택 싶어요. 이것은 deep 학습의 목적입니다. 각 계층은 이전 계층에서 인식 한 개념을 기반으로하므로 학습 할 수있는 개념의 복잡성이 증가합니다.

    따라서 단일 레이어에서 20 개의 노드를 사용하는 대신 10 개의 노드로 구성된 2 개의 레이어를 사용하는 것이 좋습니다. 이는 앞에서 언급 한 클래스 계층 구조와 일치합니다.

내가 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의 경우 0 대신 정의되지 않습니다.

+0

btw입니다. Cross Validated 네트워크로 옮겨야한다고 생각합니다. 분석에서 더 나은 답변과 수정 사항을 얻을 수 있습니다. – VillasV