使用spaCy进行NLP时特殊情况词形还原触发ValueError求助
问题原因与解决方案
错误原因
你在设置tokenizer特殊规则时犯了逻辑错误:spaCy的ORTH字段是用来匹配输入文本的原始形式,不能用它来修改输入文本的内容。你试图将输入的"Frisco"的ORTH设为"San Francisco",这违反了spaCy的规则——tokenizer特殊规则仅能调整token的属性(如标准化形式、词形等),不能篡改输入文本的实际内容。
正确实现方式
根据你的需求,分两种场景给出解决方案:
场景1:仅标准化"Frisco"为"San Francisco"(不修改原文本,仅调整token属性)
如果只是希望在后续NLP处理中,将"Frisco"的标准化形式替换为"San Francisco",只需将NORM设为目标值,ORTH保留原输入词:
import spacy from spacy.symbols import * nlp = spacy.load("en_core_web_sm") # 正确的特殊规则:ORTH匹配输入原词,NORM设置标准化值 special_case = [{ORTH: "Frisco", NORM: "San Francisco"}] nlp.tokenizer.add_special_case("Frisco", special_case) doc = nlp("I am flying to Frisco.") print([token.text for token in doc]) # 输出: ['I', 'am', 'flying', 'to', 'Frisco', '.'] print([token.norm_ for token in doc]) # 输出: ['i', 'am', 'flying', 'to', 'san francisco', '.'] # 如果需要同时修改词形(lemma),可以添加LEMMA字段 # special_case = [{ORTH: "Frisco", NORM: "San Francisco", LEMMA: "San Francisco"}]
场景2:直接将文本中的"Frisco"替换为"San Francisco"(修改输出文本)
如果需要实际替换输出文本中的词,tokenizer特殊规则无法实现,需自定义管道组件处理:
import spacy from spacy.tokens import Doc nlp = spacy.load("en_core_web_sm") def replace_frisco(doc): tokens = [] for token in doc: if token.text == "Frisco": # 将单个token拆分为"San"和"Francisco"两个token tokens.extend(nlp("San Francisco")) else: tokens.append(token) # 基于新的token列表创建新的Doc对象 return Doc(nlp.vocab, words=[t.text for t in tokens]) # 将自定义管道添加到nlp流程最前端 nlp.add_pipe(replace_frisco, first=True) doc = nlp("I am flying to Frisco.") print([token.text for token in doc]) # 输出: ['I', 'am', 'flying', 'to', 'San', 'Francisco', '.']
内容的提问来源于stack exchange,提问作者jack
相关产品推荐
相关产品推荐

