不幸的是,在 spacy v2 中实际上就是这么难。向GoldParse 添加内容非常困难(基本上是在家中不要尝试这个级别),Scorer 也很难扩展。
我们正在为即将推出的 spacy v3 进行这项工作,其中将更普遍地实施评分方法,并且每个组件都将能够提供自己的 score 方法。请注意,这仍然不稳定,但如果您好奇,可以查看:https://github.com/explosion/spaCy/pull/5731。 GoldParse 已被替换为 Example,它将黄金注解和预测注解存储在单个 Doc 对象上,摆脱了与 GoldParse 相关的限制。
如果您有文档级扩展(如上所述),那么您可能应该只使用不同的库进行评估。您可能会使用spacy.scorer 中的ROCAUCScore 或PRFScore,但使用sklearn 之类的指标可能更容易。 (ROCAUCScore 只是sklearn ROC AUC 指标的简化版本。)
如果您有令牌级别的扩展,对于 v2,我认为您可以在 spacy 中做的最好的事情是使用 PRFScore 并根据来自 GoldParse 的单词提取对齐位,以便在记分器本身之外使用。像这样的:
import spacy
from spacy.scorer import PRFScore
nlp = spacy.load("my_model")
score = PRFScore()
for text, gold_words, gold_attrs in zip(texts, gold_words_list, gold_attrs_list):
# NOTE: gold_attrs must be aligned with gold_words
# gold_words = ["a", "b", "c", ...]
# gold_attrs = ["a1", "b1", "c1", ...]
gold = GoldParse(nlp.make_doc(text), words=gold_words)
doc = nlp(text)
gold_values = set()
cand_values = set()
for i, gold_attr in enumerate(gold_attrs):
gold_values.add((i, gold_attr))
for token in doc:
if token.orth_.isspace():
continue
gold_i = gold.cand_to_gold[token.i]
if gold_i is not None:
cand_values.add((gold_i, doc._.attr))
score.score_set(cand_values, gold_values)
print(score.fscore)
这是一个未经测试的草图,应该与token.tag 在Scorer 中的评估方式相同。对齐位是最棘手的部分,因此如果您在黄金词和 spacy 的标记化之间没有错位,那么您最好导出结果并使用不同的库进行评估。