alterna ai
ALTERNA AI / ГЛАВА 03 · 04

03.4 Много входов и много выходов

На предыдущей странице: собираем чувствительности в вектор.

Соберём в таблицу, как каждый выход зависит от каждого входа. Эта таблица местных чувствительностей называется матрицей Якоби.

Два выхода: [x², xy]; x=2, y=1.

Одна строка чувствительности на каждый выход

Если F:Rn→RmF:\mathbb R^n\to\mathbb R^m, результат имеет несколько компонент, поэтому одного gradient-вектора недостаточно. В курсе используется соглашение

JF(x)∈Rm×n,(JF)ij=∂Fi∂xj.J_F(x)\in\mathbb R^{m\times n}, \qquad (J_F)_{ij}=\frac{\partial F_i}{\partial x_j}.

Строка относится к одному выходу, столбец — к одному входу. Некоторые источники используют транспонированный layout; формулы корректны только после явного объявления соглашения.

Для

F(x,y)=[x2xy]F(x,y)= \begin{bmatrix} x^2\\xy \end{bmatrix}

получаем

JF(x,y)=[2x0yx].J_F(x,y)= \begin{bmatrix} 2x&0\\y&x \end{bmatrix}.

В точке z=[2,1]Tz=[2,1]^T:

F(z)=[4,2]T,JF(z)=[4012].F(z)=[4,2]^T, \qquad J_F(z)= \begin{bmatrix}4&0\\1&2\end{bmatrix}.

Первый столбец [4,1]T[4,1]^T описывает изменение обоих выходов при движении входа по xx; второй [0,2]T[0,2]^T — при движении по yy.

Jacobian является локальной матрицей преобразования

Для малого δ\delta

F(z+δ)≈F(z)+JF(z)δ.F(z+\delta)\approx F(z)+J_F(z)\delta.

При δ=[0.1,−0.2]T\delta=[0.1,-0.2]^T:

Jδ=[4012][0.1−0.2]=[0.4−0.3].J\delta= \begin{bmatrix}4&0\\1&2\end{bmatrix} \begin{bmatrix}0.1\\-0.2\end{bmatrix} =\begin{bmatrix}0.4\\-0.3\end{bmatrix}.

Линейное предсказание равно [4.4,1.7]T[4.4,1.7]^T, а точный выход

F(2.1,0.8)=[4.41,1.68]T.F(2.1,0.8)=[4.41,1.68]^T.

Ошибка [0.01,−0.02]T[0.01,-0.02]^T состоит из членов второго порядка: δx2\delta_x^2 и δxδy\delta_x\delta_y.

Forward и backward используют разные произведения

Произведение JδJ\delta переносит малое изменение входа вперёд и имеет shape [m,1][m,1]. Теперь пусть скалярный loss зависит от FF, а upstream gradient равен

gF=∇FL∈Rm×1.g_F=\nabla_F L\in\mathbb R^{m\times1}.

Chain rule даёт gradient по входу:

gz=JTgF,[n,m][m,1]=[n,1].g_z=J^Tg_F, \qquad [n,m][m,1]=[n,1].

Например, при gF=[1,−2]Tg_F=[1,-2]^T:

JTgF=[4102][1−2]=[2−4].J^Tg_F= \begin{bmatrix}4&1\\0&2\end{bmatrix} \begin{bmatrix}1\\-2\end{bmatrix} =\begin{bmatrix}2\\-4\end{bmatrix}.

Это сумма вкладов всех выходных путей к каждому входу. Транспонирование появляется из согласования shapes и скалярного дифференциала:

dL=gFT dF=gFTJ dz=(JTgF)Tdz.dL=g_F^T\,dF=g_F^TJ\,dz=(J^Tg_F)^Tdz.

В больших системах полный Jacobian часто не материализуют. Forward-mode вычисляет Jacobian-vector product JvJv, reverse-mode — vector-Jacobian product uTJu^TJ, эквивалентный JTuJ^Tu в столбцовой записи. Это разные способы применить ту же производную, а не разные определения.

В лаборатории меняйте xx и yy отдельно. Нулевой элемент J01=0J_{01}=0 означает, что первый выход локально не зависит от yy, но не отменяет существование второго выхода.

J = [[4, 0], [1, 2]]
delta = [.1, -.2]
forward = [sum(a*b for a, b in zip(row, delta)) for row in J]
upstream = [1, -2]
backward = [sum(J[i][j]*upstream[i] for i in range(2)) for j in range(2)]
assert all(abs(a - b) < 1e-12 for a, b in zip(forward, [.4, -.3]))
assert backward == [2, -4]

Код повторяет только что разобранные операции. Полный проверяемыйPython-пример главы доступен отдельным файлом; показанный короткий фрагмент не заменяет его реализацию.

Один изменённый вход может влиять на несколько выходов. Таблица Якоби собирает все такие местные влияния.

Как меняется сам наклон. Как этот вопрос продолжает полученный результат?

Python-примеры главы 03 Академическая база →