【算法记事本#NLP-1】最大匹配算法分词

本文地址http://www.javashuo.com/article/p-cokwjmir-mm.htmlhtml

#NLP-1 最大匹配算法(MM)

最大匹配算法(Maximum Matching)被用于对一个文段进行词语划分(Word Segmentation)。算法

注意

这是词元化(Tokenization)算法
此方法不适用于无分隔符的字母语言(e.g.:德语、使用假名替代汉字的日语、被取消分词符的英文等)
可是对汉语这类无词间分隔符但不依赖字母的语言效果拔群ui

输入输出

graph LR input1(文段P) input2(单词表W) processor(MM) output(词元表T) input1--输入-->processor input2--输入-->processor processor--输出-->output

算法内容

人话版本(天然描述)

输入:文段$\small P$,单词表$\small W$
过程:对于给定的$\small P$和$\small W$:指针

  1. 令指针$\small i$从$\small P$的起点开始
  2. 每当找到最长匹配于$\small i$引领文段的单词$\small w$,则将$\small w$加入词元分析表$\small T$(一个顺序表结构)中
  3. $\small i$向后移动$\small w$长度个位置
  4. 回到2,直至$\small i$没法向后移动为止

输出:词元分析表$\small T$code

说明

最长匹配??

这个概念用定义去描述其实很不容易理解,这里直接上例子,好比,有一个字符串htm

The quick brown fox jumps over a lazy dog

如今给出这么几个字符串:ThTheThe slowThe quick brown fox jumps over a lazy dog and a little duckquick brownblog

注意,最长匹配的前提是能匹配得上,此外还要求是端点匹配字符串

先看Th,很明显,尽管Th不能完美的匹配上原有字符串,但倒是原字符串的子串(Substring),也就是说它可以完美的和原字符串的局部相匹配,并且是从起始位置相匹配,能够暂时认为是原字符串的最长匹配get

再看The,和Th同样,其总体可以匹配上原字符串的部分,并且也是从起始位置匹配,所以也多是最长匹配,这样一来ThThe都能匹配上原字符串,可是input

一个字符串在一个给定的字符串集合中只能找到一个最长匹配,并且是尽量长的那个

考虑到TheTh长,所以The替掉了Th成为了目前的最长匹配

接下来看看The slow,截止到The都能匹配到原字符串上,但接下来的s没法匹配原字符串,尽管匹配部分的长度比The还长,但很遗憾,The slow只能认为是不匹配

The quick brown fox jumps over a lazy dog and a little duck也是同理,别看它甚至是原字符串的延长串(也就是原字符串是它的子串),但后面多出来的部分匹配不回去,因此也只能认为是不匹配

原字符串是大爷!!

最后再看看quick brown,固然这也是原字符串的子串,并且匹配长度为11,甚至比The的匹配性还强,可是也很遗憾,这并不是从起点匹配的,因此这个没法认为匹配

因而咱们获得告终论:

在上述给出的5个字符串中,最长匹配为The

固然,这都是目前的最长匹配,若是咱们继续给出The quickThe quick brown、……这个结果仍是会跟着变化的,由于:

理论上,从全部字符串构成的全集寻找某一字符串的最长匹配,其结果只能是该字符串自己

为何对汉语效果拔群??

这里先说对英语吧…… 由于是作词元化工做,因此这里暂时无视英语中的空格分隔符

We are talking about weather.
    ↓  移除全部分词符
Wearetalkingaboutweather.

固然,咱们要对下面的内容作分词,按说分词工做作完后其分割结果应该和移除以前是同样的:We|are|talking|about|weather|. 但若是采用MM算法使用一个标准词库进行匹配,就会是下面这样:

首先从W开始,从词库中寻找从W开始可以最长匹配的字符串,而后很是巧,咱们在词典中找到了……Wear!! ……

因而,咱们先无论后面能不能分出来,反正分完确定是这样子:Wear|...|...

很明显这种分法是不行的。

这里面的缘由就在于:英语一共就26个字母,随便找若干个字母凑成一个单词的几率仍是很大的,特别是移除分隔符后出现大量辅音字母+若干元音字母的状况。 并且,英语中词汇的长度方差很大,短的只有一个字母,长的能够10多个,极端状况下也有40多个的甚至更多,不少短单词会成为一些长单词的子串(we之于wear等),而移除分隔符后两个本来独立的子串被拼合成一个更长的单词也不是什么新鲜事。 一种极端状况:

graph LR origin("Hear the voice") obfuscated("Hearthevoice") mm("Heart|he|voice") origin--移除分隔符-->obfuscated obfuscated--MM算法分割-->mm

可是汉语就不同了,就以GB2312里面的6700多个汉字想随便挑出来几个字就凑巧拼出一个词语仍是很困难的,并且词语长度的方差很低,不考虑诗句和歇后语的话,经常使用的词语和成语绝大多数为2~4个字,较长一些的8个字(比较少),这种状况下即便没有分隔符,两个独立的词语可以被混淆成一个的概率仍是比较小的,好比:

一只穿云箭,千军万马来相见
一只|穿云|箭|,|千军万马|来|相见

基本上分割的彻底正确,并且即便把标点符号都去掉,也不太影响其分割的结果,斯坦福大学也给出了这样的评价:

Doesn’t generally work in English! But works astonishingly well in Chinese!

不过其实说到底,这种算法比较依赖于词典(事实上不少词元化算法都挺依赖词典),若是词典编写的不够好,那么即便是汉语其词元化的质量也不尽如人意(特别是汉语须要足够完善的词汇库,其工做量是至关庞大的)。

相关文章
相关标签/搜索