Диффузия и потоки

Численные решатели ОДУ

Эйлер, Хойн, Рунге–Кутта — и что означает слово «порядок», если его измерить

Шаг 91 из 117 · ~28 мин

Зачем это в ветке про диффузию

Забегая вперёд: сэмплирование диффузионной модели — это решение дифференциального уравнения численно. Урок 060 покажет, откуда оно берётся; здесь нужен аппарат.

Задача Коши: известна производная и начальное условие, нужно значение в конце.

dxdt=f(t,x),x(0)=x0xn+1=xn+hΦ(tn,xn,h)\frac{dx}{dt} = \htmlData{k=field}{f(t, x)}, \quad x(0) = x_0 \qquad\Longrightarrow\qquad x_{n+1} = x_n + \htmlData{k=step}{h}\,\Phi(t_n, x_n, h)

ff в диффузии — это и есть выход нейросети. Значит любое утверждение о численных методах здесь превращается в утверждение о том, сколько раз нужно вызвать сеть, — и вот почему эта тема практически важна, а не формальна.

Три метода

Эйлер — двигаться по производной в текущей точке:

xn+1=xn+hf(tn,xn)x_{n+1} = x_n + h f(t_n, x_n)

Хойн (он же метод трапеций, он же RK2) — сделать пробный шаг, посмотреть производную там и усреднить:

x~=xn+hf(tn,xn),xn+1=xn+h2[f(tn,xn)+f(tn+1,x~)]\tilde{x} = x_n + h f(t_n, x_n), \qquad x_{n+1} = x_n + \frac{h}{2}\big[f(t_n, x_n) + f(t_{n+1}, \tilde{x})\big]

Рунге–Кутта 4 — четыре пробных вычисления с известными весами:

xn+1=xn+h6(k1+2k2+2k3+k4)x_{n+1} = x_n + \frac{h}{6}(k_1 + 2k_2 + 2k_3 + k_4)

Ключевая цифра, которую стоит держать в голове: число вызовов ff на шаг — один, два и четыре соответственно. В диффузии это буквально число прогонов сети.

Что такое порядок и как его измерить

Метод имеет порядок pp, если ошибка на конце ведёт себя как O(hp)O(h^p). Проверяется это без всякой теории: удвоить число шагов и посмотреть, во сколько раз упала ошибка. Отношение 2p2^p, значит

plog2e(h)e(h/2)p \approx \log_2 \frac{e(h)}{e(h/2)}

Виджет считает именно это. Возьмите dx/dt=xdx/dt = x, где точный ответ ee, и пройдитесь по методам.

время x

шагов 8
шум σ 0
x в конце
2.56578
ошибка
1.52e-1
измеренный порядок
0.92
разброс траекторий
разница методов
0.1525
Измеренный порядок при σ = 0: около 1 у Эйлера, 2 у Хойна, 4 у RK4. Это не теория из книги, а логарифм отношения ошибок при удвоении числа шагов.

Классический тест: точный ответ равен e = 2.718281828…, поэтому ошибку видно до последнего знака.

Шум выключен: столбец «измеренный порядок» осмыслен, и его стоит сравнить с 1, 2 и 4.

Измерено на dx/dt=xdx/dt = x, T=1T = 1:

методвызовов ffошибка при N=8N=8ошибка при N=64N=64измеренный порядок
Эйлер111.51011.5\cdot10^{-1}2.11022.1\cdot10^{-2}0.980.98
Хойн226.41036.4\cdot10^{-3}1.11041.1\cdot10^{-4}1.981.98
RK4445.01065.0\cdot10^{-6}1.31091.3\cdot10^{-9}3.983.98

Обратите внимание, что порядок измеряется как 0.980.98, а не ровно 11: он асимптотический, и на крупном шаге проявляется не полностью. Это сам по себе полезный факт — «второй порядок» не означает, что при четырёх шагах ошибка будет квадратично мала.

Как правильно сравнивать методы

Здесь стоит поправить типичное сравнение «RK4 точнее Эйлера». Точнее при равном числе шагов, но каждый шаг стоит вчетверо больше. Честное сравнение — при равном числе вызовов ff:

бюджет: 32 вызовашаговошибка
Эйлер32324.11024.1\cdot10^{-2}
Хойн16161.71031.7\cdot10^{-3}
RK4885.01065.0\cdot10^{-6}

RK4 всё равно выигрывает, и с большим запасом. Но вывод не универсален: выигрыш высокого порядка пропадает, когда либо поле ff негладко, либо в задаче есть шум (урок 030), либо бюджет вызовов настолько мал, что асимптотика не наступила. Все три случая встречаются в диффузии, и поэтому DDIM с Эйлером остаётся конкурентоспособным.

Устойчивость — не то же самое, что точность

Возьмите в виджете жёсткое уравнение dx/dt=12xdx/dt = -12x с четырьмя шагами. Точный ответ убывает до e126106e^{-12} \approx 6\cdot10^{-6}; Эйлер даёт (112h)4=(13)4=16(1 - 12h)^4 = (1-3)^4 = 16 — на семь порядков не туда, да ещё с чередованием знака.

Причина не в порядке метода. Эйлер устойчив только при 1+hλ<1|1 + h\lambda| < 1, то есть при h<2/λh < 2/|\lambda| для отрицательного вещественного λ\lambda. Это в точности то же условие α<2/L\alpha < 2/L, которое ограничивало шаг градиентного спуска в блоке 5, урок 040 — и не случайно: градиентный спуск и есть метод Эйлера для x˙=f(x)\dot{x} = -\nabla f(x).

точностьустойчивость
про чтокак быстро ошибка падает с hhрасходится ли метод вовсе
лечитсяметодом выше порядкатолько уменьшением шага (или неявной схемой)
проявляетсялишними знакамивзрывом или колебаниями

Различать их обязательно: увидев расходимость, повышать порядок метода бессмысленно.

Что из этого понадобится дальше

  • Сэмплирование диффузии — численное интегрирование, и число вызовов сети равно числу вычислений ff. Отсюда все разговоры про «сколько шагов нужно».
  • Порядок метода — измеримая величина, и на крупных шагах он проявляется частично.
  • Сравнивать методы нужно по бюджету вызовов, а не по числу шагов.
  • Устойчивость ограничивает шаг независимо от точности, и её ограничение — то же, что у градиентного спуска.

Источники

Проверки

0 из 2
  1. Порядок, бюджет и устойчивость

    Отметьте все верные утверждения о численных решателях ОДУ.

  2. Измерить порядок и множитель за шаг

    Реализуйте solve_linear(method, lam, t_end, steps) для задачи dx/dt=λxdx/dt = \lambda x с x(0)=1x(0) = 1. Метод — строка "euler", "heun" или "rk4"; формулы даны в уроке. Верните [final, error, observed_order, amplification]:

    • final — численное решение в точке t_end при steps шагах;
    • error = finaleλtend|{\texttt{final}} - e^{\lambda\, t_{\text{end}}}|;
    • observed_order = log2e(steps)e(2steps)\log_2 \dfrac{e(\texttt{steps})}{e(2 \cdot \texttt{steps})} — придётся решить задачу второй раз, с удвоенным числом шагов;
    • amplification = final1/steps|\texttt{final}|^{1/\texttt{steps}} — во сколько раз решение умножается за один шаг.

    Последняя величина устроена так специально: для линейной задачи любой из трёх методов умножает xx на одно и то же число каждый шаг, поэтому корень степени steps из результата и есть этот множитель. Для Эйлера он обязан равняться 1+hλ|1 + h\lambda| — проверьте.

    функция solve_linear

    Загрузка редактора…

    Ctrl/⌘ + Enter