一、前言
在《机器翻译专用词开发实践》一文中,我们提出了一种基于泊松分布的目标片段抽取方法,并利用该方法批量加工词约束的专用词模型训练语料。还记得当时文中提出了一个问题,就是如何求序列中任意 s i s_i si的选取率问题。当时介绍说这个概率的计算公式是一种递推形式,本文我们来探讨下这个递推公式及其背后的常用思想----动态规划。
二、理论部分
假设给定一输入序列 S S S,其长度为 n n n,执行一次泊松抽取后的结果只能有两种情况:
- 执行后到达末尾;
- 执行后未到达末尾。
其中1又分为两种子情况:①跨越时就到达末尾;②片段选取时到达末尾。
这里要注意的是,如果跨越时就到达末尾,说明序列长度 n n n小于或等于 s s s,否则一次跨越无论如何也不能结束;对于1执行后到达末尾的情况,则是在任何情况下都有可能发生的,很大程度取决于泊松分布观察值的大小,当然在序列较长时一般不会发生。
对于情况2,即执行后未到达末尾时,则需要针对剩余部分递归调用抽取算法,并返回子问题的结果。
因此若要保证
s
n
s_n
sn有效命中,至少需要确保上述的①跨越时就到达末尾不能发生。我们来分别探讨不同情况,为保持一个清晰的思路,在分析
s
i
s_i
si的命中率时,假定
s
i
s_i
si是序列
S
S
S的最后一个token,即
s
n
s_n
sn, 并分别讨论以下情况:
1.如果执行一次泊松抽取时到达了末尾,则
s
n
s_n
sn的命中率计算如下:
E
e
n
d
e
d
(
s
n
)
=
{
0
n
<
=
1
,
1
s
∑
i
=
1
M
i
n
(
n
−
1
,
s
−
1
)
(
1
−
∑
j
=
0
n
−
i
−
1
λ
j
j
!
e
−
λ
)
,
e
l
s
e
E_{ended}(s_n)=\begin{cases} 0 & n<=1,\\\\ \frac{1}{s}\sum_{i=1}^{Min(n-1,s-1)}(1-\sum_{j=0}^{n-i-1} \frac{λ^{j}}{j!}e^{-λ}), & else\\ \end{cases}
Eended(sn)=⎩
⎨
⎧0s1∑i=1Min(n−1,s−1)(1−∑j=0n−i−1j!λje−λ),n<=1,else
其中
λ
j
j
!
e
−
λ
\frac{λ^{j}}{j!}e^{-λ}
j!λje−λ是泊松分布在
j
j
j的概率函数,相信有些读者看出来了。其他说明如下:
① 第一个条件即
n
<
=
1
n<=1
n<=1是一定不会命中
s
n
s_n
sn的,因为跨越量服从
U
(
1
,
s
)
U(1,s)
U(1,s)均匀分布,长度等于1时
s
n
s_n
sn一定会被跳过;
② 第二个条件为从起始位置到
(
n
−
1
)
(n-1)
(n−1)跨度情况的累加,为什么将累加计算的上界限定到了
(
n
−
1
)
(n-1)
(n−1)?因为跨越量不能涉及到
s
n
s_n
sn. 内层的累加代表排除的非法泊松抽取长度,例如
s
=
8
s=8
s=8,
n
=
6
n=6
n=6时,当
i
=
1
i=1
i=1情况下,跨越量为1,则剩下的5个词需全部被泊松抽取才能使
s
n
s_n
sn命中,因此需要扣除不合法的泊松观察值(即0-4),即内层累加的
(
n
−
i
−
1
)
(n-i-1)
(n−i−1)上限设置。此外由于跨越量只能限制在
(
1
,
s
)
(1, s)
(1,s)之间,因此如果
n
>
s
n>s
n>s,需要限制累加上界到
(
s
−
1
)
(s-1)
(s−1)以内,因此最终上界形式为
M
i
n
(
n
−
1
,
s
−
1
)
Min(n-1,s-1)
Min(n−1,s−1).
2.如果执行后未到达末尾,即上述说明②中排除的情况时,则需要递归调用方法了。但又由于执行操作也伴随着多样变化(跨越量和抽取长度的不确定性),因此
s
n
s_n
sn命中率的计算包含不同变化的累加形式,公式如下:
E
r
e
c
u
r
s
i
o
n
(
s
n
)
=
∑
i
=
1
n
−
1
C
o
m
b
(
i
,
s
,
λ
)
∗
E
r
e
c
u
r
s
i
o
n
(
s
n
−
i
)
E_{recursion}(s_n)=\sum_{i=1}^{n-1}Comb(i, s, λ)*E_{recursion}(s_{n-i})
Erecursion(sn)=i=1∑n−1Comb(i,s,λ)∗Erecursion(sn−i)
其中
C
o
m
b
(
i
,
s
,
λ
)
Comb(i, s, λ)
Comb(i,s,λ)代表在参数
s
s
s、均值
λ
λ
λ的条件下,对执行一次抽取步骤的遍历长度为
i
i
i时的概率,计算如下:
C
o
m
b
(
i
,
s
,
λ
)
=
1
s
∑
n
=
1
M
i
n
(
i
,
s
)
λ
(
i
−
n
)
(
i
−
n
)
!
e
−
λ
Comb(i, s, λ)=\frac{1}{s}\sum_{n=1}^{Min(i,s)}\frac{λ^{(i-n)}}{(i-n)!}e^{-λ}
Comb(i,s,λ)=s1n=1∑Min(i,s)(i−n)!λ(i−n)e−λ
说明:如果限定了遍历长度为
i
i
i,则需要考虑所有和为
i
i
i的不同
m
,
p
m, p
m,p的组合,因此最终计算是一个累加形态;同时还要考虑
i
i
i与
s
s
s之间的大小关系,如果
i
i
i大于
s
s
s,则累加计算只能到
s
s
s为止,因此累加上界为
M
i
n
(
i
,
s
)
{Min(i,s)}
Min(i,s),最终构成上述这种加了
M
i
n
Min
Min操作的累加形式。
应用条件
s i s_i si的命中率可以采用上述计算方式,当且仅当起始位置位于跨越操作前的位置,即起始位置是执行算法第1步(《机器翻译专用词开发实践》第3.3节)的位置。
三、算法描述
本章我们详细介绍泊松抽取算法命中率求解及Comb子算法的实现。
3.1 Combination算法
第二章理论介绍时涉及到一个叫 C o m b Comb Comb的计算方法,用于计算给定 s , λ s, λ s,λ参数下求解长度遍历长度 i i i的概率表示,同时也给出了其形式。本节使用伪代码方式实现计算,给出伪代码描述如下:
输入:跨度参数s,均值λ,长度i
输出:概率p_i
p_i ← 0.0
for each(n) in [1,2,..., i] do
if n <= s then
total ← total + (1/s * Poisson(i-n, λ)) # Poisson(i-n, λ)获得均值λ的泊松分布在(i-n)的概率
end if
end for
return p_i
3.2 命中率算法实现
接下来就是命中率期望的算法描述,二中给出“终止”和“递归”两种形态的算法表述,使用伪代码实现如下:
输入:长度n, 跨度参数s,均值λ
输出:命中率E_n
E_n ← 0.0
if n == 1 then
return 0
for each(i) in [1,2,...,n-1] do
E_n ← E_n + Comb(i, s, λ) * Call(n-i, s, λ) # Call代表递归调用当前算法
end for
if n <= s then # 如果长度n小于s,则需要考虑一次达到末尾的情况
for each(i) in [1,2,...,n-1] do
E_n ← E_n + 1/s * Sigma(Poisson(x, s, λ), 0, n-i-1) # 这里我定义了个Sigma代表使用Poisson累加,起止为[0, n-i-1]
end for
end if
return E_n
3.3 动态规划
伪代码读到这里,也相信很多读者看出来这个算法执行时多次以“较小的 n n n”为参数调用本身,这意味着算法可以拆分出“子问题”。前文的理论部分介绍到,泊松抽取的命中率计算在“未到达末尾”的情况下存在递归调用关系,同时也伴随多个跨越量 m m m采样情况下的累加,因而这个递归调用很可能成为多次的重复操作,因此多次调用+子问题便构成了动态规划思路。因此3.2的命中率算法加入备忘录机制,构造成执行效率更高的方案:
输入:长度n, 跨度参数s,均值λ
输出:命中率E_n
E_n ← 0.0
combs ← [-1] * (n-1)
probs ← [-1] * (n-1)
if n == 1 then
return 0
for each(i) in [1,2,...,n-1] do
cm = 0
pb = 0
if combs[i] != -1 then #判断备忘录中有无目标值,如果有则直接获取,没有再执行计算
cm = combs[i]
else
cm = Comb(i, s, λ)
combs[i] = cm
if probs[n-i] != -1 then
cm = probs[n-i]
else
cm = Call(n-i, s, λ)
probs[n-i] = cm
E_n ← E_n + cm * pb
end for
if n <= s then # 如果长度n小于s,则需要考虑一次达到末尾的情况
for each(i) in [1,2,...,n-1] do
E_n ← E_n + 1/s * Sigma(Poisson(x, s, λ), 0, n-i-1) # 这里我定义了个Sigma代表使用Poisson累加,起止为[0, n-i-1]
end for
end if
return E_n
四、最终形式
4.1 命中率计算
我们将第二章的公式描述整合为一个统一的形式,表述如下:在跨度参数为
s
s
s,泊松均值为
λ
λ
λ的泊松片段抽取算法中,对于序列中任意位置的词
s
i
s_i
si,假设算法在
s
i
s_i
si的位置上可以从第1步开始执行,则从
s
i
s_i
si起向后第
n
n
n个词的命中率期望值
E
(
s
i
+
n
)
E(s_{i+n})
E(si+n)可以简化表示为
E
(
n
)
E(n)
E(n),其计算公式如下:
E
(
n
)
=
{
0
,
n <= 1,
E
e
n
d
e
d
(
s
n
)
+
∑
i
=
1
n
−
1
C
o
m
b
(
i
,
s
,
λ
)
∗
E
(
n
−
i
)
,
else
=
{
0
,
n <= 1,
1
s
∑
i
=
1
M
i
n
(
n
−
1
,
s
−
1
)
(
1
−
∑
j
=
0
n
−
i
−
1
λ
j
j
!
e
−
λ
)
+
∑
i
=
1
n
−
1
C
o
m
b
(
i
,
s
,
λ
)
∗
E
(
n
−
i
)
,
else
E(n)= \begin{cases} 0, & \text {n <= 1,}\\\\ E_{ended}(s_n)+\sum_{i=1}^{n-1} Comb(i, s, λ)*E(n-i), & \text {else}\\ \end{cases}\\ =\begin{cases} 0, & \text {n <= 1,}\\\\ \frac{1}{s}\sum_{i=1}^{Min(n-1,s-1)}(1-\sum_{j=0}^{n-i-1} \frac{λ^{j}}{j!}e^{-λ})+\sum_{i=1}^{n-1} Comb(i, s, λ)*E(n-i), & \text {else}\\ \end{cases}\\\\
E(n)=⎩
⎨
⎧0,Eended(sn)+∑i=1n−1Comb(i,s,λ)∗E(n−i),n <= 1,else=⎩
⎨
⎧0,s1∑i=1Min(n−1,s−1)(1−∑j=0n−i−1j!λje−λ)+∑i=1n−1Comb(i,s,λ)∗E(n−i),n <= 1,else
4.2 不命中率计算
与命中率类似,不命中率是指泊松抽取时 s n s_n sn未被选中的概率,我们在此也给出相应的表达形式。首先分析不命中的情况,分析如下:
- 执行后到达末尾时, s n s_n sn不命中当且仅当抽取时就到达末尾,否则一定命中;
- 执行后未到达末尾时,同样需要递归调用来计算。
给出条件1中
s
n
s_n
sn的不命中率
E
e
n
d
e
d
u
n
t
(
s
n
)
E_{ended}^{unt}(s_n)
Eendedunt(sn)(unt即untargeted,未命中)的计算公式如下:
E
e
n
d
e
d
u
n
t
(
s
n
)
=
{
0
n
=
0
,
M
a
x
(
0
,
s
−
n
+
1
s
)
else
E_{ended}^{unt}(s_n)=\begin{cases} 0 & n=0,\\\\ Max(0, \frac{s-n+1}{s}) & \text {else}\\\\ \end{cases}
Eendedunt(sn)=⎩
⎨
⎧0Max(0,ss−n+1)n=0,else
说明如下:
①条件二下,
s
n
s_n
sn不被命中当且仅当跨越量
m
>
=
n
m>=n
m>=n时,例如
s
=
8
s=8
s=8、
n
=
6
n=6
n=6条件下,使
s
n
s_n
sn不被命中的跨越量为6、7或8,因此不命中率为
3
/
8
3/8
3/8;当
n
=
1
n=1
n=1时,
s
n
s_n
sn一定会被跳过,因此不命中率为1;
②当长度
n
n
n大于均匀分布的最大观测值时,
s
n
s_n
sn会超出最大跨越范围,不命中率变成0,因此使用Max函数囊括该情况和①.
最终在跨度参数为
s
s
s,泊松均值为
λ
λ
λ的泊松片段抽取算法中,对于序列中任意位置的词
s
i
s_i
si,假设算法在
s
i
s_i
si的位置上可以从第1步开始执行,则从
s
i
s_i
si起向后第
n
n
n个词的不命中率期望值
E
u
n
t
(
s
i
+
n
)
E^{unt}(s_{i+n})
Eunt(si+n)可以简化表示为
E
u
n
t
(
n
)
E^{unt}(n)
Eunt(n),其计算公式如下:
E
u
n
t
(
n
)
=
{
0
,
n = 0,
E
e
n
d
e
d
u
n
t
(
s
n
)
+
∑
i
=
1
n
−
1
C
o
m
b
(
i
,
s
,
λ
)
∗
E
(
n
−
i
)
,
else
=
{
0
,
n = 0,
1
,
n = 1,
M
a
x
(
0
,
s
−
n
+
1
s
)
+
∑
i
=
1
n
−
1
C
o
m
b
(
i
,
s
,
λ
)
∗
E
u
n
t
(
n
−
i
)
,
else
E^{unt}(n)= \begin{cases} 0, & \text {n = 0,}\\\\ E_{ended}^{unt}(s_n)+\sum_{i=1}^{n-1} Comb(i, s, λ)*E(n-i), & \text {else}\\ \end{cases}\\ =\begin{cases} 0, & \text {n = 0,}\\\\ 1, & \text {n = 1,}\\\\ Max(0, \frac{s-n+1}{s})+\sum_{i=1}^{n-1} Comb(i, s, λ)*E^{unt}(n-i), & \text {else}\\ \end{cases}\\\\
Eunt(n)=⎩
⎨
⎧0,Eendedunt(sn)+∑i=1n−1Comb(i,s,λ)∗E(n−i),n = 0,else=⎩
⎨
⎧0,1,Max(0,ss−n+1)+∑i=1n−1Comb(i,s,λ)∗Eunt(n−i),n = 0,n = 1,else
由公式可以看出,其实命中率和不命中率的整体公式差别在于
E
e
n
d
e
d
E_{ended}
Eended形式不同,其次是对于
n
=
1
n=1
n=1时的取值也不同。除此之外整体基本保持一致,都是递推形式。