首页 > 其他分享 >【NLP】使用 SpaCy 通过 LLM 合成数据微调 NER 模型

【NLP】使用 SpaCy 通过 LLM 合成数据微调 NER 模型

时间:2024-11-08 14:16:31浏览次数:3  
标签:nlp 训练 NLP doc 模型 LLM docs test NER

在我们之前的文章“使用 SpaCy、ollama 创建用于命名实体识别的合成数据集”中,我们探讨了如何使用 Qwen 生成合成数据,以自动化命名实体识别 (NER) 的注释过程。通过利用合成数据,我们能够高效地准备来自 SmoothNLP金融新闻数据集  的高质量数据集。现在,在这篇文章中,我们将更进一步,使用 SpaCy 训练各种 NER 模型,比较它们的性能,并检查它们在我们合成生成的数据集中识别实体的能力。

步骤 1:加载模型并准备管道

import spacy
nlp = spacy.load('zh_core_web_sm')
from spacy.training import Example
from spacy.util import minibatch
from tqdm import tqdm
import random
from spacy.tokens import DocBin

# Get the Named Entity Recognizer (NER) component or add it if not present
if "ner" not in nlp.pipe_names:
    ner = nlp.add_pipe("ner")
else:
    ner = nlp.get_pipe("ner")

在这里,我们加载了 SpaCy 的预训练中文模型,zh_core_web_sm其中包括大型词向量以提高准确性。我们检查ner管道中是否存在命名实体识别器 ( ) 组件。这对于识别文本中的名称、位置和组织等实体至关重要。

步骤 2:加载训练数据

# 加载训练数据(它是 .spacy 格式)
train_doc_bin = DocBin().from_disk(r"train.spacy")

# 将文档箱转换为文档对象
docs = list(train_doc_bin.get_docs(nlp.vocab))

# 将数据分成训练和验证集(例如,80% 训练,20% 验证)
train_ratio = 0.8
split_idx = int(len(docs) * train_ratio)
train_docs = docs[:split_idx]
valid_docs = docs[split_idx:]

我们使用 SpaCy 的类加载以 .spacy格式存储的训练数据(DocBin),这对于大型数据集非常有效。该get_docs()方法将二进制文件转换为 SpaCy的Doc对象。然后,我们将数据分成训练集 (80%) 和验证集 (20%),使我们能够在训练期间评估模型性能。

步骤 3:准备训练示例

train_examples = [Example.from_dict(doc, {"entities": [(ent.start_char, ent.end_char, ent.label_) for ent in doc.ents]}) for doc in train_docs]

在这里,我们通过创建对象来准备训练示例Example。每个示例将原始文本(doc)与其实体注释(起始和终止字符索引以及实体标签)配对。这些Example对象对于训练 SpaCy 模型至关重要,因为它们封装了输入(原始文本)和预期输出(实体)。

步骤 4:初始化优化器并设置训练参数

# 初始化优化器以进行微调
optimizer = nlp.resume_training() 

# 设置训练参数
n_iter = 20   # 训练周期次数
patient = 4   # 提前停止耐心
batch_size = 8   # 训练批次大小
best_f1 = 0   # 跟踪最佳 F1 分数
no_improvement = 0   # 用于提前停止

我们使用 SpaCy 的内置resume_training()方法恢复训练,该方法初始化优化器。然后我们定义训练参数:

  • n_iter:训练周期数(模型查看整个训练数据的次数)。
  • patience:在触发早期停止之前,等待未出现改进的时期数。
  • batch_size:每次训练的示例数。
  • best_f1:在验证期间跟踪最佳 F1 分数。
  • no_improvement:计算 F1 分数没有提高的时期数,用于早期停止。

步骤 5:训练循环

# 使用早期停止和验证的训练循环
for epoch in tqdm(range(n_iter)):
    print(f"Epoch {epoch + 1}/{n_iter}")

    # 打乱训练数据
    random.shuffle(train_examples)

    # 创建训练数据批次
    batches = minibatch(train_examples, size=batch_size)

    # 在每个批次上进行训练
    for batch in tqdm(batches, leave=False):
        nlp.update(batch, sgd=optimizer)

    # 在每个 epoch 之后对验证集进行评估
    print("Evaluating on validation set...")

    valid_examples = []
    for doc in valid_docs:
        # 创建一个包含原始文本(无注释)的新 Doc 对象用于预测
        pred_doc = nlp.make_doc(doc.text)  
        
        # 创建一个将预测与原始带注释文档配对的 Example 对象
        example = Example(pred_doc, doc)
        valid_examples.append(example)

    # 将 nlp.evaluate() 与新创建的 Example 对象一起使用
    results = nlp.evaluate(valid_examples)

    # 提取 F1 分数、精度和召回率
    precision = results["ents_p"]
    recall = results["ents_r"]
    f1 = results["ents_f"]

    print(f"Validation Precision: {precision:.4f}, Recall: {recall:.4f}, F1 Score: {f1:.4f}")

    # 根据验证 F1 分数的早期停止逻辑
    if f1 > best_f1:
        best_f1 = f1
        no_improvement = 0
        # Save the best model
        nlp.to_disk("best_model")
    else:
        no_improvement += 1
        print(f"No improvement for {no_improvement} epochs.")

    if no_improvement >= patience:
        print("Early stopping triggered. Stopping training.")
        break

 

这是主要的训练循环。对于每个周期:

  • 我们对训练示例进行打乱,以避免过度拟合。
  • 我们用来minibatch创建小批量数据进行梯度更新。
  • nlp.update()对每一批训练示例执行单步优化,调整模型的权重以最小化损失。
  • 在每个时期之后,我们都会在验证集上评估模型。对于每个验证示例,我们使用生成预测nlp.make_doc()并将它们与原始注释进行比较。我们使用nlp.evaluate()来计算评估指标,例如精确度召回率F1 分数。这些指标可帮助我们评估模型在未见过的数据上的表现。如果 F1 分数在一个时期后有所提高,我们会重置计数器no_improvement并保存模型。如果模型在一定数量的时期内没有显示出任何改进(patience),我们会停止训练以避免过度拟合。表现最佳的模型将保存到磁盘。

步骤 6:评估最终模型

为了使用手动注释的测试集有效地评估最终模型,我们可以按如下方式进行设置:

# 从磁盘加载表现最佳的模型
nlp = spacy.load("best_model")

# 测试数据
test_doc_bin = DocBin().from_disk(r"test.spacy")
test_docs = list(test_doc_bin.get_docs(nlp.vocab))

# 将测试文档转换为示例以供评估
test_examples = [Example.from_dict(doc, {"entities": [(ent.start_char, ent.end_char, ent.label_) for ent in doc.ents]}) for doc in test_docs]

# 在测试示例上评估最终模型
test_results = nlp.evaluate(test_examples)
test_precision = test_results["ents_p"]
test_recall = test_results["ents_r"]
test_f1 = test_results["ents_f"]

print(f"Test Precision: {test_precision:.4f}, Recall: {test_recall:.4f}, F1 Score: {test_f1:.4f}")

步骤 7:使用我们微调的模型进行预测

为了使用我们微调的 NER 模型进行预测,我们可以加载保存的模型并使用它来识别新文本数据中的实体:

# 加载微调后的模型
nlp = spacy.load("best_model")

# 定义要分析的文本
text = "贵州:扫黑风暴使在逃多年涉案人员自首\n新华社贵阳2月15日电(记者 汪军)记者从贵州省公安厅了解到,在扫黑除恶专项斗争高压态势下,在逃8年多的涉嫌组织、领导、参加黑社会性质组织的胡某河近日主动到贵州省铜仁市公安机关投案自首。\n2009年8月,贵州省公安厅统一指挥,成功打掉了铜仁市思南县一涉嫌组织、领导、参加黑社会性质的犯罪团伙,当地群众拍手称快,但该案主要犯罪嫌疑人胡某河在逃。\n今年1月,全国扫黑除恶专项斗争开展以来,贵州省市县三级公安机关协调联动,通过媒体发布相关通告,宣讲有关政策,广泛发动群众检举揭发,深入宣传党和政府扫黑除恶的决心,敦促涉黑涉恶人员主动投案自首、争取宽大处理,积极营造全社会参与支持扫黑除恶的氛围。\n近日在公安机关强大宣传攻势下,在逃8年多的涉嫌组织、领导、参加黑社会性质组织的胡某河迫于压力,主动到公安机关投案自首。目前,该案相关工作正在进一步进行中。"

# 使用模型处理文本
doc = nlp(text)

# 打印识别出的带有标签的实体
for ent in doc.ents:
    print(f"Entity: {ent.text}, Label: {ent.label_}")

结论

本文详细介绍了如何使用SpaCy库训练和优化中文命名实体识别(NER)模型。首先,我们加载了SpaCy的预训练中文模型,并确保了NER组件的存在。接着,我们从.spacy格式的文件中加载训练数据,并将其分为训练集和验证集。然后,我们准备了训练示例,初始化了优化器,并设置了训练参数。在训练循环中,我们对训练数据进行打乱和分批处理,同时在每个周期后评估模型在验证集上的性能,并根据F1分数进行早期停止判断。最终,我们保存了表现最佳的模型,并在手动注释的测试集上进行了评估。文章最后展示了如何使用微调后的模型对新文本进行实体识别预测,从而验证了模型的实用性和准确性。 

标签:nlp,训练,NLP,doc,模型,LLM,docs,test,NER
From: https://blog.csdn.net/sikh_0529/article/details/143614090

相关文章

  • 大模型(LLMs)学习笔记——进阶知识
    一.生成式大模型简介1.什么是生成式大模型前排提示,文末有大模型AGI-CSDN独家资料包哦!生成式大模型(一般简称大模型LLMs)是指能用于创作新内容,例如文本、图片、音频以及视频的一类深度学习模型。相比普通深度学习模型,主要有两点不同:模型参数量更大,参数量都在Billion......
  • 大模型(LLMs)学习笔记——基础知识
    一.大模型介绍1.目前主流的开源模型体系有哪些?前排提示,文末有大模型AGI-CSDN独家资料包哦!(1)CausalDecoder(因果解码器)介绍:从左到右的单项注意力代表模型:ChatGPT、LLaMA-7B、LLaMa系列。(2)PrefixDecoder(前缀解码器)介绍:输入双向注意力,输出单向注意力代表模型:ChatGLM、......
  • 利用FreeSql.Generator自动根据数据库表动态生成实体类
    安装dotnettoolinstall-gFreeSql.Generator示例FreeSql.Generator-Razor1-NameOptions0,0,0,1-NameSpaceLinCms.Core.Entities-DB"MySql,DataSource=127.0.0.1;Port=3306;UserID=root;Password=123456;InitialCatalog=lincms;Charset=utf8;SslMode=none;M......
  • 101_api_intro_metadata_collegeenrollmentplan
    历年高校招生计划数据API数据接口基础数据/高校招生,各高校历年招生计划数据,高校招生数据/历年计划。1.产品功能支持历年高校招生计划数据查询;包含各高校招生计划详细数据;多维度查询条件支持;毫秒级查询性能;全接口支持HTTPS(TLSv1.0/v1.1/v1.2/v1.3);全面兼容......
  • Pytorch用BERT对CoLA、新闻组文本数据集自然语言处理NLP:主题分类建模微调可视化分析-C
     原文链接:https://tecdat.cn/?p=38181原文出处:拓端数据部落公众号自然语言处理(NLP)领域在近年来发展迅猛,尤其是预训练模型的出现带来了重大变革。其中,BERT模型凭借其卓越性能备受瞩目。然而,对于许多研究者而言,如何高效运用BERT进行特定任务的微调及应用仍存在诸多困惑。本文......
  • 推荐一款业内领先的建模工具:SAP PowerDesigner
    SAPPowerDesigner是一款业内领先的建模工具,帮助您改进商务智能,打造更卓越的信息架构。通过该软件的元数据管理功能,可以构建关键信息资产的360度全方位视图,从而使数据管理、BI、数据集成和数据整合工作大获裨益。其分析功能有助于整个信息架构中进行相关变更时,缩短时间,降低风......
  • 微调LLM时,full、freeze、lora区别
    LLama-Factory支持full、freeze、lora三种微调,区别:1.Full微调:Full微调是指在微调过程中更新整个模型的所有参数。这意味着所有的层和参数都会被更新,并且在微调期间都会参与训练。Full微调通常用于对模型进行全面的调整,以适应新的任务或领域。2.Freeze微调:Freeze微调是指在微调......
  • LLM的Prompt竟然是图灵完备的?LLM提示范式的第一个研究 | 重磅
    LLM的Prompt竟然是图灵完备的?LLM提示范式的第一个研究|重磅原创 AI修猫Prompt AI修猫Prompt 2024年11月07日08:10 北京点击上方蓝字关注我本文:5100字阅读 12分钟 开创性研究揭示Prompt的理论基础近日,伊利诺伊大学香槟分校的研究团队发布了一篇开创性论文,首次从......
  • js 的generator函数是什么
    在JavaScript中,Generator函数(生成器函数)是一种特殊类型的函数,它可以暂停执行并且可以在后续的某个时刻恢复执行。与普通函数不同,Generator函数不会在调用时立即执行,而是返回一个Generator对象,你可以通过该对象控制函数的执行过程。1.如何定义一个Generator函数Generato......
  • 研0找实习【学nlp】12-简历修改篇,应体现的内容
    在申请NLP实习时,简历应该突出与自然语言处理相关的技能和经验。以下是一些建议,帮助你在简历中展示你的能力:简历应体现的内容1.编程语言Python:大多数NLP库和工具都是用Python编写的,因此熟练掌握Python是必不可少的。R或Java(可选):如果你有使用这些语言的经验,可......