Перечислите все возможные комбинированные вероятности серии испытаний Бернулли с разными вероятностями.
Предположим, у меня есть ряд из n вероятностей успеха независимых испытаний Бернулли, p1-pn, таких что p1!= P2!= ...!= Pn. Дайте каждому испытанию уникальное имя.
p <- c(0.5, 0.12, 0.7, 0.8, .02)
a <- c("A","B","C","D","E")
Из обмена стека поиска (например, здесь и здесь) я знаю, что могу найти cdf, pmf и т. Д., Используя функцию биномиального распределения Пуассона.
Меня интересует точная вероятность каждой возможной комбинации успеха и неудач. (Например, если я нарисовал дерево вероятностей, я хочу знать вероятность в конце каждой ветви.)
all <- prod(p)
all
[1] 0.000672
o1 <- (0.5 * (1-0.12) * 0.7 * 0.8 * .02)
o1
[1] 0.004928
o2 <- (0.5 * 0.12 * (1-0.7) * 0.8 * .02)
o2
[1] 0.000288
... для всех 2^5 возможных комбинаций успеха / неудачи.
Какой эффективный способ сделать это в R?
В случае моего фактического набора данных, число испытаний составляет 19, поэтому мы говорим о 2^19 общих путей в дереве вероятности.
2 ответа
Ключом к быстрому вычислению является выполнение этого в пространстве логарифмической вероятности, чтобы произведение для каждой ветви дерева представляло собой сумму, которая может быть вычислена как внутренняя сумма умножения матрицы. Таким образом, все ветви могут быть вычислены вместе в векторизованном виде.
Сначала мы строим перечисление всех ветвей. Для этого мы используем intToBin
функция от R.utils
пакет:
library(R.utils)
enum.branches <- unlist(strsplit(intToBin(seq_len(2^n)-1),split=""))
где n
число переменных Бернулли. Для вашего примера n=5
:
matrix(enum.branches, nrow=n)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17]
##[1,] "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "1"
##[2,] "0" "0" "0" "0" "0" "0" "0" "0" "1" "1" "1" "1" "1" "1" "1" "1" "0"
##[3,] "0" "0" "0" "0" "1" "1" "1" "1" "0" "0" "0" "0" "1" "1" "1" "1" "0"
##[4,] "0" "0" "1" "1" "0" "0" "1" "1" "0" "0" "1" "1" "0" "0" "1" "1" "0"
##[5,] "0" "1" "0" "1" "0" "1" "0" "1" "0" "1" "0" "1" "0" "1" "0" "1" "0"
## [,18] [,19] [,20] [,21] [,22] [,23] [,24] [,25] [,26] [,27] [,28] [,29] [,30] [,31] [,32]
##[1,] "1" "1" "1" "1" "1" "1" "1" "1" "1" "1" "1" "1" "1" "1" "1"
##[2,] "0" "0" "0" "0" "0" "0" "0" "1" "1" "1" "1" "1" "1" "1" "1"
##[3,] "0" "0" "0" "1" "1" "1" "1" "0" "0" "0" "0" "1" "1" "1" "1"
##[4,] "0" "1" "1" "0" "0" "1" "1" "0" "0" "1" "1" "0" "0" "1" "1"
##[5,] "1" "0" "1" "0" "1" "0" "1" "0" "1" "0" "1" "0" "1" "0" "1"
В результате получается матрица, в которой каждый столбец является результатом ветви дерева вероятностей.
Теперь используйте это для построения матрицы логарифмических вероятностей того же размера, что и enum.branches
где значение log(p)
если enum.branches=="1"
а также log(1-p)
иначе. Для ваших данных, с p <- c(0.5, 0.12, 0.7, 0.8, .02)
, это:
logp <- matrix(ifelse(enum.branches == "1", rep(log(p), 2^n), rep(log(1-p), 2^n)), nrow=n)
Затем сложите логарифмические вероятности и возьмите экспоненту, чтобы получить произведение вероятностей:
result <- exp(rep(1,n) %*% logp)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
##[1,] 0.025872 0.000528 0.103488 0.002112 0.060368 0.001232 0.241472 0.004928 0.003528 7.2e-05
[,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20]
##[1,] 0.014112 0.000288 0.008232 0.000168 0.032928 0.000672 0.025872 0.000528 0.103488 0.002112
[,21] [,22] [,23] [,24] [,25] [,26] [,27] [,28] [,29] [,30]
##[1,] 0.060368 0.001232 0.241472 0.004928 0.003528 7.2e-05 0.014112 0.000288 0.008232 0.000168
[,31] [,32]
##[1,] 0.032928 0.000672
result
будет в том же порядке, что и нумерация ветвей в enum.branches
,
Мы можем заключить вычисление в функцию:
enum.prob.product <- function(n, p) {
enum.branches <- unlist(strsplit(intToBin(seq_len(2^n)-1),split=""))
exp(rep(1,n) %*% matrix(ifelse(enum.branches == "1", rep(log(p), 2^n), rep(log(1-p), 2^n)), nrow=n))
}
Сроки это с 19
независимые переменные Бернулли:
n <- 19
p <- runif(n)
system.time(enum.prob.product(n,p))
## user system elapsed
## 24.064 1.470 26.082
Это на моем MacBook 2 ГГц (около 2009 г.). Следует отметить, что само вычисление довольно быстрое; это перечисление ветвей дерева вероятностей (я бы unlist
внутри этого), что занимает большую часть времени. Будем благодарны за любые предложения сообщества по поводу другого подхода к этому.
Просто попробуйте это в базе R:
p <- c(0.5, 0.12, 0.7, 0.8, .02)
a <- c("A","B","C","D","E")
n <- length(p)
apply(expand.grid(replicate(n,list(0:1)))[n:1], 1,
function(x) prod(p[which(x==1)])*prod(1-p[which(x==0)]))
#[1] 0.025872 0.000528 0.103488 0.002112 0.060368 0.001232 0.241472 0.004928 0.003528 0.000072 0.014112 0.000288 0.008232 0.000168 0.032928 0.000672 0.025872
#[18] 0.000528 0.103488 0.002112 0.060368 0.001232 0.241472 0.004928 0.003528 0.000072 0.014112 0.000288 0.008232 0.000168 0.032928 0.000672