使用spaCy Matcher无法正常工作的简单示例

时间:2017-11-30 21:05:04

标签: spacy

我正在尝试使用spaCy Matcher工作来获得以下简单示例:

import en_core_web_sm
from spacy.matcher import Matcher

nlp = en_core_web_sm.load()
matcher = Matcher(nlp.vocab)

pattern1 = [{'IS_DIGIT': True}, {'ORTH': '.'}, {'IS_DIGIT': True}, {'ORTH': '.'}, {'IS_DIGIT': True}, {'ORTH': '.'}, {'IS_DIGIT': True}]
pattern2 = [{'LIKE_NUM': True}, {'ORTH': '.'}, {'LIKE_NUM': True}, {'ORTH': '.'}, {'LIKE_NUM': True}, {'ORTH': '.'}, {'LIKE_NUM': True}]
pattern3 = [{'IS_DIGIT': True}, {'IS_PUNCT': True}, {'IS_DIGIT': True}, {'IS_PUNCT': True}, {'IS_DIGIT': True}, {'IS_PUNCT': True}, {'IS_DIGIT': True}]

matcher.add('IP', None, pattern1, pattern2, pattern3)

doc = nlp(u'This is an IP address: 192.168.1.1')

matches = matcher(doc)

但是,没有一个模式匹配,此代码返回[] matches。 spaCy示例代码中提供的简单“Hello World”示例工作正常。

我做错了什么?

1 个答案:

答案 0 :(得分:2)

使用Matcher时,请记住模式中的每个字典代表一个单独的标记。这也意味着它找到的匹配取决于spaCy如何标记您的文本。默认情况下,spaCy的英语标记器会将您的示例文本拆分为:

>>> doc = nlp("This is an IP address: 192.168.1.1")
>>> [t.text for t in doc]
['This', 'is', 'an', 'IP', 'address', ':', '192.168.1.1']

192.168.1.1保留一个令牌(客观上,这可能是非常合理的 - 一个IP地址可以被认为是一个单词)。因此,期望其部分为单独令牌的匹配模式将不匹配。

为了改变这种行为,您可以customise the tokenizer使用额外的规则告诉spaCy在数字之间分割句点。但是,这也可能产生其他意外的副作用。

因此,在您的情况下,更好的方法是使用令牌形状,可用作token.shape_属性。形状是令牌的字符串表示形式,用于描述各个字符,以及它们是否包含数字,大写/小写字符和标点符号。 IP地址形状如下所示:

>>> ip_address = doc[6]
>>> ip_address.shape_
'ddd.ddd.d.d'

您可以只过滤文档并检查token.shape_ == 'ddd.ddd.d.d',或使用'SHAPE'作为匹配模式中的键(对于单个标记)来查找包含该形状标记的句子或短语