您好,欢迎访问三七文档
这是一篇旧文,点击此处以旧主题模式浏览。互联网时代的社会语言学:基于SNS的文本数据挖掘今年上半年,我在人人网实习了一段时间,期间得到了很多宝贵的数据,并做了一些还算有意义的事情,在这里和大家一块儿分享。感谢人人网提供的数据与工作环境,感谢赵继承博士、詹卫东老师的支持和建议。在这项工作中,我得到了很多与众人交流的机会,特别感谢OpenParty、TEDxBeijing提供的平台。本文已发表在了《程序员》杂志,分上下两部分刊于2012年7月刊和8月刊,在此感谢卢鸫翔编辑的辛勤工作。由于众所周知的原因,《程序员》刊出的文章被和谐过(看到后面大家就自动地知道被和谐的内容是什么了),因而我决定把完整版发在Blog上,同时与更多的人一同分享。对此感兴趣的朋友可以给我发邮件继续交流。好了,开始说正文吧。作为中文系应用语言学专业的学生以及一名数学Geek,我非常热衷于用计算的方法去分析汉语资料。汉语是一种独特而神奇的语言。对汉语资料进行自然语言处理时,我们会遇到很多其他语言不会有的困难,比如分词——汉语的词与词之间没有空格,那计算机怎么才知道,“已结婚的和尚未结婚的青年都要实行计划生育”究竟说的是“已/结婚/的/和/尚未/结婚/的/青年”,还是“已/结婚/的/和尚/未/结婚/的/青年”呢?这就是所谓的分词歧义难题。不过,现在很多语言模型已经能比较漂亮地解决这一问题了。但在中文分词领域里,还有一个比分词歧义更令人头疼的东西——未登录词。中文没有首字母大写,专名号也被取消了,这叫计算机如何辨认人名地名之类的东西?更惨的则是机构名、品牌名、专业名词、缩略语、网络新词等等,它们的产生机制似乎完全无规律可寻。最近十年来,中文分词领域都在集中攻克这一难关。自动发现新词成为了关键的环节。挖掘新词的传统方法是,先对文本进行分词,然后猜测未能成功匹配的剩余片段就是新词。这似乎陷入了一个怪圈:分词的准确性本身就依赖于词库的完整性,如果词库中根本没有新词,我们又怎么能信任分词结果呢?此时,一种大胆的想法是,首先不依赖于任何已有的词库,仅仅根据词的共同特征,将一段大规模语料中可能成词的文本片段全部提取出来,不管它是新词还是旧词。然后,再把所有抽出来的词和已有词库进行比较,不就能找出新词了吗?有了抽词算法后,我们还能以词为单位做更多有趣的数据挖掘工作。这里,我所选用的语料是人人网2011年12月前半个月部分用户的状态。非常感谢人人网提供这份极具价值的网络语料。Matrix67:TheAhaMoments互联网时代的社会语言学:基于SNS的文本数据挖掘|Matrix67...第1页共50页2015/10/2721:59要想从一段文本中抽出词来,我们的第一个问题就是,怎样的文本片段才算一个词?大家想到的第一个标准或许是,看这个文本片段出现的次数是否足够多。我们可以把所有出现频数超过某个阈值的片段提取出来,作为该语料中的词汇输出。不过,光是出现频数高还不够,一个经常出现的文本片段有可能不是一个词,而是多个词构成的词组。在人人网用户状态中,“的电影”出现了389次,“电影院”只出现了175次,然而我们却更倾向于把“电影院”当作一个词,因为直觉上看,“电影”和“院”凝固得更紧一些。为了证明“电影院”一词的内部凝固程度确实很高,我们可以计算一下,如果“电影”和“院”真的是各自独立地在文本中随机出现,它俩正好拼到一起的概率会有多小。在整个2400万字的数据中,“电影”一共出现了2774次,出现的概率约为0.000113。“院”字则出现了4797次,出现的概率约为0.0001969。如果两者之间真的毫无关系,它们恰好拼在了一起的概率就应该是0.000113×0.0001969,约为2.223×10次方。但事实上,“电影院”在语料中一共出现了175次,出现概率约为7.183×10次方,是预测值的300多倍。类似地,统计可得“的”字的出现概率约为0.0166,因而“的”和“电影”随机组合到了一起的理论概率值为0.0166×0.000113,约为1.875×10,这与“的电影”出现的真实概率很接近——真实概率约为1.6×10次方,是预测值的8.5倍。计算结果表明,“电影院”更可能是一个有意义的搭配,而“的电影”则更像是“的”和“电影”这两个成分偶然拼到一起的。当然,作为一个无知识库的抽词程序,我们并不知道“电影院”是“电影”加“院”得来的,也并不知道“的电影”是“的”加上“电影”得来的。错误的切分方法会过高地估计该片段的凝合程度。如果我们把“电影院”看作是“电”加“影院”所得,由此得到的凝合程度会更高一些。因此,为了算出一个文本片段的凝合程度,我们需要枚举它的凝合方式——这个文本片段是由哪两部分组合而来的。令p(x)为文本片段x在整个语料中出现的概率,那么我们定义“电影院”的凝合程度就是p(电影院)与p(电)·p(影院)比值和p(电影院)与p(电影)·p(院)的比值中的较小值,“的电影”的凝合程度则是p(的电影)分别除以p(的)·p(电影)和p(的电)·p(影)所得的商的较小值。可以想到,凝合程度最高的文本片段就是诸如“蝙蝠”、“蜘蛛”、“彷徨”、“忐忑”、“玫瑰”之类的词了,这些词里的每一个字几乎总是会和另一个字同时出现,从不在其他场合中使用。光看文本片段内部的凝合程度还不够,我们还需要从整体来看它在外部的表现。考虑“被子”和“辈子”这两个片段。我们可以说“买被子”、“盖被子”、“进被子”、“好被子”、“这被子”等等,在“被子”前面加各种字;但“辈子”的用法却非常固定,除了“一辈子”、“这辈子”、“上辈子”、“下辈子”,基本上“辈子”前面不能加别的字了。“辈子”这个文本片段左边可以出现的字太有限,以至于直觉上我们可能会认为,“辈子”并不单独成词,真正成词的其实是“一辈子”、“这辈子”之类的整体。可见,文本片段的自由运用程度也是判断它是否成词的重要标准。如果一个文本片段能够算作一个词的话,它应该能够灵活地出现在各种不同的环境中,具有非常丰富的左邻字集合和右邻字集合。-8-6-6-5互联网时代的社会语言学:基于SNS的文本数据挖掘|Matrix67...第2页共50页2015/10/2721:59“信息熵”是一个非常神奇的概念,它能够反映知道一个事件的结果后平均会给你带来多大的信息量。如果某个结果的发生概率为p,当你知道它确实发生了,你得到的信息量就被定义为–log(p)。p越小,你得到的信息量就越大。如果一颗骰子的六个面分别是1、1、1、2、2、3,那么你知道了投掷的结果是1时可能并不会那么吃惊,它给你带来的信息量是–log(1/2),约为0.693。知道投掷结果是2,给你带来的信息量则是–log(1/3)≈1.0986。知道投掷结果是3,给你带来的信息量则有–log(1/6)≈1.79。但是,你只有1/2的机会得到0.693的信息量,只有1/3的机会得到1.0986的信息量,只有1/6的机会得到1.79的信息量,因而平均情况下你会得到0.693/2+1.0986/3+1.79/6≈1.0114的信息量。这个1.0114就是那颗骰子的信息熵。现在,假如某颗骰子有100个面,其中99个面都是1,只有一个面上写的2。知道骰子的抛掷结果是2会给你带来一个巨大无比的信息量,它等于–log(1/100),约为4.605;但你只有百分之一的概率获取到这么大的信息量,其他情况下你只能得到–log(99/100)≈0.01005的信息量。平均情况下,你只能获得0.056的信息量,这就是这颗骰子的信息熵。再考虑一个最极端的情况:如果一颗骰子的六个面都是1,投掷它不会给你带来任何信息,它的信息熵为–log(1)=0。什么时候信息熵会更大呢?换句话说,发生了怎样的事件之后,你最想问一下它的结果如何?直觉上看,当然就是那些结果最不确定的事件。没错,信息熵直观地反映了一个事件的结果有多么的随机。我们用信息熵来衡量一个文本片段的左邻字集合和右邻字集合有多随机。考虑这么一句话“吃葡萄不吐葡萄皮不吃葡萄倒吐葡萄皮”,“葡萄”一词出现了四次,其中左邻字分别为{吃,吐,吃,吐},右邻字分别为{不,皮,倒,皮}。根据公式,“葡萄”一词的左邻字的信息熵为–(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,我们不应该把它看作一个能灵活运用的词。当然,一些文本片段的左邻字没啥问题,右邻字用例却非常贫乏,例如“交响”、“后遗”、“鹅卵”等,把它们看作单独的词似乎也不太合适。我们不妨就把一个文本片段的自由运用程度定义为它的左邻字信息熵和右邻字信息熵中的较小值。互联网时代的社会语言学:基于SNS的文本数据挖掘|Matrix67...第3页共50页2015/10/2721:59在实际运用中你会发现,文本片段的凝固程度和自由程度,两种判断标准缺一不可。只看凝固程度的话,程序会找出“巧克”、“俄罗”、“颜六色”、“柴可夫”等实际上是“半个词”的片段;只看自由程度的话,程序则会把“吃了一顿”、“看了一遍”、“睡了一晚”、“去了一趟”中的“了一”提取出来,因为它的左右邻字都太丰富了。我们把文本中出现过的所有长度不超过d的子串都当作潜在的词(即候选词,其中d为自己设定的候选词长度上限,我设定的值为5),再为出现频数、凝固程度和自由程度各设定一个阈值,然后只需要提取出所有满足阈值要求的候选词即可。为了提高效率,我们可以把语料全文视作一整个字符串,并对该字符串的所有后缀按字典序排序。下表就是对“四是四十是十十四是十四四十是四十”的所有后缀进行排序后的结果。实际上我们只需要在内存中存储这些后缀的前d+1个字,或者更好地,只储存它们在语料中的起始位置。十十十四是十四四十是四十十是十十四是十四四十是四十十是四十十四是十四四十是四十十四四十是四十是十十四是十四四十是四十是十四四十是四十是四十是四十是十十四是十四四十是四十四十四十是十十四是十四四十是四十四十是四十四是十四四十是四十四是四十是十十四是十四四十是四十四四十是四十这样的话,相同的候选词便都集中在了一起,从头到尾扫描一遍便能算出各个候选词的频数和右邻字信息熵。将整个语料逆序后重新排列所有的后缀,再扫描一遍后便能统计出每个候选词的左邻字信息熵。另外,有了频数信息后,凝固程度也
本文标题:文本数据挖掘
链接地址:https://www.777doc.com/doc-5032070 .html