Spacy 2.0 NER实体拆分与日期识别异常问题求助
解决Spacy 2.0 NER的实体拆分与日期识别问题
我来帮你搞定这个Spacy NER的小麻烦,刚好对2.0版本的模型特性比较熟悉。你遇到的两个问题其实都和预训练模型的上下文判断有关:单独识别公司名时没有额外干扰,模型能正常识别;但整段文本里的“-”分隔符和年份上下文,干扰了模型的实体边界判断,才导致公司名被拆分、2013没被标记为DATE。下面给你两个实用的解决思路:
方案一:规则匹配快速补全(见效最快)
Spacy 2.0自带的Matcher可以自定义规则,强制修正实体识别结果,完美适配你的场景:
- 初始化模型和匹配器:
import spacy from spacy.matcher import Matcher nlp = spacy.load("en_core_web_md-2.0.0") matcher = Matcher(nlp.vocab)
- 定义匹配规则:针对你的公司名格式和四位数字日期,分别设置规则:
# 匹配完整公司名的分词序列 company_pattern = [ {"TEXT": "ZS"}, {"TEXT": "L-1"}, {"TEXT": "Cocoa"}, {"TEXT": "&"}, {"TEXT": "Burgers"}, {"TEXT": "Ltd"} ] matcher.add("FULL_COMPANY", None, company_pattern) # 匹配四位数字格式的日期(覆盖2013、2017) date_pattern = [{"SHAPE": "dddd"}] matcher.add("FOUR_DIGIT_DATE", None, date_pattern)
- 处理文本并修正实体:
text = "ZS L-1 Cocoa & Burgers Ltd - 2013 to 2017" doc = nlp(text) # 先清空原有实体,避免规则匹配和模型结果冲突 doc.ents = () # 应用匹配规则,添加自定义实体 matches = matcher(doc) for match_id, start, end in matches: span = doc[start:end] match_name = nlp.vocab.strings[match_id] if match_name == "FULL_COMPANY": doc.ents += (spacy.tokens.Span(doc, start, end, label="ORG"),) elif match_name == "FOUR_DIGIT_DATE": doc.ents += (spacy.tokens.Span(doc, start, end, label="DATE"),) # 输出修正后的结果 print([(i.text, i.label_) for i in doc.ents])
运行后就能得到你想要的结果:[('ZS L-1 Cocoa & Burgers Ltd', 'ORG'), ('2013', 'DATE'), ('2017', 'DATE')]
方案二:微调预训练模型(长期适配)
如果你的场景里有大量类似格式的文本,规则匹配可能不够灵活,这时候可以微调模型让它学会识别这类实体:
- 准备少量标注数据(10-20条即可),用Spacy的JSON格式:
[ {"text": "ZS L-1 Cocoa & Burgers Ltd - 2013 to 2017", "ents": [{"start": 0, "end": 32, "label": "ORG"}, {"start": 35, "end": 39, "label": "DATE"}, {"start": 43, "end": 47, "label": "DATE"}]} ]
- 用Spacy 2.0的训练命令微调模型:
python -m spacy train en ./fine_tuned_model ./train_data.json --base-model en_core_web_md-2.0.0
微调后的模型会记住这类文本的实体模式,后续处理类似内容时就不用再写规则了。
内容的提问来源于stack exchange,提问作者joel
相关产品推荐
相关产品推荐

