Alterna · учебный материал
03.4 Много входов и много выходов
Соберём в таблицу, как каждый выход зависит от каждого входа. Эта таблица местных чувствительностей называется матрицей Якоби.
Что в этом материале
- Одна строка чувствительности на каждый выход
- Jacobian является локальной матрицей преобразования
- Forward и backward используют разные произведения
Содержание и основные понятия
На предыдущей странице: собираем чувствительности в вектор.
Соберём в таблицу, как каждый выход зависит от каждого входа. Эта таблица местных чувствительностей называется матрицей Якоби.
Два выхода: [x², xy]; x=2, y=1.
Для изменения рисунка включитеJavaScript; расчёт и теория доступны далее.
Одна строка чувствительности на каждый выход
Если
F
:
R
n
→
R
m
F:\mathbb R^n\to\mathbb R^m
F
:
R
n
→
R
m
, результат имеет несколько компонент, поэтому одного gradient-вектора недостаточно. В курсе используется соглашение
J
F
(
x
)
∈
R
m
×
n
,
(
J
F
)
i
j
=
∂
F
i
∂
x
j
.
J_F(x)\in\mathbb R^{m\times n},
\qquad (J_F)_{ij}=\frac{\partial F_i}{\partial x_j}.
J
F
(
x
)
∈
R
m
×
n
,
(
J
F
)
ij
=
∂
x
j
∂
F
i
.
Строка относится к одному выходу, столбец — к одному входу. Некоторые источники используют транспонированный layout; формулы корректны только после явного объявления соглашения.
Для
F
(
x
,
y
)
=
[
x
2
x
y
]
F(x,y)=
\begin{bmatrix}
x^2\\xy
\end{bmatrix}
F
(
x
,
y
)
=
[
x
2
x
y
]
получаем
J
F
(
x
,
y
)
=
[
2
x
0
y
x
]
.
J_F(x,y)=
\begin{bmatrix}
2x&0\\y&x
\end{bmatrix}.
J
F
(
x
,
y
)
=
[
2
x
y
0
x
]
.
В точке
z
=
[
2
,
1
]
T
z=[2,1]^T
z
=
[
2
,
1
]
T
:
F
(
z
)
=
[
4
,
2
]
T
,
J
F
(
z
)
=
[
4
0
1
2
]
.
F(z)=[4,2]^T,
\qquad J_F(z)=
\begin{bmatrix}4&0\\1&2\end{bmatrix}.
F
(
z
)
=
[
4
,
2
]
T
,
J
F
(
z
)
=
[
4
1
0
2
]
.
Первый столбец
[
4
,
1
]
T
[4,1]^T
[
4
,
1
]
T
описывает изменение обоих выходов при движении входа по
x
x
x
; второй
[
0
,
2
]
T
[0,2]^T
[
0
,
2
]
T
— при движении по
y
y
y
.
Jacobian является локальной матрицей преобразования
Для малого
δ
\delta
δ
F
(
z
+
δ
)
≈
F
(
z
)
+
J
F
(
z
)
δ
.
F(z+\delta)\approx F(z)+J_F(z)\delta.
F
(
z
+
δ
)
≈
F
(
z
)
+
J
F
(
z
)
δ
.
При
δ
=
[
0.1
,
−
0.2
]
T
\delta=[0.1,-0.2]^T
δ
=
[
0.1
,
−
0.2
]
T
:
J
δ
=
[
4
0
1
2
]
[
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}.
J
δ
=
[
4
1
0
2
]
[
0.1
−
0.2
]
=
[
0.4
−
0.3
]
.
Линейное предсказание равно
[
4.4
,
1.7
]
T
[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.
F
(
2.1
,
0.8
)
=
[
4.41
,
1.68
]
T
.
Ошибка
[
0.01
,
−
0.02
]
T
[0.01,-0.02]^T
[
0.01
,
−
0.02
]
T
состоит из членов второго порядка:
δ
x
2
\delta_x^2
δ
x
2
и
δ
x
δ
y
\delta_x\delta_y
δ
x
δ
y
.
Forward и backward используют разные произведения
Произведение
J
δ
J\delta
J
δ
переносит малое изменение входа вперёд и имеет shape
[
m
,
1
]
[m,1]
[
m
,
1
]
. Теперь пусть скалярный loss зависит от
F
F
F
, а upstream gradient равен
g
F
=
∇
F
L
∈
R
m
×
1
.
g_F=\nabla_F L\in\mathbb R^{m\times1}.
g
F
=
∇
F
L
∈
R
m
×
1
.
Chain rule даёт gradient по входу:
g
z
=
J
T
g
F
,
[
n
,
m
]
[
m
,
1
]
=
[
n
,
1
]
.
g_z=J^Tg_F,
\qquad [n,m][m,1]=[n,1].
g
z
=
J
T
g
F
,
[
n
,
m
]
[
m
,
1
]
=
[
n
,
1
]
.
Например, при
g
F
=
[
1
,
−
2
]
T
g_F=[1,-2]^T
g
F
=
[
1
,
−
2
]
T
:
J
T
g
F
=
[
4
1
0
2
]
[
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}.
J
T
g
F
=
[
4
0
1
2
]
[
1
−
2
]
=
[
2
−
4
]
.
Это сумма вкладов всех выходных путей к каждому входу. Транспонирование появляется из согласования shapes и скалярного дифференциала:
d
L
=
g
F
T
d
F
=
g
F
T
J
d
z
=
(
J
T
g
F
)
T
d
z
.
dL=g_F^T\,dF=g_F^TJ\,dz=(J^Tg_F)^Tdz.
d
L
=
g
F
T
d
F
=
g
F
T
J
d
z
=
(
J
T
g
F
)
T
d
z
.
В больших системах полный Jacobian часто не материализуют. Forward-mode вычисляет Jacobian-vector product
J
v
Jv
J
v
, reverse-mode — vector-Jacobian product
u
T
J
u^TJ
u
T
J
, эквивалентный
J
T
u
J^Tu
J
T
u
в столбцовой записи. Это разные способы применить ту же производную, а не разные определения.
В лаборатории меняйте
x
x
x
и
y
y
y
отдельно. Нулевой элемент
J
01
=
0
J_{01}=0
J
01
=
0
означает, что первый выход локально не зависит от
y
y
y
, но не отменяет существование второго выхода.
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
Академическая база →