无锡网站制作企业阳江58房产网
2026/3/14 16:21:14 网站建设 项目流程
无锡网站制作企业,阳江58房产网,推广平台网站制作,网站开发是用模版还是纯手打小白必看#xff01;用Qwen2.5-0.5B实现中文命名实体识别全流程 1. 引言#xff1a;为什么选择Qwen2.5-0.5B做NER任务#xff1f; 在自然语言处理#xff08;NLP#xff09;领域#xff0c;命名实体识别#xff08;Named Entity Recognition, NER#xff09; 是一项基…小白必看用Qwen2.5-0.5B实现中文命名实体识别全流程1. 引言为什么选择Qwen2.5-0.5B做NER任务在自然语言处理NLP领域命名实体识别Named Entity Recognition, NER是一项基础而关键的任务广泛应用于信息抽取、知识图谱构建、智能客服等场景。传统方法依赖于标注数据训练BiLSTM-CRF或BERT类模型但随着大语言模型LLM的发展我们可以通过指令微调Instruction Tuning的方式让通用大模型学会结构化输出能力从而高效完成NER任务。本文面向初学者手把手带你使用阿里开源的轻量级大模型Qwen2.5-0.5B-Instruct基于中文NER数据集 CLUENER2020 实现从环境准备、数据预处理、全参数微调到模型测试的完整流程。该方案具备以下优势✅ 模型体积小仅0.5B适合单卡甚至消费级显卡训练✅ 支持多语言和结构化输出JSON格式天然适配NER任务✅ 提供网页推理接口部署便捷✅ 全程代码可复现附带详细解析通过本教程你将掌握如何将一个通用大模型“教会”执行专业NLP任务的核心思路与工程实践。2. 技术背景与数据准备2.1 Qwen2.5-0.5B模型特性解析Qwen2.5-0.5B-Instruct是通义千问系列中最小的指令调优版本专为轻量化部署和快速迭代设计。其核心能力包括支持最长128K上下文输入适用于长文本理解生成长度可达8K tokens满足复杂结构化输出需求内置对JSON等结构化格式的强解析能力支持超过29种语言其中中文表现尤为出色经过高质量指令微调能准确理解系统提示system prompt这些特性使其非常适合用于需要精确提取并格式化输出实体信息的NER任务。 官方ModelScope地址https://modelscope.cn/models/Qwen/Qwen2.5-0.5B-Instruct2.2 数据集介绍CLUENER2020 中文命名实体识别基准我们采用业界广泛使用的CLUENER2020数据集进行实验包含10类中文实体标签标签类别示例address北京、上海book《三体》company阿里巴巴game英雄联盟government教育部movie流浪地球name张三organization联合国儿童基金会position总经理scene故宫博物院原始数据格式如下{ text: 浙商银行企业信贷部叶老桂博士则从另一个角度对五道门槛进行了解读。, label: { name: {叶老桂: [[9, 11]]}, company: {浙商银行: [[0, 3]]} } }由于我们更关注实体内容而非位置索引因此对数据进行了简化转换仅保留实体名称列表。2.3 数据预处理统一为结构化JSON输出格式为了适配大模型的生成式NER任务我们将原始数据转换为如下格式{ text: 彭小军认为国内银行现在走的是台湾的发卡模式, label: { address: [台湾], name: [彭小军] } }对应的Python转换脚本如下import json def trans(file_path, save_path): with open(save_path, a, encodingutf-8) as w: with open(file_path, r, encodingutf-8) as r: for line in r: line json.loads(line) text line[text] label line[label] trans_label {} for key, items in label.items(): items list(items.keys()) # 只保留实体名 trans_label[key] items trans { text: text, label: trans_label } line json.dumps(trans, ensure_asciiFalse) w.write(line \n) w.flush() if __name__ __main__: trans(ner_data_origin/train.json, ner_data/train.json) trans(ner_data_origin/dev.json, ner_data/val.json)2.4 Token分布分析确定最大序列长度为合理设置输入输出长度我们统计了训练集的Token分布情况from transformers import AutoTokenizer import json import numpy as np def get_token_distribution(file_path, tokenizer): input_tokens, output_tokens [], [] with open(file_path, r, encodingutf-8) as f: for line in f: data json.loads(line) text data[text] label json.dumps(data[label], ensure_asciiFalse) input_tokens.append(len(tokenizer(text).input_ids)) output_tokens.append(len(tokenizer(label).input_ids)) return np.mean(input_tokens), np.max(input_tokens), np.mean(output_tokens), np.max(output_tokens) # 加载 tokenizer tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen2.5-0.5B-Instruct, trust_remote_codeTrue) i_avg, i_max, o_avg, o_max get_token_distribution(ner_data/train.json, tokenizer) print(fInput - Avg: {i_avg:.1f}, Max: {i_max}) print(fOutput - Avg: {o_avg:.1f}, Max: {o_max})结果表明 - 输入最大约50个Token - 输出最大约70个Token据此设定max_source_length 50 # 输入文本最大长度 max_target_length 140 # 输出标签最大长度预留冗余3. 模型微调从零构建NER数据集与训练流程3.1 自定义Dataset类构造对话式训练样本我们利用Qwen的apply_chat_template方法将NER任务构造成“系统指令用户提问”的对话形式激发其结构化输出能力。# ner_dataset.py from torch.utils.data import Dataset import torch import json import numpy as np class NerDataset(Dataset): def __init__(self, data_path, tokenizer, max_source_length, max_target_length): super().__init__() self.tokenizer tokenizer self.max_source_length max_source_length self.max_target_length max_target_length self.max_seq_length max_source_length max_target_length self.data [] if data_path: with open(data_path, r, encodingutf-8) as f: for line in f: if not line.strip(): continue item json.loads(line) self.data.append({ text: item[text], label: json.dumps(item[label], ensure_asciiFalse) }) print(fLoaded {len(self.data)} samples.) def preprocess(self, text, label): messages [ {role: system, content: 你的任务是做NER任务提取根据用户输入提取出完整的实体信息并以JSON格式输出。}, {role: user, content: text}, {role: assistant, content: label} ] # 构造prompt prompt self.tokenizer.apply_chat_template( messages[:-1], tokenizeFalse, add_generation_promptTrue ) response label # 编码输入 input_enc self.tokenizer( prompt, truncationTrue, max_lengthself.max_source_length, paddingmax_length, return_tensorspt, add_special_tokensFalse ) # 编码输出 output_enc self.tokenizer( response, truncationTrue, max_lengthself.max_target_length, paddingmax_length, return_tensorspt, add_special_tokensFalse ) input_ids input_enc[input_ids][0].tolist() attention_mask input_enc[attention_mask][0].tolist() labels [-100] * len(input_ids) output_enc[input_ids][0].tolist() return { input_ids: torch.LongTensor(input_ids), attention_mask: torch.LongTensor(attention_mask), labels: torch.LongTensor(labels) } def __getitem__(self, index): return self.preprocess(**self.data[index]) def __len__(self): return len(self.data) 关键点说明 - 使用-100填充非输出部分的labels确保损失函数只计算Assistant回复部分 -add_generation_promptTrue自动添加|im_start|assistant\n触发生成3.2 训练脚本详解全参数微调策略# train.py import torch from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter from transformers import AutoModelForCausalLM, AutoTokenizer from ner_dataset import NerDataset from tqdm import tqdm import time, sys def train_model(model, train_loader, val_loader, optimizer, device, num_epochs, model_output_dir, writer): batch_step 0 for epoch in range(num_epochs): model.train() start_time time.time() for idx, batch in enumerate(tqdm(train_loader, descfTrain Epoch [{epoch1}/{num_epochs}])): input_ids batch[input_ids].to(device) attention_mask batch[attention_mask].to(device) labels batch[labels].to(device) optimizer.zero_grad() outputs model( input_idsinput_ids, attention_maskattention_mask, labelslabels ) loss outputs.loss loss.backward() optimizer.step() writer.add_scalar(Loss/Train, loss.item(), batch_step) batch_step 1 if idx % 100 0: avg_time (time.time() - start_time) / (idx 1) print(fStep {idx}, Loss: {loss:.4f}, Time per step: {avg_time:.2f}s) # Validation model.eval() val_loss 0.0 with torch.no_grad(): for batch in tqdm(val_loader, descValidation): input_ids batch[input_ids].to(device) attention_mask batch[attention_mask].to(device) labels batch[labels].to(device) outputs model(input_idsinput_ids, attention_maskattention_mask, labelslabels) val_loss outputs.loss.item() val_loss / len(val_loader) writer.add_scalar(Loss/Val, val_loss, epoch) print(fEpoch {epoch1} | Val Loss: {val_loss:.4f}) # Save checkpoint model.save_pretrained(model_output_dir) print(fModel saved to {model_output_dir}) def main(): model_name Qwen/Qwen2.5-0.5B-Instruct train_path ner_data/train.json val_path ner_data/val.json output_dir output_ner log_dir logs device torch.device(cuda if torch.cuda.is_available() else cpu) tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(model_name, trust_remote_codeTrue) # Dataset train_set NerDataset(train_path, tokenizer, max_source_length50, max_target_length140) val_set NerDataset(val_path, tokenizer, max_source_length50, max_target_length140) train_loader DataLoader(train_set, batch_size16, shuffleTrue, num_workers4) val_loader DataLoader(val_set, batch_size16, shuffleFalse) # Optimizer Writer optimizer torch.optim.AdamW(model.parameters(), lr1e-4) writer SummaryWriter(log_dir) model.to(device) train_model( modelmodel, train_loadertrain_loader, val_loaderval_loader, optimizeroptimizer, devicedevice, num_epochs30, model_output_diroutput_dir, writerwriter ) writer.close() if __name__ __main__: main()⚙️ 训练建议 - 显存不足时可降低batch_size至8或4 - 可加入学习率调度器如CosineAnnealingLR - 监控TensorBoard曲线防止过拟合4. 模型测试与效果验证4.1 推理脚本编写# test.py from transformers import AutoModelForCausalLM, AutoTokenizer import torch def predict(text, model, tokenizer, device): messages [ {role: system, content: 你的任务是做NER任务提取根据用户输入提取出完整的实体信息并以JSON格式输出。}, {role: user, content: text} ] prompt tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) inputs tokenizer(prompt, return_tensorspt).to(device) with torch.no_grad(): outputs model.generate( **inputs, max_new_tokens140, do_sampleFalse, # 贪心解码保证稳定性 top_k1 ) # 截取新生成的部分 new_tokens outputs[0][inputs[input_ids].shape[-1]:] response tokenizer.decode(new_tokens, skip_special_tokensTrue) return response # 加载模型 device torch.device(cuda if torch.cuda.is_available() else cpu) model AutoModelForCausalLM.from_pretrained(output_ner, trust_remote_codeTrue).to(device) tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen2.5-0.5B-Instruct, trust_remote_codeTrue) # 测试案例 test_cases [ 三星WCG2011北京赛区魔兽争霸3最终名次, 新华网孟买3月10日电记者聂云印度国防部10日说印度政府当天批准, 证券时报记者肖渔 ] for case in test_cases: result predict(case, model, tokenizer, device) print(f输入: {case}) print(f输出: {result}\n)4.2 实际输出示例输入: 新华网孟买3月10日电记者聂云印度国防部10日说印度政府当天批准 输出: {organization: [新华网], address: [孟买], position: [记者], name: [聂云], government: [印度国防部, 印度政府]}✅ 模型成功识别出媒体、地点、职位、人名和政府机构等多种实体且输出为标准JSON格式便于后续系统集成。5. 总结本文完整展示了如何使用Qwen2.5-0.5B-Instruct实现中文命名实体识别任务的端到端流程数据准备选用CLUENER2020数据集并转换为结构化输出格式模型适配通过对话模板引导模型理解NER任务意图训练实现基于PyTorch和HuggingFace Transformers完成全参数微调推理验证模型能够稳定输出JSON格式的实体识别结果。核心价值总结 - 利用大模型强大的泛化能力和结构化输出能力简化传统NER流水线 - 0.5B小模型即可胜任专业NLP任务适合资源受限场景 - 指令微调范式易于迁移到其他信息抽取任务如关系抽取、事件识别未来可进一步探索 - 结合LoRA进行高效微调节省显存 - 引入Few-shot Prompt提升少样本性能 - 部署为API服务或Web应用获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询