【NLP】使用 SpaCy、ollama 创建用于命名实体识别的合成数据集

命名实体识别 (NER) 是自然语言处理 (NLP) 中的一项重要任务,用于自动识别和分类文本中的实体,例如人物、位置、组织等。尽管它很重要,但手动注释大型数据集以进行 NER 既耗时又费钱。受本文 ( https://huggingface.co/blog/synthetic-data-save-costs#31-prompt-an-llm-to-annotate-your-data ) 的启发,我们讨论了一种创新方法,使用 qwen2.5:7b 生成的合成数据来有效应对这些挑战。通过使用合成数据,我们可以有效地训练 NER 模型,以从大量文本语料库(例如金融新闻文章)中提取有意义的信息。

在本教程中,我们将演示如何使用 SpaCy 构建 NER 管道,SpaCy 是一个流行的开源 NLP 库,以其速度和效率而闻名。SpaCy 广泛用于标记化、词性标记和命名实体识别等任务,尤其擅长在 CPU 上快速处理文本。其强大的架构使其无需专门的硬件即可处理大量数据,使其成为许多实际应用的理想选择。

我们将使用 SmoothNLP金融新闻数据集 进行案例研究,展示合成数据如何显著提高 NER 模型的性能并降低与传统数据注释方法相关的成本。通过将合成数据与 SpaCy 集成,我们旨在创建可扩展且准确的 NER 解决方案来处理大规模新闻数据集。

我们的方法

为了克服传统方法的局限性,我们利用合成数据生成在新闻文章中进行 NER。以下是我们流程的分步概述:

步骤 1:数据收集

数据下载地址

步骤 2:使用ollama加载 qwen2.5-7b

1、下载ollama

ollama下载地址(以windows版为例)

2、下载qwen2.5-7b模型

ollama pull qwen2.5

如下图所示为下载完成

我们使用langchain_ollama来启用语言模型 qwen2.5-7b 来注释收集的数据。以下是如何加载模型:

from langchain_ollama import OllamaLLMmodel = OllamaLLM(model="qwen2.5:7b")
model.invoke("你是谁")

这里发生了什么事?

  • qwen2.5-7b模型:我们加载一个大型预先训练的 Qwen模型

步骤 3:准备数据集

1.设置模型后,我们加载样本数据并准备数据集以供处理:

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
import pandas as pd
from tqdm import tqdm
from pydantic import BaseModel, Field, ValidationError
from typing import List
from datasets import Dataset
import spacy
from spacy.tokens import DocBin, Span
import re
import jsonnlp = spacy.load('zh_core_web_sm')financial_news_sample = pd.read_excel("./SmoothNLP金融新闻数据集样本20k.xlsx")
financial_news_sample.head()

数据如图所示 

 2.合并标题和内容

financial_news_sample['text'] = financial_news_sample['title'].str.cat(financial_news_sample['content'], sep='\n')
financial_news_sample.head()

news_texts = [text for text in list(financial_news_sample["text"]) if type(text)==str][-100:]
dataset = Dataset.from_dict({"text": news_texts})

步骤 4:使用 SpaCy 对文本进行标记

我们使用 SpaCy 对文本数据进行标记。标记化是将文本拆分为单个单词或子单词的过程。

def tokenize_with_spacy(texts):tokenized_texts = []token_offsets_list = []for text in texts:if isinstance(text, str):doc = nlp(text)tokens = [token.text for token in doc]token_offsets = [(token.idx, token.idx + len(token.text)) for token in doc]tokenized_texts.append(tokens)token_offsets_list.append(token_offsets)else:raise ValueError(f"Expected a string but got {type(text)}")return tokenized_texts, token_offsets_list

第 5 步:准备 Qwen 的输入

def prepare_qwen_input(tokenized_texts):return [" ".join(tokens) for tokens in tokenized_texts]

步骤 6:查询我们的 Qwen 的提示

接下来,我们创建一个查询 LLM 的系统提示。由于我们想从新闻文章中提取结构化信息,因此我们要求 LLM 以 JSON 格式响应。我们还包含示例输入和输出,以指导模型正确构建其响应。

system_prompt="""
你是一个在自然语言处理和信息提取方面受过训练的高级人工智能。你的任务是阅读以下新闻文章,并提取文中提到的所有人名。对于识别的每个人名,提供具有以下结构的JSON输出:[
{"entity_type":"人名","entity_value":"内容中的人名"}
]
确保提取人名的确切字符串,而不进行任何更正或转换。不要提供任何解释。仅使用JSON结构化数据进行响应。###示例1:
输入:
李明远当选陕西省西安市市长
新华社西安2月19日电 西安市第十六届人民代表大会第四次会议2月18日选举李明远为西安市人民政府市长。输出:
[
{"entity_type":"人名","entity_value":"李明远"},
]###示例2:
输入:
原央行征信中心主任王煜调任中国金融培训中心主任
中国金融培训中心官网显示,原中国人民银行征信中心主任王煜已出任该中心主任。
王煜毕业于五道口央行研究生部,在央行体系工作多年,先后出任过央行货币政策司副司长、央行货币政策委员会秘书长,随后王煜进入征信领域,先后出任央行征信管理局局长、中国人民银行征信中心主任。(澎湃)输出:
[
{"entity_type":"人名","entity_value":"王煜"}
]###示例3:
输入:
人民大学教授叶林:完善法制体系  提高我国期货市场核心竞争力本报见习记者 王宁中国期货市场经过二十多年的探索发展,已经成为金融体系的重要组成部分,为宏观决策部门预研预判经济形势、微观企业进行风险管理提供了有力支持。随着期货市场各项创新以及国际化业务的深入推进,需要的法律支持也越来越多,“尽快出台《期货法》”的呼声越来越高。法治强,则市场兴。如今,中国期货市场已经开启了多元、开放的新时代,这对中国期货市场的法律制度体系提出了更高要求。近日,记者采访了中国人民大学教授叶林,深入解读我国期货市场立法的探索、困境及出台《期货法》的重要意义。记者:目前我国期货市场的有关法律法规都有哪些,相较国际期货市场的主要差距是什么?叶林:二十多年来,我国期货市场法制建设取得了显著的进步,逐渐摸索出了一条适应期货市场发展需要、符合期货市场规律、有中国特色的期货市场法制建设道路。2007年3月,国务院颁布了《期货交易管理条例》,2012年10月、2013年7月、2016年2月和2017年3月进行了四次修订。目前初步形成了以《期货交易管理条例》、最高人民法院司法解释为支撑,以部门规章和规范性文件为配套,以期货交易所、期货业协会自律规则为补充的期货市场法规体系。这一制度体系对于规范期货市场的稳定运行起到了积极作用,但是相较域外期货市场法制而言,存在法律位阶较低、民事规范不完整、跨境监管与协作规范缺失等问题,法律制度并不完备。输出:[
{"entity_type":"人名","entity_value":"叶林"},
{"entity_type":"人名","entity_value":"王宁"} 
]请使用相同的格式继续执行任务。
"""

JSON 是一种轻量级的结构化数据格式,易于通过编程进行解析,因此非常适合自动化和一致性至关重要的机器学习流程。使用 JSON 可以明确定义提取的实体,确保每个识别的实体都遵循标准结构(具有“entity_type”和“entity_value”等字段)。此结构简化了下游任务(例如验证和存储),并确保输出可以轻松集成到其他处理工具或库中。

在提示中提供示例是有益的,因为它有助于指导语言模型理解所需的输出格式和结构。示例充当“指令调整”的一种形式,向模型展示如何以特定方式响应,从而降低生成的输出中出现错误和不一致的可能性。在我们的案例中,使用多个输入文本示例与相应的 JSON 输出配对,向模型展示如何一致地识别和格式化城市名称。这提高了模型响应的可靠性,尤其是在应用于多样化和复杂的现实世界数据时。

步骤 7:从模型响应中提取实体

系统提示准备好后,我们定义一个函数来从模型的输出中提取实体:

def extract_json_from_response(response):try:if isinstance(response, list):return responsematch = re.search(r'(\[.*)', response, re.DOTALL)if match:json_content = match.group(0).strip()if not json_content.endswith(']'):json_content += ']'return json.loads(json_content)except json.JSONDecodeError as e:print(f"Failed to decode JSON: {e}")return []

此函数在响应中查找 JSON 格式的数据并提取它,确保即使响应结构不正确,我们的管道仍然保持稳健。

步骤 8:实体提取的批处理

然后我们设置批处理来有效地处理大型数据集:

rom loguru import loggerdef predict_entities_in_batches(test_dataset, model, system_prompt, batch_size=1):extracted_entities = []for i in tqdm(range(0, len(test_dataset), batch_size), desc="Processing batches"):batch_texts = test_dataset[i:i + batch_size]["text"]batch_prompts = [system_prompt+text for text in batch_texts]logger.info(batch_prompts)results = [model.invoke(batch_prompt) for batch_prompt in batch_prompts]for result in results:generated_text = resultlogger.info(f"result::{result}")assistant_response = generated_textif assistant_response:entities = extract_json_from_response(assistant_response)logger.info(f'entities::{entities}')extracted_entities.append(entities)else:extracted_entities.append(None)return extracted_entitiesprocessed_data = predict_entities_in_batches(dataset, model, system_prompt)

当处理 Qwen2.5 等大型模型和大量数据集时,高效的内存管理至关重要。批处理是一种策略,它通过将数据集划分为较小的块或批次并按顺序处理每个批次来帮助管理内存使用量。这种方法可以防止系统内存耗尽,因为整个数据集不需要一次加载到内存中。它还允许通过根据可用硬件调整批处理大小来更好地控制计算资源(例如 GPU 内存)。

使用批处理还可以优化并行性,其中模型可以在一个批次内同时生成多个数据点的输出。这可以加快处理速度而不会使系统内存过载,从而可以处理数据集(如 SmoothNLP金融新闻数据集)。此外,在批次之间清除内存缓存有助于防止内存碎片化(在处理非常大的数据集时可能会发生这种情况),从而保持性能稳定性。总体而言,批处理可确保计算效率和资源管理之间的平衡,从而实现机器学习管道中大型数据集的可扩展处理。

步骤 9:验证和错误处理

我们使用 Pydantic 模型验证提取的实体,确保数据符合预期格式:

from validators import validatorclass EntityList(BaseModel):def validate_entity_type(entities):entities_last = []try:for entitie in entities:if entitie['entity_type'] != '人名':raise ValueError(f"{v} is not a valid entity type")else:entities_last.append(entitie)except:passreturn entities_lastvalidated_data = []
for i, entities in enumerate(processed_data):try:validated_output = EntityList.validate_entity_type(entities=entities)validated_data.append({"text": dataset[i], "entities": validated_output})except ValidationError as e:print("Validation error:", e)validated_data.append({"text": dataset[i], "entities": None})

这可确保仅接受有效的实体类型(例如city_names)。如果实体类型与预期格式不匹配,则会引发错误。

步骤 10:准备 SpaCy 模型训练的数据

最后,我们使用 SpaCy 的DocBin来存储处理后的数据,包括实体跨度:

def create_spans(doc, entities):"""Creates spaCy spans for detected entities in the text."""spans = []warnings = []for entity in entities:entity_value = entity.get('entity_value', '').strip()entity_type = entity.get('entity_type', '')if not entity_value:warnings.append(f"Skipping empty entity for type: '{entity_type}'")continuestart = 0while True:start = doc.text.find(entity_value, start)if start == -1:breakend = start + len(entity_value)span = doc.char_span(start, end, label=entity_type, alignment_mode="contract")if span:spans.append(span)else:warnings.append(f"Could not create span for entity: '{entity_value}' at position {start}-{end}")start = endreturn spans, warningsdef filter_overlapping_spans(spans):"""Filters out overlapping spans, keeping non-overlapping spans."""filtered_spans = []for span in sorted(spans, key=lambda x: (x.start, -x.end)):if all(span.start >= s.end or span.end <= s.start for s in filtered_spans):filtered_spans.append(span)return filtered_spans
def process_data(data_list):doc_bin = DocBin(store_user_data=True)for item in tqdm(data_list, desc="Processing Data", unit="doc"):text = item.get('text', '')if not text.strip():continueentities = item.get('entities', {}).get('entities', [])doc = nlp(text)spans, warnings = create_spans(doc, entities)doc.ents = filter_overlapping_spans(spans)if warnings:doc._.warnings = warningsdoc_bin.add(doc)return doc_bin

结论

合成数据与 LLAMA3 等高级语言模型的集成对降低命名实体识别 (NER) 任务的成本和提高可扩展性具有重大影响。生成合成数据可以创建大型注释数据集,而无需耗时且昂贵的手动标记过程,从而可以快速训练用于各种 NER 应用程序的模型。大型语言模型 (LLM) 通过利用上下文理解从文本中提取有意义的信息,提供了一种注释这些数据集的有效方法。合成数据生成和 LLM 相结合,为开发高性能 NER 系统提供了一种可扩展的解决方案,能够处理来自 SmoothNLP金融新闻数据集 的大规模文本语料库,例如新闻文章。这种方法不仅可以降低注释成本,还可以确保即使在数据需求很大的情况下也可以大规模训练和部署模型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/59656.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【51单片机】串口通信原理 + 使用

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 串口硬件电路UART串口相关寄存器 编码单片机通过串口发送数据电脑通过串口发送数据控制LED灯 串口 串口是一种应用十分广泛的通讯接…

线程函数和线程启动的几种不同形式

线程函数和线程启动的几种不同形式 在C中&#xff0c;线程函数和线程启动可以通过多种形式实现。以下是几种常见的形式&#xff0c;并附有相应的示例代码。 1. 使用函数指针启动线程 最基本的方式是使用函数指针来启动线程。 示例代码&#xff1a; #include <iostream&g…

C语言网络编程 -- TCP/iP协议

一、Socket简介 1.1 什么是socket socket通常也称作"套接字"&#xff0c;⽤于描述IP地址和端⼝&#xff0c;是⼀个通信链的句柄&#xff0c;应⽤ 程序通常通过"套接字"向⽹络发出请求或者应答⽹络请求。⽹络通信就是两个进程 间的通信&#xff0c;这两个进…

Qt字符编码

目前字符编码有以下几种&#xff1a; 1、UTF-8 UTF-8编码是Unicode字符集的一种编码方式(CEF)&#xff0c;其特点是使用变长字节数(即变长码元序列、变宽码元序列)来编码。一般是1到4个字节&#xff0c;当然&#xff0c;也可以更长。 2、UTF-16 UTF-16是Unicode字符编码五层次…

Linux下的ADC

ADC ADC简介 ADC是 Analog Digital Converter 的缩写&#xff0c;翻译过来为模数转换器&#xff0c;ADC可以将模拟值转换成数字值。模拟值是什么呢?比如我们日常生活中的温度&#xff0c;速度&#xff0c;湿度等等都是模拟值。所以如果我们想测量这些模拟值的值是多少&#x…

理解Web登录机制:会话管理与跟踪技术解析(二)-JWT令牌

JWT令牌是一种用于安全地在各方之间传递信息的开放标准&#xff0c;它不仅能够验证用户的身份&#xff0c;还可以安全地传递有用的信息。由于其结构简单且基于JSON&#xff0c;JWT可以在不同的系统、平台和语言间无缝传递&#xff0c;成为现代Web开发中不可或缺的一部分。 文章…

论 ONLYOFFICE:开源办公套件的深度探索

公主请阅 引言第一部分&#xff1a;ONLYOFFICE 的历史背景1.1 开源软件的崛起1.2 ONLYOFFICE 的发展历程 第二部分&#xff1a;ONLYOFFICE 的核心功能2.1 文档处理2.2 电子表格2.3 演示文稿 第三部分&#xff1a;技术架构与兼容性3.1 技术架构3.2 兼容性 第四部分&#xff1a;部…

sql报错信息将字符串转换为 uniqueidentifier 时失败

报错信息&#xff1a; [42000] [Microsoft][SQL Server Native Client 10.0][SQL Server]将字符串转换为 uniqueidentifier 时失败 出错行如下&#xff1a; 表A.SourceCode 表B.ID 出错原因&#xff1a; SourceCode是nvarchar,但ID是uniqueidentifier 数据库查询字段和类…

[复健计划][紫书]Chapter 7 暴力求解法

7.1 简单枚举 例7-1 Division uva725 输入正整数n&#xff0c;按从小到大的顺序输出所有形如abcde/fghij n的表达式&#xff0c;其中a&#xff5e;j恰好为数字0&#xff5e;9的一个排列&#xff08;可以有前导0&#xff09;&#xff0c;2≤n≤79。枚举fghij&#xff0c;验证a…

大语言模型鼻祖Transformer的模型架构和底层原理

Transformer 模型的出现标志着自然语言处理&#xff08;NLP&#xff09;技术的一次重大进步。这个概念最初是针对机器翻译等任务而提出的&#xff0c;Transformer 后来被拓展成各种形式——每种形式都针对特定的应用&#xff0c;包括原始的编码器-解码器&#xff08;encoder-de…

基于MySQL的企业专利数据高效查询与统计实现

背景 在进行产业链/产业评估工作时&#xff0c;我们需要对企业的专利进行评估&#xff0c;其中一个重要指标是统计企业每一年的专利数量。本文基于MySQL数据库&#xff0c;通过公司名称查询该公司每年的专利数&#xff0c;实现了高效的专利数据统计。 流程 项目流程概述如下&…

canfestival主站多电机对象字典配置

不要使用数组进行命名&#xff1a;无法运行PDO 使用各自命名的方式&#xff1a;

bat批量处理脚本细节研究

文章目录 bat批处理脚本&#xff08;框架&#xff09;set变量设置基本语法显示环境变量 自定义环境变量临时环境变量和永久环境变量特殊环境变量和系统默认环境变量set命令利用选项的其他应用 !与%解析变量的区别/为什么使用setlocal enabledelayedexpansion区别%的规则!使用 %…

Java 网络编程(一)—— UDP数据报套接字编程

概念 在网络编程中主要的对象有两个&#xff1a;客户端和服务器。客户端是提供请求的&#xff0c;归用户使用&#xff0c;发送的请求会被服务器接收&#xff0c;服务器根据请求做出响应&#xff0c;然后再将响应的数据包返回给客户端。 作为程序员&#xff0c;我们主要关心应…

使用C++来编写VTK项目时,就是要写自己的算法

其实&#xff0c;使用VTK可以使用很多种语言&#xff0c;比如java&#xff0c;python&#xff0c;和C。那么为什么非要使用C 呢&#xff1f;一个原因是觉得C语言处理数据比较快&#xff0c;另一个原因是需要自己写算法。通过继承polyDataAlgorithm来写自己的算法&#xff0c;很…

[ 内网渗透实战篇-2 ] 父域子域架构的搭建与安装域环境判断域控定位组策略域森林架构配置信任关系

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

FileLink跨网数据摆渡系统:打破网络隔阂,轻松实现跨网络数据传输

在数字化时代&#xff0c;跨网络、跨区域的数据传输成为了企业和个人信息流通的重大挑战。而如今&#xff0c;FileLink跨网数据摆渡系统的问世&#xff0c;彻底解决了这一难题&#xff0c;帮助用户实现快速、安全、无缝的跨网络数据传输。 1. 跨网络数据传输的痛点 随着企业信…

MySQL_聚合函数分组查询

上篇复习&#xff1a; 设计数据库时的三大范式1.第一范式&#xff0c;一行数据中每一列不可再分 关系型数据库必须要满足第一范式&#xff0c;设计表的时候&#xff0c;如果每一列都可以用SQL规定的数据类型描述&#xff0c;就天然满足第一范式. 2.第二范式&#xff0c;在第一…

【Ai教程】Ollma安装 | 0代码本地运行Qwen大模型,保姆级教程来了!

我们平时使用的ChatGPT、kimi、豆包等Ai对话工具&#xff0c;其服务器都是部署在各家公司的机房里&#xff0c;如果我们有一些隐私数据发到对话中&#xff0c;很难保证信息是否安全等问题&#xff0c;如何在保证数据安全的情况下&#xff0c;又可以使用大预言模型&#xff0c;O…

FastAPI全方位分析:优劣尽显

近年来,随着技术的飞速发展,快速构建高性能API的需求越来越强烈。Python作为一个广泛使用的编程语言,也在这一领域下涌现出了许多优秀的框架。FastAPI便是其中一颗璀璨的新星。 FastAPI以其卓越的性能和独特的功能吸引了众多开发者。本文将深入剖析FastAPI的各个方面,详细…