Допущения, валидность и границы применимости

Урок про самое важное и самое игнорируемое: допущения модели и границы, за которыми ей нельзя верить.

Допущение — упрощающее предположение, которое модель принимает как истину; область применимости — множество ситуаций, где эти допущения достаточно близки к реальности.

«Все модели неверны, но некоторые полезны»

Эту фразу статистика Джорджа Бокса стоит выучить наизусть. Она означает: не существует «правильной» модели, потому что любая модель упрощает, а значит, в чём-то лжёт. Спрашивать «верна ли модель?» бессмысленно. Осмысленный вопрос — «полезна ли она для моей задачи и где проходят её границы?».

Модель идеального газа PV = nRT «неверна»: молекулы имеют размер и притягиваются. Но для воздуха при комнатных условиях она полезна до третьего знака. А вот для газа под огромным давлением она ломается — там нужна модель сложнее. Та же формула: внутри своей области применимости — полезна, снаружи — опасна.

Откуда берутся допущения

Каждое упрощение при формализации — это допущение. Полезно выписывать их явным списком. Для модели эпидемии типичные допущения:

  • популяция перемешана однородно (каждый может встретить каждого);
  • заразность одинакова у всех и не меняется во времени;
  • переболевший получает пожизненный иммунитет;
  • рождений и смертей за время эпидемии нет.

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

Чувствительность к допущениям

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

# как допущение о заразности влияет на размер эпидемии
def final_size(beta, gamma=0.1):
    S, I, R, N = 999.0, 1.0, 0.0, 1000.0
    for _ in range(300):
        new_inf = beta * S * I / N
        new_rec = gamma * I
        S -= new_inf
        I += new_inf - new_rec
        R += new_rec
    return R   # сколько всего переболело

print(f"{'beta':>5} {'R0':>4} {'переболело':>11}")
for beta in (0.12, 0.15, 0.20, 0.30):
    print(f"{beta:>5.2f} {beta/0.1:>4.1f} {final_size(beta):>11.1f}")

Вывод:

 beta   R0  переболело
 0.12  1.2       270.5
 0.15  1.5       586.6
 0.20  2.0       802.8
 0.30  3.0       946.7

Видно, что небольшое изменение допущения о заразности (с 0.12 до 0.30) меняет ответ в три раза — с трети населения до почти всех. Значит, это допущение критично, и его надо обосновывать тщательно. А вот точное начальное число больных (1 или 10) на финальный размер почти не влияет — это допущение «дешёвое».

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

Граница применимости — не абстракция, она кодируется. Хорошая модель проверяет входы и честно отказывается работать вне области: если dt слишком велик, если число особей стало отрицательным, если параметр вне разумного диапазона. Молчаливое продолжение счёта за границей применимости — источник красивых, убедительных и совершенно ложных результатов. Лучше упасть с ошибкой, чем выдать правдоподобную чушь.

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

  • Не выписывать допущения. Если список допущений живёт только в голове автора, модель невозможно ни проверить, ни безопасно переиспользовать.
  • Применять модель вне её области. Формула, отличная для воздуха, врёт для плазмы. Перенос модели в новый режим без проверки — классическая катастрофа.
  • Считать все допущения равноценными. Без анализа чувствительности вы тратите силы на уточнение неважного и упускаете критичное.

Итоги

  • Любая модель держится на допущениях и потому «неверна»; вопрос — полезна ли она в своей области применимости.
  • Допущения стоит выписывать явным списком, иначе модель нельзя проверить и безопасно переиспользовать.
  • Чувствительность к допущению проверяют, шевеля его и наблюдая за ответом: критичные требуют обоснования, «дешёвые» — нет.
  • Границу применимости полезно кодировать как явные проверки, а не надеяться на удачу.
Проверьте себя
1. Что означает фраза «все модели неверны, но некоторые полезны»?
AМоделями не стоит пользоваться
BЛюбая модель упрощает реальность, поэтому судят не о её истинности, а о пользе в своей области применимости
CТочные модели существуют, но их трудно найти
DПолезность модели не связана с допущениями
2. Зачем выписывать допущения модели явным списком?
AДля объёма документации
BЧтобы модель можно было проверить и понять границы её применимости
CЭто требование Python
DЧтобы скрыть ошибки
3. Как понять, что допущение критично для результата?
AПо длине его описания
BПошевелить его и посмотреть, насколько сильно меняется ответ модели
CКритичны всегда все допущения
DСпросить у пользователя