Jupyter Notebook环境下用SpaCy匹配专有名词出现结果重复冗余问题
SpaCy人名匹配出现拆分重复片段的问题解决
实际问题表现
在Jupyter Notebook中完成PDF文本提取后,使用SpaCy的Matcher组件做专有名词匹配,会出现同一完整人名被拆分为多段重复输出的异常情况,典型输出结果如下:
- Sarra Ben
- Sarra Ben Moussa
- Ben Moussa
- Ghofrane Challouf
- Malika Ben
- Malika Ben Slima
- Ben Slima
异常产生原因
当前匹配逻辑存在两个核心缺陷,直接导致了重复拆分的结果:
- 同时定义了「2个连续专有名词」「3个连续专有名词」两类人名匹配规则,两类规则的匹配标签统一为
FULL_NAME,权重完全一致 - SpaCy默认的
Matcher会扫描文本中所有符合规则的片段,不会主动跳过存在范围重叠的匹配结果。当文本中出现连续3个PROPN构成的完整人名时,会同时命中「前两个PROPN片段」「全量三个PROPN的完整人名」「后两个PROPN片段」三个不同范围的匹配项,最终形成多段拆分重复输出的结果。
可落地的调整方案
1. 规则优先级适配
调整规则添加顺序,利用SpaCy Matcher的权重机制:规则的优先级随添加顺序递减,后添加的规则权重更低。调整时优先添加长度更长的人名匹配规则,让匹配器优先识别完整长人名结构。
2. 重叠片段去重
遍历匹配结果时,按片段长度从长到短排序,逐段校验片段的Token范围是否已经被更长的有效匹配覆盖,被覆盖的短冗余片段直接剔除,最终仅保留无重叠的最长匹配结果。
调整后的完整参考代码:
from spacy.matcher import Matcher matcher = Matcher(nlp.vocab) # 规则定义 pattern_two_part_name = [{'POS': 'PROPN'}, {'POS': 'PROPN'}] pattern_three_part_name = [{'POS': 'PROPN'}, {'POS': 'PROPN'}, {'POS': 'PROPN'}] # 按规则长度从长到短添加,长规则优先级更高 matcher.add('FULL_NAME', [pattern_three_part_name]) matcher.add('FULL_NAME', [pattern_two_part_name]) matches = matcher(doc) # 按匹配片段长度从长到短排序,过滤重叠的短片段 valid_matches = [] covered_token_spans = set() for match_id, start, end in sorted(matches, key=lambda item: item[2] - item[1], reverse=True): # 判断当前片段是否被已保留的长片段覆盖 if not any(token_idx in covered_token_spans for token_idx in range(start, end)): valid_matches.append((match_id, start, end)) covered_token_spans.update(range(start, end)) # 输出最终有效匹配结果 for match_id, start, end in valid_matches: print(doc[start:end])
调整后的输出效果
调整后原有重复拆分的人名片段将被全部过滤,最终仅输出最长的完整人名结构,典型输出为:
- Sarra Ben Moussa
- Ghofrane Challouf
- Malika Ben Slima
内容的提问来源于stack exchange,提问作者Ghofran Challouf
相关产品推荐
相关产品推荐

