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

自定义spaCy词性标注器报错:未注册扩展属性pos_tag无法分配

解决spaCy自定义标注器的AttributeError(E047)问题

错误原因分析

你遇到的AttributeError: [E047]是因为:

  • 未正确导入Token类就尝试注册扩展,且错误使用Doc而非Token来注册token级别的扩展
  • 自定义管道的初始化和添加逻辑冲突,手动实例化标注器但未正确关联到nlp流程
  • 扩展注册时机不正确,导致spaCy无法识别自定义的pos_tag属性

分步解决方案

1. 正确注册Token扩展属性

要给单个token添加自定义扩展属性,需导入spaCy的Token类并完成注册:

from spacy.tokens import Token

# 注册token级别的扩展属性,允许覆盖已有同名扩展
Token.set_extension('pos_tag', default=None, force=True)

2. 修正自定义标注器的管道添加逻辑

不需要手动实例化KeywordPosTagger,nlp.add_pipe会通过你定义的Language.factory自动创建实例。同时config参数无需传递nlp,spaCy会自动注入该参数。

3. 完整修正后的代码

import requests
import spacy
from spacy.tokens import Token
from spacy.language import Language

# 注册token扩展属性
Token.set_extension('pos_tag', default=None, force=True)

# 加载外部词典(保留原代码定义,若后续需使用可直接调用)
dictionary = requests.get(
    "https://github.com/dglopes/NBR15575/raw/main/unidades_medidas.json").json()

# 定义自定义标注器Factory
@Language.factory("keyword_pos_tagger")
class KeywordPosTagger:
    def __init__(self, name, nlp, keywords, pos_tag):
        self.keywords = keywords
        self.pos_tag = pos_tag

    def __call__(self, doc):
        for token in doc:
            if token.text in self.keywords:
                token._.pos_tag = self.pos_tag
        return doc

# 加载葡萄牙语预训练模型
nlp = spacy.load('pt_core_news_md')

# 配置目标关键词和自定义POS标签
keywords = ('m²', 'm2', '(W/K)', 'ºC')
pos_tag = 'UNM'

# 将自定义标注器添加到nlp处理流程
nlp.add_pipe('keyword_pos_tagger', config={"keywords": keywords, "pos_tag": pos_tag})

# 测试调用
doc = nlp('A temperatura tem 159ºC ou 20 ºC. Também precisa ter 20m de largura e 14 m² de área, caso contrário terá 1 Kelvin (W/K)')
for token in doc:
    print(token.text, token._.pos_tag)

额外需求:将自定义标签赋值给token.pos_

如果希望自定义标签像内置的NOUN/VERB一样直接赋值给token.pos_(而非扩展属性),需要先将自定义标签添加到spaCy词汇表,并修改标注器逻辑:

# 加载nlp模型后添加以下代码
# 为词汇表注册自定义POS标签
nlp.vocab.strings.add('UNM')
UNM_POS = nlp.vocab.strings['UNM']

# 修改标注器的__call__方法
def __call__(self, doc):
    for token in doc:
        if token.text in self.keywords:
            token.pos = UNM_POS  # 直接设置内置pos属性
            token.tag_ = 'UNM'   # 同步设置tag_(可选,保持标签一致性)
    return doc

修改后即可直接通过token.pos_获取自定义的UNM标签。

内容的提问来源于stack exchange,提问作者Douglas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:15:57