中文无库取词

最近看吴军博士的《数学之美》。对自然语言处理非常感兴趣,惊叹于数学之美。于是自己抽空实现了一个无库取词方法。下面针对实现方法和遇到的一些问题做一些分享。

首先要知道计算机不是人,并不了解中文语句中哪些是词语。那我们如何利用计算机得到词语呢?很简单,用它最基本的功能-计算。废话不多说,让我们一起认识数学的吧。

         语料
        大家可以理解为取词的文本,可以是一部书籍、一篇文章、一些用户操作日志等。

         词频
        词频就是一个字在语料中出现的次数。往往作为取词的一个标准。但是光词频是不够的,下面我来介绍下“魔法师”和“了一”两个词。

凝合度
        我将小说《罪恶之城》免费章节部分做为语料,总共827973个字。其中“魔法师”一词出现了479次。下面我们假设“魔”和“法师”两个部分是偶然出现在一起的。“魔”字出现了3768次,“法师”一词出现了1246次。求出他们的概率。

        p(魔)=3768/827973≈0.004550873

        p(法师)=1246/827973≈0.00150488

        那么理论上“魔法师”出现的概率为:

        p(魔法师)=p(魔)*p(法师)≈0.00000685

        但是“魔法师”的实际概率为:

        p2(魔法师)=479/827973≈0.00057852

        可以看出“魔法师”出现的实际概率是理论概率的84倍之多(通过p2/p得到)。这样我们不得不考虑“魔法师”中的“魔”和“法师”两部分并非偶然组合在了一起。他们是“魔法师”一词的一部分,紧密的凝合在一起。p2/p得到的比值84,我们就称之为-凝合度。

        下面我们在看看一个词语“了一”,当然这里是假设它是词。“了一”一词出现了1534次,其中“了”字出现了11868次,“一”字出现14946次,我们不难算出其凝合度数为7。这说明“了”和“一”是随机组合在一起的可能性较大。我们可以给凝合度设定为一个阀值,如果这个值比7大,那么“了一”将不会出现在你的结果中。

        以上发现“了一”的词频比“魔法师”更高,而“魔法师”更像一个词语。所以取词不能完全靠词频来判断,还需要凝合度。

        相信大家对凝合度有了一定的了解。有些同学会问:“魔法师”也可以是“魔法”和“师”的随机组合。对,我们不能忽略这种可能。按照这种组合,计算出来的凝合度为86。这种情况下,我们取较小的值,也就是84。

        信息熵
        每次买可乐,打开瓶盖的时候,如果是谢谢惠顾,我相信大家一定很淡定。我们可以理解为抽到谢谢惠顾的概率很高,所以给我们的信息量很低,低到不足以使得我们激动。反过来如果是再来一瓶,这时候肯定会小激动一下,同理再来一瓶的概率比谢谢惠顾小的多,所以我们得到的信息量就比较大,固然惊讶。这种反映一个事件之后你能获得多少信息量的概念我们称之为-信息熵。

        我们再来深层次的了解信息熵,当一个事件发生的概率是p,那么如果这个事件真的发生了,那么你得到的信息量为:-log(p)。一个封闭的箱子里面有5个铜币和1个金币。你闭上眼睛去里面取东西,如果你拿到了铜币,那么你得到的信息量H(铜)=-log(5/6)≈0.182321。如果你运气足够好,拿到了金币,那么你得到的信息量H(金)=-log(1/6)≈1.791759。可见你得到金币的信息量是得到铜币信息量的10倍左右。当然如果箱子里面全都是铜币,那么你得到的信息量是:-log(6/6)=0,因为你已经能知道自己拿到的是铜币,没什么好惊讶的,也没有得到信息量。

        说了这么多信息熵的概念与计算方法,那么它对取词有什么用呢?我们来看一个句子“吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮”。其中“葡萄”出现了4次,我们来看看葡萄左边出现的字有哪些:“吃、吐、吃、吐”,右边出现的字是:“不、皮、倒、皮”。我们可以算出葡萄左边出现字的信息量:H(吃)=-log(1/2)≈0.69314,H(吐)=-log(1/2)≈0.69314。因此我们可以得到葡萄左边的信息量H(左)=H(吃)/2+H(吐)/2≈0.69314。这其实很好理解,这里葡萄左边出现字就两种情况,所以信息量H(左)=-log(1/2)≈0.69314。和上面的计算相等。同理我们计算出右边的信息量H(右边)=-log(1/2)/2-log(1/4)/4-log(1/4)/4≈1.04。由此可见葡萄右边得到的信息量大一些,为什么呢?因为右边的字更加丰富一些。说到这里,我想大家应该明白信息熵对取词的意义。那就是分析一个词语的自由组合程度。一个好的词语,往往有很多左邻字和右邻字。作为评价一个词语的信息熵,我们通常取左右信息熵中较小的那个,然后将信息熵设置一个阀值,我们将会筛选出更优秀的词语。

    取词方法
    我们来看这个句子“一二三”,首先我们得穷举出其所有组合可能(并按字典排序,更好的可以把有邻词都放在后面用空格隔开,方便统计):

    一        二
    一二        三
    一二三
    二    一    三
    二三    一
    三    二

    这样从头扫描到尾部,我们基本上就能算出每个词的词频、信息熵、以及部分凝合度(三个字以上的词缺少一些组合情况的凝合度)。然后将每行文字倒序后按照字典排序,再次扫描。我们就得到了剩下的凝合度。这样取词步骤就完成了。

    实现方法虽然简单,但是过程中遇到了很多问题,其中比较麻烦的莫过于排序。大文本排序:如果纯粹的使用内存来进行排序操作,处理1M以上文本的时候就会出现内存溢出。这时候我们可以采用分割排序方法,将文本分割成很多份,然后对每份进行排序。然后对排序好的所有文件进行归并排序,这样基本上解决了大文本排序问题。效率方面:我的Mac处理10M文本的速度大概是3分钟左右。换成服务器机器或者使用hadoop会有质的提升,当然这些都是后话了。

    洋洋洒洒写了这么多,只是希望以最简单的方式让大家明白取词并不困难。不得不惊叹于数学之美,统计之霸道。同时也要感谢给予我帮助的同事,以及一些激起我灵感的文章。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值