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

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

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

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

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

Однонейронний класифікатор

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

Почнемо з набору даних, який може розділяти один рядок. Уявіть собі чотири яблука одного сорту з назвами A, B, C і D. Кожна точка в наведеному нижче наборі даних представляє одне яблуко, яке описується двома безперервними вимірюваннями: показником кольору (x1x_1, від зеленішого до червонішого) та показником м’якості (x2x_2, від твердішого до м’якшого). Етикетки показують нам, чи кожне яблуко незріле (0) чи стигле (1).

ЯблукоКолір (x1x_1)М’якість (x2x_2)Клас
A−1-1−0.5-0.5Незрілі (0)
B−0.5-0.5+0.5+0.5Незрілі (0)
C+0.5+0.5+0.5+0.5Стиглий (1)
D+1+100Стиглий (1)

Значення, які ми використовуємо для кольору та м’якості, є ілюстративними та були відцентровані та масштабовані, тому нуль представляє еталонний рівень для кожної функції: від’ємні значення означають зеленіший або жорсткіший, а позитивні значення означають червоніший або м’якший відносно цих еталонних рівнів.

Кожне яблуко відображається як точка на графіку, але два його вимірювання також утворюють вхідний вектор: x=(color,softness)\mathbf{x}=(\text{color},\text{softness}). Ми можемо розділити цей вектор на два внески: (color,0)+(0,softness)(\text{color},0)+(0,\text{softness}). Вагові коефіцієнти класифікатора визначають, який внесок кожного в оцінку. Якщо достатньо лише кольору, тренування може зменшити вагу м’якості до нуля, зміни м’якості мало впливають на прогноз.

Наша перша мережа має два входи та один вихідний нейрон, без прихованого шару.

Два вхідних і один вихідний нейронКолір і м’якість одного яблука живлять один нейрон через ваги w1 і w2. Він додає зміщення та передбачає клас 1 для позитивного результату, клас 0 в іншому випадку. Прихованого шару немає.Вхідний векторВихідний нейронКласx₁x₂w₁w₂Σ + bs > 0?0 або 1

Нейрон обчислює оцінку для кожного яблука, а потім застосовує порогове значення, щоб передбачити його клас. Ми можемо організувати дві ваги нейрона в однорядкову матрицю WW, а два входи яблука — у вектор-стовпець x\mathbf{x}:

W=[w1w2],x=[x1x2]W=\begin{bmatrix}w_1&w_2\end{bmatrix}, \qquad \mathbf{x}=\begin{bmatrix}x_1\\x_2\end{bmatrix}

Щоб обчислити оцінку для одного яблука, ми множимо вагову матрицю WW на її вхідний вектор x\mathbf{x} і додаємо зміщення bb. Ми записуємо результат як s(x)s(\mathbf{x}), де ss означає бал, а x\mathbf{x} містить вимірювання кольору та м’якості яблука:

s(x)=Wx+b=[w1w2]×[x1x2]+b=w1x1+w2x2+bs(\mathbf{x})=W\mathbf{x}+b =\begin{bmatrix}w_1&w_2\end{bmatrix}\times\begin{bmatrix}x_1\\x_2\end{bmatrix}+b =w_1x_1+w_2x_2+b

Тут WxW\mathbf{x} обчислює один скалярний добуток між двома векторами: вектором ваги нейрона (w1,w2)(w_1,w_2), що зберігається як рядок WW, і вхідним вектором яблука (x1,x2)(x_1,x_2). Помножте кожну вагу на відповідні вхідні дані, а потім додайте два добутки. Додавання зміщення дає результат.

Множення WxW\mathbf{x} вже є лінійним перетворенням від R2\mathbb{R}^2 до R\mathbb{R}: від площини до прямої. Перетворення може перетворити вектор на скаляр; йому не потрібно зберігати однакову кількість координат. Ми повернемося до геометричної інтерпретації через базисні вектори, коли будемо будувати прихований шар.

Ця модель є перцептроном, однонейронним лінійним класифікатором. Його поетапна активація перетворює оцінку на передбачену мітку класу, y^\hat y:

y^=step⁡(s(x))={1if s(x)>0(ripe),0if s(x)≤0(unripe)\hat y=\operatorname{step}(s(\mathbf{x}))= \begin{cases} 1 & \text{if }s(\mathbf{x})>0 \quad \text{(ripe)},\\ 0 & \text{if }s(\mathbf{x})\le0 \quad \text{(unripe)} \end{cases}

Прочитайте step⁡(s(x))\operatorname{step}(s(\mathbf{x})) зсередини. По-перше, функція оцінки ss приймає вхідний вектор x\mathbf{x} і обчислює s(x)=w1x1+w2x2+bs(\mathbf{x})=w_1x_1+w_2x_2+b. Цей результат є числом, наприклад 0.40.4 або −0.5-0.5, а не міткою класу.

Потім функція step⁡\operatorname{step} бере цей бал і порівнює його з нулем. Позитивна оцінка дає позначку 1 (стиглий); нульовий або негативний бал дає позначку 0 (незрілий). Наприклад, s(x)=0.4s(\mathbf{x})=0.4 веде до step⁡(0.4)=1\operatorname{step}(0.4)=1, тоді як s(x)=−0.5s(\mathbf{x})=-0.5 веде до step⁡(−0.5)=0\operatorname{step}(-0.5)=0. Нотація y^\hat y позначає цю передбачену мітку. Ваги та зміщення визначають оцінку; функція step застосовує фіксоване правило, яке перетворює його на прогноз.

З математичної точки зору функція показників s(x)=w1x1+w2x2+bs(\mathbf{x})=w_1x_1+w_2x_2+b ділить вхідну площину на дві області прийняття рішень: позитивні оцінки дають зрілий клас, тоді як нульові або негативні бали дають незрілий клас. Порогове значення – це одне число в баловому просторі; вона відповідає межі рішення у вхідному просторі. Якщо принаймні одна вага відмінна від нуля, ця межа є лінією, що складається з усіх вхідних даних, оцінка яких дорівнює нулю:

w1x1+w2x2+b=0.w_1x_1+w_2x_2+b=0.

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

У початкових налаштуваннях віджета w1=w2=1w_1=w_2=1 і b=−0.5b=-0.5, тому оцінка x1+x2−0.5x_1+x_2-0.5, а межа x1+x2=0.5x_1+x_2=0.5. Ми прогнозуємо дозрілий, коли x1+x2>0.5x_1+x_2>0.5, і незрілий інакше, включаючи точки точно на межі. Порівняння результату з нулем еквівалентно порівнянню зваженої суми з 0.50.5:

x1 + x2 - 0.5 > 0   # Score exceeds zero
x1 + x2 > 0.5       # Weighted sum exceeds the threshold

Ми можемо реалізувати це правило прийняття рішення для одного яблука наступним чином:

def classify(x1, x2, w1, w2, b):
    score = w1 * x1 + w2 * x2 + b
    return int(score > 0)  # 1 = ripe, 0 = unripe

Ваги та зміщення визначають положення та орієнтацію межі. Коли w2≠0w_2\ne0, ми можемо побачити це, переписавши його рівняння у формі нахилу та перетину:

x2=−w1w2x1−bw2.x_2=-\frac{w_1}{w_2}x_1-\frac{b}{w_2}.

Нахил дорівнює −w1/w2-w_1/w_2, а точка перетину — −b/w2-b/w_2. Якщо w2=0w_2=0 і w1≠0w_1\ne0, кордоном є вертикальна лінія x1=−b/w1x_1=-b/w_1.

Геометрично, ваговий вектор (w1,w2)(w_1,w_2) вказує перпендикулярно межі в бік збільшення балів. Підтримуючи ваги фіксованими та змінюючи нахил, лінія зсувається паралельно самій собі. Отже, нанесена лінія та заштриховані області є геометричним виглядом того самого правила прийняття рішень, реалізованого в classify.

Давайте тепер візуалізуємо, як наш нейрон класифікує чотири яблука. У двовимірному перегляді за замовчуванням колір і м’якість кожного яблука визначають його положення на площині. Затінений фон показує прогнозований клас для кожної можливої ​​пари вхідних даних із прямою лінією, що розділяє незрілі та зрілі області. Кожен колір маркера показує відому етикетку яблука; рожеве кільце означає неправильне передбачення.

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

Переключіться на Огляд під кутом (3D), щоб побачити бали за цими прогнозами. Площина введення містить координати кольору та м’якості яблук, тоді як синя площина показує обчислену оцінку як висоту над або під нею. Там, де дві площини перетинаються, оцінка дорівнює нулю: це та сама межа, показана у 2D.

s(x) = 1.00x₁ + 1.00x₂ − 0.50

4 з 4 класифіковано правильно

1.00
1.00
-0.50
x₁-11x₂-11Яблуко A: Колір -1, М’якість -0.5, Оцінка -2.00, Прогнозування 0Яблуко B: Колір -0.5, М’якість 0.5, Оцінка -0.50, Прогнозування 0Яблуко C: Колір 0.5, М’якість 0.5, Оцінка 0.50, Прогнозування 1Яблуко D: Колір 1, М’якість 0, Оцінка 0.50, Прогнозування 1ABCD
● Нестигле (0)■ Стигле (1)

Формула над графіком — це обчислення оцінки нейрона з заміною поточних параметрів. Повзунки керують вагами w1w_1 і w2w_2 і зсувом bb, показаним на схемі мережі. Це параметри, за якими навчається.

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

Ми можемо перевірити два яблука в початкових налаштуваннях віджета. Для точки C на (0.5,0.5)(0.5,0.5) оцінка s(xC)=0.5+0.5−0.5=0.5s(\mathbf{x}_C)=0.5+0.5-0.5=0.5, отже прогноз зрілий (1). Для точки B на (−0.5,0.5)(-0.5,0.5) оцінка s(xB)=−0.5+0.5−0.5=−0.5s(\mathbf{x}_B)=-0.5+0.5-0.5=-0.5, тому прогноз незрілий (0). Ці точки лежать по різні боки межі.

Ми також можемо обчислити бали для всіх чотирьох яблук в одному матричному множенні. Ось як ми обробляємо пакет: збираємо вхідні вектори в матрицю XX з одним яблуком на рядок і кольором і м’якістю в двох стовпцях:

X=[−1−0.5−0.50.50.50.510]X=\begin{bmatrix} -1&-0.5\\ -0.5&0.5\\ 0.5&0.5\\ 1&0 \end{bmatrix}

Параметри все ті ж дві ваги і одне зміщення. Якщо ми починаємо з w1=1w_1=1, w2=1w_2=1 і b=−0.5b=-0.5, як у віджеті, вагова матриця та її транспонування:

W=[11],W⊤=[11]W=\begin{bmatrix}1&1\end{bmatrix}, \qquad W^\top=\begin{bmatrix}1\\1\end{bmatrix}

Зміщення b=−0.5b=-0.5 є окремим від WW і додається до зваженої суми кожного яблука.

Для одного яблука, записаного як вектор-стовпець, ми використали WxW\mathbf{x}. З яблуками, які зберігаються як рядки, ми використовуємо XW⊤XW^\top: транспонування перетворює рядок ваги нейрона на стовпець, тому кожен рядок яблука отримує скалярний добуток з однаковими вагами. Додавання однакового відхилення до кожного балу дає:

S=XW⊤+b1=[−1−0.5−0.50.50.50.510]×[11]+[−0.5−0.5−0.5−0.5]=[−2−0.50.50.5]S=XW^\top+b\mathbf{1} =\begin{bmatrix} -1&-0.5\\ -0.5&0.5\\ 0.5&0.5\\ 1&0 \end{bmatrix} \times\begin{bmatrix}1\\1\end{bmatrix} +\begin{bmatrix}-0.5\\-0.5\\-0.5\\-0.5\end{bmatrix} =\begin{bmatrix}-2\\-0.5\\0.5\\0.5\end{bmatrix}

Тут 1\mathbf{1} — стовпчик із чотирьох одиниць, тому b1b\mathbf{1} повторює зміщення для всіх чотирьох яблук. Рядки SS містять свої оцінки в порядку A–D. Для яблука A перший рядок обчислює 1(−1)+1(−0.5)−0.5=−21(-1)+1(-0.5)-0.5=-2, точно так само, як коли ми обробляємо його окремо. Застосування крокової функції до кожного балу дає прогнози (0,0,1,1)(0,0,1,1), усі правильні. Групування не змінює спосіб обчислення оцінки для окремого яблука. Наша партія містить увесь набір даних із чотирьох прикладів; великі набори даних часто поділяють на менші пакети, як обговорюється в як розмір пакету впливає на навчання.

Чотири яблука один нейрон не може розділити

Давайте продовжимо з нашими чотирма яблуками, які все ще описуються кольором (x1x_1) і м’якістю (x2x_2). Ми змінюємо їхні вхідні значення (x1,x2)(x_1,x_2) вручну, зберігаючи їхні мітки: A і B залишаються незрілими (0), а C і D залишаються дозрілими (1). Нові координати поміщають кожен клас на діагональ квадрата:

ЯблукоКолір (x1x_1)М’якість (x2x_2)Клас
A−0.5-0.5−0.5-0.5Незрілі (0)
B+0.5+0.5+0.5+0.5Незрілі (0)
C−0.5-0.5+0.5+0.5Стиглий (1)
D+0.5+0.5−0.5-0.5Стиглий (1)

Це знайомий шаблон XOR. Ми змістили звичайні двійкові координати, 0 і 1, до −0.5-0.5 і +0.5+0.5, розмістивши їх по обидві сторони від нуля на кожній осі. Чотири точки яблука утворюють квадрат із центром у початку координат: яблука з протилежними знаками для двох вхідних значень позначаються як стиглі (1), а яблука з відповідними знаками – як незрілі (0).

Кожен клас займає різну діагональ квадрата. Діагоналі перетинаються, тому жодна пряма лінія не може помістити всі незрілі яблука з одного боку, а всі стиглі яблука – з іншого. Це класична ілюстрація обмежень персептронів, проаналізованих Марвіном Мінскі та Сеймуром Пейпертом у їхній книзі Perceptrons 1969 року.

Коли ми поміщаємо яблука з оновленого набору даних через наш вихідний класифікатор, ті самі параметри w1=1w_1=1, w2=1w_2=1 і b=−0.5b=-0.5 тепер правильно класифікують лише одне з чотирьох. Відкрийте елементи керування параметрами віджета та спробуйте змінити w2w_2 на −1-1: це досягає трьох із чотирьох, а C все ще неправильно класифіковано.

Відрегулюйте ваги та зсув
1.00
1.00
-0.50

s(x) = 1.00x₁ + 1.00x₂ − 0.50

x₁-11x₂-11Яблуко A: Колір -0.5, М’якість -0.5, Оцінка -1.50, Прогнозування 0Яблуко C: Колір -0.5, М’якість 0.5, Оцінка -0.50, Прогнозування 0Яблуко D: Колір 0.5, М’якість -0.5, Оцінка -0.50, Прогнозування 0Яблуко B: Колір 0.5, М’якість 0.5, Оцінка 0.50, Прогнозування 1ABCD

Щоб вирішити XOR, ми збережемо два вхідних і один вихідний нейрони і вставимо прихований шар із двома нейронами, які використовують нелінійну активацію ReLU. Цей шар перетворює вимірювання кожного яблука в нові координати (h1,h2)(h_1,h_2), де вихідний нейрон може розділяти класи прямою лінією:

Два входи, два прихованих нейрона та один вихідний нейронОбидва входи підключаються до обох прихованих нейронів через W. Кожен додає своє зміщення та застосовує ReLU для отримання h1 або h2. Вихідний нейрон поєднує їх через V, додає c і прогнозує клас 1 для позитивного результату, клас 0 в іншому випадку.Вхідний векторПрихований шарВихідний нейронWVx₁x₂h₁Σ + b₁ReLUh₂Σ + b₂ReLUΣ + cs > 0?Клас: 0 або 1

На ілюстрації показано багатошаровий персептрон (MLP): мережа повністю з’єднаних шарів, де кожен нейрон отримує всі виходи від попереднього шару. Це також мережа прямого зв’язку (FFN), тобто інформація протікає від входу до виходу без повернення назад. Інші архітектури використовують різні види шарів. Згорткові нейронні мережі (CNN) використовують згорткові шари, які застосовують спільні фільтри до локальних регіонів, а також можуть включати повністю пов’язані шари, наприклад, для виконання остаточної класифікації. Рекурентні нейронні мережі (RNN) використовують повторювані рівні, які передають стан між кроками послідовності.

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

Представлення наших яблук у вигляді векторів і матриць

Кожне яблуко представлено у вигляді вектора двох чисел: оцінки кольору та оцінки м’якості. Ми використовуємо малі літери x\mathbf{x} для позначення вхідного вектора одного яблука, що містить його колірну оцінку x1x_1 і оцінку м’якості x2x_2. Для apple C ми запишемо цей вектор у вигляді стовпця:

xC=[−0.50.5]∈R2\mathbf{x}_C = \begin{bmatrix} -0.5 \\ 0.5 \end{bmatrix} \in \mathbb{R}^2

R2\mathbb{R}^2 — простір усіх пар дійсних чисел. Він є двовимірним, тому що для визначення будь-якої точки достатньо двох незалежних координатних напрямків: рухатися по першій осі, потім по другій.

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

Apple C як вектор у вхідній площиніСтрілка йде від початку координат до яблука C із кольором −0,5 і м’якістю 0,5. Пунктирні напрямні з’єднують його кінцеву точку з цими значеннями на осях. Стрілка та її кінцева точка представляють ту саму пару координат.М’якість (x₂)Колір (x₁)C(−0.5, 0.5)

Почніть приклад NumPy з цього представлення apple C:

import numpy as np

# One apple's representation: color and softness, in that order.
x = np.array([-0.5, 0.5])        # Shape (2,)

Ми пишемо xC\mathbf{x}_C у вигляді стовпця в математиці. У NumPy цей одновимірний масив надає вхідний вектор, коли ми множимо його на WW.

Простір репрезентації — це вся площина. Наш набір даних містить лише чотири точки в цій площині. Наявність чотирьох прикладів не робить простір чотиривимірним; кожен приклад все ще має дві координати.

Ми можемо зібрати чотири вектори в матрицю подання, з одним прикладом на рядок. XX у верхньому регістрі позначає матрицю, що містить усі чотири яблука, з одним вхідним вектором на рядок.

X=[−0.5−0.50.50.5−0.50.50.5−0.5]∈R4×2X = \begin{bmatrix} -0.5 & -0.5 \\ 0.5 & 0.5 \\ -0.5 & 0.5 \\ 0.5 & -0.5 \end{bmatrix} \in \mathbb{R}^{4 \times 2}

Рядки підраховують приклади (наші чотири яблука); колонки підраховують особливості (колір і м’якість). Ярлики стиглості зберігаються окремо.

Усі чотири яблукові вектори в одній вхідній площиніЧотири стрілки йдуть від початку координат до точки A (–0,5, −0,5), B (0,5, 0,5), C (–0,5, 0,5) і D (0,5, −0,5). Бірюзовими колами позначені незрілі яблука A і B; кораловими квадратами позначені стиглі яблука C і D. Усі чотири вектори мають дві координати.М’якість (x₂)Колір (x₁)A(−0.5, −0.5)B(0.5, 0.5)C(−0.5, 0.5)D(0.5, −0.5)

Це ті самі чотири позиції введення, які показано у віджеті XOR. Стрілки чітко показують, що кожна точка представляє вектор із початку координат.

Матриця представлення може містити вектори з вихідних вхідних даних, як тут робить XX, або вектори, створені попереднім шаром. В обох випадках кожен рядок представляє один приклад; що змінюється між шарами, так це інформація, закодована в його координатах, і, можливо, кількість координат. Ми відрізняємо цю роль від ролі матриці перетворення: XX містить уявлення, тоді як вагова матриця WW визначає лінійне перетворення, застосоване до них.

Наші яблука вже мають два числові вимірювання, тому сформувати їхні вхідні вектори просто. Для інших типів даних нам потрібно вирішити, як представити кожен приклад у вигляді вектора. Зображення 28×2828 \times 28 у відтінках сірого може стати вектором із 784 значеннями пікселів у фіксованому порядку, тоді як маркер може бути представлений вектором вбудовування. У кожному випадку кількість координат у векторі визначає кількість вхідних даних, які приймає щільний шар.

Наш шар потребує двох входів, навіть якщо ми зберемо ще мільйон прикладів.

Як базисні вектори визначають лінійне перетворення

Перш ніж перейти до перетворень, які виконує шар, давайте подивимося, як матриця описує лінійне перетворення через пункти призначення вхідних базисних векторів. Як тільки ми дізнаємося, де знаходяться ці вектори, лінійність підкаже нам, де знаходяться всі інші вхідні вектори.

У двовимірному просторі нам потрібні два лінійно незалежні вектори, щоб сформувати базис. Ми використовуємо звичайні одиничні вектори, по одному вздовж кожної координатної осі:

e1=[10],e2=[01]\mathbf{e}_1=\begin{bmatrix}1\\0\end{bmatrix}, \qquad \mathbf{e}_2=\begin{bmatrix}0\\1\end{bmatrix}

Вони утворюють звичайну основу вхідної площини. Розміщення цих двох векторів у стовпці дає одиничну матрицю:

I=[ e1  e2 ]=[1001]I=[\,\mathbf{e}_1\;\mathbf{e}_2\,] =\begin{bmatrix}1&0\\0&1\end{bmatrix}

Базисна матриця дає нам змогу реконструювати будь-який вектор з його координат у цьому базисі. Припустімо, ми визначаємо вектор як

x=[x1x2]\mathbf{x}=\begin{bmatrix}x_1\\x_2\end{bmatrix}

Його перша координата, x1x_1, масштабує перший стовпець, e1\mathbf{e}_1, а друга координата, x2x_2, масштабує другий стовпець, e2\mathbf{e}_2. Тепер ми використовуємо лінійну комбінацію базисних векторів із x1x_1 і x2x_2 як коефіцієнтами, щоб реконструювати вихідний вектор:

Ix=x1e1+x2e2⏟linear combination of basis vectors=x1[10]+x2[01]=[x1x2]=xI\mathbf{x}=\underbrace{x_1\mathbf{e}_1+x_2\mathbf{e}_2}_{\text{linear combination of basis vectors}} =x_1\begin{bmatrix}1\\0\end{bmatrix} +x_2\begin{bmatrix}0\\1\end{bmatrix} =\begin{bmatrix}x_1\\x_2\end{bmatrix}=\mathbf{x}

Це означає, що для визначення лінійного перетворення ми можемо вибрати нові координати для базисних векторів e1\mathbf{e}_1 і e2\mathbf{e}_2 і розмістити ці пункти призначення в стовпцях матриці. Потім ми використовуємо ту саму логіку лінійної комбінації, зберігаючи вихідні координати вхідного вектора як коефіцієнти, щоб побудувати перетворений вектор і побачити, де він потрапляє у вихідний простір.

Припустимо, лінійне перетворення надсилає e1\mathbf{e}_1 до [a,b]⊤[a,b]^\top і e2\mathbf{e}_2 до [c,d]⊤[c,d]^\top. Матриця перетворення записує ці нові пункти призначення як свої стовпці:

M=[acbd],Me1=[ab],Me2=[cd]M=\begin{bmatrix}a&c\\b&d\end{bmatrix}, \qquad M\mathbf{e}_1=\begin{bmatrix}a\\b\end{bmatrix}, \qquad M\mathbf{e}_2=\begin{bmatrix}c\\d\end{bmatrix}

Як ми бачили вище, ми можемо реконструювати трансформований вхідний вектор, взявши лінійну комбінацію цих трансформованих напрямків, використовуючи його вихідні координати як коефіцієнти. Ми масштабуємо перший стовпець MM на x1x_1 і другий на x2x_2, а потім додаємо результати:

M[x1x2]=x1[ab]+x2[cd]=[ax1+cx2bx1+dx2]M\begin{bmatrix}x_1\\x_2\end{bmatrix} =x_1\begin{bmatrix}a\\b\end{bmatrix} +x_2\begin{bmatrix}c\\d\end{bmatrix} =\begin{bmatrix}ax_1+cx_2\\bx_1+dx_2\end{bmatrix}

Вхідні координати (x1,x2)(x_1,x_2) стали вихідними координатами (ax1+cx2,  bx1+dx2)(ax_1+cx_2,\;bx_1+dx_2). Деякі лінійні перетворення згортають площину на лінію або точку. Вони все ще дійсні, і нейронні мережі можуть використовувати такі перетворення, щоб відкидати інформацію, зберігаючи відмінності, корисні для завдання.

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

Матриця шару визначає перетворення

Давайте спочатку розглянемо, як прихований шар створює нове представлення будь-якого вхідного вектора. Потім ми виберемо конкретні ваги та прослідкуємо за яблуком A через множення матриці, обчислюючи, де припадає його вектор.

Вагова матриця прихованого шару WW є нашою матрицею перетворення: вона визначає, як вектори з вхідних даних або попереднього шару лінійно перетворюються. Його форма залежить як від кількості входів, так і від кількості нейронів: із входами dd і нейронами mm WW має mm рядків і dd стовпців.

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

Наш рівень має два нейрони та два входи, тому WW має два рядки та два стовпці. Кожен рядок містить вагу одного нейрона для кольору (x1x_1) і його вагу для м’якості (x2x_2).

W=[1−0.8−0.81]W = \begin{bmatrix} 1 & -0.8 \\ -0.8 & 1 \end{bmatrix}

Ці ваги є параметрами, які мережа дізнається під час навчання. Тут ми вибрали їх вручну, щоб кожен крок був точним і легким для перевірки.

Тепер ми можемо підключити базисно-векторний вигляд до нейронів. Одну і ту ж матрицю можна читати в двох напрямках:

Вхідний базисний вектор e1\mathbf{e}_1Вхідний базисний вектор e2\mathbf{e}_2
Нейрон 111−0.8-0.8
Нейрон 2−0.8-0.811

Прочитайте на стовпець, щоб побачити, де знаходиться базисний вектор введення. Для e1=(1,0)\mathbf{e}_1=(1,0) нейрон 1 виробляє 11, а нейрон 2 виробляє −0.8-0.8, тому його призначенням є We1=(1,−0.8)W\mathbf{e}_1=(1,-0.8).

Прочитайте по рядку, щоб побачити ваги одного нейрона. Нейрон 1 надає першу координату обох трансформованих базисних векторів; нейрон 2 забезпечує другу координату обох.

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

Щоб застосувати це перетворення, ми множимо вектор вхідних даних x\mathbf{x} на WW, як WxW\mathbf{x}. Це обчислює одну зважену суму на нейрон.

Окрім вагової матриці, наш прихований шар також має вектор зміщення b\mathbf{b} з одним зміщенням для кожного з двох нейронів. Додавання b\mathbf{b} дає z=Wx+b\mathbf{z}=W\mathbf{x}+\mathbf{b}, вектор попередньої активації. Разом множення та зсувне додавання утворюють афінне перетворення: лінійне перетворення з наступним зсувом. Той самий вектор зміщення зсуває кожен результат. Лінійне перетворення завжди відображає початок координат у початок; додавання зміщення переміщує його до b\mathbf{b}. У нашому прикладі нижче b=0\mathbf{b}=\mathbf{0}, тому немає зсуву, і карта також є лінійною.

b=[00]\mathbf{b}=\begin{bmatrix}0\\0\end{bmatrix}

Потім ReLU замінює кожну від’ємну координату z\mathbf{z} нулем, утворюючи h=(h1,h2)\mathbf{h}=(h_1,h_2), результат прихованого шару. Це нове представлення яблука, яке вихідний нейрон використовуватиме для обчислення свого балу. Повна послідовність:

x  →  W    Wx  →  +b    z  →  ReLU    h\mathbf{x} \;\xrightarrow{\;W\;}\; W\mathbf{x} \;\xrightarrow{\;+\mathbf{b}\;}\; \mathbf{z} \;\xrightarrow{\;\text{ReLU}\;}\; \mathbf{h}

Визначте ту саму матрицю перетворення та зсув у NumPy:

# Two input coordinates -> two pre-activation coordinates.
# Rows hold neuron weights; columns record input basis-vector images.
W = np.array([[1.0, -0.8],
              [-0.8, 1.0]])     # Shape (2, 2)
b = np.array([0.0, 0.0])        # Bias vector; no shift here

Ми використаємо яблуко А як приклад, але наведений нижче віджет дозволяє вам стежити за будь-яким із чотирьох яблук через ту саму матрицю WW. Початковий вектор A є

xA=[−0.5−0.5]\mathbf{x}_A=\begin{bmatrix}-0.5\\-0.5\end{bmatrix}

Використовуючи правило поєднання стовпців, ми можемо обчислити WxAW\mathbf{x}_A крок за кроком, виходячи з його вихідних координат і стовпців WW.

  1. Прочитайте стовпці WW як пункти призначення базисних векторів e1\mathbf{e}_1 і e2\mathbf{e}_2. Перший стовпець повідомляє нам, де знаходиться e1=(1,0)\mathbf{e}_1=(1,0); другий говорить нам, де приземляється e2=(0,1)\mathbf{e}_2=(0,1):

    W=[1−0.8−0.81],We1=[1−0.8],We2=[−0.81].W=\begin{bmatrix}1&-0.8\\-0.8&1\end{bmatrix}, \qquad W\mathbf{e}_1=\begin{bmatrix}1\\-0.8\end{bmatrix}, \qquad W\mathbf{e}_2=\begin{bmatrix}-0.8\\1\end{bmatrix}.

    Це вихідні базисні вектори після застосування WW.

  2. Використовуйте вихідні координати A як коефіцієнти. Як ми показали вище, ми можемо використовувати лінійну комбінацію трансформованих базисних векторів для побудови вектора A в трансформованому просторі:

    WxA=−0.5(We1)+(−0.5)(We2)W\mathbf{x}_A=-0.5(W\mathbf{e}_1)+(-0.5)(W\mathbf{e}_2)

    Коефіцієнти залишаються незмінними; вектори, на які вони множать, тепер є перетвореними напрямками. Перша координата, −0.5-0.5, масштабує перший стовпець WW, який є перетвореним першим базисним вектором, We1W\mathbf{e}_1. Друга координата, також −0.5-0.5, масштабує другий стовпець, трансформований другий базисний вектор, We2W\mathbf{e}_2.

    Отже, повний розрахунок виглядає так:

    WxA=−0.5[1−0.8]+(−0.5)[−0.81]=[(−0.5)×1(−0.5)×(−0.8)]+[(−0.5)×(−0.8)(−0.5)×1]=[−0.50.4]+[0.4−0.5]=[−0.5+0.40.4+(−0.5)]=[−0.1−0.1]\begin{aligned} W\mathbf{x}_A &=-0.5\begin{bmatrix}1\\-0.8\end{bmatrix} +(-0.5)\begin{bmatrix}-0.8\\1\end{bmatrix}\\[6pt] &=\begin{bmatrix}(-0.5)\times 1\\(-0.5)\times(-0.8)\end{bmatrix} +\begin{bmatrix}(-0.5)\times(-0.8)\\(-0.5)\times 1\end{bmatrix}\\[6pt] &=\begin{bmatrix}-0.5\\0.4\end{bmatrix} +\begin{bmatrix}0.4\\-0.5\end{bmatrix} =\begin{bmatrix}-0.5+0.4\\0.4+(-0.5)\end{bmatrix} =\begin{bmatrix}-0.1\\-0.1\end{bmatrix} \end{aligned}

Два внески частково компенсують один одного, залишаючи (−0.1,−0.1)(-0.1,-0.1). Ми використали вихідні координати А, щоб об’єднати перетворені базові напрямки. Те саме правило застосовується до B, коефіцієнти якого +0.5+0.5:

WxB=0.5[1−0.8]+0.5[−0.81]=[0.10.1]W\mathbf{x}_B =0.5\begin{bmatrix}1\\-0.8\end{bmatrix} +0.5\begin{bmatrix}-0.8\\1\end{bmatrix} =\begin{bmatrix}0.1\\0.1\end{bmatrix}

A і B наближаються до початку координат, але залишаються різними точками. Матриця змінює їх уявлення, не зливаючи їх.

Анімація нижче показує обидва кроки разом: базові стрілки рухаються до пунктів призначення, записаних у WW, а вибране яблуко слідує їх лінійній комбінації, використовуючи свої вихідні координати як коефіцієнти. Синя сітка дотримується тієї самої трансформації, тоді як вихідна сітка залишається фіксованою для довідки.

Виберіть A, B, C або D, а потім виберіть Трансформувати. Коли спочатку вибрано A, його вектор переміщується від (−0.5,−0.5)(-0.5,-0.5) до (−0.1,−0.1)(-0.1,-0.1).

Яблуко:
-1-1110e₁e₂Яблуко A: (−0.50, −0.50)A
Оригінал: (−0.50, −0.50)Зараз: (−0.50, −0.50)

Ми можемо побачити, що робить перетворення, дотримуючись двох діагоналей:

W[11]=0.2[11],W[1−1]=1.8[1−1]W\begin{bmatrix}1\\1\end{bmatrix} =0.2\begin{bmatrix}1\\1\end{bmatrix}, \qquad W\begin{bmatrix}1\\-1\end{bmatrix} =1.8\begin{bmatrix}1\\-1\end{bmatrix}

Напрям A–B скорочується до однієї п’ятої своєї довжини, тоді як напрямок C–D розтягується в 1.81.8. Жоден напрямок не зникає. Це змінює форму квадрата з чотирма точками, але зберігає перетин діагоналей класу. Саме лінійне перетворення не зробило роздільним XOR. Для цього нам потрібно буде додати нелінійність через активацію ReLU, яку ми розглянемо нижче.

Ось як реалізувати це перетворення в NumPy, використовуючи матрицю W, визначену вище. Оператор @ виконує множення матриць:

x_A = np.array([-0.5, -0.5])    # A's original coordinates

# Apply W to the whole vector.
transformed_A = W @ x_A
print(transformed_A)             # [-0.1 -0.1]

Для матриці-векторного множення W @ x_A еквівалентно масштабуванню кожного стовпця W за відповідною координатою x_A і додаванню отриманих векторів. Ми можемо записати цю лінійну комбінацію явно:

# W[:, 0] is the first column; W[:, 1] is the second.
transformed_A = x_A[0] * W[:, 0] + x_A[1] * W[:, 1]
print(transformed_A)             # [-0.1 -0.1]

Як нейрони працюють разом, щоб трансформувати вектор

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

Ваги кожного нейрона утворюють один ряд WW. Ми записуємо ваги нейрона ii як вектор-стовпець wi\mathbf{w}_i, так що цей рядок буде wi⊤\mathbf{w}_i^\top. За допомогою нейронів mm рівень обчислює:

Wx=[w1⊤xw2⊤x⋮wm⊤x]W\mathbf{x}= \begin{bmatrix} \mathbf{w}_1^\top\mathbf{x}\\ \mathbf{w}_2^\top\mathbf{x}\\ \vdots\\ \mathbf{w}_m^\top\mathbf{x} \end{bmatrix}

Кожен скалярний добуток дає один скаляр; укладання цих скалярів дає перетворений вектор:

matrix–vector multiplication=stack of neuron dot products\boxed{\text{matrix–vector multiplication}=\text{stack of neuron dot products}}

Це описує множення ваги шару; додавання зміщення та функція активації слідують окремо.

Вище ми використовували матрицю перетворення шару для перетворення вхідного вектора apple A:

W=[1−0.8−0.81],xA=[−0.5−0.5]⟼WxA=[−0.1−0.1]W=\begin{bmatrix}1&-0.8\\-0.8&1\end{bmatrix}, \qquad \mathbf{x}_A=\begin{bmatrix}-0.5\\-0.5\end{bmatrix} \quad\longmapsto\quad W\mathbf{x}_A=\begin{bmatrix}-0.1\\-0.1\end{bmatrix}

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

У нашому повністю зв’язаному шарі кожен нейрон отримує однаковий повний вхідний вектор. Кожне яблуко має дві вхідні координати, тому кожному нейрону потрібні дві ваги: ​​одна для x1x_1 і одна для x2x_2. У нас є два нейрони, кожен з яких забезпечує один ряд вагових коефіцієнтів:

нейронВага для x1x_1Вага для x2x_2Ряд WW
111−0.8-0.8(1,−0.8)(1,-0.8)
2−0.8-0.811(−0.8,1)(-0.8,1)

Кожен рядок містить вагові коефіцієнти одного нейрона, тоді як кожен стовпець записує, де знаходиться один вхідний базисний вектор. Наприклад, перший стовпець містить ваги обох нейронів для x1x_1. Для вхідних даних e1=(1,0)\mathbf{e}_1=(1,0) ці ваги дають дві вихідні координати We1=(1,−0.8)W\mathbf{e}_1=(1,-0.8). Тож стовпець об’єднує внески обох нейронів.

Складання цих рядків дає нашу матрицю 2×22\times2 WW. Загалом, щільний шар із вхідними координатами dd і нейронами mm має

W∈Rm×d,x∈Rd  ⟼  Wx∈RmW\in\mathbb{R}^{m\times d}, \qquad \mathbf{x}\in\mathbb{R}^d \;\longmapsto\; W\mathbf{x}\in\mathbb{R}^m

Вхідний розмір визначає кількість стовпців; кількість нейронів визначає кількість рядків і вихідних координат. Ці підрахунки визначають форму матриці. Значення ваги визначають, яке лінійне перетворення вона виконує. Наприклад, два нейрони, які отримують тривимірні вхідні дані, дадуть матрицю 2×32\times3, яка відображає три вхідні координати на дві вихідні координати.

Об’єднання стовпців матриці та складання її скалярних добутків рядків дає той самий перетворений вектор. Ми отримали WxA=(−0.1,−0.1)W\mathbf{x}_A=(-0.1,-0.1) шляхом масштабування стовпців за вихідними координатами A та додавання їх. Тепер ми обчислимо це через два нейрони.

Для фіксованих ваг цей скалярний добуток визначає функцію, яка приймає вхідний вектор і повертає одне скалярне число: fi(x)=wi⋅xf_i(\mathbf{x})=\mathbf{w}_i\cdot\mathbf{x}. Для нашого першого нейрона ця скалярна лінійна функція є f1(x)=x1−0.8x2f_1(\mathbf{x})=x_1-0.8x_2, що відображає R2\mathbb{R}^2 на R\mathbb{R}. Тому матрицю трансформації та лінійну частину шару, який вона описує, можна розглядати як набір цих функцій, по одній на нейрон. Разом їхні результати утворюють T(x)=(f1(x),f2(x))⊤=WxT(\mathbf{x})=(f_1(\mathbf{x}),f_2(\mathbf{x}))^\top=W\mathbf{x}, відображаючи R2\mathbb{R}^2 на R2\mathbb{R}^2.

З нашими нульовими зміщеннями результати двох функцій також є координатами перед активацією. Виписування їх скалярних добутків дає

z=Wx=[w1⋅xw2⋅x]=[1⋅x1+(−0.8)⋅x2(−0.8)⋅x1+1⋅x2]\mathbf{z}=W\mathbf{x} =\begin{bmatrix} \mathbf{w}_1\cdot\mathbf{x}\\ \mathbf{w}_2\cdot\mathbf{x} \end{bmatrix} =\begin{bmatrix} 1\cdot x_1+(-0.8)\cdot x_2\\ (-0.8)\cdot x_1+1\cdot x_2 \end{bmatrix}

Для того самого яблука A обидва нейрони отримують (−0.5,−0.5)(-0.5,-0.5):

нейронЙого розрахунокКоординувати його виробляє
11(−0.5)+(−0.8)(−0.5)=−0.11(-0.5)+(-0.8)(-0.5)=-0.1z1=−0.1z_1=-0.1
2(−0.8)(−0.5)+1(−0.5)=−0.1(-0.8)(-0.5)+1(-0.5)=-0.1z2=−0.1z_2=-0.1

Збір цих двох чисел дає zA=(−0.1,−0.1)\mathbf{z}_A=(-0.1,-0.1), саме той вектор, який ми побудували, об’єднавши стовпці. Зважені суми нейронів разом виконують множення матриці шару. Кожен нейрон вносить одну координату результату; він не застосовує всю матрицю незалежно. Для кожного яблука використовуються однакові ваги.

Два представлення по-різному групують ту саму арифметику. Стовпець збирає внески однієї вхідної координати для всіх нейронів. Рядок збирає всі вагові коефіцієнти, які використовує один нейрон для обчислення вихідної координати. Жоден стовпець не належить одному нейрону. Обраний нами WW є симетричним, тому його рядки та стовпці містять однакові числа, але їхні ролі різні.

x1[1−0.8]+x2[−0.81]⏟column combination=[x1−0.8x2−0.8x1+x2]=[(1,−0.8)⋅(x1,x2)(−0.8,1)⋅(x1,x2)]⏟row dot products\underbrace{ x_1\begin{bmatrix}1\\-0.8\end{bmatrix} +x_2\begin{bmatrix}-0.8\\1\end{bmatrix} }_{\text{column combination}} =\begin{bmatrix}x_1-0.8x_2\\-0.8x_1+x_2\end{bmatrix} =\underbrace{ \begin{bmatrix} (1,-0.8)\cdot(x_1,x_2)\\ (-0.8,1)\cdot(x_1,x_2) \end{bmatrix} }_{\text{row dot products}}

Ми можемо зробити обчислення окремих нейронів явними в NumPy:

# Each row is one neuron's weight vector.
z1_A = np.dot(W[0], x_A)
z2_A = np.dot(W[1], x_A)
z_A = np.array([z1_A, z2_A])
print(z_A)                      # [-0.1 -0.1], the same as W @ x_A

Додавання зміщення кожного нейрона робить його функцію афінною; застосування ReLU робить його нелінійним. Разом ці виходи утворюють приховане представлення h\mathbf{h}. Ми розглянемо ефект ReLU нижче. Щоб продовжити код прямого проходу для apple C, використовуючи його попередній вхідний вектор x, ми обчислюємо зважені суми обох нейронів і додаємо їхні зміщення за одну операцію:

z = W @ x + b
print(z)                        # [-0.9  0.9] for apple C

Тепер, коли ми об’єднуємо всі вхідні вектори в матрицю представлення, ми можемо застосувати перетворення шару до всіх чотирьох яблук в одному множенні матриці. Ми розміщуємо A, B, C і D у рядках XX з двома їхніми вхідними координатами в стовпцях.

Для одного вектора стовпця ми використали WxW\mathbf{x}. Оскільки наш пакет зберігає вектори як рядки, ми використовуємо XW⊤XW^\top: транспонування WW поміщає вагові коефіцієнти кожного нейрона в стовпець, тому кожен рядок яблука отримує скалярний добуток з ваговими коефіцієнтами кожного нейрона.

Транспонування відповідає нашій угоді про зберігання: прикладами є рядки XX, а ваги нейронів — рядки WW. Якби ваги зберігалися з одним нейроном на стовпець, ми б використовували XWXW безпосередньо. Транспонування вирівнює розміри; це не змінює наміченої трансформації.

З нашими нульовими упередженнями розрахунок є

Z=XW⊤=[−0.5−0.50.50.5−0.50.50.5−0.5]×[1−0.8−0.81]=[−0.1−0.10.10.1−0.90.90.9−0.9]Z=XW^\top =\begin{bmatrix} -0.5&-0.5\\ 0.5&0.5\\ -0.5&0.5\\ 0.5&-0.5 \end{bmatrix} \times \begin{bmatrix} 1&-0.8\\ -0.8&1 \end{bmatrix} =\begin{bmatrix} -0.1&-0.1\\ 0.1&0.1\\ -0.9&0.9\\ 0.9&-0.9 \end{bmatrix}

Кожен рядок ZZ містить один перетворений вектор яблука; кожен стовпець містить зважені суми одного нейрона в групі. Перший рядок все ще (−0.1,−0.1)(-0.1,-0.1) для A, точно так само, як коли ми обробляли його окремо. Обраний нами WW є симетричним, тому W⊤W^\top має ті самі записи, що й WW, але транспонування виражає правильну операцію для прикладів, збережених у вигляді рядків.

У NumPy, використовуючи ті самі W і b, визначені вище:

# One input vector per row, in A, B, C, D order.
X = np.array([
    [-0.5, -0.5],
    [ 0.5,  0.5],
    [-0.5,  0.5],
    [ 0.5, -0.5],
])

# (4 apples, 2 inputs) @ (2 inputs, 2 neurons) -> (4, 2)
# Each apple's row takes a dot product with each neuron's weights.
Z = X @ W.T + b                  # Add the same bias vector to every row
print(Z)
# [[-0.1 -0.1]   A
#  [ 0.1  0.1]   B
#  [-0.9  0.9]   C
#  [ 0.9 -0.9]]  D

Пакетування групує обчислення без зміни перетворення будь-якого окремого вектора. Кожне яблуко проходить через обидва нейрони, використовуючи однакові ваги та зміщення; його розміри ніколи не поєднуються з розмірами іншого яблука.

Активація робить нове представлення роздільним

Поки що ми розрахували лінійну частину прихованого шару: кожен нейрон створює одну координату z=Wx\mathbf{z}=W\mathbf{x} без зсуву, оскільки наші зміщення дорівнюють нулю. Ось координати до активації:

точкаКласz=Wx\mathbf{z}=W\mathbf{x}
A0(−0.1,−0.1)(-0.1,-0.1)
B0(0.1,0.1)(0.1,0.1)
C1(−0.9,0.9)(-0.9,0.9)
D1(0.9,−0.9)(0.9,-0.9)

Сегмент A–B коротший, а сегмент C–D довший, але вони все одно перетинаються. Пряма лінія не може розділити два класи.

Перед В
-1-111x₁x₂ABCD
Після В
-1-111z₁z₂ABCD

В обох графіках однаковий масштаб. Відрізки з’єднують точки одного класу та перетинаються в початку координат.

Прихований шар має виконати ще одну операцію. Кожен нейрон застосовує нелінійну активацію ReLU до власної зваженої суми. Разом ці результати утворюють вихідний вектор прихованого шару, h\mathbf{h}:

ReLU⁡(z)=max⁡(0,z),h=ReLU⁡(z)\operatorname{ReLU}(z)=\max(0,z), \qquad \mathbf{h}=\operatorname{ReLU}(\mathbf{z})

ReLU — це кусково-лінійна функція: вона використовує одне правило для від’ємних вхідних даних, f(z)=0f(z)=0, і інше для невід’ємних вхідних даних, f(z)=zf(z)=z. Кожна частина пряма, але їх точка зустрічі створює вигин, тому вся функція є нелінійною. Застосований до зваженої суми нейрона, ReLU дозволяє цьому нейрону поводитися по-різному в різних областях вхідного простору.

Ми можемо записати ці два правила явно, використовуючи покускову нотацію. Дужка групує формули, а умова біля кожної формули повідомляє нам, коли вона застосовна:

ReLU⁡(z)={0,z<0,z,z≥0.\operatorname{ReLU}(z)= \begin{cases} 0, & z<0,\\ z, & z\geq0. \end{cases}

Він зберігає додатні значення та замінює від’ємні значення нулем. Наші дві приховані координати стають

h1=max⁡(0,x1−0.8x2),h2=max⁡(0,x2−0.8x1)h_1=\max(0,x_1-0.8x_2), \qquad h_2=\max(0,x_2-0.8x_1)

h1h_1 вимірює позитивну частину x1−0.8x2x_1-0.8x_2, тоді як h2h_2 вимірює позитивну частину x2−0.8x1x_2-0.8x_1. Це дві функції, які обчислює прихований шар.

Щоб побачити вплив ReLU на представлення кожного яблука, виберіть A, B, C або D, а потім виберіть Застосувати ReLU. Віджет починається з координат, створених WW. Якщо початково вибрано A, його вектор змінюється з (−0.1,−0.1)(-0.1,-0.1) на (0,0)(0,0). Вибір іншого яблука скидає анімацію до координат цього яблука перед активацією.

Яблуко:
-1-1110z₁z₂A
До ReLU: (−0.10, −0.10)Зараз: (−0.10, −0.10)

Ось координати до та після ReLU для всіх чотирьох яблук, які відповідають результатам, показаним у віджеті:

точкаКласПеред ReLU: z\mathbf{z}Після ReLU: h\mathbf{h}
A0(−0.1,−0.1)(-0.1,-0.1)(0,0)(0,0)
B0(0.1,0.1)(0.1,0.1)(0.1,0.1)(0.1,0.1)
C1(−0.9,0.9)(-0.9,0.9)(0,0.9)(0,0.9)
D1(0.9,−0.9)(0.9,-0.9)(0.9,0)(0.9,0)

A рухається до початку координат, оскільки обидві його координати від’ємні. B залишається на (0.1,0.1)(0.1,0.1), оскільки обидва позитивні. C і D втрачають свою негативну координату і приземляються на різні позитивні осі. Сегменти класу більше не перетинаються.

У NumPy застосуйте ReLU до обчисленої вище пакетної матриці Z. Операція maximum порівнює кожну координату з нулем і зберігає більше значення. Кожен рядок H містить одне приховане зображення яблука:

# Keep positive coordinates; replace negative ones with zero.
H = np.maximum(0, Z)
print(H)
# [[0.  0. ]   A
#  [0.1 0.1]   B
#  [0.  0.9]   C
#  [0.9 0. ]]  D

ReLU не обмежує вихід до 0 або 1. Тут він зберігає такі значення, як 0.10.1 і 0.90.9. Остаточним порогом класифікації є операція, яка повертає лише 0 або 1.

Вихідний рівень класифікує приховані представлення

Прихований шар створив новий вектор для кожного яблука. Вихідний нейрон отримує свої дві координати, h1h_1 і h2h_2.

Два входи, два прихованих нейрона та один вихідний нейронОбидва входи підключаються до обох прихованих нейронів через W. Кожен додає своє зміщення та застосовує ReLU для отримання h1 або h2. Вихідний нейрон поєднує їх через V, додає c і прогнозує клас 1 для позитивного результату, клас 0 в іншому випадку.Вхідний векторПрихований шарВихідний нейронWVx₁x₂h₁Σ + b₁ReLUh₂Σ + b₂ReLUΣ + cs > 0?Клас: 0 або 1

Цей вихідний нейрон має власні ваги, що зберігаються в VV, і зміщення cc. Навчання вивчатиме ці параметри разом із вагами та упередженнями прихованого шару. Для нашої демонстрації ми вибираємо їх вручну:

V=[11],c=−0.5V=\begin{bmatrix}1&1\end{bmatrix}, \qquad c=-0.5

Його оцінка — це ще один скапальний добуток, за яким слідує зміщення:

s(h)=Vh+c=[11]×[h1h2]+(−0.5)=1⋅h1+1⋅h2−0.5=h1+h2−0.5s(\mathbf{h})=V\mathbf{h}+c =\begin{bmatrix}1&1\end{bmatrix} \times\begin{bmatrix}h_1\\h_2\end{bmatrix}+(-0.5) =1\cdot h_1+1\cdot h_2-0.5 =h_1+h_2-0.5

Як і раніше, позитивна оцінка передбачає стиглість (1); нульовий або негативний бал передбачає незрілість (0). Границя рішення містить уявлення, оцінка яких дорівнює нулю:

h1+h2−0.5=0⟹h1+h2=0.5h_1+h_2-0.5=0 \quad\Longrightarrow\quad h_1+h_2=0.5

Цей поріг знаходиться між сумами для двох класів:

ЯблукоПриховане представлення (h1,h2)(h_1,h_2)h1+h2h_1+h_2ОцінкаПрогноз
A(0,0)(0,0)00−0.5-0.5Незрілі (0)
B(0.1,0.1)(0.1,0.1)0.20.2−0.3-0.3Незрілі (0)
C(0,0.9)(0,0.9)0.90.90.40.4Стиглий (1)
D(0.9,0)(0.9,0)0.90.90.40.4Стиглий (1)

A і B мають суми нижче 0.50.5, тоді як C і D мають суми вище. Тому лінія h1+h2=0.5h_1+h_2=0.5 розділяє класи. Обраний нами вручну поріг не є унікальним: будь-яке значення між 0.20.2 і 0.90.9 також розділятиме ці чотири представлення.

Давайте подивимося, як повна мережа класифікує наші яблука у вихідній площині введення. Віджет відкривається у виді зверху (2D), показуючи регіони прийняття рішень з усіма чотирма яблуками, правильно класифікованими відповідно до вибраних нами значень параметрів. Переключіться на Огляд під кутом (3D), щоб побачити (x1,x2,s(x))(x_1,x_2,s(\mathbf{x})): початкові координати кожного яблука разом із його остаточною оцінкою як висотою. Ця третя вісь візуалізує скалярний вихід; приховане представлення все ще має дві координати. Блакитна поверхня має складки, де приховані нейрони перемикаються між нульовим і позитивним виходами, а її перетин із вхідною площиною утворює межу прийняття рішення. Налаштуйте повзунки ваги та зсуву, щоб дослідити, як змінюються поверхня та прогнози, або виберіть Скинути, щоб відновити значення наших параметрів.

Відрегулюйте ваги та зміщення
Прихований нейрон 1: h1 = ReLU(1.00x₁ + (-0.80)x₂ + (0.00))
1.00
-0.80
0.00
Прихований нейрон 2: h2 = ReLU(-0.80x₁ + (1.00)x₂ + (0.00))
-0.80
1.00
0.00
Вихід: s = 1.00h₁ + (1.00)h₂ + (-0.50)
1.00
1.00
-0.50

Налаштуйте приховані ваги, щоб змінити складки, приховані зміщення, щоб змістити їх, і виведіть ваги, щоб змінити їхній внесок у оцінку. Вихідний зсув піднімає або опускає всю поверхню. Reset відновлює значення статті.

s(x) = Σⱼ vⱼ ReLU(wⱼ₁x₁ + wⱼ₂x₂ + bⱼ) + c

x₁-11x₂-11Яблуко A: Колір -0.5, М’якість -0.5, Оцінка -0.50, Прогнозування 0Яблуко B: Колір 0.5, М’якість 0.5, Оцінка -0.30, Прогнозування 0Яблуко C: Колір -0.5, М’якість 0.5, Оцінка 0.40, Прогнозування 1Яблуко D: Колір 0.5, М’якість -0.5, Оцінка 0.40, Прогнозування 1ABCD

Межа є прямою у прихованому просторі, але згинається у вихідному просторі введення. А і В лежать в незрілій області; C і D лежать в області стиглості по різні боки від неї. За допомогою цих ваг дві зрілі сторони з’єднуються далі вздовж позитивної діагоналі, за чотирма зразковими точками. Правильна класифікація чотирьох прикладів не визначає, що мережа повинна передбачити скрізь.

Щоб реалізувати вихідний рівень у NumPy, ми застосовуємо його ваги та зміщення до всіх чотирьох прихованих зображень. З одним яблуком на рядок HH ми обчислюємо S=HV⊤+cS=HV^\top+c, додаючи однакове зміщення до оцінки кожного яблука:

# Output transformation: two hidden coordinates -> one score.
V = np.array([[1.0, 1.0]])       # Shape (1, 2)
c = -0.5                        # Output bias

# (4 apples, 2 hidden coordinates) @ (2, 1) -> (4, 1)
# Each row takes a dot product with the same output weights.
S = H @ V.T + c
predictions = (S > 0).astype(int)  # 1 = ripe, 0 = unripe

for apple, score, prediction in zip("ABCD", S[:, 0], predictions[:, 0]):
    print(f"{apple}: score={score:.1f}, prediction={prediction}")
# A: score=-0.5, prediction=0
# B: score=-0.3, prediction=0
# C: score=0.4, prediction=1
# D: score=0.4, prediction=1

Чому тільки ReLU не вирішує цей набір даних

Що, якби прихований шар використовував матрицю ідентичності II для своїх ваг з нульовими зміщеннями? Це обчислить h=ReLU⁡(Ix)=ReLU⁡(x)\mathbf{h}=\operatorname{ReLU}(I\mathbf{x})=\operatorname{ReLU}(\mathbf{x}), точно так само, як застосувати ReLU безпосередньо до вихідних вхідних даних. Результат все одно буде компонуванням XOR: негативні вхідні координати стають нульовими, залишаючи A на (0,0)(0,0), B на (0.5,0.5)(0.5,0.5), C на (0,0.5)(0,0.5) і D на (0.5,0)(0.5,0). Це чотири кути меншого квадрата, причому кожен клас все ще займає окрему діагональ. Жодна пряма лінія не розділяє їх.

Перемикайтеся між Original, ReLU(x) і ReLU(Wx), щоб порівняти три розташування. Другий погляд використовує вагові коефіцієнти ідентичності; третій використовує обраний нами WW. Обидві альтернативи прихованого шару починаються з оригінальних вхідних векторів і використовують нульові зміщення.

Оригінальні входи: дві діагоналі класу перетинаються.

-1-1-0.5-0.500.50.511x₁x₂A: (−0.5, −0.5), Мітка 0AB: (0.5, 0.5), Мітка 0BC: (−0.5, 0.5), Мітка 1CD: (0.5, −0.5), Мітка 1D

Кожен квадрат має розмір 0,1 × 0,1. Осі використовують однаковий масштаб у всіх трьох видах.

A: (−0.5, −0.5)B: (0.5, 0.5)C: (−0.5, 0.5)D: (0.5, −0.5)

Жодна пряма лінія не розділяє два класи.

Матриця WW спочатку змінює координати так, що ReLU діє на більш корисну схему. Він розміщує B на (0.1,0.1)(0.1,0.1), а C і D на (−0.9,0.9)(-0.9,0.9) і (0.9,−0.9)(0.9,-0.9). Тоді ReLU тримає B біля початку координат і розміщує C і D далі вздовж додатних осей, тоді як A потрапляє в початок координат. Отримані зображення можна розділити прямою лінією.

Ні WW окремо, ні ReLU, застосовані безпосередньо до цих входів, не вирішують цей приклад; їхня комбінація робить класи лінійно роздільними. Рівень виводу може розділити результуючі представлення, як ми бачили вище.

Функції складання шарів

Деякі книги описують нейронні мережі як композицію функцій, які відображають вектори з одного векторного простору в інший. Наш прихований шар відображає R2\mathbb{R}^2 на R2\mathbb{R}^2, створюючи приховане представлення, а наш вихідний шар відображає R2\mathbb{R}^2 на R\mathbb{R}, створюючи одну скалярну оцінку. Кожна функція отримує результат попередньої. Ці функції можуть бути лінійними або нелінійними, як ми бачили з ваговою матрицею та ReLU.

Для нашої мережі викличте функцію прихованого рівня FF і функцію вихідного рівня GG:

F(x)=ReLU⁡(Wx+b),G(h)=Vh+cF(\mathbf{x})=\operatorname{ReLU}(W\mathbf{x}+\mathbf{b}), \qquad G(\mathbf{h})=V\mathbf{h}+c

Отже, перехід вперед, який ми прослідкували через віджети

x→Fh→Gs(x)\mathbf{x}\xrightarrow{F}\mathbf{h}\xrightarrow{G}s(\mathbf{x})

Заміна виводу прихованого шару у функцію вихідного шару дає

s(x)=G(F(x))=V×ReLU⁡(Wx+b)+cs(\mathbf{x})=G(F(\mathbf{x})) =V\times\operatorname{ReLU}(W\mathbf{x}+\mathbf{b})+c

Ось що тут означає композиція функції. Загальна нотація для цієї композиції – G∘FG\circ F, тобто спочатку застосувати FF, а потім GG. Більш глибока мережа дотримується того ж шаблону, FL∘⋯∘F2∘F1F_L\circ\cdots\circ F_2\circ F_1: кожен рівень перетворює представлення, яке він отримує, і передає свій результат наступному.

Без нелінійних активацій шари об’єднуються в одну афінну карту

Можливо, ви також читали, що без нелінійних активацій усі шари згортаються в один. Це легко побачити за допомогою наших двох вагових матриць. Тимчасово видаліть ReLU. Оскільки наші приховані зміщення дорівнюють нулю, вихідний нейрон тепер отримує WxW\mathbf{x} безпосередньо:

swithout ReLU(x)=V(Wx)+c=(VW)x+cs_{\text{without ReLU}}(\mathbf{x}) =V(W\mathbf{x})+c =(VW)\mathbf{x}+c

Ми можемо спочатку помножити VV і WW і використати їхній добуток як єдину вагову матрицю:

VW=[11]×[1−0.8−0.81]=[1⋅1+1⋅(−0.8)1⋅(−0.8)+1⋅1]=[0.20.2]VW= \begin{bmatrix}1&1\end{bmatrix} \times\begin{bmatrix}1&-0.8\\-0.8&1\end{bmatrix} =\begin{bmatrix}1\cdot1+1\cdot(-0.8)&1\cdot(-0.8)+1\cdot1\end{bmatrix} =\begin{bmatrix}0.2&0.2\end{bmatrix}

Отримана мережа обчислює

swithout ReLU(x)=0.2x1+0.2x2−0.5s_{\text{without ReLU}}(\mathbf{x})=0.2x_1+0.2x_2-0.5

Ми повернулися до такого ж результату, як і наш вихідний єдиний нейрон: два зважених вхідних даних плюс упередження з прямою межею рішення. Ці конкретні ваги дають оцінки −0.7-0.7, −0.3-0.3, −0.5-0.5 і −0.5-0.5 для A, B, C і D, передбачаючи незрілість для всіх чотирьох. Зміна вагових коефіцієнтів може покращити ці прогнози, але жодна афінна оцінка не може правильно класифікувати це розташування XOR.

Слово «згортання» відноситься до функції, яку обчислює мережа: один афінний рівень може створювати точно такі ж результати, як і весь стек. Ненульові зміщення не змінюють цього висновку. Вони об’єднуються в один ухил:

V(Wx+b)+c=(VW)x+(Vb+c)V(W\mathbf{x}+\mathbf{b})+c =(VW)\mathbf{x}+(V\mathbf{b}+c)

Повторення цього обчислення об’єднує будь-який стек афінних шарів в одну афінну карту. Застосування нашого останнього порогового значення кроку все ще створює пряму межу; сам по собі поріг не може дати нам ефект нелінійного прихованого шару.

Матричне множення записує складене перетворення

Це прямо пов’язано з нашим попереднім уявленням про стовпці як пункти призначення базисних векторів вхідних даних. Стовпці WW повідомляють нам, де e1\mathbf{e}_1 і e2\mathbf{e}_2 потрапляють після першого перетворення. Застосування VV до цих пунктів призначення повідомляє нам, де вони приземляються після обох:

VW=[V(We1)V(We2)]=[0.20.2]VW=\begin{bmatrix}V(W\mathbf{e}_1)&V(W\mathbf{e}_2)\end{bmatrix} =\begin{bmatrix}0.2&0.2\end{bmatrix}

Кожен вхідний базисний вектор закінчується на 0.20.2 на вихідному числовому прямому. Таким чином, для будь-якого введення те саме правило поєднання стовпців дає (VW)x=0.2x1+0.2x2(VW)\mathbf{x}=0.2x_1+0.2x_2.

Загалом, перемноження двох матриць перетворення застосовує ліву матрицю до кожного стовпця правої матриці. Якщо ми застосуємо M1M_1, а потім M2M_2, їхній продукт записує кінцеві пункти призначення базисних векторів вхідних даних:

x→M1M1x→M2M2(M1x)=(M2M1)x\mathbf{x}\xrightarrow{M_1}M_1\mathbf{x} \xrightarrow{M_2}M_2(M_1\mathbf{x}) =(M_2M_1)\mathbf{x}

Крайня права матриця діє першою. Продукт представляє обидва лінійні перетворення як одне.

ReLU змінює те, що отримує наступний рівень

Тепер поставте ReLU між WW і VV. Вихідний нейрон отримує ReLU⁡(Wx)\operatorname{ReLU}(W\mathbf{x}), тому він більше не просто додає дві координати, створені WW. Він додає їх невід’ємні частини:

s(x)=max⁡(0,x1−0.8x2)+max⁡(0,x2−0.8x1)−0.5s(\mathbf{x}) =\max(0,x_1-0.8x_2)+\max(0,x_2-0.8x_1)-0.5

Наприклад, координати C після WW є (−0.9,0.9)(-0.9,0.9). Вихідний нейрон отримує скалярний добуток своїх ваг (1,1)(1,1) із цим вектором, а потім додає зсув −0.5-0.5. Без ReLU розрахунок є

(1,1)⋅(−0.9,0.9)−0.5=1(−0.9)+1(0.9)−0.5=−0.5.(1,1)\cdot(-0.9,0.9)-0.5 =1(-0.9)+1(0.9)-0.5=-0.5.

За допомогою ReLU вхідний вектор стає (0,0.9)(0,0.9):

(1,1)⋅(0,0.9)−0.5=1(0)+1(0.9)−0.5=0.4.(1,1)\cdot(0,0.9)-0.5 =1(0)+1(0.9)-0.5=0.4.

Скасування походить від вихідних ваг (1,1)(1,1): вони дають двом протилежним значенням однакову вагу. Точковий добуток не завжди скасовує їх; різні ваги можуть дати ненульову суму. У термінах лінійної алгебри (−0.9,0.9)(-0.9,0.9) лежить у нульовому просторі вихідної матриці: він дає нульовий внесок у оцінку до зміщення. ReLU змінює його на (0,0.9)(0,0.9), який більше не лежить у цьому нульовому просторі і, отже, сприяє оцінці.

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

VReLU⁡(Wx)≠(VW)xin generalV\operatorname{ReLU}(W\mathbf{x})\neq(VW)\mathbf{x} \quad\text{in general}

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

Таким чином, оцінка нашої мережі є кусково-афінною: у кожній області, де активні ті самі нейрони, вона дотримується одного афінного правила. Різні шаблони активації створюють різні правила, утворюючи плоскі поверхні, які зустрічаються вздовж країв. Остаточна межа класифікації проходить за місцями, де ці поверхні досягають нульового балу. Ми часто називаємо це кусково-лінійною поведінкою; кусково-афінний тут більш точний, оскільки оцінка включає зміщення. Ця структура походить від ReLU: нелінійні активації, такі як сигмоїда, натомість створюють вигнуті поверхні.

Щоб записати оцінку в кускових нотаціях, використовуйте aa і bb як скорочення для зважених сум двох прихованих нейронів:

a=x1−0.8x2,b=x2−0.8x1.a=x_1-0.8x_2,\qquad b=x_2-0.8x_1.

Тоді стає s(x)=max⁡(0,a)+max⁡(0,b)−0.5s(\mathbf{x})=\max(0,a)+\max(0,b)-0.5

s(x1,x2)={−0.5,a≤0, b≤0,x1−0.8x2−0.5,a>0, b≤0,x2−0.8x1−0.5,a≤0, b>0,0.2x1+0.2x2−0.5,a>0, b>0.s(x_1,x_2)= \begin{cases} -0.5, & a\leq0,\ b\leq0,\\ x_1-0.8x_2-0.5, & a>0,\ b\leq0,\\ x_2-0.8x_1-0.5, & a\leq0,\ b>0,\\ 0.2x_1+0.2x_2-0.5, & a>0,\ b>0. \end{cases}

Чотири випадки відповідають тому, які приховані нейрони активні: жоден, тільки перший, тільки другий або обидва. Кожна формула описує плоский шматок поверхні партитури; разом вони утворюють нелінійну функцію. Фігури збігаються там, де вони зустрічаються, тому партитура залишається безперервною навіть там, де її нахил змінюється.

Це також з’єднує два види у нашому віджеті класифікатора. У прихованому просторі вихідною межею є пряма лінія h1+h2=0.5h_1+h_2=0.5. Підстановка функцій прихованого шару дає ту саму межу у початкових вхідних координатах:

max⁡(0,x1−0.8x2)+max⁡(0,x2−0.8x1)=0.5\max(0,x_1-0.8x_2)+\max(0,x_2-0.8x_1)=0.5

Якщо активний лише перший нейрон, це зводиться до x1−0.8x2=0.5x_1-0.8x_2=0.5. Якщо активна лише друга, вона стає x2−0.8x1=0.5x_2-0.8x_1=0.5. Якщо обидва активні, він стає 0.2(x1+x2)=0.50.2(x_1+x_2)=0.5. Ці прямі частини з’єднуються в кутах, утворюючи межу, яку ми бачимо у вихідній вхідній площині.

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

Запустіть модель на всіх чотирьох яблуках за допомогою NumPy

Давайте тепер об’єднаємо операції в одному прикладі NumPy, який можна запускати. У кожному рядку залишається одне яблуко протягом усього проходу вперед:

X⏟4×2  ⟶  Z⏟4×2  →  ReLU⁡    H⏟4×2  ⟶  S⏟4×1\underbrace{X}_{4\times2} \;\longrightarrow\; \underbrace{Z}_{4\times2} \;\xrightarrow{\;\operatorname{ReLU}\;}\; \underbrace{H}_{4\times2} \;\longrightarrow\; \underbrace{S}_{4\times1}

Ми використовуємо ту саму домовленість про рядок для прикладу, що й вище: Z=XW⊤+bZ=XW^\top+\mathbf{b}, H=ReLU⁡(Z)H=\operatorname{ReLU}(Z) і S=HV⊤+cS=HV^\top+c, з кожним зміщенням, доданим до кожного рядка. Розмір партії та розмір представлення є різними параметрами: чотири приклади залишаються незмінними, а дві приховані координати кожного яблука стають одним вихідним балом.

import numpy as np

# Representation matrix X, shape (4, 2):
# rows = apples A, B, C, D; columns = color and softness.
X = np.array([
    [-0.5, -0.5],
    [ 0.5,  0.5],
    [-0.5,  0.5],
    [ 0.5, -0.5],
])
labels = np.array([0, 0, 1, 1])   # Targets, kept separate from X

# Transformation matrix W, shape (2, 2), shared by all apples.
# Rows hold neuron weights; columns are transformed basis vectors.
W = np.array([
    [ 1.0, -0.8],
    [-0.8,  1.0],
])
b = np.array([0.0, 0.0])

# Output transformation V, shape (1, 2): two coordinates -> one score.
V = np.array([[1.0, 1.0]])
c = -0.5

# The examples are rows, so transpose W to compute each
# apple's dot product with each neuron's weights: (4, 2) @ (2, 2).
# NumPy adds the same bias vector to every row.
Z = X @ W.T + b                  # Shape (4, 2)

# ReLU replaces negative coordinates with zero.
H = np.maximum(0, Z)             # Shape (4, 2): new representations

# Compose the output map with the hidden map, row by row:
# (4, 2) @ (2, 1) -> (4, 1), then add the same scalar bias.
scores = H @ V.T + c             # One score per apple
predictions = (scores[:, 0] > 0).astype(int)

print(H)
# [[0.  0. ]   A
#  [0.1 0.1]   B
#  [0.  0.9]   C
#  [0.9 0. ]]  D

print(scores[:, 0])             # [-0.5 -0.3  0.4  0.4]
print(predictions)              # [0 0 1 1]

XX і HH описують однакові приклади в різних просторах. WW і VV визначають перетворення між цими просторами. Активація між ними – це те, що дозволяє повній мережі виражати нелінійне правило.

Чому зміна представлення допомагає

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

XOR робить це бетоном. У вихідній площині колір–м’якість немає прямої лінії, що розділяє класи. Вагова матриця змінює це розташування, а ReLU змінює його нелінійно. У результуючому представленні достатньо зваженої суми та порогового значення. Проблема класифікації залишилася незмінною; представлення, що використовується для її вирішення, змінилося.

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

Більші мережі можуть вивчати представлення з набагато більшою кількістю координат, властивостей кодування та зв’язків, корисних для їхніх завдань. Їхня архітектура визначає доступні розміри; навчання регулює те, як входи представлені в них. Концепції не обов’язково відповідають окремим координатам: інформація може бути розподілена між багатьма координатами та використана наступними рівнями. Мережі також можуть представляти більше функцій, ніж вони мають виміри, кодуючи їх у напрямках, що перекриваються, це явище називається суперпозиція.

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

Перегляд зображення

Змінюйте масштаб жестом щипка або клавішами + / −. Переміщуйте зображення перетягуванням або стрілками. Esc — закрити.