初涉自然语言处理(二):统计词频

昨天那篇文章是根据需求一步步向上反推的,真正开始时应该是从第五步开始一步步到第一步。由于我已经在网上找到了勉强足够的语料(143,347,023 words,in 1,508 files),所以就直接从统计词频开始讲了。

先来说说为什么要统计词频。

语言模型的本质就是根据已经出现的单词来预测下一个可能出现的单词。

例如: I want to eat Chinese food

这一句,在用户已经输入 I want to eat Chinese 时,下一个单词是 food 的概率其实就是求条件概率(conditional probability)

$P(food|I,want,to,eat,Chinese)$

根据贝叶斯公式,有

$P(food | I, want, to, eat, Chinese) = \frac{P(I, want, to, eat, Chinese, food)}{P(I, want, to, eat, Chinese)}$

所以理论上我们只要统计出足够多的单词组合的频率,就能推出他们出现的概率,也就能计算出任意单词在一个给定词语或短语后出现的概率。即:

$P(food | I, want, to, eat, Chinese) = \frac{Count(I, want, to, eat, Chinese, food)}{Count(I, want, to, eat, Chinese)}$

但是显然,我们很难去统计出 I want to eat Chinese food 的频率,因为可能的单词组合太多了。所以我们退而求其次,根据 Andrei Markov 提出的以下假设:

$P(food \:|\: I, want, to, eat, Chinese)\approx P(food | Chinese)$

$Or$

$P(food \:|\: I, want, to, eat, Chinese)\approx P(food | eat, Chinese)$

这样我们只需要统计出任意两个或三个单词的组合频率就可以了。

事实上,统计两个单词组合出现频率的模型叫 Bigram,三个的叫 Trigram, Google 拥有 5-gram 的数据。很显然,模型的维数越高,计算所得出来的结果就越精确,所需要的数据也就越多。

而只统计单个词频的模型叫 Unigram,这种模型只是简单地将一个句子中的每个单词相乘,即将每个单词的出现看做相对独立事件,这显然是非常不精确的。

在本项目中,我选择 Bigram 模型,即需要统计任意单词出现的频率和任意两个单词同时出现的频率。

初涉自然语言处理(一):概述

毕业设计做的是一个基于 JS 的拼写检查插件,涉及到自然语言处理的一些东西。因为初次接触踩了不少坑,所以专门写一系列文章来记录一下。我会在后续几篇中陆续发出细节部分,这篇先讲一下大致的原理和目标。

首先提到拼写检查很自然能够想到需要一个词典。将输入的单词与词典中的单词相比较,如果不存在符合的那么就认为拼写出错。

这部分需要解决的问题:

  • 大小写是否重要
  • 缩略词(CIA)、地名(San Francisco)、连接词(year-old)、缩写(you’d)如何处理
  • 英式英语和美式英语怎么算

第二,在有了词典之后,我们就可以筛选出输入的错误单词,这时需要给用户输出一个更正建议(Correction Suggestion),这步可以使用 Levenshtein 算法来完成,此算法通过计算编辑距离(edit distance)来找出与错误单词“足够相似的”正确单词。

这部分需要解决的问题:

  • 每种编辑的权重

第三,我们需要对第二步的结果进行筛选和排序,之所以需要这一步的原因如下图,如果仅仅基于 Levenshtein 算法来提供结果反倒会使用户更加困惑。这一步也是整个项目的重点,就是需要通过训练语料库建立语言模型,给出最有可能的建议。

这部分需要解决的问题:

  • 相似阈值设置为多少
  • 对语料库平滑处理(smoothing)
  • 选择合适的训练维度(uni-gram、 bi-gram or tri-gram)

第四,为了完成第三步,我们需要写一个程序来对大量文本进行处理,比如通过正则匹配进行分词(word tokenization)、计数(counting)等,有可能还需要对一些特殊单词进行规范化(normalization),例如 I’ll -> I will 。

这部分需要解决的问题:

  • 对文本进行格式化,去除数字、网址、汉字、标点等
  • 选择相应的语言和数据结构
  • 不在字典内的单词如何处理
  • 统计语料库中字典内词语的词频
  • 统计任意 n 个字典内单词一起出现的概率

第五,为了获得大量文本作为语料库,我们可能会需要一个爬虫(Spider),当然也可能不需要,一切根据需求来。

这部分需要解决的问题:

  • 获得大量英文文本文件

这篇先写这么多,其余的慢慢补上来。

分享一首歌

一个暑假没写文,因为暑假忘记带移动硬盘了 = =!

其实有挺多想写的,但最近确实忙得不要不要的,过了这阵子再说吧。

逛站酷时无意听到一首歌《白兰鸽巡游记》很棒,分享一下。

我对泸医更名的看法

本来不想对这个事情发表言论的,因为我有几个关系非常好的华西的朋友。但川大学生会最近的一篇倡议书实在是让我无法忍受。在微信上跟人讨论了不少,在此记录一下观点。

首先陈述一下事实:

泸州医学院于 2015 年 2 月 27 日 获得通过进入公示期,在 2015 年 3 月 17 日 公示结束,更名成功。

鉴于在这长达 20 天的公示中川大没有发表任何反对意见,所以我做出以下合理推测:

泸州医学院改名公示的时候,川大觉得并无不妥,决定睁一只眼闭一只眼。更名正式批复下来之后,老华西医务工作者向川大表达了严重的不满。为安抚他们的情绪,川大向教育部发函声明不同意泸医更名(然而川大很清楚这并没有什么用)。
随后川大学生开始撕逼,并且学生会带头开始了尤其傻逼的撕逼。

内容在此:四川大学学生会关于泸医更名的倡议书

随后泸州医学院进行了回应(原帖已被删):驳斥川大学生会发言,并细数川大三宗罪

很明显川大学生会的牌子这次被砸了,对那篇倡议书的吐槽我在微信上骂了许多次也就不重复了,只说一下立场的问题。

以下摘自对一位同学的回复:

Instant Chat —— 初学 WebSocket

之前偶然发现个游戏:agar.io,觉得好有意思,想学习一下。

看了下是用 WebSocket 做的,是自己写的,没有用 Socket.io 来做。

于是就和 iojs 一起,做了个即时聊天的应用,取名叫 Instant Chat

用户输入自己的昵称后将页面转发给好友即可实现通话,特点是没有发送键,输入的内容会实时显示在对方屏幕上。

从前端到后端完全事件驱动,即时性非常好。

用了 bootstrap ,但是精简了其代码,全部 CSS 只有 1.8K 。

同样没有用 Socket.io ,虽说可以优雅降级,但实在太过臃肿,前端库就 89.3K 。而且我试了一下,offline 事件的延迟很严重,达不到我的要求。