关于新词发现

本笔记摘自:http://www.matrix67.com/blog/archives/5044

概述

挖掘新词的传统方法是,先对文本进行分词,然后猜测未能成功匹配的剩余片段就是新词。这似乎陷入了一个怪圈:分词的准确性本身就依赖于词库的完整性,如果词库中根本没有新词,我们又怎么能信任分词结果呢?
一种大胆的想法是,首先不依赖于任何已有的词库,仅仅根据词的共同特征,将一段大规模语料中可能成词的文本片段全部提取出来,不管它是新词还是旧词。然后,再把所有抽出来的词和已有词库进行比较,不就能找出新词了吗?有了抽词算法后,我们还能以词为单位做更多有趣的数据挖掘工作。

凝固度

solide()=min(p()p()×p(),p()p()×p())

solide()=min(p()p()×p(),p()p()×p())

可以想到,凝合程度最高的文本片段就是诸如“蝙蝠”、“蜘蛛”、“彷徨”、“忐忑”、“玫瑰”之类的词了,这些词里的每一个字几乎总是会和另一个字同时出现,从不在其他场合中使用。

自由度

光看文本片段内部的凝合程度还不够,我们还需要从整体来看它在外部的表现。考虑“被子”和“辈子”这两个片段。我们可以说“买被子”、“盖被子”、“进被子”、“好被子”、“这被子”等等,在“被子”前面加各种字;但“辈子”的用法却非常固定,除了“一辈子”、“这辈子”、“上辈子”、“下辈子”,基本上“辈子”前面不能加别的字了。“辈子”这个文本片段左边可以出现的字太有限,以至于直觉上我们可能会认为,“辈子”并不单独成词,真正成词的其实是“一辈子”、“这辈子”之类的整体。可⻅,文本片段的自由运用程度也是判断它是否成词的重要标准。如果一个文本片段能够算作一个词的话,它应该能够灵活地出现在各种不同的环境中,具有非常丰富的左邻字集合和右邻字集合。
我们用信息熵来衡量一个文本片段的左邻字集合和右邻字集合有多随机。考虑这么一句话“吃葡萄不吐葡萄皮不吃葡萄倒吐葡萄皮”,“葡萄”一词出现了四次,其中左邻字分别为 {吃,吐,吃,吐} ,右邻字分别为 {不,皮, 倒, 皮} 。根据公式,“葡萄”一词的左邻字的信息熵为 – (1/2) ·log(1/2) – (1/2) · log(1/2) ≈ 0.693 ,它的右邻字的信息熵则为 – (1/2) · log(1/2) – (1/4) ·log(1/4) – (1/4) · log(1/4) ≈ 1.04 。可⻅,在这个句子中,“葡萄”一词的右邻字更加丰富一些。
在人人网用戶状态中,“被子”一词一共出现了 956 次,“辈子”一词一共出现了 2330 次,两者的右邻字集合的信息熵分别为 3.87404 和 4.11644,数值上非常接近。但“被子”的左邻字用例非常丰富:用得最多的是“晒被子”,它一共出现了 162 次;其次是“的被子”,出现了 85 次;接下来分别是“条被子”、“在被子”、“床被子”,分别出现了 69 次、 64 次和 52 次;当然,还有“叠被子”、“盖被子”、“加被子”、“新被子”、“掀被子”、“收被子”、“薄被子”、“踢被子”、“抢被子”等 100 多种不同的用法构成的长尾……所有左邻字的信息熵为 3.67453 。但“辈子”的左邻字就很可怜了,2330 个“辈子”中有 1276 个是“一辈子”,有 596 个“这辈子”,有 235 个“下辈子”,有 149 个“上辈子”,有 32 个“半辈子”,有 10 个“八辈子”,有 7 个“几辈子”,有 6 个“哪辈子”,以及“n 辈子”、“两辈子”等 13 种更罕⻅的用法。所有左邻字的信息熵仅为 1.25963 。因而,“辈子”能否成词,明显就有争议了。“下子”则是更典型的例子,310 个“下子”的用例中有 294个出自“一下子”, 5 个出自“两下子”, 5 个出自“这下子”,其余的都是只出现过一次的罕⻅用法。事实上,“下子”的左邻字信息熵仅为 0.294421,我们不应该把它看作一个能灵活运用的词。当然,一些文本片段的左邻字没啥问题,右邻字用例却非常贫乏,例如“交响”、“后遗”、“鹅卵”等,把它们看作单独的词似乎也不太合适。我们不妨就把一个文本片段的自由运用程度定义为它的左邻字信息熵和右邻字信息熵中的较小值。

总结

在实际运用中你会发现,文本片段的凝固程度和自由程度,两种判断标准缺一不可。只看凝固程度的话,程序会找出“巧克”、“俄罗”、“颜六色”、“柴可夫”等实际上是“半个词”的片段;只看自由程度的话,程序则会把“吃了一顿”、“看了一遍”、“睡了一晚”、“去了一趟”中的“了一”提取出来,因为它的左右邻字都太丰富了。

算法实现技巧

我们把文本中出现过的所有长度不超过 d 的子串都当作潜在的词(即候选词,其中 d 为自己设定的候选词长度上限,我设定的值为 5 ),再为出现频数、凝固程度和自由程度各设定一个阈值,然后只需要提取出所有满足阈值要求的候选词即可。为了提高效率,我们可以把语料全文视作一整个字符串,并对该字符串的所有后缀按字典序排序。下表就是对“四是四十是十十四是十四四十是四十”的所有后缀进行排序后的结果。实际上我们只需要在内存中存储这些后缀的前 d + 1 个字,或者更好地,只储存它们在语料中的起始位置。

十
十十四是十四四十是四十
十是十十四是十四四十是四十
十是四十
十四是十四四十是四十
十四四十是四十
是十十四是十四四十是四十
是十四四十是四十
是四十
是四十是十十四是十四四十是四十
四十
四十是十十四是十四四十是四十
四十是四十
四是十四四十是四十
四是四十是十十四是十四四十是四十
四四十是四十

这样的话,相同的候选词便都集中在了一起,从头到尾扫描一遍便能算出各个候选词的频数和右邻字信息熵。将整个语料逆序后重新排列所有的后缀,再扫描一遍后便能统计出每个候选词的左邻字信息熵。另外,有了频数信息后,凝固程度也都很好计算了。这样,我们便得到了一个无需任何知识库的抽词算法,输入一段充分长的文本,这个算法能以大致 O(n · logn) 的效率提取出可能的词来。

别忘了,我们的目标是新词抽取。需要将所有抽出来的词过滤掉词库中的词,筛选出新词。

其他意思的应用

我还想到了更有意思的玩法。为什么不拿每一天状态里的词去和前一天的状态作对比,从而提取出这一天里特有的词呢?这样一来,我们就能从人人网的用戶状态中提取出每日热点了!从手里的数据规模看,这是完全有可能的。

一个问题摆在了我们面前:我们如何去量化一个词的“当日热度”?第一想法当然是简单地看一看每个词的当日频数和昨日频数之间的倍数关系,不过细想一下你就发现问题了:它不能解决样本过少带来的偶然性。
忽略所有样本过少的词?这似乎也不太好,样本少的词也有可能真的是热词。
让计算机也能聪明地排除偶然因素,这是我们在数据挖掘过程中经常遇到的问题。我们经常需要对样本过少的项目进行“平滑”操作,以避免分母过小带来的奇点。这里,我采用的是一个非常容易理解的方法:一个词的样本太少,就给这个词的热度打折扣。
这种与全局平均取加权平均的思想叫做 Bayesian average ,从上面的若干式子里很容易看出,它实际上是最常⻅的平滑处理方法之一——分子分母都加上一个常数——的一种特殊形式。

我们可以任意比较两段不同文本中的用词特点。更有趣的是,人人网状态的大多数发布者都填写了性别和年龄的个人信息,我们为何不把状态重新分成男性和女性两组,或者 80 后和 90 后两组,挖掘出不同属性的人都爱说什么?要知道,在过去,这样的问题需要进行大规模语言统计调查才能回答!然而,在互联网海量用戶生成内容的支持下,我们可以轻而易举地挖掘出答案来。

不仅如此,不少状态还带有地理位置信息,因而我们可以站在空间的维度对信息进行观察。这个地方的人都爱说些什么?爱说这个词的人都分布在哪里?借助这些包含地理位置的签到信息,我们也能挖掘出很多有意思的结果来。例如,对北京用戶的签到信息进行抽词,然后对于每一个抽出来的词,筛选出所有包含该词的签到信息并按地理坐标的位置聚类,这样我们便能找出那些地理分布最集中的词。结果非常有趣:“考试”一词集中分布在海淀众高校区,“天津”一词集中出现在北京南站,“逛街”一词则全都在西单附近扎堆。北京首都国际机场也是一个非常特别的地点,“北京”、“登机”、“终于”、“再⻅”等词在这里出现的密度极高。

从全国范围来看,不同区域的人也有明显的用词区别。我们可以将全国地图划分成网格,统计出所有签到信息在各个小格内出现的频数,作为标准分布;然后对于每一个抽出来的词,统计出包含该词的签到信息在各个小格内出现的频数,并与标准分布进行对比(可以采用余弦距离等公式),从而找出那些分布最反常的词。程序运行后发现,这样的词还真不少。一些明显具有南北差异的词,分布就会与整个背景相差甚远。例如,在节假日的时候,“滑雪”一词主要在北方出现,“登山”一词则主要在南方出现。地方特色也是造成词语分布差异的一大原因,例如“三里屯”一词几乎只在北京出现,“热干面”一词集中出现在武汉地区,“地铁”一词明显只有个别城市有所涉及。这种由当地人的用词特征反映出来的真实的地方特色,很可能是许多旅游爱好者梦寐以求的信息。另外,方言也会导致用词分布差异,例如“咋这么”主要分布在北方地区,“搞不懂”主要分布在南方城市,“伐”则非常集中地出现在上海地区。当数据规模足够大时,或许我们能通过计算的方法,自动对中国的方言区进行划分。

其实,不仅仅是发布时间、用戶年龄、用戶性别、地理位置这四个维度,我们还可以对浏览器、用戶职业、用戶活跃度、用戶行为偏好等各种各样的维度进行分析,甚至可以综合考虑以上维度,在某个特定范围内挖掘热点事件,或者根据语言习惯去寻找出某个特定的人群。或许这听上去太过理想化,不过我坚信,有了合适的算法,这些想法终究会被一一实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值