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

В недавней статье Эрик Клеппен исследовал так называемый «парадокс дня рождения», моделируя и визуализируя распределения дней рождения, и все это на Python. Как энтузиаст JavaScript, я не мог не использовать эту идею для веб-браузера.

Парадокс дня рождения представляет собой парадоксальный факт, что не так уж маловероятно найти двух людей, у которых один день рождения, даже в небольшой группе…

Как показал пример Эрика, в группе всего из 23 человек вероятность того, что у кого-то общий день рождения, составляет около 50%, согласно аналитической формуле, которую можно вывести из биномиальных распределений. Более того, в группе из 70 человек вероятность того, что двое из них родятся в один день, составляет 99,9%!

Моделирование, а не вывод уравнений

Если аналитическая математика вас не убеждает, то лучше всего просто смоделировать примеры… много, много, много примеров, а затем собрать частоты.

Здесь я сделал это (с примером из 23 человек) очень легко, просто в Excel. Конечно, это плохо масштабируется, поэтому в следующий раз мы сделаем это на JavaScript. Но давайте сначала посмотрим на электронную таблицу, чтобы понять суть протокола.

По сути, мы выполняем следующий «симуляционный эксперимент» несколько раз:

  • Моделирование 23 целых чисел от 1 до 365 (строки со 2 по 24)
  • Проверьте, повторяются ли какие-либо два числа (строки с 27 по 50), присвоив 1, если верно, или 0 в противном случае.

Наконец, мы просто суммируем единицы по всем реализациям эксперимента и делим на количество реализаций. для простоты, поскольку мы решили присвоить 1 и 0, это соответствует среднему значению всех вычисленных 0 и 1. Это число является результатом, который мы ищем.

Например, здесь я провел 192 эксперимента (каждый эксперимент — это один столбец), вытягивая 23 случайных числа от 1 до 365 (каждая строка от 2 до 24 — это одно из этих случайных чисел). Вы видите, что среднее значение равно 0,52, что довольно близко к полученному аналитически значению около 0,5.

Моделирование 23 дней рождения в JavaScript

Смоделировать 23 дня рождения и проверить, разделяют ли их хотя бы два человека в JavaScript, очень просто:

<script>
var birthdays=[]  //Array that will contain the birthdays
//A function to generate the birthdays
function generatebirthdays() {
 birthdays=[]                  //Clear array
 for (var i=0;i<23;i++)        //Push 23 random numbers   
   {birthdays.push(parseInt(Math.random()*365+1))}
}
//A function to print the birthdays
function printbirthdays() {
 for (var i=0;i<23;i++) {document.write(birthdays[i] + “<br>”)}
}
//Function to check if there's a repeat in the list
//Notice each number is checked against all the others
function istherearepeat() {
 var repeatfound=false
 for (var i=0;i<23;i++) {
 for (var j=i+1;j<23;j++) {
 if (birthdays[i] == birthdays[j]) {
 repeatfound=true
 return repeatfound
 }
 }
 }
 return repeatfound
}
//Now call the functions to generate and print the birthdays
generatebirthdays()
printbirthdays()
//Also print whether there is a repeat or not.
document.write(“<br>” + istherearepeat())
</script>

Вы можете увидеть это в действии здесь:

http://lucianoabriata.altervista.org/tests/birthdays/simulation23-example1.html

(Нажав CTRL+U в большинстве браузеров, вы можете увидеть полный код веб-страницы.)

В этом небольшом веб-приложении каждый раз, когда вы нажимаете F5 (обновить), вы получаете новый список из 23 чисел в диапазоне от 1 до 365, а в конце — флаг, указывающий, есть ли повторение или нет. Если вы запустите его много раз и подсчитаете количество попаданий, после нескольких обновлений ваше среднее значение должно приблизиться к 50%. Но, конечно, мы можем автоматизировать это, как я покажу вам дальше.

Повторное моделирование 23 дней рождения для сближения частот

Мы можем вложить вышеуказанные функции в цикл и вызывать их снова и снова.

Вместо использования цикла for здесь я предпочел использовать функцию setInterval, которая выводит 23 случайных числа из диапазона 1–365 и вычисляет, есть ли повтор каждые 100 миллисекунд:

var ntrue = 0
var ntotal = 0
setInterval(function() {
 generatebirthdays()
 //printbirthdays()
 var repeated = istherearepeat()
 if (repeated == true) {ntrue++}
 ntotal++
 document.write(“New random draw: “ + repeated + “ ||||| So “ + ntrue + “ trues out of “ + ntotal + “ experiments = “ + Math.round(ntrue/ntotal*10000)/100 + “ %<br>”)
 } , 100)

Функция подсчитывает количество повторений в ntrue и общее количество «экспериментов» (т. е. розыгрышей 23 чисел) в ntotal. . Вероятность, которую мы ищем, аппроксимируется частотой повторений, которая представляет собой просто отношение истинное/общее. Обратите внимание, что код форматирует это соотношение как % с не более чем двумя десятичными знаками:

Math.round(ntrue/ntotal*10000)/100

Вы можете протестировать этот пример по этой ссылке:

http://lucianoabriata.altervista.org/tests/birthdays/simulation23-example2.html

Как только вы загрузите страницу, начнется вычисление. Программа добавит строки, сообщающие ntrue, total и соответствующую частоту:

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

Проще всего было бы отслеживать, как частота меняется с течением времени, чтобы проверить, как она медленно сходится примерно к 50%:

Обратите внимание, что переключение оси X на логарифмическую шкалу приводит к более четкому представлению колебаний во время первых раундов экспериментов. Например:

Обратите внимание, что каждый новый прогон может начинаться совершенно по-разному, но после достаточного количества раундов он снова должен приближаться к примерно 50%. Здесь я сравниваю прогон выше (синий) с другим запуском с нуля (оранжевый):

И вот: вы подошли к проблеме статистики на практике с помощью моделирования и в JavaScript, так что без накладных расходов. Просто напишите код и запустите его в браузере — вот что мне больше всего нравится в этом языке!

Я надеюсь, что вы нашли это полезным. Спасибо за чтение.

Дополнительные идеи и чтения

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

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

Вот еще несколько материалов, которые могут вас заинтересовать:

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



Об анализе данных в веб-браузерах:



Один конкретный пример: PCA:



И, наконец, оригинальная статья Эрика о парадоксе дня рождения, но на Python:



Я увлекаюсь природой, наукой, технологиями, программированием и самоделками. Биотехнолог и химик, в мокрой лаборатории и с компьютерами. Пишу обо всем, что входит в широкую сферу моих интересов. Проверьте мои списки для большего количества историй. Стать участником Medium, чтобы получить доступ ко всем его историям, и подписаться на получение моих новых историй по электронной почте (оригинальные партнерские ссылки платформы, за которые я получаю небольшой доход без особые расходы для вас). Пожертвуйте здесь различными способами. Свяжитесь со мной здесь.

Для консультаций по поводу небольших вакансий (по программированию, оценке биотехнологических и биоинформационных проектов, научной работе + общению, анализу и проектированию молекулярных данных, молекулярной графике, фотографии, учебным пособиям по moleculARweb, преподаванию и репетиторству по естественным наукам и т. д. .) проверьте мою страницу услуг здесь.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Посетите наш Community Discord и присоединитесь к нашему Коллективу талантов.