自然语言处理:盘点一下数据平滑算法

  在自然语言处理中,经常要计算单词序列(句子)出现的概率估计。我们知道,算法在训练时,语料库不可能包含所有可能出现的序列。因此,为了防止对训练样本中未出现的新序列概率估计值为零,人们发明了好多改善估计新序列出现概率的算法,即数据平滑算法。

Laplace 法则

  最简单的算法是Laplace法则,思路很简单,统计测试数据集中的元素在训练数据集中出现的次数时,计数器的初始值不要设成零,而是设成1。这样,即使该元素没有在训练集中出现,其出现次数统计值至少也是1。因此,其出现的概率估计值就不会是零了。

  假设测试集 V 中某个元素在训练集 T 中出现 r 次,经过Laplace法则调整后的统计次数为:

r=r+1

  当然这样做,纯粹是为了不出现零概率,并没有解决对未见过的实例进行有效预测的问题。因此,Laplace法则仅仅是一种非常初级的技术,有点太小儿科了。

Good-Turing 估计

  Laplace方法一个很明显的问题是 rr Good-Turning 方法认为这是一个重大缺陷,需要给予改进。其实我觉得这真不算重要,只要能合理估计未见过的新实例的概率,总的统计次数发生变化又怎样呢?
  
  Good-Turing 修正后的计算公式还真的很巧妙,它在Laplace法则后面乘了一个修正系数,就可以保证总次数不变。这个拿出来炫一炫还是没问题的:
  

r=(r+1)nr+1nr

其中, nr 表示测试集 V 中,一共有nr个元素在训练集 T 中出现过 nr 次。

  虽然我觉得这个方法没啥用,但是它的确保证了测试集中元素在训练集中出现的总次数不变。即:

N1=r=0rnr=0×n0+1×n1+2×n2+...N2=r=0rnr=1×n1n0×n0+2×n2n1×n1+...=1×n1+2×n2+...

  显然, N1=N2 。或许这个方法解决不了自然语言处理问题,而且 nr=0 时公式也会失效,但其思路应该还是很有价值的,或许解决其他问题能用得上。

绝对折扣和线性折扣

  估计发明的作者受到 Good-Turing 的刺激了,认为这个方法就是“劫富济贫”,把数量较大的统计次数拿出一部分均给了较小的统计次数,减少贫富差距。只不过这个方法用了一个很有技巧的公式掩盖的其本质。
  
  与其羞羞答答“劫富济贫”,不如来个赤裸裸的方法,于是乎就出现了绝对折扣和线性折扣方法。
  
  问题是,“劫富济贫”并不是我们的目的,我们需要的是能够对语料库中从未出现过的句子做出概率判断。要得到正确的判断,需要“劫”多少?“济”多少?这个问题绝对折扣和线性折扣都回答不了。所以,无论Good-Turing方法,还是这两种折扣方法,本质上都没跳出 Laplace 法则的思路。
  

Witten-Bell算法

  Witten-Bell算法终于从 Laplace 算法跳了出来,有了质的突破。这个方法的基本思想是:如果测试过程中一个实例在训练语料库中未出现过,那么他就是一个新事物,也就是说,他是第一次出现。那么可以用在语料库中看到新实例(即第一次出现的实例)的概率来代替未出现实例的概率。
  
  假设词汇在语料库出现的次数参见下表:

r 1 2 3 4 5
nr 5040302010


N=1×50+2×40+3×30+4×20+5×10=350T=50+40+30+20+10=150

  那么,我们可以用
  

TN+T=150350+150=0.3

近似表示在语料库看到新词汇的概率。

  我不能说这个方法有多少道理,但与那些“劫富济贫”的方法相比,它至少提供了一个说得过去的理由。
  

扣留估计和交叉检验

  
  扣留估计和交叉检验这两种方法估计是受到Witten-Bell算法启发了,但是思路没跳出该方法套路,而且手法比较卑劣。和Witten-Bell算法一样,对于所有遇到的新事物,都给出完全相同的概率预测。

插值算法

  
  前面的平滑算法对于从来没出现的n-gram都给与相同的概率估计,有些情况下这并不合适。事实上我们可以考虑根据n-gram中的(n-1)gram的频率产生一个更好的概率估计。如果 (n-1)gram很少出现,就给n-gram一个较小的估计,反之给出一个较大的估计。
  例如,假定要在一批语料库上构建二元语法模型,其中有两对词的同现次数为0:
  

  C(send the)=0  C(send thou)=0  

那么,按照前面提到的任何一种平滑方法都可以得到:
p(the|send)=p(thou|send)

  
但是,直觉上我们认为应该有
p(the|send)>p(thou|send)

因为冠词the要比单词thou出现的频率要高得多。因此,可以通过组合不同信息资源的方法来产生一个更好的模型。

基本思路

  一般来讲,使用低阶的n元模型向高阶n元模型插值是有效的,因为当没有足够的语料估计高阶模型时,低阶模型往往可以提供有用的信息。例如,bigram模型中的删除插值法,最基本的做法是:
  

Pinterp(wi|wi1)=λPML(wi|wi1)+(1λ)PML(wi),  0λ1

由于
PML(the|send)=PML(thou|send)=0

而且
PML(the)PML(thou)

所以
Pinterp(the|send)>Pinterp(thou|send)

定义

  在统计自然语言处理中,这种方法通常被称为线性插值法(Linear Interpolation),在其他的地方常常被称为混合模型(Mixture Model)。插值模型的递归定义如下:

Pinterp(wi|wi(n1)...wi1)=λPML(wi|wi(n1)...wi1)+(1λ)Pinterp(wi|wi(n2)...wi1)

例子

  对于三元模型,有

Pinterp(wi|wi(n1)...wi1)=λPML(wi|wi(n1)...wi1)+(1λ)Pinterp(wi|wi1)

  对于二元模型,有  
Pinterp(wi|wi1)=λPML(wi|wi1)+(1λ)PML(wi)
 
于是,
Pinterp=...=λ3PML(wi|wi2wi1)+λ2PML(wi|wi1)+λ1PML(wi),  λ1+λ2+λ3=1
 
  

Katz回退算法

  katz方法也是一种插值方法,不过它仅对语料库中未出现的数据进行预测。
  
  总起来说,这类插值方法与传统数学中用已知数据插值预测未知数据的方法思路相同,属于比较靠谱的方法。
  


参考文献

[1] 陈鄞,自然语言处理基本理论和方法,哈尔滨工业大学出版社, 第1版 (2013年8月1日)

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
贝塞尔数据平滑算法是一种常用于数据平滑处理算法,它可以通过通过一系列控制点来定义曲线,并且能够对给定的输入数据进行平滑处理。在Java中,我们可以编写一个贝塞尔数据平滑算法的工具类来实现这一功能。 首先,我们需要定义一个Point类,用于表示二维空间中的一个点。这个类可以包含两个属性x和y,分别表示点的横坐标和纵坐标。同时,我们还可以为这个类实现一些常用的方法,例如获取点的横坐标和纵坐标的方法。 接下来,我们可以在工具类中定义一个方法,用于根据给定的控制点列表和平滑度参数来计算出平滑后的曲线上的点。这个方法可以接受一个Point类型的列表作为输入,以及一个平滑度参数smoothness,表示控制点之间的平滑程度。 在这个方法中,我们可以首先计算出每个控制点之间的插值点,通过贝塞尔曲线的计算公式来确定。具体的计算过程可以在for循环中实现,每次计算出一个插值点,然后将其添加到结果列表中。在计算过程中,我们可以根据平滑度参数来调整曲线的平滑程度,例如可以通过调整控制点之间的距离来实现。 最后,我们可以在工具类中定义一个主方法,用于测试这个贝塞尔数据平滑算法。在这个方法中,我们可以创建一个测试用的控制点列表,调用平滑算法的方法来获取平滑后的曲线上的点,并输出结果。 总之,通过编写一个贝塞尔数据平滑算法的工具类,我们可以方便地在Java中进行数据平滑处理。这个工具类可以根据控制点列表和平滑度参数来计算出平滑后的曲线上的点,并可以方便地进行测试和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许野平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值