Speech and Language Processing: An introduction to Natural Language Processing, Computational Linguistic, and Speech Recognition. Chapter 2
前言: 早期的自然语言处理工具ELIZA采用的方法是pattern matching. 而对于文本模式(text pattern)的描述,有一个很重要的工具:正则表达式(regular expression).
对文本处理任务的统称,就是文本标准化(text normalization)。其中有:
- tokenizing: 分词?
- lemmatization: 词形还原。 确定表面不一样的词是否是同一个词根,针对时态比较复杂的语言非常必要。
- stemming:词干提取。 针对前缀后缀,一种简单的lemmatization
- sentence segmantation: 句子分割. 用时态或者标点符号
最后提到编辑距离(edit distance):一种算法,在自然语言处理和语音识别中都很常用。
正则表达式 regular expression
- 用斜线(slashes)来分隔正则表达式,斜线不是正则表达式的一部分。
正则表达式的区分大小写的,可以用方括号(square braces)来解决这个问题。
- 对所有的数字(digits)可以用/[1234567890]/,但对于所有的字母这样就不太方便了,可用连字符(dash)(-)来表示一个范围(range).
- 脱字符(caret)(^)
用脱字符表示否定,或者仅仅表示它自身。放在方括号的第一个位置时才有效。
- 用问号?表示前一个字符是可选的。
问号除了表示可选外,还有贪婪和非贪婪的区别。/.* ?/ 和 /.* /
用 * 表示前一个字符的零个或多个;用 + 表示前一个字符的一个或多个
举个栗子:baa!(至少两个a)
baaa!
baaaaaa!
用 /baaa*/ 或 /baa+/ 可匹配上面这种形式。
单位数的价格可用 /[0-9]/,一个整数(字符串)的正则表达式:/[0-9][0-9]* / 或者 /[0-9]+/
- 通配符(wildcard) /./
/./表示匹配任何字符,那么和星号一起使用,就可以表示任何字符串了。/.* /
锚号(anchor)是一种把正则表达式锚在字符串中的特定位置,最普通的锚号是脱字符^和美元符$.
- 脱字符 ^ 与行的开始相匹配。/^ The/ 表示单词只出现在一行的开始,这样脱字符就有三种用法了。
- 美元符 $ 表示一行的结尾./^ The dog\\.\$/表示这一行只有The dog. 其中点号前面必须加反斜杠,因为我们要让它表示点号,而不是通配符。
还有两个锚号: \b表示词界, \B表示非词界
非数字、下划线或字母,可以看做词界。
Disjunction,Grouping, and Precedence 析取,组合和优先关系
析取算符(Disjunction operator)(|),正则表达式 /cat|dog/ 表示字符串是dog或者cat,对于后缀guppy和guppies,可以写作 /gupp(y|ies)/
圆括号算符“()”.我们知道 * 只能表示前一个字符的重复,但如果要重复一个字符串呢,那就得用括号了。比如 /(column [0-9]+_*)*/ 就表示column后面跟一个数字和任意数目空格的重复~
运算符的优先级
正式因为 * 的优先级高于序列,所以 /the* / 表示与theeeee匹配,而不是与thethe匹配。
还有正则表达式的匹配是贪心的(greedy).比如 /[a-z]* / 可以匹配零个或多个字母,所以结果是尽可能长的符号串。
怎么让它不贪心呢(non-greedy)? 可以这么写 /[a-z]* ?/ 或 /[a-z]+?/会匹配尽可能少的符号串。
一个简单的栗子
要用正则表达式找到the
/the/
并不能找到the位于句子开头的情况The
/[tT]he/
当the嵌入在其他单词之间时theology,也是不对的
/\b[tT]he\b/
加入词界后也不包括the_或者the25了,但如果我们也想找到这种情况中的the呢?那就说明,在the两侧不能出现字母。
/[\^a-zA-Z][tT]he[\^a-zA-Z]/
这样仍然有问题,这意味着前面必须有个非字母符。所以应该这样:
/(^|[\^a-zA-Z])[tT]he[\^a-zA-Z]/
更多算符
通用字符集的别名(aliases)
用于计数符的算符
需要加反斜杠的特殊算符
正则表达式中的替换(substitution)、存储器(capture group)和ELIZA
s/regexp1/regexp2/ 表示用第二个正则表达式替换第一个的内容
s/colour/color/
s/([0-9]+)/<\1>/ 其中 \1表示参照第一个模式中的内容,也就是括号的内容,然后加上<>后对它进行替换。实际上就是找到这样的,加上<>
/the (.* )er they were, the \1er they will be/
可以匹配 The bigger they were, the bigger they will be 但不能匹配 bigger they were, the faster they will be.
括号中用于存储的模式叫做 capture group,而用于存储的数字存储器叫做 寄存器(register).
这样一来圆括号就有了两种含义了,可以用来优先级的运算符,也可以用来capture group. 所以必须加以区别,用 ?: 来表示 non-capturing group. (?: pattern )
举个栗子:
- /(?:some|a few) (people|cats) like some \1/
可以用来匹配 some cats like some people,而不能匹配 some people like some a few. 因为\1 表示的是(people|cats)这个括号中的内容。
ELIZA:
这可真是“人工”智能啊。。。hahha
Lookahead assertions
最后,有时候我们需要预测未来look ahead:在文本中向前看,看看有些模式是否匹配,但不会推进匹配游标(match cursor),以便我们可以处理模式。 不推进匹配游标是什么意思?
lookahead assertions 使用(?=pattern)和(?!pattern).
The operator (?= pattern) is true if pattern occurs, but is zero-width.
负向预测:
/(ˆ?!Volcano)[A-Za-z]+/ 表示
这个不太理解,到regex.com上试了下:
Words and Corpora
在我们对word进行处理时,我们需要确定怎么样才算一个word.
语料库:
written texts from different genres (newspaper, fiction, non-fiction