Нейронні мережі за 1 день

Всім привіт. Цього разу ми спробуємо розібратися з нейронними мережами без біології і за 1 день.

image

Навіщо вони потрібні?
Для того щоб зрозуміти навіщо потрібні нейронні мережі, потрібно розібратися з тим, що вони з себе представляють.

Штучні нейронні мережі — це сукупність штучних нейронів, які виконують роль суматорів.

Штучні нейронні мережі потрібні для вирішення складних завдань, наприклад: прогнозування, розпізнавання образів. Так само вони застосовуються в області машинного навчання і штучного інтелекту, ви можете вбудовувати їх в свої ігри.

Головна особливість нейронних мереж — вони здатні навчатися.

Штучний нейрон
Перед тим як переходити до побудови нейронних мереж, потрібно розібратися з їх одиницею — нейронами.



За входи позначені x1, x2. На них надходять дані, або у речовому вигляді, або в цілому. Дуже часто доводиться проводити нормалізацію вхідних даних. Для цього достатньо: $1 / number$
Кількість входів залежить від завдання.

Так само ми маємо ваги: w1, w2. В них і полягає суть нейронних мереж, через них проходить навчання. Про нього трохи пізніше.

Перед початком обробки даних, входи множаться на відповідні їм ваги. Т. е x1 * w1, x2 * w2. Далі результати творів надходять на нейрон і підсумовуються. (x1 * w1) + (x2 * w2)

Наприклад: x1 = 1; x2 = 3; w1 = 0; w2 = -1;
(1 * 0) + (3 * (-1) ) = -3

Засвоїмо для себе, що кількість ваг повинна відповідати кількості входів.

Далі результат підсумовування надходить у блок нелінійного перетворення. У ньому повинна знаходитися функція активації.

Функція активації
Функції активації потрібні для нормалізації вихідних даних. Припустимо відповідь -3 нам ні про що не говорить, і ми хотіли б перетворити його до 1 або 0.

Для такого є функція єдиного стрибка. Коли в нейроні заряд перевищив якийсь поріг, нейрон видає 1. Якщо заряд нижче порогу, то нейрон видасть 0. Наприклад, T — поріг. Він дорівнює 0. Результат підсумовування -3. -3 < 0, значить і відповідь нейрона 0. Якщо заряд був би більше, наприклад рівний 0.5 або 1 або 124124, то нейрон видав би 1.
Поріг встановлюється за вашим бажанням, так як нейронна мережа все одно підлаштуватися під нього.

Коли нам необхідно перетворити дані для більшого вибору варіанту, то нам необхідно перетворити підсумований результат у вид від 0 до 1.

Для такого у нас є логістична функція.
$1 / (1 + exp(-a * net))$
Або: $1 / (1 + exp(-net))$
a — ступінь крутизни на графіку функції.
net — результат підсумовування

У нашому випадку -3 перетворюється в 0.9525741268224334
У такому випадку ми можемо провідміняти таку відповідь до хорошого результату.

Практика
Уявімо собі таку задачу. Ми хотіли б отримати підказку від нейронної мережі, зустрічатися нам з дівчиною чи ні. Ми маємо такі вхідні дані:
Зріст дівчини, (у метрах)
На скільки вона красива, (1% — 100%)
Є розум, ( 1/0 )
Вміє готувати. (1/0)

Припустимо встановимо всі ці входи такими числами: 1.66, 100%, 1, 1
4 входи — 5 ваг. t(поріг) = 400
Встановимо зараз ваги без навчання, як ступінь важливості параметра:
1, 5,5, 4.

Множимо входи на відповідні їм за номером ваги: (1.66 * 1) + (100 * 5) + (1 * 5) + (1 * 4) = 1.66 + 500 + 5 + 4 = 510.66 > 400, значить зустрічатися з дівчиною можна, так як нейрон видасть 1.

Тепер спробуємо перевірити через логістичну функцію. 1 / (1 + exp(-510.66)) = 1.0
В даному випадку ми теж отримали 1, значить можна зустрічатися. Але тут у нас більше варіантів, бо тут ми можемо розподілити відповіді НС так:
net => 0.80, зустрічатися можна.
net < 0.80 && net != 0.5, потрібно ще подумати.
net <= 0.5, зустрічатися не потрібно.

Сподіваюся вам було зрозуміло.

Типи нейронних мереж
Тепер потрібно зрозуміти будову нейронних мереж. Вони поділяються на одношарові і багатошарові, з прямими зв'язками та зворотними зв'язками.


Єдине, що об'єднує ОНБ і МНС — це те, що вхідні нейрони не обробляють, лише передають сигнали на обробку.

Одношарові НС
У таких НС дані з вхідних шарів передаються відразу на вихідні нейрони, які обробляють сигнали.



В даному прикладі три вхідних нейрона(x1, x2, x3), три вихідних нейрона(out1, out2, out3).
В такому разі, виходить, три зв'язки кожного вихідного нейрона.
out1: w1, w2, w3. out2: w1, w2, w3. out3: w1, w2, w3.
Кожен зв'язок може мати різне значення.

Як нейрон обробляє сигнал — я писав вище.

Багатошарові НС
Такі НС працюють набагато складніше, але й вони здатні на більше.



Головна їх особливість — вони мають приховані(обробляють) шари.
Названі вони так, з-за того, що ми не бачимо які вони передають сигнали на виходи.
Сигнали вони обробляють, часто мають логістичну функцію активації, але можна і порогову(єдиний стрибок). З кількістю шарів і нейронів у них вам потрібно розібратися самим, бо для цього формул немає.

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

Мережі із зворотними зв'язками
Ці мережі мають як прямі зв'язки, так і зворотні.



Такі нейронні мережі можуть мати різну кількість шарів, або можуть бути взагалі одношаровими. Але головна їх особливість — вони мають асоціативну(короткочасну пам'ять. На таких нейронних мережах ви можете зробити чат-ботів. Так само вони можуть застосовуватися в управлінні, вирішувати завдання класифікації і багато іншого.

Персептрон
Персептрон — нейронна мережа рецептор. Він має вхідний шар(S), обробні шари(A),
вихідний шар®
Нейрони S шару вхідні. Вони можуть знаходитися в стані збудження(1), або в стані спокою(-1 або 0). Звичайно ж, ніхто не забороняє вам використовувати й інші числа. Так само ви можете їх нормалізувати, наприклад 1 / num, де num — ваше число.
Перш ніж потрапити в A шар, сигнали з S шару повинні пройти по терезам SA, значення яких можуть бути в межах від -1 до 1 в матеріальному вигляді. Далі, сигнали надходять в A шар, підсумовуються, проходять через функцію активації. Далі, сигнали, які йдуть по AR ваг. Тут вони можуть мати будь-які значення, які встановляться навчанням.
В нейронах R шару сигнали обробляються так само, проходять через функцію активації і ви отримайте відповідь.

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

Правило Хеба №1
Дане правило діє найчастіше з одношаровими перцептронами, вхідні сигнали яких дорівнюють 1, -1 або 0. З іншими числами у вас воно працювати не буде.
Працює воно просто:
1. Якщо нейронна мережа видає правильний результат, то вагові коефіцієнти не змінюються.
2. Якщо нейронна мережа помилилася і не дала правильну відповідь(розпізнала невірно), то вагові коефіцієнти зменшуються.
3. Якщо нейронна мережа помилилася і відкинула правильну відповідь, то вагові коефіцієнти збільшуються.


Правило Хеба №2
Це правило працює з усіма числами. По-іншому воно називається delta правилом.
Воно має дві формули, в яких потрібно розібратися, так як delta правило присутня в методах навчання для багатошарових нейронних мереж.
Для delta формули нам необхідно знати помилку мережі. Найчастіше, помилка — це різниця правильного і неправильного відповідей.
$err = d - b$
Де d — правильна відповідь, b — відповідь мережі.

Тепер розглянемо саму формулу:
$w(t+1) = w + err * n * xi$

w(t + 1) — новий ваговий коефіцієнт.
w — старий ваговий коефіцієнт
err — помилка(різниця правильної відповіді і відповіді мережі)
n — швидкість навчання
xi — значення яке прийшло на i-ий вхід

Я думаю, що вам не зовсім зрозуміла швидкість навчання і як її шукати. Шукається вона в діапазоні чисел від 0 до 1, дуже часто ставлять 0.001, 0.0001 або 1.

Метод зворотного поширення помилки
Це найкращий метод навчання мереж, який використовується як з багатошаровими, так і одношаровими мережами. Чим-то він може нагадати вам delta правило, бо формула та сама.
В даному випадку, нам необхідно створити лічильник помилок. Якщо показник лічильника дорівнює 0 — значить нейронна мережа навчена. Звичайно ж, в даному випадку нам необхідно мати навчальну добірку.

Алгоритм такого навчання наступний:
1. Ініціалізація ваг випадковими значеннями.
2. Вибрати навчальні дані, подати на входи мережі.
3. Обчислити вихід мережі.
4. Обчислити різницю між правильною і неправильною.
5. Коректуємо ваги для мінімізації помилки.
6. Повторюємо 2 і 5 крок, поки помилка не досягне 0 або прийнятного рівня.


Практика
Ось тепер ми практикуємо свої знання. Зараз ми спробуємо зробити одношаровий персептрон, який буде працювати з методом зворотного поширення помилки.
Нехай він будує логічну таблицю функцій 'AND' і 'OR'. Хто знайомий з алгеброю логіки, той зрозуміє.


Почнемо описувати цю мережу через ООП.
Ми бачимо, що у нас два вхідних нейрона, дві зв'язку, один вихідний нейрон.

public class NeuralNetwork {
static double enters[] = new double[2]; // створюємо входи
static double out; // зберігаємо вихід мережі
static double[] weights = {0,0}; // вагові коефіцієнти


Тепер нам необхідно створити матрицю готових відповідей і входів для таблиці AND.
static double tableOfLearn[][] = {
{0,0,0},
{1,0,0},
{0,1,0},
{1,1,1}
};


Створюємо обробку вхідних даних. Тут не так все складно. Якщо ви пам'ятаєте, то вхідні дані множать на відповідні їм за індексом ваги і результати творів підсумовуються. Скористаємося пороговою функцією. Якщо вихід > 0.1, то НС дає 1.

public static void summator(){
out = 0; обнуляем вихід
for ( int i = 0; i < enters.length; i++ )
out+=enters[i]*weights[i]; // вхід * вага, підсумовуємо.

if ( out > 0.1 ) out=1; else out=0; // функція активації
}


Тепер пишемо навчання мережі. Метод зворотного поширення помилки.
Створили лічильник помилок, запускаємо цикл. Копіюємо в входи НС вхідні дані з навчальної таблиці. Запускаємо обробник, отримуємо помилку. Далі використовуємо delta правило.

public static void train(){
double gError = 0; // створюємо лічильник помилок
int it = 0; // кількість ітерацій
do {
gError = 0; // лічильник обнуляем
it++; // збільшуємо на 1 ітерації
for ( int i = 0; i < tableOfLearn.length; i++ ){
enters = java.util.Arrays.copyOf(tableOfLearn[i], 
tableOfLearn[i].length - 1); // копіюємо в входи навчальні входи
summator(); // додаємо
double error = tableOfLearn[i][2] - out; // отримуємо помилку
gError+=Math.abs(error); // додаємо помилку в модулі
for ( int j = 0; j < enters.length; j++ )
weights[j]+=0.1*error*enters[j]; // старий вага + швидкість помилку * i-ий вхід
}
} while(gError!=0); // поки gError не дорівнює 0, виконуємо код
} 


Тепер ми запускаємо тестер НС. Включаємо навчання; НС навчилася; перевіряємо її роботу.

train();
for ( int p = 0; p < tableOfLearn.length; p++ ){
enters = java.util.Arrays.copyOf(tableOfLearn[p], 
tableOfLearn[p].length - 1);

summator();

System.out.println(out);
}


Включаємо тестування при запуску програми.
public static void main(String[] args) {
new NeuralNetwork().test();
}


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


Висновок
Звичайно, багато що може бути вам було не зрозуміло. На сайті я буду писати безліч статей про створення різних проектів з НС, тому пояснювати про них я буду не один раз. Я сподіваюся, що кому-то ця стаття сподобається. Спасибі за увагу, вдалого коду і слухняного ШІ.
Джерело: Хабрахабр

0 коментарів

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