SRILM Ngram 折扣平滑算法

关于n-gram 语言模型,大部分在这篇博客里 记过了,    SRILM 语言模型格式解读 , 其实看完了,ngram的大概用法都比较清楚了,
可是关于平滑算法,一直很模糊,就晓得一个"劫富济贫" ,也不知 回退 ,插值,折扣,平滑,都说的什么东西,模模糊糊的,找了不少资料,仍是看官方文档吧,看具体公式,就明白了.
 
看所有翻译 参考 :    Ngram 折扣平滑算法 ,本文里夹带着本身的一些理解. 
本文档翻译自 srilm 手册  ngram-discount.7.html

NAME

ngram-discount – 这里主要说明 srilm 中实现的平滑算法

NOTATION

a_ z         表明以  a 为起始词,以  z 为结束词的 ngram,其中_表明 0 个或多个词
p( a_ z)     前 n-1 个词为  a_的状况下,第 n 个词为  z 的条件几率
a_           n 元  a_ z 的前 n-1 个词构成的前缀
_ z           n 元  a_ z 的后 n-1 个词构成的后缀
c( a_ z)     n 元  a_ z 在训练语料中出现的次数   ,表示次数
n(*_ z)     符合 *_z 这一模式的独立 n 元数目,“*_z” 中‘*’表明通配符  , 表示多少种类
n1, n[1]    出现次数为 1 的 ngram 数目 , 不论是几元的, 只要出现1次,就算在内 
举个例子:   语料为
ABC 2
DBC 3
则:
c(*_C)=5
n(*_C)=2
n2=1

DESCRIPTION

Ngram 语言模型主要用于估计前 n-1 词为  a_的状况下,第 n 个词为 z 的几率,即几率  Pr( z| a_),为简单起见,通常使用  P( a_ z) 表示。估算几率最直接的方式就是分别在训练集中统计 c( a_ z) 和  c( a_),而后求以下公式,即获得相关几率运算结果:
(1)                    p( a_ z) =  c( a_ z)/ c( a_)               
如上的几率估算方法又称为最大似然估计方法。该方法比较直观易懂,但存在一个不足点就是对于语料中不存在的 n 元,其几率估算结果将为 0。为了不该状况的发生,能够经过将观察到的 ngram 一部分几率分布出去,并将这部分几率值分配到未观察到的 ngram 上。这种几率从新分配方式即为一般所说的平滑 (smoothing) 或折扣 (discounting)。
 
大部分平滑算法均可以使用以下公式来表示
(2)                    p(a_z) = (c(a_z) > 0) ? f(a_z) : bow(a_) p(_z)
若 ngram  a_z 在训练集中发生了,则直接使用几率  f(a_z),该几率值通常都小于最大似然估计几率值结果,这样留下的一部分几率值可用于训练语料中未覆盖到的 n 元  a_*。不一样的平滑算法区别主要在于采用何种折扣方法对最大似然估计结果进行折扣。
 
应用公式(2)计算几率  p(a_z) 时,若 ngram  a_ z 在训练语料中没有出现,则直接使用低阶几率分布  p(_z) 若历史  a_在训练语料中没有出现,即  c( a_) = 0,这时能够直接使用  p(_z) 做为当前 ngram 的几率值,即 bow( a_) = 1;不然须要将 bow( a_) 乘到  p(_z) 上,以保证几率分布的归一性,即:
Sum_ z  p( a_ z) = 1
 
假设 Z 为词典中全部词构成的集合,Z0 为词典中全部知足条件  c( a_ z) = 0 的词构成的集合,Z1 为词典中全部知足条件  c( a_ z) > 0 的词构成的集合。在  f(a_z) 计算好的状况下,bow( a_)能够经过以下方式估算获得:
(3)    Sum_Z  p(a_z) = 1
       Sum_Z1 f(a_z) + Sum_Z0 bow(a_) p(_z) = 1
       bow(a_) = (1 - Sum_Z1 f(a_z)) / Sum_Z0 p(_z)
                       = (1 - Sum_Z1 f(a_z)) / (1 - Sum_Z1 p(_z))
                       = (1 - Sum_Z1 f(a_z)) / (1 - Sum_Z1 f(_z))
上式中分母  Sum_Z0 p(_z) 表明在历史 “_” 条件下,全部知足条件  c( a_ z) = 0 的词几率之和,而 Z1 为词典中全部知足条件  c( a_ z) > 0 的词构成的集合,所以存在以下的关系
Sum_Z0 p(_z) Sum_Z1 p(_z) = 1
由于  Z0 和  Z1 构成了 ngram “ _z” 全部可能的状况。所以有:
        Sum_Z0 p(_z) = 1 - Sum_Z1 p(_z)
 
平滑通常采用如下两种策略中的一种
  •   回退平滑
      当 ngrma 统计结果  c( a_ z) > 0,回退平滑算法以  c( a_ z) 为基础计算  p( a_ z) ,不然在  c( a_ z) = 0 的状况,回退平滑算计算  p( a_ z) 时只考虑  c(_ z);
  • 插值平滑
   插值平滑算法在  c( a_ z) > 0 的状况下,计算  p( a_ z) 时,除了考虑  c( a_ z) 以外,还须要考虑低阶的 ngram,如  c(_ z) 等。
 
插值平滑算法可用以下公式来表示
(4)   p(a_z) = g(a_z) + bow(a_) p(_z)
其中  g(a_z) 在  c( a_ z) = 0 的状况下,为 0。和回退平滑算法同样,在  c( a_ z)>0 的状况下,插值平滑算法也须要从  g(a_z) 中折扣掉一部分几率,用于  c( a_ z) = 0 的全部 z 构成的 ngram。
折扣平滑算法的  bow(a_) 计算公式:
(5)   Sum_Z p(a_z) = 1
       Sum_Z1 g(a_z) + Sum_Z bow(a_) p(_z) = 1
       bow(a_) = 1 - Sum_Z1 g(a_z)
插值平滑算法,一样能够用公式 (2) 的表示方式表示,以下所示:
(6)   f(a_z) = g(a_z) + bow(a_) p(_z)
       p(a_z) = (c(a_z) > 0) ? f(a_z) : bow(a_) p(_z)
 
SRILM 中的大部分平滑算法同时拥有回退和插值两种方式。根据以往的经验,通常插值方式的效果要优于回退方式。平滑算法方面,kneser-ney 平滑要优于其余的平滑算法。 
ps:公式2,3  是回退平滑的计算方式  , 公式4,5 是插值平滑的计算方式. 通常状况下 任何一个平滑算法均可以分为回退 和 插值  ,即 backoff  和 interpolate
 

OPTIONS

本部分主要介绍 ngram-count 中各个折扣算法的公式。介绍各折扣算法时,首先介绍各折扣算法的动机,而后介绍如何根据 counts 值计算公式(2)中  f(a_z) 和  bow(a_)
须要注意的是一些 counts 因为 -gtmin 参数的缘由,可能在统计模型不存在;参考下一部份 Warning 4
       大部分模型中, 回退版本是默认的平滑方式,而插值版本能够经过 -interpolate 获取。在插值平滑方式中,公式(4)中  g(a_z) 和  bow(a_) 一样根据 counts 值计算获得。
       每个折扣参数选项后面均可以跟一个(1-9)的数字,用来表示只对某一个特定元数的 ngram 作折扣计算,具体能够参看 ngram-count 用户手册。
 
-cdiscount D
Ney 的绝对折扣(absolute discounting)使用参数 D 做为折扣常数。D 必需要介于 0 和 1 之间。若是  z  1 表明全部知足  c( a_ z) > 0 的单词  z 的集合,则有以下等式存在:
f(a_z)  = (c(a_z) - D) / c(a_)
       p(a_z)  = (c(a_z) > 0) ? f(a_z) : bow(a_) p(_z)   ; Eqn.2
       bow(a_) = (1 - Sum_Z1 f(a_z)) / (1 - Sum_Z1 f(_z)) ; Eqn.3
上面为回退平滑的计算公式,对于插值平滑,有以下计算公式:
        g(a_z)  = max(0, c(a_z) - D) / c(a_)
       p(a_z)  = g(a_z) + bow(a_) p(_z)       ; Eqn.4
       bow(a_) = 1 - Sum_Z1 g(a_z)              ; Eqn.5
                       = D n(a_*) / c(a_)
折扣系数 D 建议能够经过以下公式计算获取
D = n1 / (n1 + 2*n2)
上式中
n1 表明出现次数为 1 次的 ngram 数目
n2 表明出现次数为 2 次的 ngram 数目

 

 
-kndiscount 和  –ukndiscount
    Kneser-Ney 折扣。前一个参数对应于 modified Kneser-Ney 折扣,然后一个参数对应于最初的 Kneser-Ney 折扣。Kneser-Ney 折扣算法和绝对折扣算法比较类似,该算法一样是在ngram 统计量 count 上减去一个常数 D 计算折扣几率。modified Kneser-Ney 和 Kneser-Ney 的不一样点就在于如何计算该常数 D。
    Kneser-Ney 折扣的主要思想是为低阶的 ngram 使用一个修改后的几率估计(modified
probability estimation)方法。具体来讲,n 元低阶的修正几率(modified probability)和训练
语料中该低阶的不一样前驱词数量成比例。经过折扣和归一化运算,有以下公式:
f(a_z) = (c(a_z) - D0) / c(a_)      ;; for highest order N-grams
        f(_z)  = (n(*_z) - D1) / n(*_*)    ;; for lower order N-grams
其中  n(*_z) 表明不一样的  *_z 数量,这里 * 表明独立词通配符。 D0 和  D1 表明两个不一样的折扣
常数,这是由于不一样元数的 ngram 使用不一样的常数。最终的条件几率和回退权重能够经过
以下公式(2)和(3)计算:
p(a_z)  = (c(a_z) > 0) ? f(a_z) : bow(a_) p(_z)     ; Eqn.2
       bow(a_) = (1 - Sum_Z1 f(a_z)) / (1 - Sum_Z1 f(_z))  ; Eqn.3
   
对于插值平滑有以下计算公式
p(a_z) = g(a_z) + bow(a_) p(_z)  ; Eqn.4
假设  z1 为集合 { zc( a_ z) > 0},对于高阶 ngram 有:
g(a_z)  = max(0, c(a_z) - D) / c(a_)
       bow(a_) = 1 - Sum_Z1 g(a_z)
                       = 1 - Sum_Z1 c(a_z) / c(a_) + Sum_Z1 D / c(a_)
                       = D n(a_*) / c(a_)
   假设 z2 为集合 { zn(*_ z) > 0},对于低阶 ngram 有:
        g(_z)  = max(0, n(*_z) - D) / n(*_*)
       bow(_) = 1 - Sum_Z2 g(_z)
                     = 1 - Sum_Z2 n(*_z) / n(*_*) + Sum_Z2 D / n(*_*)
                     = D n(_*) / n(*_*)
最初的 Knser-Ney 折扣算法( -ukndiscount)对于任何 ngram 使用同一常数 D 进行折扣计算,该折扣常数根据以下公式计算获取:
D = n1 / (n1 + 2*n2)
上式中
n1 表明出现次数为 1 次的 ngram 数目
n2 表明出现次数为 2 次的 ngram 数目
Chen 和 Goodman 的 Modified Kneser-Ney 折扣( -kndiscount)算法对于每个 ngram 均使用三个折扣常数,一个用于出现次数为 1 次的 ngram,一个用于出现次数为 2 次的 ngram,一个用于出现次数为 3 次和 3 次以上的 ngram,公式以下所示:
        Y   = n1/(n1+2*n2)
       D1  = 1 - 2Y(n2/n1)
       D2  = 2 - 3Y(n3/n2)
       D3+ = 3 - 4Y(n4/n3)
Warning
SRILM 中 Kneser-Ney 折扣算法实际修改了低阶 ngram 的出现次数(counts)。所以当使用  -write 参数输出  -kndiscount 和  -ukndiscount 折扣算法下全部 ngram 的出现次数(counts)时,只有最高阶的 ngram 和以 开始的 ngram 的出现次数(counts)为 c(a_z),其余的 ngram 的出现次数为修改后的值 n(*_z),参考 Warning2

 

-wbdiscount
Witten-Bell 折扣算法。直观理解该算法就是分配给低阶的权重应该和在当前历史( a_)后接的不一样词的统计量成比例,用公式能够表示以下:
bow(a_) = n(a_*) / (n(a_*) + c(a_))
上式中  n(a_*) 表明训练语料中历史  a_后接的不一样种类的词条数。Witten-Bell 开始只是一个插值折扣平滑算法,所以在参数  -interpolate 下,有:
g(a_z) = c(a_z) / (n(a_*) + c(a_))
       p(a_z) = g(a_z) + bow(a_) p(_z)    ; Eqn.4
不加  -interpolate 参数,即获得了一个回退平滑版本的 Witter-Bell 折扣平滑算法,该算法中  f( a_ z) 和插值算法中的  g( a_ z) 计算方法同样。
f(a_z)  = c(a_z) / (n(a_*) + c(a_))
       p(a_z)  = (c(a_z) > 0) ? f(a_z) : bow(a_) p(_z)    ; Eqn.2
       bow(a_) = (1 - Sum_Z1 f(a_z)) / (1 - Sum_Z1 f(_z)) ; Eqn.3
 
-ndiscount
Ristad 天然折扣算法,该算法目前在 SRILM 中只存在回退平滑版本,不存在插值平滑版本,所以  -interpolate 对该算法无任何影响。该算法具体可参考 “A natural law of succession”。
 
                         c(a_z)    c(a_) (c(a_) + 1) + n(a_*) (1 - n(a_*))
       f(a_z)  =  --------  -------------------------------------------------
                         c(a_)      c(a_)^2 + c(a_) + 2 n(a_*)
 
       p(a_z)  = (c(a_z) > 0) ? f(a_z) : bow(a_) p(_z)    ; Eqn.2
       bow(a_) = (1 - Sum_Z1 f(a_z)) / (1 - Sum_Z1 f(_z)) ; Eqn.3
 
-count-lm
   暂不介绍
 
-addsmooth  D
经过对每一个 ngram 出现次数加上一个常量 D 来达到平滑效果。
p(a_z) = (c(a_z) + D) / (c(a_) + D n(*))
 
default
若用户未指定任何折扣算法,则 ngram-count 默认采用 Good-Turing 折扣算法(Katz 平滑算法)。Good-Turing 折扣算法认为,对于发生次数为 r 的 ngram,应该认为其发生次数为 r'次,其中:
r' = (r+1) n[r+1]/n[r]
上式中  n[r] 表明全部发生次数为  r 次的 ngram 数目。
对于较大的 r,能够认为 r 是一个可信的统计结果,所以不作上面的折扣计算,默认状况下 unigram 中的 r 只要大于 1,其余 ngram 中的 r 只要大于 7 就认为可信,这时采用最大似然估计几率值。这些限制能够经过使用  -gt n max 参数来控制。
f(a_z) = (c(a_z) / c(a_))  if c(a_z) > gtmax
对于出现次数知足 1 <=  c( a_ z) <=  gtmax: 的 ngram 有以下折扣公式:
                                  n[gtmax + 1]
  A = (gtmax + 1)  ----------------
                                     n[1]
 
                                         n[c(a_z) + 1]
  c'(a_z) = (c(a_z) + 1)  -----------------
                                         n[c(a_z)]
 
                    c(a_z)   (c'(a_z) / c(a_z) - A)
  f(a_z) =   --------  ----------------------
                    c(a_)         (1 - A)
-interpolate 参数对上述公式没有任何影响,所以只有回退平滑版本:
p(a_z)  = (c(a_z) > 0) ? f(a_z) : bow(a_) p(_z)    ; Eqn.2
       bow(a_) = (1 - Sum_Z1 f(a_z)) / (1 - Sum_Z1 f(_z)) ; Eqn.3 

 

FILE FORMATS
   经过使用以下的命令,SRILM 能够根据一个文本文件统计生成 ngram Count 文件
ngram-count -order  N -text  file.txt -write  file.cnt
-order 参数指定要统计的 ngram 的最大长度。file.txt 文件必定要一句话一行,且其中词与词之间经过空格隔开。输出文件 file.cnt 中一行包含一个 ngram 后接一个 table 键,后接统计到的出现次数:
a_z c(a_z)
Warning 1
SRILM 默认会在 file.txt 文件中每一个句子首尾分别加上句子开始标记 和句子结束标记,所以不须要再 file.txt 文件中每一个句子加上这两个标记。
 
笔者注:新版本的 SRILM 系统中,能够经过  -no-sos 和  -no-eos 控制不加这两个符号。
 
Warning 2
SRILM 中 Kneser-Ney 折扣算法实际修改了低阶 ngram 的出现次数(counts)。所以当使用  -write 参数输出  -kndiscount 和  -ukndiscount 折扣算法下全部 ngram 的出现次数(counts)时,只有最高阶的 ngram 和以 开始的 ngram 的出现次数(counts)为 c(a_z),其余的 ngram 的出现次数为修改后的值 n(*_z)。
 
对于大多平滑算法而言(除  -count-lm),SRILM 都使用 ARPA 格式生成和使用 N-gram 模型。生成一个模型文件的最简单的方法以下所示:
ngram-count -order  N -text  file.txt -lm  file.lm
ARPA 格式的模型文件  file.lm 每一行为一个 ngram 及其相关信息,具体格式以下:
log10(f(a_z)) a_z log10(bow(a_z))
根据公式(2),第一项  log10(f(a_z)) 表明 ngram   a_z 的几率值以 10 为底的对数结果,后面更一个 ngram,ngram 中每个单词经过空格隔开,最后一项为以  a_z 开始的 (n+1)grams 的回退系数求以 10 为底的对数结果。
 
Warning 3
   不论是回退仍是插值平滑,统一使用 ARPA 格式来表示,即插值平滑的相关系数根据公式(6)转换为回退表示。
 
Warning 4
并非全部的 ngram 都有参数指定的最高元。参数  -gtmin-gt1min, ...,  -gt9min 用于指定最小出现多少次的 n 元才会被包含在语言模型中。默认状况下,全部的一元和二元都会被包含进语言模型,高阶的 ngram 只会包含出现次数大于等于 2 的 ngram。(Some exceptions arise, because if one N-gram is included in the model file, all its prefix N-grams have to be included as well. This causes some higher order 1-count N-grams to be included when using KN discounting, which uses modified counts as described in  Warning 2.)(这句话未翻译)
 
Warning 5
并非模型中的全部 ngram 都有回退值,最高阶的 ngram 并不须要回退值。对于其余的低阶 ngram 来讲,其存在回退值是由于其构成了某个更高阶 ngram 的前缀。对于其余的低阶ngram 来讲回退值默认为 1,取以 10 为底的对数后即为 0。
相关文章
相关标签/搜索