直播视频帧替换
在上一篇博客文章中,我展示了如何得出Think Bayes骰子问题的后验概率 :
假设我有一个骰子盒,其中包含4面骰子,6面骰子,8面骰子,12面骰子和20面骰子。 如果您曾经玩过《龙与地下城》,您就会知道我在说什么。
假设我从盒子中随机选择一个骰子,将其掷骰并得到6。我掷每个骰子的概率是多少?
回顾一下,这是我的最终解决方案:
likelihoods = function(names, observations) {
scores = rep(1.0 / length(names), length(names))
names(scores) = names
for(name in names) {
for(observation in observations) {
if(name < observation) {
scores[paste(name)] = 0
} else {
scores[paste(name)] = scores[paste(name)] * (1.0 / name)
}
}
}
return(scores)
}
dice = c(4,6,8,12,20)
l1 = likelihoods(dice, c(6))
> l1 / sum(l1)
4 6 8 12 20
0.0000000 0.3921569 0.2941176 0.1960784 0.1176471
尽管它可以正常工作,但我们嵌套的循环不是非常惯用的R,所以让我们尝试摆脱它们。
我们要做的第一件事是返回数据帧而不是向量,因此我们将前两行调整为如下所示:
scores = rep(1.0 / length(names), length(names))
df = data.frame(score = scores, name = names)
接下来,我们可以摆脱内部for循环,并用包裹在dplyr mutate调用中的ifelse调用代替它:
library(dplyr)
likelihoods2 = function(names, observations) {
scores = rep(1.0 / length(names), length(names))
df = data.frame(score = scores, name = names)
for(observation in observations) {
df = df %>% mutate(score = ifelse(name < observation, 0, score * (1.0 / name)) )
}
return(df)
}
dice = c(4,6,8,12,20)
l1 = likelihoods2(dice, c(6))
> l1
score name
1 0.00000000 4
2 0.03333333 6
3 0.02500000 8
4 0.01666667 12
5 0.01000000 20
最后,我们将整理分数,使它们彼此之间具有相对的权重:
likelihoods2 = function(names, observations) {
scores = rep(1.0 / length(names), length(names))
df = data.frame(score = scores, name = names)
for(observation in observations) {
df = df %>% mutate(score = ifelse(name < observation, 0, score * (1.0 / name)) )
}
return(df %>% mutate(weighted = score / sum(score)) %>% select(name, weighted))
}
dice = c(4,6,8,12,20)
l1 = likelihoods2(dice, c(6))
> l1
name weighted
1 4 0.0000000
2 6 0.3921569
3 8 0.2941176
4 12 0.1960784
5 20 0.1176471
现在我们只讨论一个for循环。 摆脱那个有点棘手。 首先,我们将创建一个数据帧,其中每个(观察,骰子)对都包含一行,以模拟嵌套的for循环:
likelihoods3 = function(names, observations) {
l = list(observation = observations, roll = names)
obsDf = do.call(expand.grid,l) %>%
mutate(likelihood = 1.0 / roll,
score = ifelse(roll < observation, 0, likelihood))
return(obsDf)
}
dice = c(4,6,8,12,20)
l1 = likelihoods3(dice, c(6))
> l1
observation roll likelihood score
1 6 4 0.25000000 0.00000000
2 6 6 0.16666667 0.16666667
3 6 8 0.12500000 0.12500000
4 6 12 0.08333333 0.08333333
5 6 20 0.05000000 0.05000000
l2 = likelihoods3(dice, c(6, 4, 8, 7, 7, 2))
> l2
observation roll likelihood score
1 6 4 0.25000000 0.00000000
2 4 4 0.25000000 0.25000000
3 8 4 0.25000000 0.00000000
4 7 4 0.25000000 0.00000000
5 7 4 0.25000000 0.00000000
6 2 4 0.25000000 0.25000000
7 6 6 0.16666667 0.16666667
8 4 6 0.16666667 0.16666667
9 8 6 0.16666667 0.00000000
10 7 6 0.16666667 0.00000000
11 7 6 0.16666667 0.00000000
12 2 6 0.16666667 0.16666667
13 6 8 0.12500000 0.12500000
14 4 8 0.12500000 0.12500000
15 8 8 0.12500000 0.12500000
16 7 8 0.12500000 0.12500000
17 7 8 0.12500000 0.12500000
18 2 8 0.12500000 0.12500000
19 6 12 0.08333333 0.08333333
20 4 12 0.08333333 0.08333333
21 8 12 0.08333333 0.08333333
22 7 12 0.08333333 0.08333333
23 7 12 0.08333333 0.08333333
24 2 12 0.08333333 0.08333333
25 6 20 0.05000000 0.05000000
26 4 20 0.05000000 0.05000000
27 8 20 0.05000000 0.05000000
28 7 20 0.05000000 0.05000000
29 7 20 0.05000000 0.05000000
30 2 20 0.05000000 0.05000000
现在,我们需要遍历数据帧,按“滚动”分组,以便最后每行一行。
我们将添加一个新列,该列存储每个骰子的后验概率。 这将通过将先验概率乘以“得分”项的乘积来计算。
这就是我们新的似然函数的样子:
likelihoods3 = function(names, observations) {
l = list(observation = observations, roll = names)
obsDf = do.call(expand.grid,l) %>%
mutate(likelihood = 1.0 / roll,
score = ifelse(roll < observation, 0, likelihood))
return (obsDf %>%
group_by(roll) %>%
summarise(s = (1.0/length(names)) * prod(score) ) %>%
ungroup() %>%
mutate(weighted = s / sum(s)) %>%
select(roll, weighted))
}
l1 = likelihoods3(dice, c(6))
> l1
Source: local data frame [5 x 2]
roll weighted
1 4 0.0000000
2 6 0.3921569
3 8 0.2941176
4 12 0.1960784
5 20 0.1176471
l2 = likelihoods3(dice, c(6, 4, 8, 7, 7, 2))
> l2
Source: local data frame [5 x 2]
roll weighted
1 4 0.000000000
2 6 0.000000000
3 8 0.915845272
4 12 0.080403426
5 20 0.003751302
现在,我们得到的结果与嵌套for循环的结果相同,所以我认为重构已经成功。
直播视频帧替换