В этом посте продолжаю публикацию отдельных глав своей книги, посвященной программированию на языке Си.
Предыдущий пост "Послевкусие Си: решетка Кардано".
Глава 2. На початку була матриця
2.1. Множення матриць
Матрицею розміру n×m називається прямокутна таблиця спеціального вигляду, що складається з n рядків та m стовпців, заповнених числами. Елементи матриці A позначають aij, де i – номер рядка, в якому знаходяться елементи матриці, j – номер стовпця. Кількість рядків та стовпців задають розміри матриці. Зазвичай матрицю програмісти уявляють у вигляді двовимірного масиву.
Як знайти добуток матриць? Для обрахунку добутку матриць, зробимо детальний розв'язок прикладу, який дозволить зрозуміти алгоритм розв'язання таких задач.
Результатом множення матриці Am×n на матрицю Bn×k буде матриця Cm×k така, що елемент матриці C, який знаходиться в i-тому рядку та j-тому стовпчику (cij), дорівнює сумі добутків елементів i-того рядку матриці A на відповідні елементи j-того стовпчика матриці B. Дві матриці можна перемножити якщо кількість стовпчиків першої матриці дорівнює кількості рядків другої матриці.
Трохи спростим приклад і у якості матриці B візьмемо матрицю, яка містить тільки один стовпчик. Таку матрицю називають матрицею-стовпцем, або вектором. Наприклад:
У разі, якщо оновлення результуючого вектора за допомогою арифметики вказівників у тілі функції mvp вам не до смаку, то можна реалізувати цю функцію інакше:
Функція printv роздруковує вміст вектора, довжина якого передається через її другий параметр.
Компіляція файлу з вихідним кодом і запуск на виконання дадуть нам очікуваний результат:
Примітка: для компіляції коду прикладів перших трьох глав цієї книги використовувався компілятор:
Є один нюанс, на який слід звернути увагу. Якщо замість компілятора clang ви використаєте gcc, то йому (в залежності від його версії) дещо в цьому коді може не сподобатися. Ви можете отримати від компілятора gcc, наприклад, версії 7.4.0 приблизно таке повідомлення:
Спробуйте самостійно скомпілювати цей файл за допомогою компілятора gcc і проаналізуйте всі отримані від нього повідомлення.
2.2. Поширення сигналів в нейронній мережі
Використовуючи розпізнавання голосу у смартфоні або у Google Translate, ви неодмінно маєте справу з нейронною мережею, натренованою глибоким навчанням. За останні кілька років глибоке навчання забезпечило компанії Google прибуток, достатній для того, щоб покрити витрати на всі футуристичні проекти Google X, включаючи безпілотні автомобілі, окуляри Google Glass та науково-дослідний проект Google Brain. Google однією з перших почала застосовувати глибоке навчання. Ще у 2013 році Google найняла Джеффрі Хінтона, батька-засновника глибокого навчання, і зараз інші компанії намагаються її наздогнати. Ну і нам теж не до смаку пасти задніх, і якщо ви опанували обрахунок добутку матриць і розібралися з програмним кодом, що втілює цей алгоритм, то нам час перейти до вирішення нового завдання. Спробуємо використати ці знання для отримання відгуку нейронної мережі на заданий вхідний сигнал.
Буквою e математиці прийнято позначати константу, рівну 2.71828. Це так зване трансцендентне число. Якщо ви раптом не знаєте, що це таке, можете знайти цей термін в інтернеті; його пояснення виходить за межі теми цієї книги.
Дослідниками в галузі штучного інтелекту використовуються також інші функції активації аналогічного виду, але сигмоїда проста і дуже популярна, тому вона буде в нашому випадку підходящим вибором. У перцептроні вхідні дані (i) множаться на вагові коефіцієнти (w) і підсумовуються. Крім того, існує сутність під назвою зсув (bias, b) або параметр активації, який також додається до суми (Σ) вхідних даних, помножених на ваги. Параметр активації дає додаткову гнучкість навчальним можливостям персептрона, хоча перцептрон може працювати і без нього. Сума Σ проходить через сигмоїдальну функцію σ і перетворює Σ у вихідний сигнал нейрона.
Ми далі не заглиблюватимемося в теорію побудови нейронних мереж. На цю тему написано багато хороших книг, назву однієї з них ви знайдете в списку літератури [1].
Повернемося до наведеного вище зображення нейронної мережі (Рис. 2.1). На цій ілюстрації представлені три шари, перший і останній з яких включають по три штучні нейрони, або вузли, а середній шар – чотири вузли. Легко помітити, тут кожен вузол з'єднаний з кожним із вузлів попереднього та наступного шарів. З кожним з'єднанням асоціюється певна вага w. Низький ваговий коефіцієнт послаблює сигнал, високий – посилює його. Перший шар вузлів – вхідний. Його єдине призначення – представляти вхідні сигнали. У вхідних вузлах функція активації до вхідних сигналів не застосовується. Зараз немає необхідності висувати щодо цього якісь розумні доводи. Просто сприймаємо як даність: перший шар нейронних мереж є лише вхідним шаром, що представляє вхідні сигнали.
Для початку нам знадобиться кілька матриць. Перша (вектор) містить сигнали вхідного шару. Друга містить вагові коефіцієнти для зв'язків між вузлами двох шарів – вхідного та другого (так званого прихованого шару). Результатом множення цих двох матриць є об’єднаний згладжений сигнал, що надходить на вузли другого (вихідного) шару.
Обчислення вхідних сигналів, що надходять на кожен із вузлів другого шару, може бути виконано з використанням матричного множення. Немає потреби в тому, щоб якось особливо дбати про те, скільки вузлів входить у кожен шар. Збільшення кількості шарів призводить до збільшення розміру матриць. Щоб отримати вихідний сигнал другого шару, потрібно застосувати сигмоїду до кожного окремого елемента вектора, отриманого в результаті множення матриці вагових коефіцієнтів на вектор вхідних сигналів. Такий підхід застосовується для обчислення сигналів, що проходять від одного шару до наступного шару. Наприклад, за наявності трьох шарів ми просто знову виконаємо операцію множення матриць, використовуючи вихідні сигнали другого шару як вхідні для третього, але, зрозуміло, попередньо скомбінувавши їх і згладивши за допомогою додаткових вагових коефіцієнтів.
Задумайтесь на хвилину про значущість зв'язків між нейронами. У вашому мозку сотня мільярдів нейронів, але справжнє джерело вашої індивідуальності – зв'язок між цими нейронами. Кожен нейрон створює щонайменше тисячу зв'язків із іншими нейронами. Тобто у вашому мозку близько сотні трильйонів зв'язків. Наскільки велике це число? У Чумацькому Шляху приблизно 400 мільярдів зірок. У трильйоні – 1000 мільярдів. Виходить, що у вашому мозку більше нейронних зв'язків, ніж зірок у 5 тисячах Чумацьких Шляхів. Ось реальний масштаб індивідуальності – розмір вашої сутності. У світі не було, немає і мабуть ніколи не буде людини з ідентичною сотнею трильйонів зв'язків. Те, що ви запам'ятали, забули, що змушує вас сміятися, нервувати, радіти, що лякає, заспокоює чи виснажує – все це становить унікальну структуру, яка властива лише вам. Світ, який ви бачите протягом життя, видно тільки вам. Ваші реакції на цей світ – тільки ваші. Те, що ви любите – дії, морозиво в літню спеку, сміх коханої людини, рядок комп'ютерного коду, ідеальна відповідність візерунків двох потертих плиток на підлозі вашої кухні – все це доступно тільки вам. Ви все це пам'ятаєте. Усередині вас цілі галактики: вони світитимуть яскраво лише до тих пір, поки ви живі. Варто їм згаснути після вашої смерті, і ніщо і ніхто ніколи не сяятиме так само, як вони…
З теорією і філософією закінчено. Тепер час подивитися, як можна втілити теорію в коді, звернувшись до конкретного прикладу, який представлятиме нейронну мережу з трьома шарами по три вузли у вхідному і вихідному шарі та чотири вузли у прихованому шарі. Така мережа була представлена раніше.
2.3. Використання матричного множення у мережі з трьома шарами
Відомо, перший шар – вхідний, проміжний шар називається прихованим шаром, а третій – вихідний. Тепер можна розпочати створення власної нейронної мережі за допомогою мови С.
Матриця ваг Wih (input-hidden) містить вагові коефіцієнти для зв'язків між вхідним та прихованим шарами. Коефіцієнти для зв'язків між прихованим та вихідним шарами будуть зберігатися в іншій матриці, яку позначено Who (hidden-output) прихований-вихідний.
Нижче представлені вхідний вектор і всі вагові коефіцієнти (кожен з них вибирався як випадкове число). Ніякі особливі міркування поки що за їх вибором не стояли.
Комментариев нет:
Отправить комментарий