NLP干货: (3) 使用Spacy建立NER模型

NER即命名实体识别,是一种自然语言处理的基础技术,用于在给定的文本内容中提取适当的实体,并将提取的实体分类到预定义的类别下,例如公司名称、人名、地名等实体。Spacy 库允许我们通过根据特定上下文更新现有模型来训练 NER,也可以训练新的 NER 模型。在本文中,我们将探讨如何构建自定义 NER 模型。

首先加载所需的依赖库:

import os
import pandas as pd
import spacy
import random
import joblib
from spacy.training.example import Example
import time

这里假设已从label studio标注完所有NER训练数据,并导出Json文件,因此将批量文件合并转换成Excel:

# labeling studio导出数据后,pd读json
path = 'C:/Users/xxx/downloads/'
dfs = []
for file in os.listdir(path):
    data = pd.read_json(path + str(file), encoding='utf-8')
    data['created_at'] = data['created_at'].apply(lambda x: x.replace(tzinfo=None) if x is not None else None)
    data['updated_at'] = data['updated_at'].apply(lambda x: x.replace(tzinfo=None) if x is not None else None)
    dfs.append(data)
# 合并所有的dataframe
merged_df = pd.concat(dfs)
# 将合并后的dataframe输出到Excel文件
merged_df.to_excel(path + 'labeling output.xlsx', index=False)

然后再将上述Excel output转换成训练数据集:

df = pd.read_excel("C:/Users/xxx/downloads/labeling output.xlsx")
df = df.dropna()
label = df.label.values.tolist()
content = df['Content'].values.tolist()
all_label, all_values = [], []
## 处理 Label 列的数据
for line in range(len(label)):
    ner_label, values = [], []
    for i in eval(label[line]):
        start = i['start']
        end = i['end']
        labels = i['labels'][0]
        value = i['text']
        # print(start,end,labels)
        ner_label.append((start, end, labels))
        values.append(value)
    all_label.append(ner_label)
    all_values.append(values)
df['ner-label'] = all_label
df['values'] = all_values
df.to_excel("C:/Users/xxx/downloads/ner.xlsx", index=False)

下一步则需要检查ner.xlsx的数据质量,是否满足训练要求,数据格式包含如下column:

contentner-labelvalues
文本内容1(start_id1, end_id1, Entity1), (start_id2, end_id2, Entity2), ...['Entity content1', 'Entity content2', ...]
文本内容2(start_id3, end_id3, Entity3), (start_id4, end_id4, Entity2), ...['Entity content3', 'Entity content4', ...]

当数据集处理完成,就开始进入模型训练环节啦!

1.将读取好的数据集转换训练NER模型的数据格式:

def GroupData(content,label,TRAIN_DATA):
    for line in range(len(content)):
        Entity = {}
        Entities = []
        for i in eval(label[line]):
            if 'int' in str(type(i)):
                Entities.append(eval(label[line]))
                break
            if 'tuple' in str(type(i)):
                Entities.append(i)
        Entity["entities"] = Entities
        TRAIN_DATA.append((content[line],Entity))
    return TRAIN_DATA

2.进入模型训练函数,iterations:模型迭代次数

def train_spacy(TRAIN_DATA, iterations):
    # 创建一个空白英文模型:en,中文模型:zh
    nlp = spacy.blank("en")
    #若没有则添加NER组件
    if "ner" not in nlp.pipe_names:
        ner = nlp.add_pipe("ner",last=True)
    #添加所有实体标签到spaCy模型
    for _, annotations in TRAIN_DATA:
        # print(annotations.get("entities"))
        for ent in annotations.get("entities"):
            ner.add_label(ent[2])
    #获取模型中除了NER之外的其他管件
    other_pipes = [pipe for pipe in nlp.pipe_names if pipe != "ner"]
    #开始训练   #消除其他管件的影响
    with nlp.disable_pipes(*other_pipes):
        optimizer = nlp.begin_training()
        optimizer.learn_rate = 1e-3
        for itn in range(iterations):
            print("开始迭代",itn + 1,"次")
            random.shuffle(TRAIN_DATA)
            losses = {}
            for text, annotations in TRAIN_DATA:
                try:
                    doc = nlp.make_doc(text)
                    example = Example.from_dict(doc, annotations)
                    nlp.update([example], losses=losses, drop=0.4,sgd=optimizer)
                except:
                    continue
    return (nlp)

主函数:

if __name__ == '__main__':
    df = pd.read_excel(r"C:\Users\xxx\Desktop\data\NER\ner-train.xlsx")
    df = df.dropna()
    ## 转换为列表 ##
    content = df['Content'].values.tolist()
    label = df['label'].values.tolist()
    TRAIN_DATA = []
    ## 整合数据
    GroupData(content, label, TRAIN_DATA)

    ## 训练模型
    begin = time.perf_counter()
    trained_nlp = train_spacy(TRAIN_DATA,55)
    joblib.dump(trained_nlp, r"C:\Users\xxx\Desktop\data\NER\NER.m")
    end_time = time.perf_counter()
    run_time = end_time - begin
    print('模型生成成功,建模运行时间', run_time, 's')

至此,相信你已成功训练出自定义的NER模型,参考下一篇文章会继续讲述NLP干货: (4) NER模型的调用和效果评估

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spacy是一个强大的自然语言处理库,它支持各种语言,包括中文。在Spacy中,我们可以通过训练模型来识别和提取命名实体。下面是一些关于如何在Spacy中自定义中文命名实体的步骤: 1. 准备数据集:首先,需要准备一个包含中文文本和对应命名实体的数据集。这个数据集应该是一个json格式的文件,每个文本都应该包含一个“text”字段和一个“entities”字段,entities字段应该是一个列表,其中每个元素都是一个字典,包含“start”和“end”字段,分别表示命名实体在文本中的起始位置和结束位置,以及“label”字段,表示命名实体的类型。 2. 数据预处理:将数据集转换为Spacy可接受的格式。可以使用Spacy提供的工具函数,如spacy.gold.biluo_tags_from_offsets(),将实体坐标转换为BILUO(Beginning, Inside, Last, Unit, Outside)标签。还需要将数据集分为训练集、验证集和测试集。 3. 定义模型Spacy提供了一个基于卷积神经网络和条件随机场(CRF)的命名实体识别模型,可以通过调用spacy.blank()函数创建一个空模型,并使用add_pipe()方法添加组件。 4. 训练模型使用Spacy提供的训练函数,对模型进行训练。训练过程中需要指定训练数据、验证数据、迭代次数、批处理大小等参数。训练过程可以耗费较长时间,因此建议在GPU上进行训练。 5. 测试模型:在测试集上测试模型的性能。可以使用Spacy提供的evaluate()函数,计算模型的准确率、召回率和F1分数等指标。 6. 使用模型:将训练好的模型应用于新的中文文本,使用模型nlp()方法对文本进行处理,并使用ents属性获取提取的命名实体。 需要注意的是,Spacy自带的中文模型性能较差,因此建议使用自定义模型进行中文命名实体识别。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值