Create your own
Lesson illustration

Цепное правило энтропии для последовательности случайных величин

Здравствуйте! В предыдущем уроке мы разобрали цепное правило для двух переменных:

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

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


От факторизации вероятности к разложению энтропии

Пусть обозначает последовательность случайных величин:

Для конкретной реализации обычное цепное правило вероятности даёт:

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

Возьмём отрицательный логарифм. Произведение превращается в сумму:

Левая часть — surprisal конкретной полной последовательности. Правая часть говорит: неожиданность всей последовательности складывается из неожиданностей её шагов, причём на шаге мы уже знаем префикс .

Теперь усредним по всем последовательностям, порождённым распределением . Получаем цепное правило энтропии:

или, если договориться, что , в более компактной форме:

Для первого члена истории нет, поэтому:

Смысл формулы стоит читать буквально:

  • — неопределённость первого элемента;
  • — дополнительная неопределённость второго после наблюдения первого;
  • — то, что ещё неизвестно о третьем элементе после первых двух;
  • сумма — неопределённость всей последовательности как единого объекта.

[PDF] Lecture 2 — January 12 2.1 Outline 2.2 Entropy 2.3 The Chain Rule ...

В конспекте Stanford EE 376A аккуратно выводится правило сначала для двух переменных, затем для трёх и произвольной последовательности. Обратите особое внимание на то, что условная энтропия остаётся ожиданием по совместному распределению, а не энтропией одного фиксированного условного среза.

В разделе 2.3 на стр. 2-1 быстро просмотрите вывод H(X,Y)=H(X)+H(Y\mid X), связывая его с предыдущим уроком. Затем на стр. 2-2 прочитайте подраздел 2.3.1 “More than two variables”: от фразы перехода к трём переменным до интерпретации слагаемых. Проследите, почему при вычислении H(Z\mid X,Y) условием является вся уже наблюдённая история, а не только Y.


Последовательность как пошаговое раскрытие неопределённости

Для трёх переменных цепное правило имеет вид:

Это можно получить, применив уже знакомое правило дважды:

Важны две вещи.

Совместная энтропия не зависит от порядка записи, слагаемые — зависят

Величина

не меняется, если переставить переменные. Но разложение меняется. Для любой перестановки :

То есть «общий бюджет неопределённости» один и тот же, но он распределяется между этапами наблюдения по-разному.

Для языковой модели порядок не произволен: токены поступают слева направо. Поэтому естественно использовать именно

Нельзя молча выбрасывать дальнюю историю

Формула всегда содержит весь префикс:

Заменить его на

можно лишь при дополнительном предположении первого порядка Маркова:

Тогда:

Это точное упрощение для марковского источника, а не общая эвристика. В естественном языке или в сложной траектории агента дальний контекст часто меняет распределение следующего шага, поэтому отброс истории может существенно завысить реальную неопределённость.


Небольшой марковский источник: три связанных бита

Пусть — честный бит:

Каждый следующий бит с вероятностью повторяет предыдущий и с вероятностью меняется:

Так как бит симметрично «переключается», маргинально каждый из остаётся честным:

Однако из этого не следует, что энтропия тройки равна битам. Переменные зависимы: зная предыдущий бит, следующий обычно предсказуем.

Условная энтропия перехода равна бинарной энтропии шума:

Поскольку источник первого порядка Маркова:

Значит:

Хотя каждый отдельный бит имеет энтропию бит, вся тройка содержит менее двух бит совместной неопределённости. Наблюдение предыдущих значений устраняет большую часть неопределённости следующих.

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

Для :

Для :

Вторая последовательность неожиданнее: после нулевого первого бита происходит редкая смена на единицу. Цепное правило для энтропии — это среднее такой пошаговой декомпозиции surprisal по всем возможным траекториям.


Диаграмма показывает разложение совместной энтропии двух переменных: область \(H(X,Y)\) состоит из условных энтропий \(H(X\mid Y)\), \(H(Y\mid X)\) и общей части \(I(X;Y)\). Для последовательности цепное правило рекурсивно применяет это двухпеременное разложение: «вторая переменная» на каждом шаге является очередным элементом, а «первая» — всей накопленной историей.

Entropy, Mutual Information, Conditional and Joint Entropy

Короткий фрагмент “Entropy, Mutual Information, Conditional and Joint Entropy” от NPTEL IIT Delhi визуально связывает совместную энтропию с первым наблюдением и тем, что остаётся неизвестным после него. Он полезен как переход от случая двух переменных к рекурсивному применению той же идеи.

Посмотрите вывод правила. Сопоставьте формулу H(X,Y)=H(X)+H(Y\mid X) с первым шагом разложения тройки: после выделения X_1 роль второй переменной играет составной объект (X_2,X_3).


Условное цепное правило: известный контекст вне последовательности

Иногда последовательность не начинается «с нуля»: есть внешний контекст . Например, для генерации ответа контекстом могут быть system prompt, пользовательский запрос, retrieved documents и предыдущие сообщения.

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

Она выражает среднюю неопределённость последовательности после того, как контекст уже наблюдён.

Это важно читать осторожно. Условная энтропия усредняется по возможным значениям . Для некоторого конкретного контекста энтропия следующего токена

может оказаться высокой или низкой. Величина

усредняет такие локальные неопределённости по распределению контекстов и историй.


Вычисление разложения по совместному тензору в PyTorch

Для небольшой дискретной модели можно явно хранить совместное распределение как тензор. В примере ниже ось соответствует , ось , ось .

import torch


def entropy_bits(p: torch.Tensor) -> torch.Tensor:
    """Entropy of any normalized discrete probability tensor, in bits."""
    p = torch.as_tensor(p, dtype=torch.float64)

    if (p < 0).any():
        raise ValueError("Probabilities must be non-negative.")
    if not torch.isclose(p.sum(), torch.tensor(1.0, dtype=p.dtype)):
        raise ValueError("Probabilities must sum to 1.")

    log_p = torch.where(p > 0, p.log2(), torch.zeros_like(p))
    return -(p * log_p).sum()


def prefix_entropy(p_joint: torch.Tensor, t: int) -> torch.Tensor:
    """
    H(X_1, ..., X_t), where p_joint has one axis per variable.
    t is a one-based prefix length.
    """
    if not 1 <= t <= p_joint.ndim:
        raise ValueError("t must be between 1 and the number of variables.")

    suffix_dims = tuple(range(t, p_joint.ndim))
    p_prefix = p_joint.sum(dim=suffix_dims) if suffix_dims else p_joint
    return entropy_bits(p_prefix)


def chain_rule_terms(p_joint: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]:
    """
    Returns:
      prefix_entropies[t - 1] = H(X_1, ..., X_t)
      terms[t - 1] = H(X_t | X_1, ..., X_{t-1})
    """
    prefix_entropies = torch.stack([
        prefix_entropy(p_joint, t)
        for t in range(1, p_joint.ndim + 1)
    ])

    terms = torch.cat([
        prefix_entropies[:1],
        prefix_entropies[1:] - prefix_entropies[:-1],
    ])

    return prefix_entropies, terms

Построим совместное распределение для описанного марковского источника:

transition = torch.tensor([
    [0.9, 0.1],  # P(X_t | X_{t-1}=0)
    [0.1, 0.9],  # P(X_t | X_{t-1}=1)
], dtype=torch.float64)

p_x123 = torch.zeros(2, 2, 2, dtype=torch.float64)

for x1 in range(2):
    for x2 in range(2):
        for x3 in range(2):
            p_x123[x1, x2, x3] = (
                0.5
                * transition[x1, x2]
                * transition[x2, x3]
            )

prefix_h, chain_h = chain_rule_terms(p_x123)

print("Prefix entropies:", prefix_h)
print("Chain-rule terms:", chain_h)
print("Joint entropy:", entropy_bits(p_x123))
print("Sum of terms:", chain_h.sum())

Ожидаемый результат с небольшими различиями округления:

Prefix entropies: tensor([1.0000, 1.4690, 1.9380])
Chain-rule terms: tensor([1.0000, 0.4690, 0.4690])
Joint entropy: tensor(1.9380)
Sum of terms: tensor(1.9380)

Проверка цепного правила должна быть инвариантом теста:

assert torch.allclose(
    entropy_bits(p_x123),
    chain_h.sum(),
    atol=1e-12,
)

assert torch.allclose(
    chain_h[0],
    entropy_bits(p_x123.sum(dim=(1, 2))),
    atol=1e-12,
)

Здесь условные члены вычислены как разности энтропий префиксов:

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


Связь с авторегрессивными языковыми моделями

Авторегрессивная модель задаёт распределение над продолжением через локальные распределения следующего токена:

Поэтому её отрицательное лог-правдоподобие на конкретной последовательности также раскладывается по токенам:

Это формально похоже на цепное правило энтропии, но объекты различны:

ВеличинаЧто усредняетсяКакое распределение используется
Последовательности из истинного распределенияИстинное
Одна наблюдаемая последовательностьМодельное
Ожидаемый token-level NLLДанные из Оценки модели

Если модель совпадает с истинным распределением, ожидаемый NLL равен энтропии источника. Если не совпадает, появляется дополнительный член, который позднее будет описан через cross-entropy и KL-дивергенцию.

Практически цепное правило объясняет, почему token-level метрики можно агрегировать по последовательности: каждый токен вносит собственную условную неожиданность, а сумма соответствует неожиданности всей строки при выбранной модели.


Итог

Цепное правило энтропии переносит знакомое двухпеременное разложение на последовательности:

Главные выводы:

  • совместная неопределённость последовательности равна сумме дополнительных неопределённостей на каждом шаге;
  • для конкретной последовательности аналогично раскладывается surprisal;
  • порядок переменных меняет отдельные условные слагаемые, но не их сумму;
  • полную историю можно заменить последним состоянием только при обоснованной марковской структуре;
  • для авторегрессивной модели эта же факторизация лежит в основе последовательностного log-likelihood и token-level NLL.

В следующем уроке мы сменим фокус: рассмотрим энтропию как функцию распределения и докажем её вогнутость. Это свойство затем позволит строго показать, почему равномерное распределение имеет максимальную энтропию на фиксированном конечном носителе.

Can't find a good explanation? Sign up and we'll make it for you

Sign up