Статьи

Подбрасывание монеты: байесовское обновление вероятностных распределений

Когда я начал больше узнавать о байесовских статистических методах, самым большим моментом для меня стало то, что я начал думать с точки зрения распределения. Я был воспитан на понятии единого числа ответов. Из-за этого я подумал, что освоил байесовские методы, когда я мог читать P (A | B) = P (B | A) P (A) / P (B). НЕПРАВИЛЬНО.

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

Сначала позвольте мне привести конкретный пример сегодняшнего дня: подбрасывание монеты!

Chance of Heads

Если вы подбрасываете монету, и она выпадает хвостом три раза из четырех, какова вероятность того, что ваша монета на самом деле является честной монетой? Скажем, справедливость означает 45-55 процентов времени, когда оно приходит в голову.

Вероятность того, что это может прийти в голову, может быть от 0 до 100 процентов, верно? Нулевой процент означал бы, что это совершенно несправедливо, и почему-то НИКОГДА не приходит в голову. Сто процентов было бы с точностью до наоборот. Мы надеемся, что где-то посередине.

Теперь, прежде чем мы подбросим монету, нам нужно решить, каковы вероятности наших гипотез от 0 до 100 процентов. Для простоты мы будем предполагать, что каждая гипотеза одинаково вероятна. Это известно как «равномерное распределение». В Python это выглядит так:

possibilities = [1.0]*101

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

def normalize(possibilities):
  possibility_sum = sum(possibilities)
  for hypothesis in xrange(0,101):
    possibility = possibilities[hypothesis]
    possibilities[hypothesis] = possibility/possibility_sum

По сути, это просто гарантирует, что все вероятности для наших гипотез в сумме составят 100%, как хорошие малые вероятности.

Вот как это равномерное распределение выглядит визуально:

Равномерное распределение

Обновление с новой информацией

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

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

Один процент: шансы кажутся очень низкими, поскольку, учитывая, что вероятность получить голову составляет всего 1 процент, это будет первое, с чем мы столкнемся.

Пятьдесят процентов: вполне возможно. Мы перевернулись только один раз, поэтому у нас не может быть 50-процентной вероятности. Это должно быть где-то посередине.

Сто процентов: Ну, мы только один раз перевернули головы, поэтому мы не можем сказать, что это точно, но мы также не можем исключить это.

Итак, как нам обновить наши данные в Python?

Мы используем эту функцию, когда переворачиваем головы:

def update_success(possibilities):
  for hypothesis in xrange(0, 101):
    likelihood = possibilities[hypothesis]
    possibilities[hypothesis] = likelihood * hypothesis/100.0
  normalize(possibilities)

И эта функция, когда мы переворачиваем хвосты:

def update_failure(possibilities):
  for hypothesis in xrange(0, 101):
    likelihood = possibilities[hypothesis]
    possibilities[hypothesis] = likelihood*(1.0-hypothesis/100.0)
  normalize(possibilities)

Они отличаются одним тонким способом. Посмотрите внимательно на четвертую строку каждой функции.

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

Это оставляет нам следующую гистограмму вероятностей для каждой гипотезы: Один успех

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

Шагая по нашему сценарию

Далее, скажем, мы переворачиваем хвосты и продумываем то, что ожидаем увидеть. Мы уже исключили 0-процентную вероятность увидеть головы, и теперь мы можем исключить 100-процентную вероятность увидеть головы. Теперь у нас есть по одному, поэтому я ожидаю, что середина дистрибутива немного увеличится. Будь то форма треугольника или кривая, я не уверен, но что-то в этом роде.

Вот это распределение: Один успех, один провал

Это изогнуто! Конечно! Ну … Это не совсем очевидно, но, по крайней мере, кажется рациональным.

Теперь допустим, что мы переворачиваем еще два раза, и они обе головы: Многочисленные успехи и неудачи

Получение к ответу

Остановимся здесь и ответим на вопрос, который я изначально задавал. Насколько вероятно, что у этой монеты будет ~ 50-процентная вероятность перевернуть головы (где это действительно означает 45-55-процентную вероятность, потому что статистика — неточная наука)? Вот как мы можем приблизить ответ. Из имеющейся у нас гистограммы нам просто нужно сложить вероятность каждой гипотезы.

  • 45 процентов 0,68%
  • 46 процентов 0,73%
  • 47 процентов 0,78%
  • 48 процентов 0,83%
  • 49 процентов 0,88%
  • 50 процентов 0,94%
  • 51 процент 0,99%
  • 52 процента 1,05%
  • 53 процента 1,11%
  • 54 процента 1,17%
  • 55 процентов 1,24%

Добавление их всех равняется 10-процентному шансу.

Обратите внимание, как каждая отдельная гипотеза имеет очень низкую вероятность? Ровно 50 процентов — это всего лишь 0,94 процента! О чем это?

На самом деле это действительно крутой аспект этого метода. Видите ли, всякий раз, когда вы имеете дело с вероятностями (даже в статистике часто встречающихся), вам необходимо иметь дело с диапазонами вероятностей. Назовите их доверительным интервалом, доверительным интервалом, интервалом максимальной плотности и т. Д. Это та же концепция.

Кроме того, вся эта идея рассматривать индивидуальные вероятности как гипотезы меняла жизнь. Эта концепция в целом применима ко всему, где вы хотите оценить вероятности. Ось Y всегда будет вероятностью, но ось X может быть любым числовым значением. Будь то деньги, время или что у тебя есть.

На самом деле, поскольку я упомянул интервалы достоверности, давайте получим это и из этих данных.

Интервал достоверности

Самый простой способ объяснить доверительный интервал — это сказать, что по сути это доверительный интервал, который вы легко можете получить из гистограммы. Это влечет за собой высказывание, какие гипотезы охватывают 95 процентов вероятностей, которые у вас есть.

У меня мало времени, поэтому мы просто оценим это. Я взял данные из программы и поместил их в электронную таблицу. Следующим моим шагом будет сортировка данных по вероятности в порядке убывания и получение первых N значений, которые составляют до 95 процентов. Тогда мне нужно найти минимальную гипотезу в этом диапазоне и максимальную.

Я сделал это для нашего эксперимента. Девяносто пять процентов вероятности падает между 42 и 98 процентами. Мы можем интерпретировать это как означающее, что мы не можем исключить вероятность того, что наша монета может все еще выпадать в головах в 50% случаев … но тогда мы также имеем некоторую уверенность в том, что наша монета выпадет в головах более чем в 90% случаев. Действительно, этот интервал настолько широк, что его следует интерпретировать так, что нам нужно больше данных.

Заверните

Это алгоритм. Это чрезвычайно просто, но эти ~ 12 строк кода заняли у меня некоторое время, чтобы по-настоящему понять. Если вы хотите узнать больше, я предлагаю прочитать о биномиальном распределении. Я думаю, вы можете увидеть некоторые сходства между этим и тем, что мы сделали. Узнайте больше здесь.

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

def normalize(possibilities):
  possibility_sum = sum(possibilities)
  for hypothesis in xrange(0,101):
    possibility = possibilities[hypothesis]
    possibilities[hypothesis] = possibility/possibility_sum

def update_success(possibilities):
  for hypothesis in xrange(0, 101):
    likelihood = possibilities[hypothesis]
    possibilities[hypothesis] = likelihood*hypothesis/100.0
  normalize(possibilities)

def update_failure(possibilities):
  for hypothesis in xrange(0, 101):
    likelihood = possibilities[hypothesis]
    possibilities[hypothesis] = likelihood*(1.0-hypothesis/100.0)
  normalize(possibilities)

# set every possibility to be equally possible
possibilities = [1.0]*101

# Coin flip, probability of heads
normalize(possibilities)
update_success(possibilities)
update_failure(possibilities)
update_success(possibilities)
update_success(possibilities)

print possibilities

(Примечание: эта статья и высказанные мнения являются исключительно моими собственными и не отражают точку зрения моего работодателя.)