用Spacy对NER标注结果进行展示

如果我们得到了标注序列,直接比对结果非常不直观。而 Spacy 可以轻松解决这个问题。比如有文本和标注序列,如果你的得到的标注是 span 和 label 就更轻松了。

import spacy
import numpy as np
text = "故障现象: 一辆 99 年出厂的奥迪 2001.8T 电控发动机,带涡轮增压系统和 ABS 防抱死,不带车辆防盗系统。" \
       "故障原因: 装完新车,第一次通电时产生的,当时担忧线路有装错的坟,造成线路和电器的烧坏,在翻开点火开关后," \
       "用电瓶线在电瓶桩头上来回碰了几次,感觉没有问题后才将电瓶线接好。这样电脑在通电的情况下,突然断电,反复几次," \
       "造成电脑对节气门位置传感器的根本设置数值丧失,使原来正常的系统产生了故障。解决措施: 用群众专用检测仪 V1551 对节气门位置传感器进行根本设置"
tags = ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'I- 故障设备', 'I- 故障设备',
        'O', 'I- 故障原因', 'I- 故障原因', 'O', 'O', 'O', 'O', 'O', 'I- 故障设备', 'I- 故障设备',
        'O', 'I- 故障设备', 'I- 故障设备', 'O', 'I- 故障原因', 'I- 故障原因', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'I- 故障设备', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'I- 故障原因', 'I- 故障原因', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'I- 故障设备', 'I- 故障设备', 'O', 'I- 故障设备', 'I- 故障设备', 'I- 故障设备', 'I- 故障设备',
        'I- 故障设备', 'I- 故障设备', 'I- 故障设备', 'I- 故障设备', 'O', 'O', 'O', 'I- 故障原因', 'I- 故障原因',
        'I- 故障原因', 'I- 故障原因', 'I- 故障原因', 'I- 故障原因', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O',
        'O', 'O', 'O', 'O', 'O']

1. 获取标注范围和 label

def search_entity_spans(tags):
    #返回范围和 label 的元组列表
    spans = []
    start = None
    current_label = None

    for i, tag in enumerate(tags):
        if tag.startswith("B-"):
            if start is not None:
                spans.append((start, i , current_label))
            start = i
            current_label = tag.split("-", 1)[1]
        elif tag.startswith("I-"):
            if start is None:
                start = i
                current_label = tag.split("-", 1)[1]
            elif current_label != tag.split("-", 1)[1]:
                spans.append((start, i, current_label))
                start = i
                current_label = tag.split("-", 1)[1]
        else:
            if start is not None:
                spans.append((start, i, current_label))
                start = None
                current_label = None

    if start is not None:
        spans.append((start, len(tags), current_label))

    return spans

spans = search_entity_spans(tags)
print(spans)
##[(76, 78, '故障设备'), (79, 81, '故障原因')...]

2. spacy.displacy.render 渲染标注样式

通过将 ents 参数设置为包含需要标注的实体类型列表来指定自定义样式。然后,我们将 options 作为参数传递给 spacy.displacy.render 函数,并将 manual 设置为 True 以启用手动模式。

def plot_annotation(text, spans):
    colors = {'故障设备': 'linear-gradient(90deg, #aa9cfc, #fc9ce7)',
              '故障原因': 'linear-gradient(90deg, #a9ffc9, #fffea9)'}
    options = {"ents": ["故障设备", "故障原因"], "colors": colors}

    ents = []
    for s in spans:
        ents.append({"start": int(s[0]), "end": int(s[1]), "label": s[2]})

    doc = {"text": text, "ents": sorted(ents, key=lambda i: i["start"])}
    spacy.displacy.render(doc, style="ent", options=options, manual=True, jupyter=True)

plot_annotation(text, spans)
用 Spacy 对 NER 标注结果进行展示

补充:下面是只搜索实体范围函数, 这里没有使用,只是记录。

def search_entity_spans1(tags):
    """根据 tags 返回 span 范围元组列表"""
    spans = []
    start = None

    for i, tag in enumerate(tags):
        if tag.startswith("B-"):
            if start is not None:
                spans.append((start, i))
            start = i
        elif tag.startswith("I-"):
            if start is None:
                start = i
        else:
            if start is not None:
                spans.append((start, i))
                start = None

    if start is not None:
        spans.append((start, len(tags)))

    return spans

spans = search_entity_spans1(tags)
print(spans)
print(tags)
正文完
 
admin
版权声明:本站原创文章,由 admin 2023-11-26发表,共计3057字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请联系tensortimes@gmail.com。
评论(没有评论)
验证码