Нейронні мережі — XOR [JS]

Добрий день. У минулій статті «Нейронні мережі за 1 день» ми розглянули НС яка вирішувала завдання AND, причому мережа була одношарова. В цей раз ми створимо нейронну мережу, яка буде здатна вирішити завдання XOR, вона буде багатошарова. Ця стаття навчить вас використовувати метод зворотного поширення помилки, введе в класифікацію.

image

Про завдання
Часто, для того щоб продемонструвати обмежені можливості одношарових перцептронів при вирішенні завдань вдаються до розгляду так званої проблеми XOR – виключає АБО. Дана логічна функція приймає два аргументи, які можуть бути 1 або 0. Функція приймає значення 1, коли один з двох аргументів 1, а інший 0. Якщо ж обидва дорівнюють 0 або 1, то в результаті ми отримуємо 0. На таке одношарова НС не здатна.

image
Модель
Подивіться уважно на цю картинку.

Минулого разу у нас було два вхідних нейрона, один вихідний і від двох вхідних нейронів зв'язку йшли до вихідного. Тепер ми маємо нейронну мережу, вхідні нейрони які відправляють сигнал на прихований шар, де у нас два оброблювальних нейрона, і ті передають сигнал на вихідний нейрон, який теж обробляє сигнал. Для такої задачі ми використовуємо двовимірні матриці для прихованих нейронів, так як кожен нейрон має дві зв'язки. Це буде набагато зручніше, ніж використовувати звичайні матриці. Якщо ви не зрозуміли що таке матриці — прийміть це за масив.

Програмуємо
Будемо програмувати на JavaScript. Для початку нам необхідно написати всі необхідні масиви та змінні: синапси, входи, вихід і нейрони.

{
var enters = new Array(2); // 2 входи
var hidden_layer = new Array(2); // два прихованих нейрона
var synapses_hidden = [[0.3, 1.3], [0.5,0.1]]; // від входів до прихованих нейронів
var synapses_output = [0.5, 0.1]; // від прихованих нейронів до виходу
var output = 0; // вихід

Тепер створимо матрицю навчання мережі.

var learn = [[0,0],[0,1],[1,0],[1,1]];
var learn_answers = [0,1,1,0]; 
}

Далі ми описуємо суматор, функції активації, передачу сигналу. В цей раз це виглядає трохи складніше, ніж в минулий раз.

function sum(){
for ( var i = 0; i < hidden_layer.length; i++ ){
hidden_layer[i] = 0;
for ( var j = 0; j < enters.length; j++ )
hidden_layer[i] += synapses_hidden[j][i] * enters[j];
if ( hidden_layer[i] > 0.5 ) hidden_layer[i] = 1; else hidden_layer[i] = 0;
}
output = 0;
for ( var i = 0; i < hidden_layer.length; i++ )
output += synapses_output[i] * hidden_layer[i];
if ( output > 0.5 ) output = 1; else output = 0;
}

Зворотне поширення помилки
Підемо ненадовго програмування. Метод зворотного поширення помилки схожий на delta правило. Тобто спочатку ми обчислюємо помилку(правильна відповідь мінус відповідь мережі), і потім міняємо ваги за формулою: w = w_last + err * n * x
Де w_last — минулий вага, err — помилка, n — швидкість навчання і x — вхідний сигнал
В даному випадку ми передаємо помилку за таким же зв'язків, звідки прийшов сигнал. Тобто від виходу до входу. Ще необхідно завести лічильник помилок оброблювального шару і глобальну помилку(gError = Math.abs(lErr))

var gError = 0; // глобальна помилка
var errors = new Array(hidden_layer.length); // шар помилок
do {
gError = 0; // обнуляем
for ( var p = 0; p < learn.length; p++ ){
for ( var i = 0; i < enters.length; i++ )
enters[i] = learn[p][i]; // подаємо про.входи на входи мережі
sum(); // запускаємо поширення сигналу
var error = learn_answers[p] - output; // отримуємо помилку
gError += Math.abs(error); // записуємо в глобальну
for ( var i = 0; i < errors.length; i++ ) 
errors[i] = error * synapses_output[i]; // передаємо помилку на шар помилок
// зв'язків до виходу
for ( var i = 0; i < enters.length; i++ ){
for ( var j = 0; j < hidden_layer.length; j++ )
synapses_hidden[i][j] += 0.1 * errors[i] * enters[j]; // змінюємо ваги
}
for ( var i = 0; i < synapses_output.length; i++ )
synapses_output[i] += 0.1 * error * hidden_layer[i]; // змінюємо ваги
} 
} while(gError != 0);

Тепер пишемо скрипт на запуск мережі:

for ( var p = 0; p < learn.length; p++ ){
for ( var i = 0; i < enters.length; i++ )
enters[i] = learn[p][i]; // записуємо входи
sum(); // поширюємо сигнал
document.write(output + "<br/>"); // виводимо відповіді
}

Ми отримаємо такий результат:

0 1 1 0

Якщо вам цікаво — демонстрація навчання і написання мережі на відео:


Фінал
Дані метод не демонструє повні можливості багатошарових мереж, лише вводить вас в класифікацію. Всім спасибі!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.