Сеть доставки: forward
Полный прямой проход сети 3 → 2 → 1 на одном заказе
Проверяем по пути
После каждого слоя полезно проверить два вопроса: какие числа получились и сколько их должно быть.
Вернёмся к задаче прогноза времени доставки. Для одного заказа используем три признака:
- расстояние — 4 км;
- светофоры — 2;
- свободные курьеры поблизости — 6.
Запишем их одним вектором:
\[ x=[4,2,6]. \]
Наша сеть имеет структуру:
\[ 3\rightarrow2\rightarrow1. \]
Три входных значения поступают в два скрытых нейрона, а их результаты используются для получения одного прогноза.
Первый слой
У первого слоя три входа и два нейрона. Поэтому его матрица весов содержит три строки и два столбца:
\[ W_1= \begin{bmatrix} 0.5 & -0.25\\ 1 & 0.5\\ -0.5 & 0.25 \end{bmatrix}. \]
У каждого из двух нейронов есть своё смещение:
\[ b_1=[1,2]. \]
Линейная часть слоя:
\[ z_1=xW_1+b_1. \]
Проверяем размер.
На входе было 3 числа, а скрытых нейронов 2. Значит, после первого слоя мы должны получить ровно 2 значения.
Первый скрытый нейрон
Берём первый столбец \(W_1\) и первое смещение:
\[ z_{1,1} = 4\cdot0.5 + 2\cdot1 + 6\cdot(-0.5) + 1. \]
\[ z_{1,1} = 2+2-3+1 = 2. \]
Второй скрытый нейрон
Теперь используем второй столбец \(W_1\) и второе смещение:
\[ z_{1,2} = 4\cdot(-0.25) + 2\cdot0.5 + 6\cdot0.25 + 2. \]
\[ z_{1,2} = -1+1+1.5+2 = 3.5. \]
Итак, до функции активации первый слой получил:
\[ z_1=[2,3.5]. \]
Применяем ReLU
Теперь каждый скрытый нейрон пропускаем через ReLU:
\[ a_1=\operatorname{ReLU}(z_1). \]
Оба значения положительны:
\[ \operatorname{ReLU}(2)=2, \qquad \operatorname{ReLU}(3.5)=3.5. \]
Поэтому:
\[ a_1=[2,3.5]. \]
После первого слоя:
\[ x=[4,2,6] \rightarrow z_1=[2,3.5] \rightarrow a_1=[2,3.5]. \]
Значения \(z_1\) важно сохранить: они понадобятся позже во время backward, когда потребуется производная ReLU.
Выходной слой
Теперь два значения скрытого слоя превращаются в один прогноз. Весам выходного слоя зададим значения:
\[ W_2= \begin{bmatrix} 2\\ -1 \end{bmatrix}, \qquad b_2=8. \]
Выходной слой здесь линейный:
\[ \hat y=a_1W_2+b_2. \]
Подставляем значения:
\[ \hat y = 2\cdot2 + 3.5\cdot(-1) + 8. \]
\[ \hat y = 4-3.5+8 = 8.5. \]
Сеть предсказывает время доставки 8.5 минуты.
Считаем ошибку
Фактическое время доставки для этого заказа:
\[ y=20. \]
Используем квадрат ошибки:
\[ L=(\hat y-y)^2. \]
Подставляем прогноз:
\[ L=(8.5-20)^2. \]
\[ L=(-11.5)^2=132.25. \]
Forward завершён: сеть получила входные данные, вычислила прогноз и свела ошибку к одному числу \(L\).
Что получилось за весь forward
| Величина |
Значение |
Что означает |
| \(x\) |
[4, 2, 6] |
признаки заказа |
| \(z_1\) |
[2, 3.5] |
значения до ReLU |
| \(a_1\) |
[2, 3.5] |
выход скрытого слоя |
| \(\hat y\) |
8.5 |
прогноз времени |
| \(y\) |
20 |
фактическое время |
| \(L\) |
132.25 |
ошибка прогноза |
Весь прямой проход:
\[ x \rightarrow z_1 \rightarrow a_1 \rightarrow \hat y \rightarrow L \]
\[ [4,2,6] \rightarrow [2,3.5] \rightarrow [2,3.5] \rightarrow 8.5 \rightarrow 132.25. \]
Почему эти числа нужно сохранить
Forward нужен не только для получения прогноза. Его промежуточные результаты понадобятся на следующем этапе.
Во время backward мы начнём с \(L=132.25\) и пойдём по этой же сети в обратном направлении. Чтобы вычислять локальные производные, нам понадобятся уже найденные значения:
\[ x,\qquad z_1,\qquad a_1,\qquad \hat y. \]
То есть следующий шаг — не считать сеть заново, а использовать сохранённый forward, чтобы выяснить, как каждый вес повлиял на получившуюся ошибку.