Spacy Matcher长模式匹配失败,短模式抢占匹配资源问题求助
解决Spacy葡萄牙语文本匹配中短模式抢占长模式的问题
问题回顾
处理葡萄牙语文本时,定义了包含多长度的COMPONENTE匹配模式,期望匹配四token短语proteção contra descargas atmosféricas,但实际被三token的短模式proteção contra descargas抢占,调整模式顺序也无效,只有移除短模式才能匹配长模式。
问题根源
当前自定义函数中,Matcher会返回所有符合条件的匹配结果(包括短、长模式),且函数按Matcher默认返回顺序处理匹配。短模式的匹配结果先被处理,标记token为已使用后,长模式因包含已处理的token无法被匹配。即使调整模式列表顺序,Matcher内部的匹配逻辑也无法保证长模式优先被返回。
解决方案
核心思路是优先处理最长的匹配结果:
- 先收集当前标签下所有未被处理的匹配结果
- 按匹配的token长度从长到短排序
- 先处理长匹配,标记对应token为已处理,避免短模式抢占
修改后的代码
from spacy.matcher import Matcher from spacy.tokens import Span def buscar_padroes_sequencialmente(doc, patterns): resultados = [] tokens_processados = set() for pat in patterns: label = pat["label"] matcher = Matcher(doc.vocab) for i, padrao_atual in enumerate(pat["pattern"]): matcher.add(f"{label}", [padrao_atual]) # 收集所有未被处理的候选匹配 candidatos = [] for padrao_id, inicio, fim in matcher(doc): if not any(token.i in tokens_processados for token in doc[inicio:fim]): candidatos.append((padrao_id, inicio, fim)) # 按匹配长度从长到短排序 candidatos.sort(key=lambda x: x[2] - x[1], reverse=True) # 处理排序后的匹配 for padrao_id, inicio, fim in candidatos: rótulo = matcher.vocab.strings[padrao_id] # 二次确认token未被占用 if any(token.i in tokens_processados for token in doc[inicio:fim]): continue tokens_processados.update(token.i for token in doc[inicio:fim]) span = Span(doc, inicio, fim, label=rótulo) resultados.append((rótulo, span)) return resultados
验证结果
调用修改后的函数后,会优先匹配到四token的proteção contra descargas atmosféricas,标记这些token后,短模式proteção contra descargas因包含已处理的token不会被匹配,符合预期需求。
内容的提问来源于stack exchange,提问作者Douglas
相关产品推荐
相关产品推荐

