Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

2.8 基于规则的词元化

尽管 BPE 等数据驱动方法是最常见的词元化方式,有时我们仍希望把词元限制为词,而不是子词。例如,在运行英语句法分析算法时,分析器可能需要以语法词作为输入;在某些语言学应用中,我们可能已经先验地定义了希望研究的词元;在社会科学应用中,正字法词也可能是有用的研究单位。

基于规则的词元化(rule-based tokenization)中,我们预先定义一套标准,再实现相应规则以获得这种词元划分。下面以英语词语词元化为例加以说明。

对英语而言,我们有若干期望。通常希望把标点分离成独立词元:逗号能为句法分析器提供有用信息,句点则有助于标记句子边界。不过,对于 m.p.h.、Ph.D.、AT&T 和 cap’n 等例子,往往又希望保留词内标点。价格($45.55)和日期(01/02/06)中的特殊字符与数字需要保留;我们不希望把这个价格拆成“45”和“55”两个独立词元。此外还有 URL(https://www.stanford.edu)、Twitter 话题标签(#nlproc)和电子邮件地址(someone@cs.colorado.edu)。

数值表达式会带来更多复杂问题。在英语中,逗号除了出现在词边界以外,还会每隔三位出现在数字内部,例如 555,500.50。不同语言的词元化方式不同:西班牙语、法语和德语等语言使用逗号标记小数点,并在英语使用逗号的位置使用空格(有时也使用句点),例如 555 500,50。

基于规则的词元化器还可以展开由撇号标记的附着词缩约形式,把 what’re 转换成 what 和 are 两个词元,把 we’re 转换成 we 和 are。附着词是不能独立存在、只能附着于另一个词的词语组成部分。其他使用字母文字的语言也有这种缩约形式,例如法语代词 j’ai 和冠词 l’homme。

根据应用需要,词元化算法也可能把 New York 或 rock ’n’ roll 等多词表达式(multiword expression)作为单个词元;这要求使用某种多词表达式词典。因此,基于规则的词元化与命名实体识别(named entity recognition)密切相关;后者是检测名称、日期和组织的任务(第 18 章)。

一种常用的词元化标准称为 Penn Treebank 词元化标准(Penn Treebank tokenization standard)。语言数据联盟(Linguistic Data Consortium,LDC)发布的句法分析语料库(树库)采用该标准,而 LDC 是许多实用数据集的来源。这套标准会分离附着词(例如把 doesn’t 拆成 does 和 n’t),保留带连字符的词,并分离所有标点。为节省空间,下面使用可见空格“ ”表示词元间隔,尽管更常见的输出方式是每个词元占一行:

输入:“The San Francisco-based restaurant,” they said,

“doesn’t charge $10”.

输出:" The San Francisco-based restaurant , " they said ,

" does n’t charge $ 10 " .

实践中,词元化在其他所有语言处理步骤之前运行,因此速度必须非常快。基于规则的词语词元化通常使用确定性算法,这些算法以编译成高效有限状态自动机的正则表达式为基础。例如,图 2.16 展示了一个基本正则表达式,可以配合基于 Python 的自然语言工具包 NLTK 中的 nltk.regexp_tokenize 函数对英语进行词元化(Bird et al., 2009; https://www.nltk.org)。

>>> text = 'That U.S.A. poster-print costs $12.40...'
>>> pattern = r'''(?x)    # 设置标志,允许详细正则表达式
...    (?:[A-Z]\.)+    # 缩写,例如 U.S.A.
...    | \w+(?:-\w+)*    # 可以包含词内连字符的词
...    | \$?\d+(?:\.\d+)?%?    # 货币、百分数,例如 $12.40、82%
...    | \.\.\.    # 省略号
...    | [][.,;"?():_-']    # 独立词元,包括 ] 和 [
...    '''
>>> nltk.regexp_tokenize(text, pattern)
['That', 'U.S.A.', 'poster-print', 'costs', '$12.40', '...']

图 2.16 基于 Python 的 NLTK 自然语言处理工具包中,使用正则表达式进行词元化的 Python 运行记录(Bird et al., 2009)。为方便阅读,图中加入了注释;(?x) 详细模式标志会让 Python 去除注释和空白。图片来自 Bird et al.(2009)第 3 章。

精心设计的确定性算法可以处理各种歧义。例如,撇号作为所有格标记(the book’s cover)、引语标记(‘The other class’, she said)或 they’re 等附着词的一部分时,需要采用不同的词元化方式。

2.8.1 句子切分

基于规则的切分还常用于另一类词元化单位:句子。句子切分(sentence segmentation)是文本处理中一个可以选择应用的步骤;在把 NLP 算法用于检测句法分析结构等结构性任务时,它尤其重要。

句子切分取决于语言和体裁。在英语书面文本中,把文本切分成句子时最有用的线索通常是句点、问号和感叹号等标点。问号和感叹号作为句子边界标记的歧义较小,它们出现时,简单规则就能切分句子。

相比之下,句点字符“.”既可能标记句子边界,也可能标记 Dr. 或 Inc. 等缩写,因而存在歧义。你刚刚读到的上一句还展示了一种更复杂的歧义:Inc. 最后的句点同时标记缩写和句子边界。因此,句子词元化和词语词元化可以联合处理。

许多英语句子词元化方法会首先判断句点究竟属于词的一部分,还是句子边界标记;这种判断通常依据确定性规则,有时也使用机器学习。缩写词典可以帮助判断句点是否属于常用缩写;词典可以手工构建,也可以通过机器学习获得(Kiss and Strunk, 2006),最终的句子切分器同样如此。例如,在 Stanford CoreNLP 工具包(Manning et al., 2014)中,句子切分以规则为基础,是词元化的确定性结果:如果一个句末标点(.!?)没有与其他字符组合成一个词元(例如缩写或数字),它就标志句子结束;其后还可以跟有额外的闭合引号或括号。