bert新闻标题分类

2024-01-29 07:44
文章标签 分类 bert 新闻标题

本文主要是介绍bert新闻标题分类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用 bert 完成文本分类任务,数据有 20w,来自https://github.com/649453932/Bert-Chinese-Text-Classification-Pytorch/tree/master/THUCNews

 下载即可:

模型使用 bert-base-chinese 下载参考:bert预训练模型下载-CSDN博客

实现了新闻分类,小编在这做个笔记,整个流程也就是对 bert 模型的应用,写了注释,方便学习查看,把代码放这里记录一下:

import os
import torch
from transformers import (get_linear_schedule_with_warmup,BertTokenizer,AdamW,AutoModelForSequenceClassification,AutoConfig
)
from torch.utils.data import DataLoader, dataset
import time
import numpy as np
from sklearn import metrics
from datetime import timedeltadata_dir = 'THUCNews/data'
# 在代码开始部分添加全局变量和函数
global_batch_size = 4  # 初始化为固定的batch_size
max_batch_size = 32  # 根据实际情况设置最大允许的batch_sizedef get_optimal_batch_size():global global_batch_size# 这里是检查GPU可用内存并尝试增大批次大小的逻辑# 具体实现可能需要根据您的设备和任务进行调整# 以下仅为模拟示例,实际操作时请替换为正确的方法free_memory = torch.cuda.memory_allocated() / (1024**3)  # 获取当前GPU空闲显存(单位:GB)optimal_bs = min(max_batch_size, int(free_memory * 0.8))  # 按80%的空闲显存分配批次大小if optimal_bs > global_batch_size:global_batch_size = optimal_bsreturn global_batch_sizedef read_file(path):with open(path, 'r', encoding="UTF-8") as file:docus = file.readlines()newDocus = []for data in docus:newDocus.append(data)return newDocusclass Label_Dataset(dataset.Dataset):  # 建立自定义数据集def __init__(self, data):self.data = datadef __len__(self):  # 返回数据长度return len(self.data)def __getitem__(self, ind):onetext = self.data[ind]content, label = onetext.split('\t')label = torch.LongTensor([int(label)])return content, label# 读取数据内容
trainContent = read_file(os.path.join(data_dir, "train.txt"))
testContent = read_file(os.path.join(data_dir, "test.txt"))
# 封成数据类型
traindataset = Label_Dataset(trainContent)
testdataset = Label_Dataset(testContent)
# 封装成数据加载器
testdataloder = DataLoader(testdataset, batch_size=1, shuffle=False)
batch_size = 1
traindataloder = DataLoader(traindataset, batch_size=get_optimal_batch_size(), shuffle=True)
# 加载器类别名称
class_list = [x.strip() for x in open(os.path.join(data_dir, "class.txt")).readlines()]# 模型名称
pretrained_weights = 'bert-base-chinese'
tokenizer = BertTokenizer.from_pretrained(pretrained_weights)
config = AutoConfig.from_pretrained(pretrained_weights, num_labels=len(class_list))
# 单独指定config,在config中指定分类个数
# 因为是分类任务,用 AutoModelForSequenceClassification
nlp_classif = AutoModelForSequenceClassification.from_pretrained(pretrained_weights,config=config)
# 指定机器
# device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")  # 可能 gpu 显存不够
device = torch.device("cpu")
nlp_classif = nlp_classif.to(device)time_start = time.time() #开始时间
epochs = 2
gradient_accumulation_steps = 1
max_grad_norm =0.1  #梯度剪辑的阀值require_improvement = 1000                 # 若超过1000batch效果还没提升,则提前结束训练
savedir = './myfinetun-bert_chinese/'
os.makedirs(savedir, exist_ok=True)def get_time_dif(start_time):"""获取已使用时间"""end_time = time.time()time_dif = end_time - start_timereturn timedelta(seconds=int(round(time_dif)))def train(model, traindataloder, testdataloder):"""开始训练:param model::param traindataloder::param testdataloder::return:"""start_time = time.time()# 在训练模式下,模型会启用如dropout和batch normalization这样的正则化技术。model.train()# 获取模型中所有可训练参数及其名称。这样可以方便地对不同类型的参数应用不同的优化策略param_optimizer = list(model.named_parameters())# 不需要权重衰减(weight decay/L2正则化)的参数名称部分。通常包括偏置项(bias)和LayerNorm层中的偏差与权重参数no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']# 创建了两个参数组,分别对需要和不需要权重衰减的参数应用不同的权重衰减率。第一组设置了0.01的权重衰减,第二组不进行权重衰减optimizer_grouped_parameters = [{'params': [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)], 'weight_decay': 0.01},{'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}]# :使用AdamW优化器初始化模型参数。AdamW是对Adam优化器的一个改进版本,它确保了权重衰减在梯度更新之前被正确应用。# 这里的lr表示学习率,设置为5e-5;eps是Adam算法中的一个稳定系数,设置为1e-8optimizer = AdamW(optimizer_grouped_parameters, lr=5e-5, eps=1e-8)# 创建一个线性学习率调度器,并带有预热阶段(warmup)。这里没有设置预热步数(num_warmup_steps),# 意味着没有预热阶段;num_training_steps 设置为整个训练过程中迭代的总步数,# 即训练数据加载器循环次数乘以轮数(epochs)。随着训练的进行,学习率将按照预先设定的方式逐渐降低,从而有助于模型收敛并防止过拟合。scheduler = get_linear_schedule_with_warmup(optimizer,num_warmup_steps=0, num_training_steps=len(traindataloder) * epochs)total_batch = 0  # 记录进行到多少batchdev_best_loss = float('inf')last_improve = 0  # 记录上次验证集loss下降的batch数flag = False  # 记录是否很久没有效果提升for epoch in range(epochs):print('Epoch [{}/{}]'.format(epoch + 1, epochs))# sku_name代表文本序列,labels代表对应的类别标签。for i, (sku_name, labels) in enumerate(traindataloder):model.train()# 使用BERT分词器对文本序列进行编码,并根据需要补全至最大长度,同时将结果转换为PyTorch张量格式ids = tokenizer.batch_encode_plus(sku_name,#                max_length=model.config.max_position_embeddings,  #模型的配置文件中就是512,当有超过这个长度的会报错pad_to_max_length=True, return_tensors='pt')#没有return_tensors会返回list!!!!# 清零优化器中的梯度累计信息,准备进行新的反向传播过程optimizer.zero_grad()# 将标签数据从CPU转移到指定设备(如GPU)上,并去除可能存在的额外维度labels = labels.squeeze().to(device)# 将编码后的输入ID、标签和注意力掩码传入模型进行前向传播计算,得到损失和其他输出outputs = model(ids["input_ids"].to(device), labels=labels,attention_mask=ids["attention_mask"].to(device))# 从模型返回的结果中提取损失值和logits(未归一化的预测概率)loss, logits = outputs[:2]# 如果设置了梯度累积步骤大于1,则需要将损失除以这个值,这样在多个小批次上累积更新梯度if gradient_accumulation_steps > 1:loss = loss / gradient_accumulation_steps# 计算梯度并反向传播到模型参数loss.backward()# 每经过gradient_accumulation_steps次迭代后if (i + 1) % gradient_accumulation_steps == 0:# 对模型所有参数的梯度进行裁剪,防止梯度过大导致训练不稳定torch.nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm)optimizer.step()  # 应用梯度更新模型参数。scheduler.step()  # 更新学习率调度器,根据当前训练步数调整学习率model.zero_grad()  # 再次清零梯度,为下一批次的训练做准备'''评估模型在训练集和验证集上的性能,并根据验证集上的表现做出相应的决策:'''if total_batch % 100 == 0:# 每多少轮输出在训练集和验证集上的效果truelabel = labels.data.cpu()  # 真实类别predic = torch.argmax(logits,axis=1).data.cpu()  # 预测类别#                predic = torch.max(outputs.data, 1)[1].cpu()train_acc = metrics.accuracy_score(truelabel, predic)  # 比较dev_acc, dev_loss = evaluate(model, testdataloder)  # 计算验证集上的准确率和损失值if dev_loss < dev_best_loss:'''比较当前验证集损失与历史最优验证集损失(dev_best_loss),如果当前损失更低,则更新最优损失并保存模型至预设路径(savedir),同时记录最后一次改善的批次索引(last_improve)'''dev_best_loss = dev_lossmodel.save_pretrained(savedir)improve = '*'last_improve = total_batchelse:improve = ''# 输出当前迭代次数、训练损失、训练准确率、验证损失、验证准确率以及已用时间time_dif = get_time_dif(start_time)msg = 'Iter: {0:>6},  Train Loss: {1:>5.2},  Train Acc: {2:>6.2%},  Val Loss: {3:>5.2},  Val Acc: {4:>6.2%},  Time: {5} {6}'print(msg.format(total_batch, loss.item(), train_acc, dev_loss, dev_acc, time_dif, improve))model.train()total_batch += 1  # 增加累计批次计数器'''如果自上次验证集损失下降以来已经过去了超过指定数量的批次(这里是1000批次),并且在这期间验证集损失未再降低,则自动停止训练,打印提示信息,并跳出循环。'''if total_batch - last_improve > require_improvement:# 验证集loss超过1000batch没下降,结束训练print("No optimization for a long time, auto-stopping...")flag = Truebreakif flag:breakdef evaluate(model, testdataloder):model.eval()loss_total = 0predict_all = np.array([], dtype=int)labels_all = np.array([], dtype=int)with torch.no_grad():for sku_name, labels in testdataloder:ids = tokenizer.batch_encode_plus( sku_name,#                max_length=model.config.max_position_embeddings,  #模型的配置文件中就是512,当有超过这个长度的会报错pad_to_max_length=True,return_tensors='pt')#没有return_tensors会返回list!!!!labels = labels.squeeze().to(device)outputs = model(ids["input_ids"].to(device), labels=labels,attention_mask =ids["attention_mask"].to(device) )loss, logits = outputs[:2]loss_total += losslabels = labels.data.cpu().numpy()predic = torch.argmax(logits, axis=1).data.cpu().numpy()labels_all = np.append(labels_all, labels)predict_all = np.append(predict_all, predic)acc = metrics.accuracy_score(labels_all, predict_all)return acc, loss_total / len(testdataloder)train(nlp_classif, traindataloder, testdataloder)

代码输出结果会生成一个文件夹:myfinetun-bert_chinese 里面存放的是模型,最后会生成一个 best 模型,我这里没跑完哈,所以结果不全

这篇关于bert新闻标题分类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/656215

相关文章

Pytorch微调BERT实现命名实体识别

《Pytorch微调BERT实现命名实体识别》命名实体识别(NER)是自然语言处理(NLP)中的一项关键任务,它涉及识别和分类文本中的关键实体,BERT是一种强大的语言表示模型,在各种NLP任务中显著... 目录环境准备加载预训练BERT模型准备数据集标记与对齐微调 BERT最后总结环境准备在继续之前,确

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

BERT 论文逐段精读【论文精读】

BERT: 近 3 年 NLP 最火 CV: 大数据集上的训练好的 NN 模型,提升 CV 任务的性能 —— ImageNet 的 CNN 模型 NLP: BERT 简化了 NLP 任务的训练,提升了 NLP 任务的性能 BERT 如何站在巨人的肩膀上的?使用了哪些 NLP 已有的技术和思想?哪些是 BERT 的创新? 1标题 + 作者 BERT: Pre-trainin

8. 自然语言处理中的深度学习:从词向量到BERT

引言 深度学习在自然语言处理(NLP)领域的应用极大地推动了语言理解和生成技术的发展。通过从词向量到预训练模型(如BERT)的演进,NLP技术在机器翻译、情感分析、问答系统等任务中取得了显著成果。本篇博文将探讨深度学习在NLP中的核心技术,包括词向量、序列模型(如RNN、LSTM),以及BERT等预训练模型的崛起及其实际应用。 1. 词向量的生成与应用 词向量(Word Embedding)

用Pytho解决分类问题_DBSCAN聚类算法模板

一:DBSCAN聚类算法的介绍 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,DBSCAN算法的核心思想是将具有足够高密度的区域划分为簇,并能够在具有噪声的空间数据库中发现任意形状的簇。 DBSCAN算法的主要特点包括: 1. 基于密度的聚类:DBSCAN算法通过识别被低密

PMP–一、二、三模–分类–14.敏捷–技巧–看板面板与燃尽图燃起图

文章目录 技巧一模14.敏捷--方法--看板(类似卡片)1、 [单选] 根据项目的特点,项目经理建议选择一种敏捷方法,该方法限制团队成员在任何给定时间执行的任务数。此方法还允许团队提高工作过程中问题和瓶颈的可见性。项目经理建议采用以下哪种方法? 易错14.敏捷--精益、敏捷、看板(类似卡片)--敏捷、精益和看板方法共同的重点在于交付价值、尊重人、减少浪费、透明化、适应变更以及持续改善等方面。

【python计算机视觉编程——8.图像内容分类】

python计算机视觉编程——8.图像内容分类 8.图像内容分类8.1 K邻近分类法(KNN)8.1.1 一个简单的二维示例8.1.2 用稠密SIFT作为图像特征8.1.3 图像分类:手势识别 8.2贝叶斯分类器用PCA降维 8.3 支持向量机8.3.2 再论手势识别 8.4 光学字符识别8.4.2 选取特征8.4.3 多类支持向量机8.4.4 提取单元格并识别字符8.4.5 图像校正

PMP–一、二、三模–分类–14.敏捷–技巧–原型MVP

文章目录 技巧一模14.敏捷--原型法--项目生命周期--迭代型生命周期,通过连续的原型或概念验证来改进产品或成果。每个新的原型都能带来新的干系人新的反馈和团队见解。题目中明确提到需要反馈,因此原型法比较好用。23、 [单选] 一个敏捷团队的任务是开发一款机器人。项目经理希望确保在机器人被实际建造之前,团队能够收到关于需求的早期反馈并相应地调整设计。项目经理应该使用以下哪一项来实现这个目标?