自然语言处理(NLP)(*Natural language processing)也称自然语音理解(natural language understanding NLU),从人工智能研究的一开始,它就作为这一学科的重要研究内容探索人类理解自然语言这一智能行为的基本方法。在最近二三十年中,随着计算机技术,特别是网络技术的迅速发展和普及,自然语言处理研究得到了前所未有的重视和长足的进展,并逐渐发展成为一门相对独立的学科,备受关注。
NLP用计算机技术和概念来理解语言学和语音学,已经开发的领域包括自然语言处理、语音合成、言语识别、自动翻译、信息提取,机器翻译,情感分析,问题回答和自动摘要。通过使用计算方法来理解人类语言的属性。我们如何理解语言?我们如何制作语言?我们如何学习语言?语言之间有什么关系?
NLP一些问题已经发展成了自己的学科,如音韵学(phonology),形态学(morphology),语法(syntax),语义学(semantics)和语用学(pragmatics)。
在我们完全投入NLP的神经网络方法之前值得回顾一些传统的NLP概念和方法。这是本章的目标。
如果你有一些NLP的背景知识,你可以跳过这一章。
1 语料库,分词和类型
所有经典或现代的NLP方法,都从文本数据集开始,也称为语料库(corpus 复数:语料库)。语料库就是存放语言材料的数据库。通常是原始文本(ASCII或UTF-8)以及与文本相关联的任何元数据。原始文本是一系列字符(字节),但大多数情况下将字符分组为称为标记的连续单元很有用。在英语中,分词依据空格字符或标点符号分隔的单词和数字序列。
元数据可以是与文本相关联的任何辅助信息,例如标识符,标签和时间戳。在机器学习术语中,文本及其元数据称为实例或数据点。语料库(图2-1)是一组实例,也称为数据集。鉴于本书重点关注机器学习,我们可以自由地交换术语语料库和数据集。
将文本标记的过程称为分词。在实例语句中,“ Maria frapis la verda sorĉistino
,有六个token。分词可能比简单地基于非字母数字字符分割文本更复杂,如图2-2所示。对于像土耳其语这样的语言,存在白色空格和标点符号。其他更专业的技术在第4和第6章中将介绍。
最后,请考虑以下推文:
分词推文涉及保留主题标签和@handles,将表情符号
:-)
和URL 等分割为一个单元。标签#MakeAMovieCold应该是一个分词还是4个单词?尽管大多数研究论文都没有对这个问题给予太多关注,事实上,许多分词决策往往是随意的,但这些决策在实践中的准确性会比公认的更大。这就是预处理的繁重工作,幸运的是大多数开源NLP包为分词提供了合理的支持,以帮助您入门。例2-1显示了来自NLTK和SpaCy的示例,这两个常用的文本处理包。Example 2-1. 文本分词
import spacy
nlp = spacy.load(‘en’)
text = “Mary, don’t slap the green witch”
print([str(token) for token in nlp(text.lower())])
from nltk.tokenize import TweetTokenizer
tweet=u"Snow White and the Seven Degrees
#MakeAMovieCold@midnight:-)"
tokenizer = TweetTokenizer()
print(tokenizer.tokenize(tweet.lower()))
类型是语料库中存在的唯一令牌。语料库中所有类型的集合是其词汇或词汇。可以在内容词和停用词之间区分单词。诸如文章和介词之类的替代词主要用于语法目的,就像持有内容词的填充者一样。
1.1 Unigrams, Bigrams, Trigrams, …, Ngrams
Ngrams是文本中出现的固定长度(n)连续标记序列。一个二元组有两个令牌,一个是unigram。从文本生成ngrams非常简单,如例2-2所示,SpaCy和NLTK这样的包提供了更方便的方法。
def n_grams(text, n):
return [text[i:i+n] for i in range(len(text)-n+1)]
cleaned = ['many','not','slap','green', 'witch']
print(n_grams(cleaned, 3))
[['many', 'not', 'slap'], ['not', 'slap', 'green'], ['slap', 'green', 'witch']]
对于子字信息本身携带有用信息的某些情况,可能想要生成字符ngram。例如,“甲醇”中的后缀“-ol”表示它是一种醇; 如果您的任务涉及对有机化合物名称进行分类,您可以看到ngrams捕获的子词信息如何有用。在这种情况下,您可以重复使用相同的代码,除了将每个字符ngram视为一个标记。
2 Lemmas和Stems
词汇是词语的根形式。考虑动词fly
。它可以活用成许多不同的words- flow
,flew
,flies
,flown
,flowing
,等和fly是看似不同的词。有时,将它们表示一个词,这样向量表示的维度较低。这种缩减称为词形还原,您可以在示例2-3中看到它的实际效果。
import spacy
nlp = spacy.load(‘en’)
doc = nlp(u"he was running late")
for token in doc:
print('{} --> {}'.format(token, token.lemma_))
例如,SpaCy使用称为WordNet的预定义字典来提取单词,但是词形还原可以被构造为需要理解语言形态的机器学习问题。词干是词形还原。它涉及使用手工制作的规则来删除单词的结尾,以将它们缩减为称为词干的常见形式。通常在开源软件包中实现的流行词干分析器是Porter的Stemmer和Snowball Stemmer。你可以自己查找适合的SpaCy / NLTK API来执行词干提取操作。
3 中文分词
3.1 jieba分词
jieba是一个不错的中文分词库,支持三种分词模式:精确模式、
全模式,搜索引擎模式。是处理中文的不错选择
# encoding=utf-8
import jieba
seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list)) # 全模式
seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list)) # 精确模式
seg_list = jieba.cut("他来到了网易杭研大厦") # 默认是精确模式
print(", ".join(seg_list))
seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造") # 搜索引擎模式
print(", ".join(seg_list))
3.2 pkuseg
pkuseg是由北京大学语言计算与机器学习研究组研制退出的一套全新的中文分词工具包,它简单易用、支持多领域分词、在不同领域的数据上都大幅提高了分词的精度,但是分词速度比较慢,而且还有小bug,所以尝鲜的可以试用。
import pkuseg
seg = pkuseg.pkuseg()
text = seg.cut('我爱北京天安门')
print(text)
import pkuseg
lexicon = ['北京大学','北京天安门']
seg = pkuseg.pkuseg(user_dict=lexicon)
text = seg.cut('我爱北京天安门')
print(text)
4 对句子和文件进行分类
对文档进行分类或分类可能是NLP最早的应用之一。我们在第1章中描述的表示(Term-Frequency [TF]和Term-Frequency-Inverse-Document-Frequency [TF-IDF])可以立即用于对文本或句子等较长的文本块进行分类和分类。诸如分配主题标签,预测评论情绪,过滤垃圾邮件,语言识别和电子邮件分类等问题可以被视为监督文档分类问题。(半监督版本,其中只使用了一个小的标记数据集,非常有用,但超出了本书的范围。)
5 分类单词:POS标记
我们可以将标签的概念从文档扩展到单个单词或标记。分类单词的一个常见例子是词性标注,如例2-4所示。
import spacy
nlp = spacy.load(‘en’)
doc = nlp(u"Mary slapped the green witch.")
for token in doc:
print('{} - {}'.format(token, token.pos_))
Mary - PROPN
slapped - VERB
the - DET
green - ADJ
witch - NOUN
. - PUNCT
6 分类跨度:分块和命名实体识别
通常,我们需要标记一段文字; 也就是说,一个连续的多语边界。例如,考虑句子“ Mary slapped the green witch。”我们可能想要识别其中的名词短语(NP)和动词短语(VP),如下所示:
这称为Chunking或* Shallow Parse*。 Shallow Parsi旨在导出由诸如名词,动词,形容词等语法原子组成的高阶单元。如果您没有数据来训练 Shallow Parsi解析模型,则可以在词性标记上编写正则表达式来近似 Shallow Parse。幸运的是,对于英语和最广泛使用的语言,存在这样的数据和预训练模型。例2-5给出了使用SpaCy进行 Shallow Parse的示例。
import spacy
nlp = spacy.load(‘en’)
doc = nlp(u"Mary slapped the green witch.")
for chunk in doc.noun_chunks:
print '{} - {}'.format(chunk, chunk.label_)
Mary - NP
the green witch - NP
另一种有用的是命名实体。命名实体是一个字符串提及现实世界的概念,如人,地点,组织,药物名称等。这是一个例子:
7 句子结构
浅层解析识别短语单元,识别它们之间关系的任务称为解析。你可能还记得,从小学英语课,图表句子,如图2-6所示。
解析树表示句子中不同语法单位的层次关系。图2-6中的解析树显示了所谓的组成解析。显示关系的另一种可能更有用的方法是使用依赖解析,如图2-7所示。
8 词语感和语义学
词语有意义,通常不止一个。一个词的不同含义称为它的语感。WordNet是普林斯顿大学长期运行的词汇资源项目之一,其目的是将所有单词(嗯,大多数)的英语语言感知与其他词汇关系一起记录下来。例如,考虑像“平面”这样的词。图2-8显示了可以使用“平面”一词的不同含义。
即使在现代方法的存在下,像WordNet这样的项目几十年的努力值得自己利用。本书后面的章节介绍了在神经网络和深度学习方法的背景下使用现有语言资源的例子。词义也可以从语境中诱导出来。从文本中自动发现单词感觉实际上是第一个将半监督学习应用于NLP的地方。尽管我们在本书中没有涉及到这一点,但我们鼓励您阅读Jurasky和Martin(2014),第17章,以及Manning和Schutze(1999),第7章。
摘要
在本章中,我们回顾了NLP中的一些基本术语和想法,这些术语和想法在以后的章节中应该会很方便。本章仅涉及传统NLP所提供的一些内容。我们省略了传统NLP的重要方面,因为我们希望将本书的大部分内容分配给NLP的深度学习。然而,重要的是要知道有大量的NLP研究工作不使用神经网络,并且具有很强的影响力(即广泛用于生产系统)。在许多情况下,应该考虑基于神经网络的方法作为补充而不是传统方法的替代。经验丰富的从业者经常利用两全其美的优势来构建最先进的系统。