Tho*_*s W 17 javascript backpropagation neural-network
我正在尝试教一个神经网络,根据输入的生命水平决定去哪里.神经网络将始终接收三个输入[x, y, life].如果life => 0.2,它应该从输出的角度[x, y]来(1, 1).如果life < 0.2,它应该从输出的角度[x, y]来(0, 0).
由于神经元的输入和输出应该在0和之间1,我将角度除以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]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这里尝试一下:jsfiddle
因此,当我输入以下输入时[0, 1, 0.19],我希望神经网络输出接近[0.75](1.5PI / 2PI)的东西.但是我的结果完全不一致,并且与任何输入都没有任何关联.
我在教授神经网络时犯了什么错误?
我设法教一个神经网络输出
1时输入[a, b, c]与c => 0.2和0输入时[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]);
}
}
Run Code Online (Sandbox Code Playgroud)
在这里尝试一下:jsfiddle
正如您在此示例中看到的那样.它设法非常接近地达到期望的输出,通过添加更多迭代它将更加接近.
倾斜分布作为训练集采样
你的训练集是选择life里面的参数for(var j = 0; j < 100; j++),这是高度偏向于j>20和因此life>0.2.它为该子集提供了4倍的训练数据,这使您的训练功能优先.
非混乱的训练数据
您正在按顺序训练life参数,这可能是有害的.你的网络将最终更多地关注更大的js,因为它是网络传播的最新原因.你应该改变你的训练集以避免这种偏见.
这将与前一点叠加,因为您再次关注某些life值的子集.
您还应该衡量您的训练表现
尽管以前有过观察,你的网络并不是那么糟糕.您的训练错误不如您的测试那么大.这种差异通常意味着您正在对不同的样本分布进行培训和测试.
你可以说你有两类数据点:那些数据点life>0.2和其他数据点没有.但是因为你在angleToPoint函数中引入了一个不连续性,我建议你把它分成三个类:保持一个类life<0.2(因为函数连续运行)并分成life>0.2"above(1,1)"和"below(1,1) )".
网络复杂性
您可以分别为每个任务成功训练网络.现在你想要堆叠它们.这是深度学习的目的:每一层都建立在前一层感知的概念之上,因此增加了它可以学习的概念的复杂性.
因此,我建议您使用2层10个节点,而不是在单个层中使用20个节点.这与我在前一点中提到的类层次结构相匹配.
运行此代码我的训练/测试误差0.0004/ 0.0002.
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;
}
Run Code Online (Sandbox Code Playgroud)
正如我在评论和聊天中提到的,没有"(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,它是未定义的而不是零.
| 归档时间: |
|
| 查看次数: |
991 次 |
| 最近记录: |