【问题标题】:is there a way with spaCy's NER to calculate metrics per entity type?spaCy 的 NER 有没有办法计算每个实体类型的指标?
【发布时间】:2018-10-17 13:26:19
【问题描述】:

spaCy 中的 NER 模型有没有办法提取每个实体类型的指标(精度、召回率、f1 分数)?

看起来像这样的东西:

         precision    recall  f1-score   support

  B-LOC      0.810     0.784     0.797      1084
  I-LOC      0.690     0.637     0.662       325
 B-MISC      0.731     0.569     0.640       339
 I-MISC      0.699     0.589     0.639       557
  B-ORG      0.807     0.832     0.820      1400
  I-ORG      0.852     0.786     0.818      1104
  B-PER      0.850     0.884     0.867       735
  I-PER      0.893     0.943     0.917       634

平均/总计 0.809 0.787 0.796 6178

取自:http://www.davidsbatista.net/blog/2018/05/09/Named_Entity_Evaluation/

谢谢!

【问题讨论】:

    标签: python entity metrics spacy named-entity-recognition


    【解决方案1】:

    好问题。

    首先,我们应该澄清 spaCy 使用 BILUO 注释方案而不是您所指的 BIO 注释方案。 来自 spacy documentation 的字母表示以下内容:

    • B:多令牌实体的第一个令牌。
    • I:多令牌实体的内部令牌。
    • L:多令牌实体的最终令牌。
    • U:单令牌实体。
    • O:非实体令牌。

    然后,一些定义:

    Spacy 有一个内置类来评估 NER。它被称为得分手。 Scorer 使用精确匹配来评估 NER。精度分数返回为 ents_p,召回率为 ents_r,F1 分数为 ents_f。

    唯一的问题是它会返回文档中所有标签的分数。但是,我们可以只使用我们想要的 TAG 调用该函数并获得所需的结果。

    总而言之,代码应该是这样的:

    import spacy
    from spacy.gold import GoldParse
    from spacy.scorer import Scorer
    
    def evaluate(nlp, examples, ent='PERSON'):
        scorer = Scorer()
        for input_, annot in examples:
            text_entities = []
            for entity in annot.get('entities'):
                if ent in entity:
                    text_entities.append(entity)
            doc_gold_text = nlp.make_doc(input_)
            gold = GoldParse(doc_gold_text, entities=text_entities)
            pred_value = nlp(input_)
            scorer.score(pred_value, gold)
        return scorer.scores
    
    
    examples = [
        ("Trump says he's answered Mueller's Russia inquiry questions \u2013 live",{"entities":[[0,5,"PERSON"],[25,32,"PERSON"],[35,41,"GPE"]]}),
        ("Alexander Zverev reaches ATP Finals semis then reminds Lendl who is boss",{"entities":[[0,16,"PERSON"],[55,60,"PERSON"]]}),
        ("Britain's worst landlord to take nine years to pay off string of fines",{"entities":[[0,7,"GPE"]]}),
        ("Tom Watson: people's vote more likely given weakness of May's position",{"entities":[[0,10,"PERSON"],[56,59,"PERSON"]]}),
    ]
    
    nlp = spacy.load('en_core_web_sm')
    results = evaluate(nlp, examples)
    print(results)
    

    使用适当的 ent 参数调用评估函数以获取每个标签的结果。

    希望对你有帮助:)

    【讨论】:

    • 我认为这有问题,当我对所有实体进行评估时,我得到了非常好的结果(P、R 和 F 的结果>90%)但是当我使用你的过滤实体时函数 R 仍然很高,但 P 和 F 下降到极低(低于 20%)所以我认为函数在 GoldParse() 行的评估不正确。也许它考虑了第一个参数中的所有实体?
    • @gdaras 我引用你的话“Scorer 使用精确匹配来评估 NER”——你怎么知道的?你会告诉我你的来源来帮助我:) 谢谢
    【解决方案2】:

    我一直在研究这个,现在它通过Pull Request 整合到空间中。

    现在您只需调用Scorer().scores,它会返回带有附加键ents_per_type 的常用字典,其中将包含每个实体的精度、召回率和F1-Score 指标。

    希望对您有所帮助!

    【讨论】:

    【解决方案3】:

    从 spacy v3,

    #测试模型

    import spacy
    from spacy.training.example import Example
    
    nlp = spacy.load("./model_saved")
    examples = []
    data = [("Taj mahal is in Agra.", {"entities": [(0, 9, 'name'),
    (16, 20, 'place')]})]
    for text, annots in data:
        doc = nlp.make_doc(text)
        examples.append(Example.from_dict(doc, annots))
    print(nlp.evaluate(examples)) # This will provide overall and per entity metrics
    

    【讨论】:

      【解决方案4】:

      @gdaras 的回答不正确。第一条评论给出了原因。 您应该过滤

      的实体
      pred_value = nlp(input_)
      

      我是这样做的

      pred_value.ents = [e for e in pred_value.ents if e.label_ == ent]
      

      【讨论】:

      • @Ruwan,我没有完全理解你的意思,我应该在哪里添加这个?
      • 使用@gdaras 的答案作为起点。您应该在我的第一行之后添加我的第二行(在第一个答案中找到它)。在 gold = GoldParse(doc_gold_text,entities=text_entities) 之前对 text_entities 使用类似的过滤
      • 你能重写答案中的代码块吗?
      【解决方案5】:

      是的,结果是这样的:

      {'token_acc': 1.0, 'token_p': 1.0, 'token_r': 1.0, 'token_f': 1.0, 'ents_p': 0.8571428571428571, 'ents_r': 0.5454545454545454, 'ents_f': 0.6666666666666665, 'ents_per_type': {'KEY5': {'p': 0.8571428571428571, 'r': 0.5454545454545454, 'f': 0.6666666666666665}}, 'speed': 34577.72779537917}
      

      【讨论】:

      • 这看起来像一个不错的输出 put 并没有解释如何制作它
      猜你喜欢
      • 1970-01-01
      • 2020-04-28
      • 2023-02-02
      • 1970-01-01
      • 2021-06-16
      • 2020-05-09
      • 2019-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多