You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用spaCy Matcher为被分词为单个Token的序列创建规则匹配模式

如何使用spaCy Matcher为被分词为单个Token的序列创建规则匹配模式

嗨Tarran,我完全懂你遇到的困扰——spaCy的分词器把IQ=68这种连在一起的组合当成了单个token,导致你原本针对三个token设计的pattern2根本匹配不上对吧?别担心,有几个实用的解决方案,我给你一步步讲清楚:

方法一:用正则表达式匹配单个Token的文本

既然IQ=68被当成了一个完整的token,那我们直接针对这个单个token的文本写匹配规则就行。用TEXT属性搭配正则表达式,就能精准捕捉到这种包含IQ、等号(可选)和数字的格式:

import spacy
from spacy.matcher import Matcher

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

# 单个token的匹配模式:不区分大小写,匹配iq开头、等号可选、后跟数字的格式
pattern_single_token = [
    {"TEXT": {"REGEX": r"^iq=?\d+$", "LOWER": True}}
]
matcher.add("IQ_SCORE", [pattern_single_token])

# 测试文本
doc = nlp("Patient's IQ=68, previous assessment noted IQ 72 and iq90.")
matches = matcher(doc)

for match_id, start, end in matches:
    span = doc[start:end]
    print(f"匹配到IQ分数: {span.text}")

这个正则表达式^iq=?\d+$的意思是:以iq开头(不区分大小写),等号是可选的,后面跟着一个或多个数字,刚好能覆盖IQ=68、IQ72、iq90这类常见格式。

方法二:调整spaCy的分词规则,拆分组合Token

如果你希望从根源上解决这类问题——让spaCy把=单独拆分成一个token,那可以修改分词器的前缀规则,让等号被识别为单独的分词单元。这样你原来的pattern2就能正常工作了:

import spacy
from spacy.matcher import Matcher
from spacy.util import compile_prefix_regex

nlp = spacy.load("en_core_web_sm")
# 修改分词器的前缀规则,添加等号作为前缀
prefixes = list(nlp.Defaults.prefixes)
prefixes.append("=")
nlp.tokenizer.prefix_search = compile_prefix_regex(prefixes).search

# 现在用你原来的pattern2就行
pattern2 = [{"LOWER": "iq"}, {"TEXT": "=", "OP": "?"}, {"IS_DIGIT": True}]
matcher = Matcher(nlp.vocab)
matcher.add("IQ_SCORE", [pattern2])

doc = nlp("Patient's IQ=68, previous assessment noted IQ 72.")
matches = matcher(doc)

for match_id, start, end in matches:
    span = doc[start:end]
    print(f"匹配到IQ分数: {span.text}")

不过要注意,调整分词规则可能会影响其他文本的分词结果,比如如果文本里有a=b这类内容,也会被拆成a、=、b,你需要确认这种拆分符合你的整体需求。

方法三:结合PhraseMatcher补充匹配

如果你的临床总结里有很多固定格式的IQ分数短语(比如IQ=68、IQ 75),还可以用PhraseMatcher来匹配这些固定短语,作为Matcher的补充:

import spacy
from spacy.matcher import PhraseMatcher

nlp = spacy.load("en_core_web_sm")
matcher = PhraseMatcher(nlp.vocab)

# 准备固定短语列表
iq_phrases = ["IQ=68", "IQ 72", "iq90"]
phrase_patterns = [nlp(text) for text in iq_phrases]
matcher.add("IQ_SCORE", phrase_patterns)

doc = nlp("Patient's IQ=68, previous assessment noted IQ 72.")
matches = matcher(doc)

for match_id, start, end in matches:
    span = doc[start:end]
    print(f"匹配到IQ分数: {span.text}")

这种方法适合已知所有可能格式的场景,灵活性不如正则,但匹配速度会更快。

总结一下,如果你只是临时解决IQ=68这类单个token的匹配问题,方法一的正则方案最快捷;如果需要长期处理这类带符号的组合,方法二的分词规则调整更彻底;方法三则适合固定短语较多的情况。

备注:内容来源于stack exchange,提问作者Tarran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 15:44:49