Ансамбли прогонов и доверительные интервалы

Вы запустили стохастическую модель один раз и получили результат 3.0. Сосед запустил ту же модель и получил 4.0. Кто прав? Оба — и в этом проблема: по одному прогону случайной модели судить нельзя в принципе.

Ансамбль прогонов — это множество запусков одной и той же стохастической модели с разными случайными зёрнами (seed), которое позволяет оценить не одну реализацию, а всё распределение возможных исходов.

Стохастическая модель содержит случайность внутри: броски кубика, случайные приходы клиентов, шум измерений. Каждый её запуск — это одна реализация из огромного множества возможных. Один прогон похож на один бросок монеты: он ничего не говорит о вероятности орла. Чтобы понять поведение модели, нужно запустить её много раз и посмотреть на разброс результатов.

Зачем это критично. Без ансамбля вы рискуете принять случайную флуктуацию за реальный эффект: «новая стратегия дала 4.0 против старых 3.5 — она лучше!» — а на самом деле 4.0 попало в обычный разброс шума. Ансамбль и доверительный интервал отделяют настоящий сигнал от случайности.

Один прогон против ансамбля

Смоделируем простую вещь: бросаем кубик 30 раз и считаем среднее. Теоретически среднее одного броска кубика равно 3.5. Но среднее 30 бросков — случайная величина: иногда выпадет 3.1, иногда 3.9. Один такой прогон — это one_run(). Чтобы оценить, насколько он надёжен, повторим эксперимент 200 раз (это и есть ансамбль) и посмотрим на разброс между прогонами.

import random, statistics
random.seed(99)

def one_run():
    return statistics.mean(random.randint(1, 6) for _ in range(30))

runs = [one_run() for _ in range(200)]
m = statistics.mean(runs)
sd = statistics.pstdev(runs)
print(f"Прогонов: {len(runs)}")
print(f"Среднее по прогонам: {m:.3f} (теория 3.5)")
print(f"Стд между прогонами: {sd:.3f}")
print(f"95% доверительный интервал: [{m - 1.96 * sd:.2f}, {m + 1.96 * sd:.2f}]")

Вывод:

Прогонов: 200
Среднее по прогонам: 3.480 (теория 3.5)
Стд между прогонами: 0.324
95% доверительный интервал: [2.85, 4.12]

Смотрим на результат. Среднее по 200 прогонам — 3.480, почти точно теоретические 3.5: ансамбль дал надёжную оценку. А стандартное отклонение между прогонами — 0.324: вот насколько гуляет результат одного прогона. Теперь понятно, почему одному прогону доверять нельзя — отдельное one_run() вполне могло выдать и 3.0, и 4.0, и оба значения были бы «нормальными».

Доверительный интервал: $\bar{x} \pm 1.96\,\sigma$

Доверительный интервал — диапазон значений, в который результат отдельного прогона попадает с заданной вероятностью; для 95% это примерно $\bar{x} \pm 1.96\,\sigma$ (среднее ± 1.96 стандартных отклонения).

Множитель 1.96 — это квантиль нормального распределения: около 95% значений нормально распределённой величины лежат в пределах $1.96\,\sigma$ от среднего. Применяя его к нашему ансамблю, получаем интервал [2.85, 4.12]. Это и есть честный ответ: «среднее 30 бросков с вероятностью около 95% окажется между 2.85 и 4.12». Значение 3.0 и значение 4.0 оба внутри интервала — значит, ни одно из них не «удивительно», оба объясняются случайностью.

Как работает под капотом

Здесь работают сразу две статистические идеи. Первая — закон больших чисел: среднее по большому ансамблю (3.480) сходится к истинному значению (3.5), сглаживая случайность отдельных прогонов. Вторая — центральная предельная теорема: средние из 30 бросков распределены приблизительно нормально, поэтому к ним применимо правило $1.96\,\sigma$ для 95% интервала. statistics.pstdev считает стандартное отклонение по всему ансамблю как по генеральной совокупности прогонов. А random.seed(99) фиксирует поток случайных чисел, чтобы вывод воспроизводился точь-в-точь.

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

Как отличить эффект от шума

Новая стратегия дала 4.0. Реальный эффект или шум?

ДИ старой модели: [2.85, 4.12]
4.0 ВНУТРИ интервала  скорее всего просто шум, эффекта нет
4.5 ВНЕ интервала     выходит за разброс случайности, возможен реальный эффект

Правило простое: если новый результат попадает внутрь доверительного интервала базовой модели, его нельзя отличить от случайного шума. Если выходит за пределы — есть основания говорить о реальном эффекте.

Частые ошибки

  • Делать выводы по одному прогону. Отдельная реализация стохастической модели может сильно отклоняться от истины — это не результат, а одна точка из распределения.
  • Не фиксировать seed при отладке. Без random.seed вывод нельзя воспроизвести, и баг от шума не отличить.
  • Брать слишком маленький ансамбль. На 5 прогонах оценка среднего и стд сами по себе шумные; нужны десятки-сотни запусков.
  • Сообщать только среднее без разброса. «Результат 3.48» без интервала [2.85, 4.12] скрывает, насколько он может гулять.
  • Считать любое отклонение эффектом. Значение внутри доверительного интервала неотличимо от шума — это не открытие.

Итоги

  • Один прогон стохастической модели — это одна реализация из многих; по нему судить нельзя.
  • Ансамбль (здесь 200 прогонов с разными состояниями генератора) даёт надёжную оценку: среднее 3.480 близко к теории 3.5.
  • Стандартное отклонение между прогонами (0.324) показывает, насколько гуляет отдельный прогон.
  • 95% доверительный интервал $\bar{x} \pm 1.96\,\sigma$ = [2.85, 4.12] очерчивает разброс результата.
  • Результат внутри интервала неотличим от шума; выход за пределы — повод заподозрить реальный эффект. Всегда прогоняйте стохастическую модель много раз и приводите разброс.
Проверьте себя
1. Почему нельзя делать выводы по одному прогону стохастической модели?
AОдин прогон работает слишком быстро
BЭто лишь одна случайная реализация из многих — она могла дать и 3.0, и 4.0
CОдин прогон всегда даёт ошибку
DБиблиотека random это запрещает
2. Что показывает стандартное отклонение между прогонами (0.324) в выводе?
AСреднее значение броска кубика
BНасколько результат отдельного прогона гуляет от прогона к прогону
CКоличество прогонов в ансамбле
DТеоретическое среднее 3.5
3. Откуда берётся множитель 1.96 в формуле доверительного интервала?
AЭто число прогонов делёное на 100
BЭто квантиль нормального распределения: около 95% значений лежат в пределах 1.96 стд от среднего
CЭто среднее значение кубика
DЭто случайное число
4. Новая стратегия дала результат 4.0, а ДИ базовой модели = [2.85, 4.12]. Какой вывод корректен?
AНовая стратегия точно лучше
B4.0 внутри интервала, поэтому отличие от шума не доказано
C4.0 выходит за интервал, эффект реальный
DНужно сравнивать только средние без интервалов
py
Курс по теме
Пройдите курс «Python с нуля» — по шагам, с проверкой
8 уроков · ~14 ч · теория, упражнения и экзамен с бейджем
Открыть курс →