VKВлад КуликовОткрытые лекции
Теория информации для машинного обучения15 / 16

Модуль 15. Информационная геометрия: Fisher, естественный градиент и потоки распределений

Сначала попробуйте решить упражнение. Ответы, подробные решения и проектные ориентиры раскрываются отдельно и сохраняют своё состояние при переключении RU/EN.

Скачать файлы курса (.zip) 33,9 КБ

Архив содержит девять Python-файлов решений, общих для RU/EN, с сохранением структуры каталогов.

Упражнение 1. Fisher-геометрия Bernoulli

Для X∼Bernoulli⁡(p)X\sim\operatorname{Bernoulli}(p):

  1. выведите Gp(p)=1/[p(1−p)]G_p(p)=1/[p(1-p)];

  2. перейдите к логиту и получите Gz(z)=p(1−p)G_z(z)=p(1-p);

  3. покажите, что u(p)=2arcsin⁡pu(p)=2\arcsin\sqrt p превращает элемент длины в ds2=du2ds^2=du^2;

  4. найдите расстояние Fisher–Rao между p1=0.1p_1=0.1 и p2=0.9p_2=0.9.

Показать ответ и решение

Для

log⁡p(X)=Xlog⁡p+(1−X)log⁡(1−p)\log p(X)=X\log p+(1-X)\log(1-p)

скор-функция по pp:

∂∂plog⁡p(X)=X−pp(1−p).\frac{\partial}{\partial p}\log p(X) = \frac{X-p}{p(1-p)}.

Так как Var⁡(X)=p(1−p)\operatorname{Var}(X)=p(1-p),

Gp(p)=E[(X−p)2p2(1−p)2]=1p(1−p).G_p(p) = \mathbb E \left[ \frac{(X-p)^2}{p^2(1-p)^2} \right] = \boxed{\frac1{p(1-p)}}.

Для логита zz, dp/dz=p(1−p)dp/dz=p(1-p), поэтому

Gz=(dpdz)2Gp=p(1−p).G_z = \left(\frac{dp}{dz}\right)^2G_p = \boxed{p(1-p)}.

Если

u(p)=2arcsin⁡p,u(p)=2\arcsin\sqrt p,

то

dudp=1p(1−p),\frac{du}{dp}=\frac1{\sqrt{p(1-p)}},

и

ds2=dp2p(1−p)=du2.ds^2=\frac{dp^2}{p(1-p)}=du^2.

Следовательно,

dFR(p1,p2)=2∣arcsin⁡p2−arcsin⁡p1∣.\boxed{ d_{\mathrm{FR}}(p_1,p_2) =2\left| \arcsin\sqrt{p_2}-\arcsin\sqrt{p_1} \right|. }

Для 0.10.1 и 0.90.9:

dFR≈1.854590436.\boxed{d_{\mathrm{FR}}\approx1.854590436}.

Упражнение 2. Естественный шаг из доверительной области

Пусть g=∇L(θ)g=\nabla L(\theta) и G≻0G\succ0. Решите

min⁡δg⊤δпри12δ⊤Gδ≤ε.\min_\delta g^\top\delta \qquad \text{при} \qquad \frac12\delta^\top G\delta\le\varepsilon.

Получите направление и нормировочный множитель. Что меняется при сингулярной GG?

Показать ответ и решение

Лагранжиан:

L(δ,λ)=g⊤δ+λ(12δ⊤Gδ−ε).\mathcal L(\delta,\lambda) = g^\top\delta + \lambda \left( \frac12\delta^\top G\delta-\varepsilon \right).

Стационарность:

g+λGδ=0,g+\lambda G\delta=0,

поэтому

δ=−λ−1G−1g.\delta=-\lambda^{-1}G^{-1}g.

В оптимуме ограничение активно:

12λ2g⊤G−1g=ε.\frac1{2\lambda^2}g^\top G^{-1}g=\varepsilon.

Отсюда

δ∗=−2εg⊤G−1gG−1g.\boxed{ \delta^* =- \sqrt{ \frac{2\varepsilon}{g^\top G^{-1}g} } G^{-1}g }.

При сингулярной GG используют псевдообратную матрицу, ограничение на идентифицируемое подпространство или демпфирование G+λIG+\lambda I. Если целевая функция меняется вдоль ядра матрицы, исходная локальная задача может быть неограниченной.

Упражнение 3. Экспоненциальное семейство и дивергенция Брэгмана

Для

pθ(x)=h(x)eθ⊤T(x)−A(θ)p_\theta(x) =h(x)e^{\theta^\top T(x)-A(\theta)}

покажите:

∇A(θ)=Eθ[T(X)],∇2A(θ)=G(θ),\nabla A(\theta) =\mathbb E_\theta[T(X)], \qquad \nabla^2A(\theta) =G(\theta),

и

DKL(pθ1∥pθ2)=BA(θ2,θ1).D_{\mathrm{KL}} (p_{\theta_1}\|p_{\theta_2}) =B_A(\theta_2,\theta_1).
Показать ответ и решение

Нормировка даёт

eA(θ)=∫h(x)eθ⊤T(x)dx.e^{A(\theta)} = \int h(x)e^{\theta^\top T(x)}dx.

Дифференцируя,

∇A(θ)=Eθ[T(X)].\boxed{ \nabla A(\theta)=\mathbb E_\theta[T(X)] }.

Ещё одна производная:

∇2A(θ)=Cov⁡θ(T(X))=G(θ).\boxed{ \nabla^2A(\theta) = \operatorname{Cov}_\theta(T(X)) = G(\theta) }.

Для KL:

DKL(pθ1∥pθ2)=Eθ1[(θ1−θ2)⊤T(X)−A(θ1)+A(θ2)]=A(θ2)−A(θ1)−∇A(θ1)⊤(θ2−θ1)=BA(θ2,θ1).\begin{aligned} D_{\mathrm{KL}}(p_{\theta_1}\|p_{\theta_2}) &= \mathbb E_{\theta_1} \left[ (\theta_1-\theta_2)^\top T(X) -A(\theta_1)+A(\theta_2) \right]\\ &= A(\theta_2)-A(\theta_1) -\nabla A(\theta_1)^\top(\theta_2-\theta_1)\\ &= \boxed{B_A(\theta_2,\theta_1)}. \end{aligned}

Порядок аргументов развёрнут, потому что expectation и касательная берутся в точке θ1\theta_1.

Упражнение 4. Модельная и эмпирическая Fisher

Для Y∼Bernoulli⁡(q)Y\sim\operatorname{Bernoulli}(q) и модели p=σ(z)p=\sigma(z):

  1. получите модельную Fisher p(1−p)p(1-p);

  2. найдите EY∼q[(Y−p)2]\mathbb E_{Y\sim q}[(Y-p)^2];

  3. определите, когда две величины совпадают;

  4. объясните, почему совпадение в оптимуме не делает эмпирическую Fisher универсальной матрицей кривизны.

Показать ответ и решение

Для Bernoulli log-likelihood в логит-координате:

∂∂zlog⁡p(Y)=Y−p.\frac{\partial}{\partial z}\log p(Y)=Y-p.

При Y∼Bernoulli⁡(p)Y\sim\operatorname{Bernoulli}(p):

Gmodel=Ep[(Y−p)2]=p(1−p).G_{\mathrm{model}} = \mathbb E_p[(Y-p)^2] = \boxed{p(1-p)}.

При данных Y∼Bernoulli⁡(q)Y\sim\operatorname{Bernoulli}(q):

Gdata=Eq[(Y−p)2]=q(1−p)2+(1−q)p2=p(1−p)+(q−p)(1−2p).\begin{aligned} G_{\mathrm{data}} &= \mathbb E_q[(Y-p)^2]\\ &= q(1-p)^2+(1-q)p^2\\ &= p(1-p)+(q-p)(1-2p). \end{aligned}

Прямое сравнение показывает, что равенство выполняется при q=pq=p, а также в отдельных случайных точках, например p=1/2p=1/2. Но это не универсальное равенство матриц на протяжении обучения.

В оптимуме корректно специфицированной модели часто p≈qp\approx q, поэтому величины сближаются. Вдали от оптимума эмпирический второй момент может заметно переоценивать или иначе искажать геометрию.

Упражнение 5. TRPO, PPO и KL к референсу

  1. Запишите ориентацию KL в практическом TRPO.

  2. Постройте пример, где отношения PPO на выборке не меняются, а глобальный KL велик.

  3. Сравните пошаговый KL и KL к фиксированному референсу в RLHF.

  4. Объясните, почему DPO не является обновлением естественного градиента.

Показать ответ и решение

TRPO

Стандартное практическое направление KL:

EsDKL(πold(⋅∣s)∥πnew(⋅∣s))≤δ.\mathbb E_s D_{\mathrm{KL}} \left( \pi_{\mathrm{old}}(\cdot\mid s) \| \pi_{\mathrm{new}}(\cdot\mid s) \right) \le\delta.

Контрпример для PPO

Пусть

πold=(0.50,0.49,0.01)\pi_{\mathrm{old}}=(0.50,0.49,0.01)

и пакет данных содержит только первое действие с положительным преимуществом. Рассмотрим

πq=(0.50,q,0.50−q),0<q<0.50.\pi_q=(0.50,q,0.50-q), \qquad 0<q<0.50.

Отношение вероятностей фактически выбранного действия всегда равно 1, поэтому выборочная клиппированная цель не меняется. Но полная KL равна

DKL(πold∥πq)=0.49log⁡0.49q+0.01log⁡0.010.50−q.D_{\mathrm{KL}}(\pi_{\mathrm{old}}\|\pi_q) = 0.49\log\frac{0.49}{q} + 0.01\log\frac{0.01}{0.50-q}.

При q→0q\to0 первое слагаемое расходится, а второе стремится к конечному 0.01log⁡0.020.01\log0.02, поэтому

DKL(πold∥πq)→∞.D_{\mathrm{KL}}(\pi_{\mathrm{old}}\|\pi_q)\to\infty.

Клиппирование не является глобальным ограничением на KL.

Две KL

  • пошаговый KL к старой политике стабилизирует конкретное on-policy-обновление;
  • KL к фиксированной SFT- или базовой политике ограничивает накопленный дрейф.

DPO

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

π∗(y∣x)∝πref(y∣x)er(x,y)/β\pi^*(y\mid x) \propto \pi_{\mathrm{ref}}(y\mid x)e^{r(x,y)/\beta}

и правдоподобие предпочтений, но не выполняет явного обновления естественного градиента или TRPO.

Упражнение 6. Flow Matching и связка

Пусть

X0∼N(μ0,σ02),X1∼N(μ1,σ12).X_0\sim\mathcal N(\mu_0,\sigma_0^2), \qquad X_1\sim\mathcal N(\mu_1,\sigma_1^2).

Сравните:

  1. общий шум X0=μ0+σ0ZX_0=\mu_0+\sigma_0Z, X1=μ1+σ1ZX_1=\mu_1+\sigma_1Z;

  2. независимые X0X_0 и X1X_1.

Для

Xt=(1−t)X0+tX1X_t=(1-t)X_0+tX_1

найдите среднее, дисперсию и кинетическое действие. Покажите, что связка с общим шумом даёт одномерную W2W_2-геодезическую.

Показать ответ и решение

Связка с общим шумом

Пусть

X0=μ0+σ0Z,X1=μ1+σ1Z,Z∼N(0,1).X_0=\mu_0+\sigma_0Z, \qquad X_1=\mu_1+\sigma_1Z, \qquad Z\sim\mathcal N(0,1).

Тогда

Xt=(1−t)X0+tX1=μt+σtZ,X_t=(1-t)X_0+tX_1 = \mu_t+\sigma_tZ,

где

μt=(1−t)μ0+tμ1,σt=(1−t)σ0+tσ1.\mu_t=(1-t)\mu_0+t\mu_1, \qquad \sigma_t=(1-t)\sigma_0+t\sigma_1.

Следовательно,

Xt∼N(μt,σt2).X_t\sim\mathcal N(\mu_t,\sigma_t^2).

Скорость постоянна:

X˙t=(μ1−μ0)+(σ1−σ0)Z.\dot X_t =(\mu_1-\mu_0)+(\sigma_1-\sigma_0)Z.

Кинетическое действие:

E[X˙t2]=(μ1−μ0)2+(σ1−σ0)2=W22(P0,P1).\mathbb E[\dot X_t^2] = (\mu_1-\mu_0)^2+(\sigma_1-\sigma_0)^2 = W_2^2(P_0,P_1).

Это одномерная оптимальная связка и геодезическая смещения.

Независимая связка

Если X0,X1X_0,X_1 независимы,

Var⁡(Xt)=(1−t)2σ02+t2σ12.\operatorname{Var}(X_t) =(1-t)^2\sigma_0^2+t^2\sigma_1^2.

Кинетическое действие:

E[(X1−X0)2]=(μ1−μ0)2+σ02+σ12.\mathbb E[(X_1-X_0)^2] =(\mu_1-\mu_0)^2+\sigma_0^2+\sigma_1^2.

Она превышает оптимум на

2σ0σ1.2\sigma_0\sigma_1.

Конечные маргинальные распределения те же, но связка и весь промежуточный путь отличаются.

Упражнение 7. Python

Запустите

text
M15_information_geometry_experiments.py

Скрипт:

  1. сравнивает точную Bernoulli-KL с квадратичной Fisher-аппроксимацией;

  2. показывает зависимость обычного градиента от координат и согласованность потока естественного градиента;

  3. сравнивает модельную Fisher со вторым моментом градиента по данным;

  4. строит контрпример для PPO;

  5. сравнивает оптимальную и независимую связки для гауссовского пути.

Показать ответ и решение

Для p=0.2p=0.2 квадратичная аппроксимация Fisher приближается к точному KL при уменьшении δ\delta:

δ\deltaТочная KLКвадратичнаяОтношение
0.10.025732090.031250000.8234
0.010.000304990.000312500.9760
0.0010.00000311720.00000312500.9975

Обычные градиентные траектории в pp- и логит-координатах заметно различаются. Две эйлеровы дискретизации векторного поля естественного градиента отличаются только из-за конечного шага; при уменьшении шага расхождение стремится к нулю.

При q=0.8q=0.8, p=0.2p=0.2:

Gmodel=0.16,Gdata=0.52.G_{\mathrm{model}}=0.16, \qquad G_{\mathrm{data}}=0.52.

В PPO-примере выборочное отношение вероятностей остаётся 1, а

DKL(πold∥πnew)D_{\mathrm{KL}}(\pi_{\mathrm{old}}\|\pi_{\mathrm{new}})

достигает примерно 8.648.64 ната.

Эксперимент с гауссовскими связками показывает разницу кинетических действий 2σ0σ12\sigma_0\sigma_1 между независимой связкой и связкой с общим шумом.

Программная часть решения · один исходный файл для RU/EN

PythonM15_information_geometry_experiments.pyСкачать .py
from __future__ import annotations

from pathlib import Path
import math

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np

ROOT = Path(__file__).resolve().parent
OUT = ROOT / 'generated_experiment'
OUT.mkdir(exist_ok=True)


def bernoulli_kl(p: np.ndarray | float, q: np.ndarray | float) -> np.ndarray:
    p = np.asarray(p, dtype=float)
    q = np.asarray(q, dtype=float)
    eps = 1e-15
    p = np.clip(p, eps, 1 - eps)
    q = np.clip(q, eps, 1 - eps)
    return p*np.log(p/q) + (1-p)*np.log((1-p)/(1-q))


def local_kl_experiment() -> dict[str, float]:
    p0 = 0.2
    deltas = np.logspace(-5, -1, 160)
    exact = bernoulli_kl(p0, p0+deltas)
    fisher = 1/(p0*(1-p0))
    quadratic = 0.5*fisher*deltas**2
    fig, ax = plt.subplots(figsize=(8.8, 5.3))
    ax.loglog(deltas, exact, label='exact KL')
    ax.loglog(deltas, quadratic, '--', label=r'$\frac{1}{2}F(p)\delta^2$')
    ax.set_xlabel(r'$\delta$')
    ax.set_ylabel('nats')
    ax.set_title('Bernoulli: local KL and Fisher quadratic approximation')
    ax.legend()
    fig.tight_layout()
    fig.savefig(OUT/'M15_local_kl.png', dpi=190)
    plt.close(fig)
    print('LOCAL KL')
    for d in (0.1, 0.05, 0.01, 0.001):
        e=float(bernoulli_kl(p0,p0+d)); q=0.5*fisher*d*d
        print(f'delta={d:g} exact={e:.10f} quadratic={q:.10f} ratio={e/q:.6f}')
    return {'fisher': fisher, 'ratio_1e3': float(bernoulli_kl(p0,p0+1e-3)/(0.5*fisher*1e-6))}


def sigmoid(z: np.ndarray | float) -> np.ndarray:
    return 1/(1+np.exp(-np.asarray(z,dtype=float)))


def logit(p: float) -> float:
    return math.log(p/(1-p))


def reparameterization_experiment() -> dict[str,float]:
    target=0.8; p0=0.1; dt=0.01; steps=300
    time=np.arange(steps+1)*dt
    p_nat=np.empty(steps+1); p_nat[0]=p0
    z_nat=np.empty(steps+1); z_nat[0]=logit(p0)
    for t in range(steps):
        p_nat[t+1]=p_nat[t]-dt*(p_nat[t]-target)
        p=float(sigmoid(z_nat[t]))
        z_nat[t+1]=z_nat[t]-dt*(p-target)/(p*(1-p))
    pz_nat=sigmoid(z_nat)
    # Coordinate-dependent ordinary-gradient examples.
    p_gd=np.empty(steps+1); p_gd[0]=p0
    z_gd=np.empty(steps+1); z_gd[0]=logit(p0)
    for t in range(steps):
        p=np.clip(p_gd[t],1e-6,1-1e-6)
        grad=(p-target)/(p*(1-p))
        p_gd[t+1]=np.clip(p-0.002*grad,1e-6,1-1e-6)
        p=float(sigmoid(z_gd[t])); z_gd[t+1]=z_gd[t]-0.08*(p-target)
    pz_gd=sigmoid(z_gd)
    exact=target+(p0-target)*np.exp(-time)
    fig, ax = plt.subplots(figsize=(9.2,5.4))
    ax.plot(time,p_gd,label='ordinary GD in p')
    ax.plot(time,pz_gd,label='ordinary GD in logit')
    ax.plot(time,p_nat,'--',label='natural Euler in p')
    ax.plot(time,pz_nat,':',label='natural Euler in logit')
    ax.plot(time,exact,color='black',linewidth=1.2,label='exact natural flow')
    ax.set_xlabel('time / iteration scale'); ax.set_ylabel('Bernoulli p')
    ax.set_ylim(0,0.9); ax.set_title('Reparameterization: vector field vs finite steps')
    ax.legend(fontsize=9); fig.tight_layout(); fig.savefig(OUT/'M15_reparameterization.png',dpi=190); plt.close(fig)
    nat=float(np.max(np.abs(p_nat-pz_nat))); ordinary=float(np.max(np.abs(p_gd-pz_gd)))
    print('\nREPARAMETERIZATION')
    print(f'max ordinary trajectory difference={ordinary:.6f}')
    print(f'max natural Euler difference={nat:.6f}')
    return {'ordinary_difference':ordinary,'natural_difference':nat}


def empirical_fisher_experiment() -> dict[str,float]:
    q=0.8
    p=np.linspace(0.01,0.99,300)
    model=p*(1-p)
    data=q*(1-p)**2+(1-q)*p**2
    fig, ax=plt.subplots(figsize=(8.8,5.2))
    ax.plot(p,model,label=r'model Fisher $p(1-p)$')
    ax.plot(p,data,label='gradient second moment under data')
    ax.axvline(q,color='black',linewidth=0.8,alpha=0.5)
    ax.set_xlabel('model probability p'); ax.set_ylabel('matrix entry / second moment')
    ax.set_title('Model Fisher and observed-gradient second moment differ')
    ax.legend(); fig.tight_layout(); fig.savefig(OUT/'M15_empirical_fisher.png',dpi=190); plt.close(fig)
    print('\nMODEL VS EMPIRICAL')
    vals={}
    for p0 in (0.2,0.5,0.8):
        f=p0*(1-p0); e=q*(1-p0)**2+(1-q)*p0**2
        vals[p0]=(f,e); print(f'p={p0:.1f} model={f:.6f} data={e:.6f}')
    return {'model_p02':vals[0.2][0],'data_p02':vals[0.2][1]}


def categorical_kl(p: np.ndarray,q: np.ndarray)->float:
    return float(np.sum(p*np.log(p/q)))


def ppo_counterexample() -> dict[str,float]:
    old=np.array([0.50,0.49,0.01])
    q1=np.geomspace(0.49,1e-8,240)
    policies=np.column_stack([np.full_like(q1,0.50),q1,0.50-q1])
    kl=np.array([categorical_kl(old,q) for q in policies])
    ratio=policies[:,0]/old[0]
    surrogate=np.minimum(ratio,np.clip(ratio,0.8,1.2))
    x=-np.log10(q1)
    fig, ax=plt.subplots(figsize=(9.2,5.3))
    ax.plot(x,kl,label=r'$D_{KL}(\pi_{old}\|\pi_{new})$')
    ax.set_xlabel(r'$-\log_{10}\pi_{new}(a_1)$'); ax.set_ylabel('KL, nats')
    ax2=ax.twinx(); ax2.plot(x,surrogate,'--',color='black',label='sampled PPO surrogate')
    ax2.set_ylabel('sampled surrogate')
    lines,labels=ax.get_legend_handles_labels(); lines2,labels2=ax2.get_legend_handles_labels()
    ax.legend(lines+lines2,labels+labels2,loc='upper left',fontsize=9)
    ax.set_title('PPO clipping on sampled actions is not a global KL constraint')
    fig.tight_layout(); fig.savefig(OUT/'M15_ppo_counterexample.png',dpi=190); plt.close(fig)
    m=float(kl.max()); print('\nPPO COUNTEREXAMPLE'); print(f'max KL={m:.6f} nats; sampled ratio={ratio[0]:.1f}')
    return {'max_kl':m}


def flow_coupling_experiment() -> dict[str,float]:
    mu0,s0=-1.0,0.7; mu1,s1=2.0,1.4
    t=np.linspace(0,1,200)
    var_ot=((1-t)*s0+t*s1)**2
    var_ind=(1-t)**2*s0**2+t**2*s1**2
    action_ot=(mu1-mu0)**2+(s1-s0)**2
    action_ind=(mu1-mu0)**2+s0**2+s1**2
    fig, ax=plt.subplots(figsize=(8.8,5.2))
    ax.plot(t,var_ot,label='shared-noise / OT coupling')
    ax.plot(t,var_ind,label='independent coupling')
    ax.set_xlabel('t'); ax.set_ylabel(r'$\mathrm{Var}(X_t)$')
    ax.set_title('The coupling determines the Gaussian interpolation path')
    ax.legend(); fig.tight_layout(); fig.savefig(OUT/'M15_flow_couplings.png',dpi=190); plt.close(fig)
    print('\nFLOW COUPLINGS')
    print(f'OT action={action_ot:.6f}; independent action={action_ind:.6f}; gap={action_ind-action_ot:.6f}')
    return {'ot_action':action_ot,'ind_action':action_ind,'gap':action_ind-action_ot}


def main()->None:
    local_kl_experiment(); reparameterization_experiment(); empirical_fisher_experiment(); ppo_counterexample(); flow_coupling_experiment()
    print(f'\nSaved plots to {OUT}')

if __name__=='__main__':
    main()

Бонус. Probability-flow ODE

Для

dXt=f(Xt,t)dt+g(t)dWtdX_t=f(X_t,t)dt+g(t)dW_t

выведите уравнение Фоккера—Планка и покажите, что ODE

dXtdt=f(Xt,t)−12g(t)2∇log⁡pt(Xt)\frac{dX_t}{dt} =f(X_t,t) - \frac12g(t)^2\nabla\log p_t(X_t)

порождает те же маргинальные распределения ptp_t. Почему траектории различаются?

Показать ответ и решение

Уравнение Фоккера—Планка для

dXt=f(Xt,t)dt+g(t)dWtdX_t=f(X_t,t)dt+g(t)dW_t

при скалярном, не зависящем от состояния g(t)g(t):

∂tpt=−∇⋅(fpt)+12g(t)2Δpt.\partial_tp_t =-\nabla\cdot(fp_t) +\frac12g(t)^2\Delta p_t.

Пусть

vt(x)=f(x,t)−12g(t)2∇log⁡pt(x).v_t(x) =f(x,t)-\frac12g(t)^2\nabla\log p_t(x).

Тогда уравнение непрерывности для ODE:

∂tpt=−∇⋅(vtpt)=−∇⋅(fpt)+12g(t)2∇⋅(pt∇log⁡pt)=−∇⋅(fpt)+12g(t)2Δpt.\begin{aligned} \partial_tp_t &=-\nabla\cdot(v_tp_t)\\ &=-\nabla\cdot(fp_t) +\frac12g(t)^2\nabla\cdot(p_t\nabla\log p_t)\\ &=-\nabla\cdot(fp_t) +\frac12g(t)^2\Delta p_t. \end{aligned}

Оно совпадает с уравнением Фоккера—Планка, поэтому маргинальные распределения одинаковы. Траектории различаются: SDE содержит броуновскую случайность, а ODE детерминирована при фиксированном начальном состоянии.