我正在尝试将 EntityRuler 管道添加到现有的统计 NER 模型中,以更好地处理更结构化的实体类型,例如数字、年龄和金钱。
然而,其中一些数字模式可能非常相似或彼此有显着重叠,特别是当我们混合了一般模式和更具体的模式时。我面临的问题的一个例子如下:
{"label": "NUMBER", "pattern": [{"LIKE_NUM": true}]}
{"label": "AGE", "pattern": {"TEXT": {"REGEX": "^(1[0-4]|[1-9])?[0-9]$"}}]}
我有一个相当通用的模式,它简单地使用
LIKE_NUM
标记属性来标记通用 NUMBER
实体;另一个更具体的模式使用正则表达式将 0 到 149 的数字匹配为实体类型 AGE
。当我传入句子 I am 20
时,我希望 EntityRuler 在转向更一般的模式之前首先检查更具体的模式,这样在这种情况下它会返回 AGE
作为标签,而不是将其标记为通用NUMBER
。
我尝试重新排列
patterns.jsonl
文件中模式的顺序,以测试将模式添加到管道中的顺序是否会以某种方式影响分配给模式的优先级。然而,这两种情况都返回了更通用的 NUMBER
标签。
为了看看会发生什么,我输入了句子
I am 20 1 2 01 123 1410 999 001 10 51 001 010 149 150 151
并一致得到了这个结果 -
Ents: [('20', 'NUMBER'), ('1', 'AGE'), ('2', 'NUMBER'), ('01', 'NUMBER'), ('123', 'NUMBER'), ('1410', 'NUMBER'), ('999', 'NUMBER'), ('001', 'NUMBER'), ('10', 'AGE'), ('51', 'AGE'), ('001', 'NUMBER'), ('010', 'NUMBER'), ('149', 'NUMBER'), ('150', 'NUMBER'), ('151.', 'NUMBER')]
,似乎任意将 AGE
或 NUMBER
指定为从 0 到 149 的值。
这提出了两个问题,希望有人能帮忙回答:
一般来说,
EntityRuler
和NER
优先考虑最长的匹配。 “最长”或“最短”匹配的概念是基于令牌计数的,而不是基于令牌长度的。在您的情况下,所有非空格分隔的数字(如 1
、2
、20
)都是单个标记,完全匹配 AGE
和 NUMBER
。
看起来没有特定的顺序 https://github.com/explosion/spaCy/issues/12919 其中
Matcher
将其模式应用于单个令牌。因此,原始问题的解决方案是拥有 2 个(或更多)单独的管道,按照您想要实现的优先级顺序进行调用。
import spacy
nlp = spacy.load("en_core_web_lg")
nlp.remove_pipe("ner")
ruler1 = nlp.add_pipe("entity_ruler", name="er1")
ruler1.add_patterns([
{"label": "AGE", "pattern": [{"TEXT": {"REGEX": "^\d+$"}}]},
# Using some simplified regex. Full-blown AGE detection
# might require to find words: "one", "two" and maybe even "teenager", "retired", etc.
])
ruler2 = nlp.add_pipe("entity_ruler", name="er2")
ruler2.add_patterns([
{"label": "NUMBER", "pattern": [{"LIKE_NUM": True}]},
])
doc = nlp("I am 20 1 2. Not an age: 20.1")
for ent in doc.ents:
print(ent, ent.label_)