本文是一篇关于工程学的内容,讲述的是当前较先进的技术——拼写校对程序。这项技术的用处就是让低级工程师使用起来得心应手。
许多年前,我根据Peter Norvig精彩教程(http://norvig.com/spell-correct.html)的指导独自编写了第一个拼写检查程序(spelling corrector)——该程序利用21行Python代码编写而成。
最初的程序很烂。
因此,我试着改进最初的程序。我为它增添了相似双音位语音识别功能、unicode支持功能、多词表达(multi-word expression)功能、加权Damerau-Levenshtein编辑距离功能、查询效率高的单词查找树结构的功能以及智能高速缓存技术。
可是,这款程序仍旧很烂。
这款程序无法运行并不是因为其过于简单——我不是Google公司的员工(同样,你也不是)。
即便使用该程序最简单的模式,拼写出一个简短的单词也需要花费很长的时间——大约0.1秒左右。这样的拼写速度或许在某些用途中可以胜任,但是面对即将到来的机器人热潮,当你进行实时聊天时,实现实时交互才是最重要的。与此同时,请不要忘记拼写只是通过自然语言理解(NaturalLanguage Understanding)、对话管理、业务逻辑(business logic)以及实际应用输送值进行的冗长处理传递途径中的其中一个单链。
这款程序运行效果不佳的根本原因在于拼写器(speller)。拼写器试图强行通过某种途径找到正确的解决方法。以下是Norvig的核心代码,如图所示:
程序在发挥功能时会考虑输入中所有可能的编辑情况——删除任何一个字符,换位任意两个相邻的字符,以任意一个字符替换输入中任意的字符或者直接比较随意地在输入中添加一个字符。但是,如果想要知道在已编辑的字符串集合中删除、互换、替换以及添加字符后的结果——程序需要再次计算所有可能的编辑情况!
获取这个结果需要进行的计算量相当具有挑战性,而且这还会导致输入中字符串的长度以指数函数的方式增长。
……
但是我非常确信我们的大脑不会采用这种方法完成正确的拼写过程。当我们看到拼写错误的单词时就会自动修正其中的干扰。
例如:
Can yu read this massage despitethehorible sppeling msitakes? I bet you kan. 尽管这句话存在严重的拼写错误,你能看懂这条信息吗? 我猜你一定能看懂。
有的时候修正干扰的过程是下意识的,甚至会根据直觉进行处理,以至于忽略了本文中有拼写错误的事实。
你认为我们大脑有处理编辑距离为3的词(edit-3distance)的功能吗?
一定有比强制更好的办法。
一定有让计算机学习这种“直觉”的办法。
……
因此,我尝试了一种不同的方法。这种方法名为深度学习——深度学习是基于一系列算法的机器学习的一个分支,其中的算法通过利用由多个非线性的转化构成的多个处理层,在数据中尝试模仿高层抽象(不好意思,这部分内容引用自维基百科……)。
在一款名为AlphaGo的人工智能程序以五局四胜的成绩打败了世界围棋冠军之后,深度学习最近得以推广。
考虑到许多不同的深度学习架构都基于相同的前提,所以它们能够获得相似的运行结果,此时我所提出的解决办法的细节已经不再那么重要:
- 创建一个具有充足“计算能力”的人工网络(artificial network)(连通的人工神经元)。
- 给人工网络输入大量的数据,直到它知道怎么处理数据为止。
尽管如此,这里还涉及一些技术细节:
- 开放源码工具:Python/Theano/Keras
- 我们很难在EC2上安装人工网络,而且当安装的进程越来越慢时,请不要使用Google推出的TensorFlow软件库(?!) (这是一件有意思的事情——Google正在标记TensorFlow软件库,当我的Chrome浏览器中出现一个拼写错误时,该软件库就会创造一个新的术语。这是多么的讽刺啊)。
- 当输入大小可以不同于输出大小时,我就会使用sequence-to-sequence架构。输入大小也可以有很大变化。 这与用于机器翻译任务的模型非常相似。
- 基于字符;我很少会预处理字符,通常会保留75%的最受欢迎字符。 这就意味着数字和一些符号也要保留。 基本上,系统中嵌入式的“知识”都是基于语言模型的字符。我不理解在标记输入字符串(把字符串分解成单词)的同时加入干扰的原因,也不理解使用“特征工程”的原因。人工网络也是互联网数字分配机构-语言学家,模型学习特性的能力比我以往设计的好太多了。 除此之外——你如何标记“Whereisth elove”这个字符串? 在大部分键盘上,空格键比其它按键大很多是有原因的——人们常常按错空格键。 因为字符在“问题”和目标“回答”中产生了短暂的依赖,这种情况采用自助法来优化问题更加简便,所以我颠倒了输入中字符的顺序。
- 长短期记忆层(其中2层用于编码,另外2层用于解码)会利用大量的Dropout(0.3)。
- Gaussian这款综合软件包通过扇入(fan-in)(他及其他人)来拓展初始化值。
- Adam是一种随机优化的方法。
- 我的目标就是Categorical Cross-entropy目标函数:又名多层对数损失函数(multiclasslogloss)。
- 在Amazon云中训练(EC2 g2.2xlarge 运行GPU的实例)。
- 不,我安装多重单精度32位长的Tesla K40 GPU加速器显卡(multiple 32 Tesla K40 GPU)还不到3周。
- 在验证集中训练了12个小时后,其正确率达到了90%。接着连续训练3天后,其正确率达到了95.5%。 训练总成本=40美元。
……
人工神经网络的设计理念源于我们大脑中的神经元,所以其结构是非常松散,但是我并不是在暗示这种算法在某些方面与我们大脑的实际工作原理有所关联。
……
你可能会问数据的来源。数据对于拼写来说非常重要(而且通常情况下,数据对深度学习也非常重要),假设你是谷歌公司的其中一员,你的数据集中储存了“BritneySpears”和“Arnold Schwarzenegger”这两个词数以千计的的常见拼写错误,你可以利用这些资源来实现非常有效的算法。
但是,如果你是一个新手,那么你需要进行恰到好处且富有创造性的即兴而作。
我使用了Google为研究语言模型而发布的含有大量单词并且增添了人工干扰的数据集。这种干扰是模拟拼写错误,而模型试图学习怎样通过输出与原文的比较来校正输入——这是一款压缩编码器(an Autoencoder)。
在Evature公司,我们也已经有了数以百万计的记录,我打算将这些记录用于领域适应。
……
以下是一些输入和输出的实例,如图所示:
这个算法迅速学会了恒定函数,如图所示:
然后,其又学会了清除添加的干扰字符,如图所示:
替换错别字,如图所示:
校正移位字符,如图所示:
还有,重新添加缺失的字符,如图所示:
有些失误并不是错误,如图所示:
有些校正结果可能比原文更好,如图所示:
也有些错误甚至是通过算法引入的……如图所示:
……
这里的8行代码是该算法的核心。
这8行代码是由高端Keras代码和不纯粹的Python语言编写而成的。当然,这就像是苹果和橘子。
备忘录:
- 继续训练。
- 可能利用Spearmint来优化超参数。
- 在模型中添加“注意事项”。
- 添加更多的规则。
- 发布适用于Github的代码。
- 发布IPython Notebook安装包。
- 根据理论进行拓展。
- 适应其他领域——可能会在几个月前发布的Reddit语料库中进行尝试。
- 正如Stack Overflow answer网站上这个极好的提议所说的那样,试着从维基百科中摘录现实生活中的拼写错误。
- 利用混淆矩阵的平滑参数设置来产生干扰,比如来自对Church和Gale的拼写校正得分概率的干扰。
……
一位机器学习工程师的生活:
早上6:10——我手机恼人的闹钟声响起,起床时间到了,新的一天开始了。
但是,在我起床前,我通过向服务器发送SHH和Tmux A来查看最新的数值。当我发现程序有所改进时,每天早上就像过圣诞节一样开心。
> MemoryError(记忆错误)
该死!
作者观点:
- 这是一篇关于工程学的帖子和任务,讲述的是当前最先进的技术,并不是严格意义上的科学。这项技术的用处就是让低级工程师使用起来得心应手。
- 大家可能还对语言支持技术一头雾水,并没有意识到文中的任务中运用了输入语言的先验知识。其实,这个算法本来就应该适用于任何一种语言。
- 我在拼写校正干扰字符这方面取得了很好的成效,但是不能止步于此。我不明白为何你不继续进行诸如命名实体识别这样更高层次的任务,正如我最喜欢的论文之一中所阐述的自然语言处理基本都是从头开始的,只能利用干扰字符流作为输入,但最终都出奇般地让模型拥有了自动“处理”拼写错误的功能。
本文作者 Tal Weiss 是 OverOps 的联合创始人兼首席执行官。
本文由 AI100 编译,转载需得到本公众号同意。
编译:AI100
原文链接:https://medium.com/@majortal/deep-spelling-9ffef96a24f6