Нейронная сеть не обучается глубже 1 слоя
Нейросеть прекрасно справляется с линейными примерами, но когда добавляю хотя бы один скрытый слой - ошибка незначительно снижается и остается на одном и том же уровне бесконечно.
Пробовал и подбирал самые разные примеры, разное количество слоев и нейронов, но ничего не меняется. Даже y = x1 && x2 не считает (пробовал 0-3 скрытых слоя с разным количеством нейронов).
Использую логистическую функцию для начала.
function get_test_data(){
var p = [MyRand(-2, 2), MyRand(-2, 2)];
return{
p: p,
res: [p[0] && p[1] ? 1 : 0]
}
}
function activate_fn1(x, de){
if(!de){
return 1/(1 + Math.exp(-x));
}
else{
return activate_fn1(x, false)*(1 - activate_fn1(x, false));
}
}
async function learn(){
var ggg = 0;
while(1){
await sleep(sleeping);
errors[ggg] = []; // для истории ошибок
var test_data = get_test_data();
for (var i = 0; i < test_data.p.length; i++) {
layers[0][layers[0].length - i - 1].value = test_data.p[i]; // заполняю х1, х2...
}
// прогоняю данные по нейросети
for (var i = 0; i < connections.length; i++) {
for (var k = 0; k < connections[i].length; k++) {
if(layers[i + 1][k].is_bias) continue; // пропускаю нейрон смещения
layers[i + 1][k].value = 0;
for (var j = 0; j < connections[i][k].length; j++) {
layers[i + 1][k].value += layers[i][j].value*connections[i][k][j]; // значение += входное * вес связи
}
layers[i + 1][k].value = activate_fn1(layers[i + 1][k].value, false); // пропускаю значение через ф-ю активации;
}
}
//вычисляю ошибку
for (var i = 0; i < test_data.res.length; i++) {
var diff = activate_fn1(test_data.res[i], false) - layers[layers.length - 1][i].value; // ожидаемый сигнал - полученный
layers[layers.length - 1][i].error = diff;
errors[ggg].push(Math.abs(diff));
}
// вычисляю ошибки для скрытых нейронов
for (var i = connections.length - 1; i > 0; i--) {
for (var k = 0; k < connections[i][0].length; k++) {
layers[i][k].error = 0;
for (var j = 0; j < connections[i].length; j++) {
if(layers[i][k].is_bias) continue; // пропускаю нейрон смещения
layers[i][k].error += layers[i + 1][j].error*connections[i][j][k]; // ошибка += ошбика след. нейрона * вес связи
}
layers[i][k].error *= activate_fn1(layers[i][k].error, true); // ошибка = f'(x)
}
}
//исправляю ошибки
for (var i = 0; i < connections.length; i++) {
for (var j = 0; j < connections[i].length; j++) {
for (var k = 0; k < connections[i][j].length; k++) {
// вес += скорость * ошибку выходного нейрона * значение входного нейрона
connections[i][j][k] = connections[i][j][k] + speed*layers[i + 1][j].error*layers[i][k].value;
}
}
}
ggg++;
}
}