Содержание курса 22 / 22

22 / 22 · Случайные процессы и сэмплирование

Марковские методы Монте-Карло (MCMC)

Как сэмплировать из распределения, известного лишь с точностью до константы, запуская цепь Маркова, стационарное распределение которой совпадает с целевым, как понять, чего стоят такие коррелированные сэмплы, и как сэмплер Ланжевена, идущий по градиенту логарифма плотности, связан со score-моделями.

Что нужно знать

Методы Монте-Карло

На этой странице 11

Апостериорное распределение реальной модели, распределение молекулярных конфигураций или энергетическая модель (energy-based model) изображений имеют плотность, которую можно вычислить лишь с точностью до константы, p(x)=p~(x)/Zp(x) = \tilde p(x) / Z, где ZZ — вычислительно неразрешимый (intractable) интеграл, причём в пространстве высокой размерности. Прямым методам из заметки о методах Монте-Карло нужно предлагающее распределение, близкое к pp, а такого нет. Марковские методы Монте-Карло (Markov chain Monte Carlo, MCMC) переворачивают эргодическую теорему: строим цепь Маркова, стационарное распределение которой равно pp, запускаем её и используем её состояния как сэмплы. Для построения нужны только отношения p~(y)/p~(x)\tilde p(y)/\tilde p(x), в которых ZZ сокращается. В этой последней заметке курса мы выводим алгоритм Метрополиса–Гастингса, показываем, как он даёт сбой, и заканчиваем динамикой Ланжевена, которая идёт по градиенту логарифма плотности и даёт score, который затем используют диффузионные модели.

Обозначения. p(x)=p~(x)/Zp(x) = \tilde p(x)/Z — целевое распределение; q(y∣x)q(y \mid x) — предлагающее распределение (proposal); X0,X1,…X_0, X_1, \dots — цепь. ∇log⁡p(x)\nabla \log p(x) — score (функция score, градиент логарифма плотности), который не зависит от ZZ.

Условие детального баланса#

Цепь с вероятностями переходов P(x→y)P(x \to y) удовлетворяет условию детального баланса (detailed balance) относительно pp, если

p(x) P(x→y)=p(y) P(y→x)для всех x,y.p(x)\, P(x \to y) = p(y)\, P(y \to x) \quad \text{для всех } x, y .

В равновесии поток вероятности из xx в yy равен обратному потоку. Суммирование по xx даёт ∑xp(x)P(x→y)=p(y)\sum_x p(x) P(x \to y) = p(y): распределение pp стационарно. Условие детального баланса локально, и его легко обеспечить; если цепь к тому же неприводима и апериодична, то заметка о цепях Маркова гарантирует сходимость к pp из любого начального состояния — для конечного числа состояний; в непрерывных пространствах состояний нужны аналогичные, более тонкие условия.

Алгоритм Метрополиса–Гастингса#

Из текущего состояния xx предложим y∼q(⋅∣x)y \sim q(\cdot \mid x) и примем его с вероятностью

α(x,y)=min⁡(1,p~(y) q(x∣y)p~(x) q(y∣x));\alpha(x, y) = \min\Big(1, \frac{\tilde p(y)\, q(x \mid y)}{\tilde p(x)\, q(y \mid x)}\Big) ;

иначе останемся в xx. При y≠xy \ne x вероятность перехода равна q(y∣x) α(x,y)q(y \mid x)\,\alpha(x, y), а выражение p(x)q(y∣x)α(x,y)=min⁡(p(x)q(y∣x), p(y)q(x∣y))p(x) q(y \mid x) \alpha(x, y) = \min\big(p(x) q(y \mid x),\ p(y) q(x \mid y)\big) симметрично по xx и yy: условие детального баланса выполнено. Константа ZZ входит и в числитель, и в знаменатель и сокращается. При симметричном предлагающем распределении, например y=x+σεy = x + \sigma \varepsilon с ε∼N(0,1)\varepsilon \sim N(0, 1), отношение равно просто p~(y)/p~(x)\tilde p(y)/\tilde p(x): шаги вверх по плотности принимаются всегда, шаги вниз — иногда. Это случайное блуждание Метрополиса (random-walk Metropolis) — алгоритм Метрополиса и соавторов 1953 года.

Цепь корректна при любом размере шага σ\sigma, но от σ\sigma зависит, насколько хорошо она работает:

Рисунок

Метрополис со слишком малым, хорошим и слишком большим шагом

Три траектории цепейМедленно дрейфующая линия, быстро колеблющаяся линия и ступенчатая линия с долгими площадками.шаг 0.1: малые шаги, почти все приняты · принято 96%шаг 2.4: хорошее перемешивание · принято 45%шаг 25: почти все отклонены · принято 6%Три траектории цепейМедленно дрейфующая линия, быстро колеблющаяся линия и ступенчатая линия с долгими площадками.шаг 0.1: малые шаги, почти все принятыпринято 96%шаг 2.4: хорошее перемешиваниепринято 45%шаг 25: почти все отклоненыпринято 6%
Первые 500 состояний трёх цепей Метрополиса для стандартного нормального распределения. С шагом 0.1 принимается почти всё (96%), но цепь ползёт и за 500 шагов не успевает обойти распределение. С шагом 25 почти всё отклоняется (6%), и цепь подолгу стоит на месте. Шаг 2.4 принимает 45% предложений и быстро пробегает всё распределение.

За 20 000 шагов на стандартном нормальном целевом распределении при шаге 0.10.1 принимается 97% предложений, но цепь равноценна всего 57 независимым сэмплам; при шаге 2525 принимается 5%, и цепь равноценна 708; при шаге 2.42.4 принимается 44%, и цепь равноценна 4815. Для случайного блуждания Метрополиса в высокой размерности теория рекомендует подбирать шаг так, чтобы доля принятых (acceptance rate) была около 0.23; в одномерном случае — около 0.44.

Перемешивание и диагностика#

Последовательные состояния цепи коррелированы, поэтому nn состояний обычно несут меньше информации, чем nn независимых сэмплов. Эффективный размер выборки (effective sample size, ESS) относится к интересующей величине g(Xt)g(X_t), а не к цепи в целом: если ρk\rho_k — автокорреляция g(Xt)g(X_t) на лаге kk в стационарной цепи, то

ESS=n1+2∑k≥1ρk,\text{ESS} = \frac{n}{1 + 2\sum_{k \ge 1} \rho_k} ,

и эта величина показывает, скольким независимым сэмплам равноценны nn состояний при оценке Ep[g(X)]E_p[g(X)]. Ошибка среднего gg по цепи тогда примерно равна σ/ESS\sigma / \sqrt{\text{ESS}}, а не σ/n\sigma/\sqrt n, где σ2=Var⁡pg(X)\sigma^2 = \operatorname{Var}_p g(X). Для этого нужно, чтобы цепь вышла на стационарный режим, ряд автокорреляций сходился и для цепи выполнялась центральная предельная теорема — она верна для «хороших» цепей, но не для всех. Положительные корреляции делают ESS меньше nn, отрицательные могут сделать его больше: у цепи с автокорреляциями ρk=(−0.5)k\rho_k = (-0.5)^k получается ESS=3n\text{ESS} = 3n. Значения ESS в этой заметке получены простой оценкой, которая обрывает сумму там, где автокорреляции падают ниже 0.050.05; они иллюстративны, а в рабочих инструментах используют более аккуратные оценки. На практике к этому добавляются три привычки: отбрасывать начальный участок цепи, прогрев (burn-in), до выхода на стационарный режим, запускать несколько цепей из разнесённых начальных точек и сравнивать дисперсию между цепями с дисперсией внутри них (статистика R^\hat R).

Никакая диагностика не обнаружит того, чего цепь ни разу не посещала. Для целевого распределения с двумя разделёнными модами цепь с малым шагом остаётся в той моде, в которой начала:

Рисунок

Цепь, застрявшая в одной моде

Две траектории для двухмодального распределенияВерхняя линия всё время около −3; нижняя прыгает между −3 и 3.шаг 0.5: в правой моде 0% времени-33шаг 4: в правой моде 56% времени-33Две траектории для двухмодального распределенияВерхняя линия всё время около −3; нижняя прыгает между −3 и 3.шаг 0.5: в правой моде 0% времени-33шаг 4: в правой моде 56% времени-33
Целевое распределение — смесь двух нормальных с центрами −3 и 3 и одинаковыми весами. Обе цепи начинают в −3. С шагом 0.5 цепь за 2000 шагов ни разу не переходит во вторую моду, и её выборка выглядит как сэмплы одного нормального распределения: по ней нельзя заметить, что половина вероятности пропущена. С шагом 4 предложения перепрыгивают провал между модами, и цепь проводит в каждой примерно половину времени.

За 20 000 шагов цепь с малым шагом проводит в правой моде 0% времени, цепь с большим шагом — 50%. Сэмплы первой цепи выглядят совершенно здоровыми; проблему выявляет только вторая цепь, запущенная в другой моде, или знание целевого распределения. Мультимодальность (multimodality) — одна из главных практических проблем MCMC, и для преодоления барьеров между модами существуют методы темперирования (tempering), которые запускают цепи на уплощённых версиях целевого распределения.

Сэмплирование по Гиббсу#

Когда условное распределение каждой координаты при остальных фиксированных легко сэмплировать, сэмплирование по Гиббсу (Gibbs sampling) обновляет координаты по одной, каждую — из её условного распределения. Это алгоритм Метрополиса–Гастингса, в котором предлагающим распределением служит условное, и вероятность принятия всегда равна 1. Для двумерного нормального распределения из заметки о многомерном нормальном распределении с единичными дисперсиями и корреляцией ρ\rho условные распределения равны X1∣X2=x2∼N(ρx2,1−ρ2)X_1 \mid X_2 = x_2 \sim N(\rho x_2, 1 - \rho^2) и симметрично для второй координаты.

Рисунок

Сэмплирование по Гиббсу ходит зигзагом

Зигзаг Гиббса внутри узкого эллипсаСтупенчатая траектория из горизонтальных и вертикальных отрезков вдоль диагонального эллипса.стартx₁x₂Зигзаг Гиббса внутри узкого эллипсаСтупенчатая траектория из горизонтальных и вертикальных отрезков вдоль диагонального эллипса.стартx₁x₂
Двумерное нормальное распределение с корреляцией 0.95 (эллипсы расстояния 1 и 2) и первые 40 полных шагов сэмплирования по Гиббсу из точки (−2.4, −2.4). Каждое обновление меняет одну координату, выбирая её из условного распределения при другой, поэтому цепь движется только по осям. Узкий диагональный эллипс позволяет лишь короткие шаги, и цепь медленно ползёт вдоль диагонали: соседние значения сильно коррелированы (ρ² = 0.90 на шаг).

Сильная корреляция замедляет сэмплирование по Гиббсу: каждый шаг идёт вдоль оси, а условная дисперсия 1−ρ21 - \rho^2 мала. Последовательные значения X1X_1 имеют корреляцию ρ2\rho^2, что равно 0.810.81 при ρ=0.9\rho = 0.9 и 0.980.98 при ρ=0.99\rho = 0.99; 20 000 проходов (sweeps) тогда равноценны примерно 2300 и 190 независимым сэмплам. Это исправляет репараметризация, устраняющая корреляцию, или совместное обновление коррелированных координат блоками. Сэмплирование по Гиббсу — рабочая лошадка для моделей с сопряжёнными условными распределениями, таких как тематические модели и многие иерархические байесовские модели.

Динамика Ланжевена#

Предложения случайного блуждания не учитывают, где сосредоточена вероятность. Динамика Ланжевена (Langevin dynamics) использует score, чтобы сдвигать каждый шаг вверх по плотности, и добавляет шум, чтобы продолжать исследовать пространство:

xt+1=xt+ε2∇log⁡p(xt)+ε zt,zt∼N(0,I).x_{t+1} = x_t + \frac{\varepsilon}{2} \nabla \log p(x_t) + \sqrt{\varepsilon}\, z_t, \qquad z_t \sim N(0, I) .

Это нескорректированный алгоритм Ланжевена (unadjusted Langevin algorithm, ULA). Для гладкого целевого распределения и достаточно малых шагов его стационарное распределение стремится к pp при ε→0\varepsilon \to 0; при конечном шаге оно смещено, а при слишком большом шаге или score, быстро растущем на хвостах, цепь может стать неустойчивой и вовсе не иметь стационарного распределения. Для стандартного нормального целевого распределения, score которого равен −x-x, обновление имеет вид xt+1=(1−ε/2) xt+ε ztx_{t+1} = (1 - \varepsilon/2)\, x_t + \sqrt{\varepsilon}\, z_t и устойчиво только при 0<ε<40 < \varepsilon < 4; тогда стационарная дисперсия равна 1/(1−ε/4)1/(1 - \varepsilon/4): 1.0261.026 при ε=0.1\varepsilon = 0.1 и 1.1431.143 при ε=0.5\varepsilon = 0.5. При ε≥4\varepsilon \ge 4 цепь расходится. Добавление шага принятия Метрополиса–Гастингса устраняет смещение от дискретизации (MALA, Metropolis-adjusted Langevin algorithm): pp становится точно стационарным при любом размере шага, и цепь сходится к нему при обычных условиях, хотя при большом шаге принимается мало предложений; моделирование гамильтоновой динамики с переменной импульса даёт гамильтонов Монте-Карло (Hamiltonian Monte Carlo, HMC); в адаптивном варианте NUTS это сэмплер по умолчанию в современных системах вероятностного программирования, таких как Stan. С градиентами по мини-батчам то же обновление превращается в стохастическую градиентную динамику Ланжевена (stochastic gradient Langevin dynamics, SGLD), которая делает из зашумлённого градиентного спуска приближённое сэмплирование из апостериорного распределения для нейросетей.

Для score не нужны ни ZZ, ни значения самой плотности — только градиент её логарифма, и в этом мост к генеративным моделям. По этому мосту переходит score, а не сэмплер целиком, и три процедуры нужно различать:

  • Равновесная динамика Ланжевена и MALA — эта заметка: одно фиксированное целевое распределение pp, цепь запускают достаточно долго, чтобы она забыла начальную точку, и получают сэмплы из её стационарного распределения pp (приближённо, а для MALA точно).
  • Отжиг динамики Ланжевена (annealed Langevin dynamics, Song and Ermon, 2019): нейросеть учит score ∇log⁡pσ\nabla \log p_\sigma данных, размытых гауссовским шумом нескольких величин σ\sigma, и на каждом уровне, от самого большого к самому малому, делают несколько шагов Ланжевена. У каждого уровня своё целевое распределение, ни на одном из них цепь не доводят до равновесия, и результат — не MCMC-сэмпл из распределения данных (заметка о score matching).
  • Обратная диффузия (DDPM, score-модели на основе стохастических дифференциальных уравнений, Song et al., 2021): генерация моделирует обращение во времени процесса зашумления — от чистого шума в конечный момент обратно к данным — за фиксированное число шагов. Её снос содержит score ∇log⁡pt\nabla \log p_t зашумлённых данных в момент tt, поэтому правило перехода меняется от шага к шагу; это неоднородная по времени цепь Маркова без стационарного целевого распределения (сэмплирование в DDPM). На каждом шаге можно добавить шаги Ланжевена как корректор, но сам обратный процесс — не MCMC.

Что изменилось#

Прямые методы Монте-КарлоМарковские методы Монте-Карло
Что нужносэмплы из pp или близкое предлагающее распределениеp~\tilde p с точностью до константы (или её score)
Сэмплынезависимыекоррелированные; нужно считать эффективный размер выборки
Высокая размерностьпредлагающие распределения экспоненциально ухудшаютсялокальные шаги по-прежнему работают ценой времени перемешивания
Типичные алгоритмыметод обратной функции, выборка с отклонением, выборка по значимостиМетрополис–Гастингс, Гиббс, Ланжевен, HMC
Главная проблемавеса с бесконечной дисперсиеймедленное перемешивание, цепи, застрявшие в одной моде

Ограничения#

  • Сходимость асимптотическая, и её трудно проверить. Цепь может выглядеть стационарной, исследовав лишь часть целевого распределения; диагностика обнаруживает некоторые сбои, но никогда не все.
  • Настройка важна. Размеры шага, форма предлагающего распределения, параметризация и число цепей меняют эффективность на порядки.
  • Это дорого для больших данных и больших моделей. Каждый шаг вычисляет целевую плотность, часто по всему набору данных; для нейросетей вариационный вывод (variational inference), ансамбли или MCMC со стохастическими градиентами — более дешёвые приближения.

Что нужно запомнить#

  • Условие детального баланса p(x)P(x→y)=p(y)P(y→x)p(x) P(x \to y) = p(y) P(y \to x) делает распределение pp стационарным.
  • Алгоритм Метрополиса–Гастингса: предложить y∼q(⋅∣x)y \sim q(\cdot \mid x), принять с вероятностью min⁡(1,p~(y)q(x∣y)/(p~(x)q(y∣x)))\min\big(1, \tilde p(y) q(x \mid y) / (\tilde p(x) q(y \mid x))\big); нужны только отношения значений p~\tilde p.
  • При слишком малом шаге цепь ползёт, при слишком большом предложения отклоняются; в высокой размерности стоит ориентироваться на долю принятых около 0.23.
  • Для величины g(Xt)g(X_t) стационарной цепи коррелированные сэмплы равноценны выборке эффективного размера n/(1+2∑ρk)n/(1 + 2\sum \rho_k), обычно меньшего nn; нужно запускать несколько цепей и помнить о модах, которые цепь ни разу не посетила.
  • Сэмплирование по Гиббсу обновляет координаты из их условных распределений; сильная корреляция его замедляет.
  • Динамика Ланжевена движется по score с добавлением шума; без коррекции она смещена из-за размера шага и может быть неустойчивой (0<ε<40 < \varepsilon < 4 для стандартного нормального распределения), MALA устраняет смещение, а HMC использует тот же score. Отжиг динамики Ланжевена и обратная диффузия используют выученные score зашумлённых данных, но их целевые распределения меняются по уровням шума или во времени, так что это не равновесный MCMC.

Код#

Случайное блуждание Метрополиса с тремя размерами шага, целевое распределение с двумя модами, сэмплирование по Гиббсу и нескорректированная динамика Ланжевена:

import numpy as np, math

rng = np.random.default_rng(0)

def metropolis(logp, x0, step, n):
    """Random-walk Metropolis: propose x + step * N(0, 1), accept with probability min(1, p(y) / p(x))."""
    x, lp, chain, accepted = x0, logp(x0), np.empty(n), 0
    for t in range(n):
        y = x + step * rng.normal()
        ly = logp(y)
        if math.log(rng.random()) < ly - lp:
            x, lp, accepted = y, ly, accepted + 1
        chain[t] = x
    return chain, accepted / n

def ess(chain):
    """A rough effective sample size for illustration: autocorrelations summed until they drop below 0.05 (production tools use more careful estimators)."""
    c = chain - chain.mean()
    f = np.fft.rfft(c, 2 * len(c))
    ac = np.fft.irfft(f * np.conj(f))[: len(c)]
    ac /= ac[0]
    cut = np.argmax(ac < 0.05)
    return len(c) / (1 + 2 * ac[1:cut].sum())

# a standard normal target with three step sizes, 20,000 steps each: acceptance rate and effective sample size
for step in (0.1, 2.4, 25):
    chain, rate = metropolis(lambda x: -x * x / 2, 0.0, step, 20_000)
    print(step, round(rate, 3), round(ess(chain)))
# 0.1 0.971 57 | 2.4 0.443 4815 | 25 0.053 708

# two modes at -3 and 3: the share of time in the right mode with a small and a large step
mix = lambda x: math.log(0.5 * math.exp(-(x + 3) ** 2 / 0.72) + 0.5 * math.exp(-(x - 3) ** 2 / 0.72))
for step in (0.5, 4.0):
    chain, rate = metropolis(mix, -3.0, step, 20_000)
    print(step, round(float((chain > 0).mean()), 3))
# 0.5 0.0 | 4.0 0.502

# Gibbs for a bivariate normal: successive draws of x1 have correlation rho^2
for rho in (0.5, 0.9, 0.99):
    x1 = x2 = 0.0
    s, xs = math.sqrt(1 - rho ** 2), np.empty(20_000)
    for t in range(20_000):
        x1 = rho * x2 + s * rng.normal()
        x2 = rho * x1 + s * rng.normal()
        xs[t] = x1
    print(rho, round(float(np.corrcoef(xs[:-1], xs[1:])[0, 1]), 3), round(ess(xs)))
# 0.5 0.264 12075 | 0.9 0.807 2292 | 0.99 0.978 188

# unadjusted Langevin on N(0, 1), whose score is -x: the step size biases the stationary variance to 1 / (1 - eps / 4)
for eps in (0.1, 0.5):
    x, xs = 0.0, np.empty(200_000)
    for t in range(200_000):
        x = x + eps / 2 * (-x) + math.sqrt(eps) * rng.normal()
        xs[t] = x
    print(eps, round(float(xs[1000:].var()), 3), round(1 / (1 - eps / 4), 3))
# 0.1 1.026 1.026 | 0.5 1.13 1.143

Дальше#

Это последняя заметка курса. Курс начался с монет, игральных костей и вопроса о том, что такое вероятность, а заканчивается сэмплерами, на которых держится байесовская статистика, и score, который используют диффузионные модели. Курс генеративных моделей опирается почти на каждую заметку этого курса: метод максимального правдоподобия и KL-дивергенцию, многомерное нормальное распределение, формулу замены переменных, оценки математических ожиданий методом Монте-Карло и динамику Ланжевена вместе с её score.

Литература#