自然语言处理(NLP)是数据科学中最有趣的子领域之一,数据科学家越来越期望能够制定涉及利用非结构化文本数据的解决方案。尽管如此,许多应用数据科学家(来自STEM和社会科学背景)都缺乏NLP经验。
在这篇文章中,我将探讨一些基本的NLP概念,并展示如何使用Python中日益流行的spaCy包实现它们。这篇文章是针对绝对的NLP初学者,但是假设有Python的知识。
spaCy是由Matt Honnibal在Explosion AI开发的“工业强度NLP in Python”的相对较新的软件包。它的设计考虑了应用数据科学家的意义,这意味着它不会影响用户对用于常见任务的深奥算法的决策,而且速度快 - 速度极快 - 它在Cython中实现。如果您熟悉Python数据科学堆栈,那么spaCy就是您numpy
的NLP - 它相当低级但非常直观且高性能。
spaCy为任何NLP项目中常用的任务提供一站式服务,包括:
我将提供其中一些功能的高级概述,并展示如何使用spaCy访问它们。
首先,我们加载spaCy的管道,按照惯例,它存储在一个名为的变量中nlp
。声明此变量将需要几秒钟,因为spaCy会预先将模型和数据加载到其中,以便以后节省时间。实际上,这会使得早期的解决方案变得非常繁重,因此每次将nlp
解析器应用到数据时都不会产生成本。请注意,在这里,我使用的是英语语言模型,但也有一个功能齐全的德语模型,在多种语言中实现了标记化(如下所述)。
我们在示例文本上调用NLP来创建Doc
对象。该Doc
对象现在是文本本身的NLP任务的容器,文本(Span
对象)和文本的元素(Token
对象)的切片。值得注意的是Token
和Span
对象实际上没有数据。相反,它们包含指向Doc
对象中包含的数据的指针,并且被懒惰地评估(即根据请求)。spaCy的大部分核心功能是通过Doc
(n = 33),Span
(n = 29)和Token
(n = 78)对象上的方法访问的。
In[1]: import spacy
...: nlp = spacy.load("en")
...: doc = nlp("The big grey dog ate all of the chocolate,
but fortunately he wasn't sick!")
标记化是许多NLP任务的基础步骤。标记文本是将一段文本拆分为单词,符号,标点符号,空格和其他元素的过程,从而创建标记。一种天真的方法是简单地将字符串拆分为空格:
In[2]: doc.text.split()
...:
Out[2]:
['The',
'big',
'grey',
'dog',
'ate',
'all',
'of',
'the',
'chocolate,',
'but',
'fortunately',
'he',
"wasn't",
'sick!']
从表面上看,这看起来很好。但请注意,它忽略了标点符号,并且不会分割动词和副词(“是”,“不是”)。换句话说,它是天真的,它无法识别帮助我们(和机器)理解其结构和意义的文本元素。让我们看看spaCy如何处理这个问题:
In[3]: [token.orth_ for token in doc]
...:
Out[3]:
['The',
'big',
'grey',
'dog',
'ate',
'all',
'of',
'the',
'chocolate',
',',
'but',
'fortunately',
'he',
'was',
"n't",
' ',
'sick',
'!']
在这里,我们访问每个令牌的.orth_
方法,该方法返回令牌的字符串表示,而不是SpaCy令牌对象。这可能并不总是可取的,但值得注意。SpaCy识别标点符号,并能够从单词标记中分割出这些标点符号。许多SpaCy的令牌方法提供了已处理文本的字符串和整数表示:带有下划线后缀的方法返回字符串和没有下划线后缀的方法返回整数。例如:
In[4]: [(token, token.orth_, token.orth) for token in doc]
...:
Out[4]:
[(The, 'The', 517),
(big, 'big', 742),
(grey, 'grey', 4623),
(dog, 'dog', 1175),
(ate, 'ate', 3469),
(all, 'all', 516),
(of, 'of', 471),
(the, 'the', 466),
(chocolate, 'chocolate', 3593),
(,, ',', 416),
(but, 'but', 494),
(fortunately, 'fortunately', 15520),
(he, 'he', 514),
(was, 'was', 491),
(n't, "n't", 479),
( , ' ', 483),
(sick, 'sick', 1698),
(!, '!', 495)]
In[5]: [token.orth_ for token in doc if not token.is_punct | token.is_space]
...:
Out[5]:
['The',
'big',
'grey',
'dog',
'ate',
'all',
'of',
'the',
'chocolate',
'but',
'fortunately',
'he',
'was',
"n't",
'sick']
很酷,对吗?
标记化的相关任务是词形还原。词形还原是将单词缩减为基本形式的过程 - 如果你愿意的话,它的母语单词。单词的不同用法通常具有相同的根含义。例如,练习,练习和练习都基本上是指同一件事。通常希望标准化与其基本形式具有相似含义的单词。使用SpaCy,我们可以使用令牌的.lemma_
方法访问每个单词的基本表单:
In[6]: practice = "practice practiced practicing"
...: nlp_practice = nlp(practice)
...: [word.lemma_ for word in nlp_practice]
...:
Out[6]:
['practice', 'practice', 'practice']
为什么这有用?一个直接的用例是机器学习,特别是文本分类。例如,在创建“词袋”之前对文本进行词形避免可避免单词重复,因此,允许模型更清晰地描绘跨多个文档的单词使用模式。
词性标注是将语法属性(即名词,动词,副词,形容词等)分配给单词的过程。共享相同POS标签的单词往往遵循类似的句法结构,并且在基于规则的过程中很有用。
例如,在事件的给定描述中,我们可能希望确定谁拥有什么。通过利用所有格,我们可以做到这一点(提供文本在语法上是合理的!)。SpaCy使用流行的Penn Treebank POS标签(见这里)。使用SpaCy,您可以分别使用.pos_
和.tag_
方法访问粗粒度和细粒度POS标签。在这里,我访问细粒度的POS标签:
In[7]: doc2 = nlp("Conor's dog's toy was hidden under the man's sofa in the woman's house")
...: pos_tags = [(i, i.tag_) for i in doc2]
...: pos_tags
...:
Out[7]:
[(Conor, 'NNP'),
('s, 'POS'),
(dog, 'NN'),
('s, 'POS'),
(toy, 'NN'),
(was, 'VBD'),
(hidden, 'VBN'),
(under, 'IN'),
(the, 'DT'),
(man, 'NN'),
('s, 'POS'),
(sofa, 'NN'),
(in, 'IN'),
(the, 'DT'),
(woman, 'NN'),
('s, 'POS'),
(house, 'NN')]
我们可以看到's
令牌被标记为POS
。我们可以利用此标记来提取所有者及其拥有的东西:
In[8]: owners_possessions = []
...: for i in pos_tags:
...: if i[1] == "POS":
...: owner = i[0].nbor(-1)
...: possession = i[0].nbor(1)
...: owners_possessions.append((owner, possession))
...:
...: owners_possessions
...:
Out[8]:
[(Conor, dog), (dog, toy), (man, sofa), (woman, house)]
这将返回所有者拥有元组的列表。如果你想成为关于它的超级Pythonic,你可以在列表综合中做到这一点(我认为这是更好的!):
In[9]: [(i[0].nbor(-1), i[0].nbor(+1)) for i in pos_tags if i[1] == "POS"]
...:
Out[9]:
[(Conor, dog), (dog, toy), (man, sofa), (woman, house)]
在这里,我们使用每个令牌的.nbor
方法,该方法返回令牌的相邻令牌。
实体识别是将文本中找到的命名实体分类为预定义类别(如人员,地点,组织,日期等)的过程.scaCy使用统计模型对广泛的实体进行分类,包括人员,事件,艺术作品和国籍/宗教(参见完整清单的文件)。
例如,让我们从巴拉克奥巴马的维基百科条目中获取前两句话。我们将解析此文本,然后使用Doc
对象的.ents
方法访问标识的实体。通过调用Doc
方法,我们可以访问更多的Token
方法,特别是.label_
和.label
:
在 [ 10 ]:wiki_obama = “”“巴拉克奥巴马是一位美国政治家,曾担任过
您可以看到模型已识别的实体以及它们的准确程度(在本例中)。 PERSON
不言自明, NORP
是民族或宗教团体,GPE识别位置(城市,国家等), DATE
识别特定日期或日期范围,ORDINAL
识别代表某种类型的订单的单词或数字。
虽然我们讨论Doc
方法的主题,但值得一提的是spaCy的句子标识符。NLP任务想要将文档拆分成句子并不罕见。通过访问Doc's.sents
方法,使用SpaCy执行此操作非常简单:
In[11]: for ix, sent in enumerate(nlp_obama.sents, 1):
...: print("Sentence number {}: {}".format(ix, sent))
...:
Sentence number 1: Barack Obama is an American politician who served as
the 44th President of the United States from 2009 to 2017.
Sentence number 2: He is the first
African American to have served as president,
as well as the first born outside the contiguous United States.
就是这些了。在后面的文章中,我将展示如何在复杂的数据挖掘和ML任务中使用spaCy。
原文标题《NLP in Python》
译者:February
不代表云加社区观点,更多详情请查看原文链接
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。