spaCy文档-02:新手入门

语言特征

注意以下代码示例都需要导入spacy

import spacy
nlp = spacy.load('en')
#导入模型库

使用 spaCy提取语言特征,比如说词性标签,语义依赖标签,命名实体,定制tokenizer并与基于规则的matcher一起工作。

处理原始文本是很困难的:大多数单词都是很少见的,而对于有些看起来完全不同的单词来说,它们的意思可能是一样的。相同的词在不同的顺序可以意味着完全不同的东西。在很多语言中将文本分割成类单词单元都是困难的。虽然从原始字符开始解决一些问题是可能的,但是最好使用语言知识来添加有用的信息。这正是spaCy的设计目的:您输入原始文本,然后返回一个Doc对象,它带有各种注释。

词性标注(PoS)

在标记化之后,spaCy可以解析和标记给定的Doc。这就是统计模型出现的地方,它使得spaCy能够预测在这个上下文中最有可能应用的标签或标签。一个模型由二进制数据组成,它通过显示一个系统足够的例子来进行预测,从而在整个语言中进行预测——例如,在英语中“the”后面的单词最有可能是名词。

语言标注可以作为Token的属性,与许多NLP库一样,spaCy将所有字符串编码为散列值,以减少内存使用量并提高效率。为了获得属性的可读字符串表示,我们需要在其名称中添加一个_:

doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion')

for token in doc:
    print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
          token.shape_, token.is_alpha, token.is_stop)
TEXT LEMMA POS TAG DEP SHAPE ALPHA STOP
Apple apple PROPN NNP nsubj Xxxxx True False
is be VERB VBZ aux xx True True
at at ADP IN prep xx True True

使用spaCy's的内建可视化工具,还可以看到示例中的依存句法结构(这里不添加附图啦)

依存句法分析(Dependency parsing)

spaCy具有快速和准确的语法依赖解析器,并且有一个用于构建句法树的强大API。解析器有检测句子边界的强大能力,并允许您遍历基本名词短语或“块”。您可以检查Doc对象是否已经被is_parsed属性解析了,它(is_parsed)返回一个布尔值。如果此属性为False,则默认语句迭代器将引发异常。

名词块(Noun chunks)

名词块是“基本名词短语”——用名词作头部的扁平短语。你可以把名词块当作名词,再加上描述名词的词,例如“奢侈的绿草”或“世界上最大的科技基金”。要获取文档中的名词块,只需遍历Doc.noun_chunks。

nlp = spacy.load('en')
doc = nlp(u'Autonomous cars shift insurance liability toward manufacturers')
for chunk in doc.noun_chunks:
    print(chunk.text, chunk.root.text, chunk.root.dep_,
          chunk.root.head.text)

tips

text:原始的名词块文本
root text:名词的块的核心部分(见example)


QQ20180117-230252.png

命名实体识别(NER)

一个被命名的实体是一个“现实世界的对象”,它被赋予一个名字——例如,一个人,一个国家,一个产品或者一个书名。spaCy可以通过询问模型来识别文档中的各种类型的命名实体。因为模型是统计的,并且非常依赖于他们所接受的示例,所以这并不总是完美的,并且可能需要稍后进行一些调整,这取决于您的用例。

命名实体可以doc的ents中获取

doc = nlp(u'Apple is looking at buying U.K. startup for $1 billion')

for ent in doc.ents:
    print(ent.text, ent.start_char, ent.end_char, ent.label_)
1.png

运用可视化工具可以看到如下效果:


2.png

规则匹配

spaCy有一个规则匹配引擎,即Matcher,它通过token进行操作,类似于正则表达式。规则可以参考token注释(例如,token文本或标记,以及标记(例如IS_PUNCT)。规则matcher还允许您通过自定义回调来执行匹配操作——例如,合并实体并应用自定义标签。您还可以将模式与实体id关联起来,以允许一些基本的实体链接或消除歧义。为了匹配大型术语表,可以使用PhraseMatcher,它接受Doc对象作为匹配模式。

添加模型(adding patterns)

假设我们想找到由以下三个token组成的字段:
1、以小写形式匹配‘hello’,例如:‘Hello’,‘HELLO’
2、is_punct 标签为真的token,例如:任何标点
3、以小写形式匹配‘world’,例如:‘World’,‘WORLD’

[{'LOWER': 'hello'}, {'IS_PUNCT': True}, {'LOWER': 'world'}]

首先,我们用vocab初始化Matcher。matcher必须始终与它将操作的文档共享同一个vocab。我们现在可以调用matcher.add()和一个ID和我们的定制模式。第二个参数允许您传递一个可选的回调函数,以调用成功的匹配。现在,我们将它设置为None。

import spacy
from spacy.matcher import Matcher

nlp = spacy.load('en')
matcher = Matcher(nlp.vocab)
# add match ID "HelloWorld" with no callback and one pattern
pattern = [{'LOWER': 'hello'}, {'IS_PUNCT': True}, {'LOWER': 'world'}]
matcher.add('HelloWorld', None, pattern)
#这里的“helloworld”可以理解为一种代号,和索引,可以取其他任何名字
doc = nlp(u'Hello, world! Hello world!')
matches = matcher(doc)

matcher返回一个(match_id, start, end)元组列表——在本例中,[(HelloWorld', 0,2)],映射到我们原始文档的span doc[0:2]。我们还可以选择添加多个模式,例如在“hello”和“world”之间不加标点的匹配序列。

matcher.add('HelloWorld', None,
            [{'LOWER': 'hello'}, {'IS_PUNCT': True}, {'LOWER': 'world'}],
            [{'LOWER': 'hello'}, {'LOWER': 'world'}])

默认情况下,matcher只会返回匹配项,而不会执行其他操作,比如合并实体或分配标签。这一切都取决于您,可以为每个模式单独定义,通过传入一个回调函数作为add()的on_match参数。这是有用的,因为它允许您编写完全自定义和模式特定的逻辑。例如,您可能希望将一些模式合并到一个令牌中,同时为其他模式类型添加实体标签。您不应该为每个流程创建不同的匹配器。

可获取的token属性

attribute description
ORTH token精确的文本
LOWER, UPPER token文本的大小写形式
IS_ALPHA, IS_ASCII, IS_DIGIT token文本由字母数字字符、ASCII字符、数字组成
IS_LOWER, IS_UPPER, IS_TITLE token文本为大写,小写,标题格式
IS_PUNCT, IS_SPACE, IS_STOP token文本是标点,空白,停用词
LIKE_NUM, LIKE_URL, LIKE_EMAIL token文本类似于数字,网址,邮件地址
POS, TAG, DEP, LEMMA, SHAPE token文本的词性之类的……

可获取的pattern就是大写的token属性,和匹配相关的大部分属性如下:

attribute description
ORTH token精确的文本
LOWER, UPPER token文本的大小写形式
IS_ALPHA, IS_ASCII, IS_DIGIT token文本由字母数字字符、ASCII字符、数字组成
IS_LOWER, IS_UPPER, IS_TITLE token文本为大写,小写,标题格式
IS_PUNCT, IS_SPACE, IS_STOP token文本是标点,空白,停用词
LIKE_NUM, LIKE_URL, LIKE_EMAIL token文本类似于数字,网址,邮件地址
POS, TAG, DEP, LEMMA, SHAPE token文本的词性之类的……

使用通配符token样式

虽然token属性提供了许多选项来编写高度特定的模式,但您也可以使用空的字典({})作为表示任何标记的通配符。如果你知道你想要匹配的内容的上下文,但是对于特定的token和它的字符非常少,那么通配符就显得很有用了。例如,假设您试图从数据中提取用户的用户名。您只知道它们被列为“用户名:{用户名}”。名称本身可能包含任何字符,但没有空格——因此您将知道它将作为一个token处理。

[{'ORTH': 'User'}, {'ORTH': 'name'}, {'ORTH': ':'}, {}]

使用类似正则表达式一样的通配符号

待补充

添加短语样式

如果您需要匹配大型术语表,您还可以使用PhraseMatcher并创建Doc对象,而不是token模式,这在总体上更有效。Doc模式可以包含单个或多个token。

import spacy
from spacy.matcher import PhraseMatcher

nlp = spacy.load('en')
matcher = PhraseMatcher(nlp.vocab)
terminology_list = ['Barack Obama', 'Angela Merkel', 'Washington, D.C.']
patterns = [nlp(text) for text in terminology_list]
matcher.add('TerminologyList', None, *patterns)

doc = nlp(u"German Chancellor Angela Merkel and US President Barack Obama "
          u"converse in the Oval Office inside the White House in Washington, D.C.")
matches = matcher(doc)

由于spaCy用于处理模式和匹配的文本,因此您不必担心特定的标记化——例如,您可以简单地通过nlp(u“Washington, D.C.”),而不必编写一个复杂的token模式来覆盖术语的确切标记。

添加on-match规则

为了实现一个更现实的例子,假设您正在处理大量的博客文章,您想要匹配所有提到的"Google I/O"(spaCy将其标记为['Google', 'I', '/', 'O'])。为了安全起见,您只匹配大写版本,以防有人将其写成"Google i/o"。您还添加了一个附加的{IS_DIGIT: True}标记的第二个模式——这将确保您也匹配"Google I/O 2017"。如果您的模式匹配,spaCy应该执行您的自定义回调函数add_event_ent。

import spacy
from spacy.matcher import Matcher

nlp = spacy.load('en')
matcher = Matcher(nlp.vocab)

# Get the ID of the 'EVENT' entity type. This is required to set an entity.
EVENT = nlp.vocab.strings['EVENT']

def add_event_ent(matcher, doc, i, matches):
    # Get the current match and create tuple of entity label, start and end.
    # Append entity to the doc's entity. (Don't overwrite doc.ents!)
    match_id, start, end = matches[i]
    doc.ents += ((EVENT, start, end),)

matcher.add('GoogleIO', add_event_ent,
            [{'ORTH': 'Google'}, {'UPPER': 'I'}, {'ORTH': '/'}, {'UPPER': 'O'}],
            [{'ORTH': 'Google'}, {'UPPER': 'I'}, {'ORTH': '/'}, {'UPPER': 'O'}, {'IS_DIGIT': True}])

除了提到“谷歌I/O”之外,你的数据还包含一些恼人的预处理程序,比如剩下的HTML行中断(例如: <br>或<br />)。当您在它的时候,您希望将它们合并到一个标记中并标记它们,以确保您稍后可以轻松地忽略它们。因此,添加第二个模式并传入函数merge_and_flag:

BAD_HTML_FLAG = nlp.vocab.add_flag(lambda text: False)

def merge_and_flag(matcher, doc, i, matches):
    match_id, start, end = matches[i]
    span = doc[start : end]
    span.merge(is_stop=True) # merge (and mark it as a stop word, just in case)
    span.set_flag(BAD_HTML_FLAG, True) # set BAD_HTML_FLAG

matcher.add('BAD_HTML', merge_and_flag,
            [{'ORTH': '<'}, {'LOWER': 'br'}, {'ORTH': '>'}],
            [{'ORTH': '<'}, {'LOWER': 'br/'}, {'ORTH': '>'}])

我们现在可以在文档上调用matcher。模式将按照它们在文本中出现的顺序进行匹配。然后,matcher将迭代匹配,查找匹配的匹配ID的回调,并调用它。

doc = nlp(LOTS_OF_TEXT)
matcher(doc)

当调用回调时,它会传递四个参数:matcher本身、文档、当前匹配的位置和匹配的总列表。这让您可以编写回调函数来考虑所有匹配的短语,这样您就可以以您喜欢的方式解决重叠和其他冲突。

正则表达式

待补充

例子-01

假设你正在分析用户评论,你想知道人们对Facebook的看法。你想从“脸书”或“脸书”这样的形容词入手。这显然是一个非常简单的解决方案,但是它会很快,而且很好地理解了数据中的内容。你的模式可能是这样的:

[{'LOWER': 'facebook'}, {'LEMMA': 'be'}, {'POS': 'ADV', 'OP': '*'}, {'POS': 'ADJ'}]

这就转化为一个标记,它的小写形式与“facebook”(如facebook、facebook或facebook)相匹配,然后是一个带有引理“be”(例如,是,或者是)的标记,后面跟着一个可选的副词,后面跟着一个形容词。使用这里的语言注释特别有用,因为你可以告诉spaCy匹配“Facebook的烦人”,而不是“Facebook烦人的广告”。可选的副词确保你不会漏掉形容词,比如“pretty awful”或“very nice”。
为了快速了解结果,您可以收集包含匹配的所有句子,并使用displaCy可视化工具呈现它们。在回调函数中,您将访问每个匹配的开始和结束,以及父文档。这让您可以确定包含匹配的语句,doc[start: end]。发送,并计算在句子中匹配跨度的开始和结束。在“手动”模式中使用displaCy可以让您传入包含文本和实体的字典列表。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335