深度学习每周学习总结N4:中文文本分类-Pytorch实现(基本分类(熟悉流程)、textCNN分类(通用模型)、Bert分类(模型进阶))

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊 | 接辅导、项目定制

目录

    • 0. 总结:
    • 1. 基础模型
      • a. 数据加载
      • b. 数据预处理
      • c. 模型搭建与初始化
      • d. 训练函数
      • e. 评估函数
      • f.拆分数据集运行模型
      • g. 结果可视化
      • h. 测试指定数据
    • 2. TextCNN(通用模型-待拓展)
    • 3. Bert(高级模型-待拓展)

0. 总结:

之前有学习过文本预处理的环节,对文本处理的主要方式有以下三种:

1:词袋模型(one-hot编码)

2:TF-IDF

3:Word2Vec(词向量(Word Embedding) 以及Word2vec(Word Embedding 的方法之一))

详细介绍及中英文分词详见pytorch文本分类(一):文本预处理

上上期主要介绍Embedding,及EmbeddingBag 使用示例(对词索引向量转化为词嵌入向量) ,上期主要介绍:应用三种模型的英文分类

本期将主要介绍中文基本分类(熟悉流程)、拓展:textCNN分类(通用模型)、拓展:Bert分类(模型进阶)

1. 基础模型

a. 数据加载

import torch
import torch.nn as nn
import torchvision
from torchvision import transforms,datasetsimport numpy as np
import pandas as pdimport os,PIL,pathlib,warnings
import matplotlib.pyplot as plt
import warningswarnings.filterwarnings("ignore") # 忽略警告信息
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False   # 用来正常显示负号
plt.rcParams['figure.dpi'] = 100  # 分辨率
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device
device(type='cuda')
# 加载自定义中文数据集
train_data = pd.read_csv('./data/N4-train.csv',sep = '\t',header = None)
train_data.head()
01
0还有双鸭山到淮阴的汽车票吗13号的Travel-Query
1从这里怎么回家Travel-Query
2随便播放一首专辑阁楼里的佛里的歌Music-Play
3给看一下墓王之王嘛FilmTele-Play
4我想看挑战两把s686打突变团竞的游戏视频Video-Play
train_data[0]
0                  还有双鸭山到淮阴的汽车票吗13号的
1                            从这里怎么回家
2                   随便播放一首专辑阁楼里的佛里的歌
3                          给看一下墓王之王嘛
4              我想看挑战两把s686打突变团竞的游戏视频...             
12095          一千六百五十三加三千一百六十五点六五等于几
12096                      稍小点客厅空调风速
12097    黎耀祥陈豪邓萃雯畲诗曼陈法拉敖嘉年杨怡马浚伟等到场出席
12098                  百事盖世群星星光演唱会有谁
12099                 下周一视频会议的闹钟帮我开开
Name: 0, Length: 12100, dtype: object
# 构建数据迭代器
def custom_data_iter(texts,labels):for x,y in zip(texts,labels):yield x,ytrain_iter = custom_data_iter(train_data[0].values[:],train_data[1].values[:])

b. 数据预处理

# 构建词典
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
import jieba# 中文分词方法
tokenizer = jieba.lcut # jieba.cut返回的是一个生成器,而jieba.lcut返回的是一个列表def yield_tokens(data_iter):for text,_ in data_iter:yield tokenizer(text)vocab = build_vocab_from_iterator(yield_tokens(train_iter),specials=["<unk>"])
vocab.set_default_index(vocab["<unk>"])
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\Cheng\AppData\Local\Temp\jieba.cache
Loading model cost 0.549 seconds.
Prefix dict has been built successfully.
tokenizer('我想看和平精英上战神必备技巧的游戏视频')
['我', '想', '看', '和平', '精英', '上', '战神', '必备', '技巧', '的', '游戏', '视频']
vocab(['我','想','看','和平','精英','上','战神','必备','技巧','的','游戏','视频'])
[2, 10, 13, 973, 1079, 146, 7724, 7574, 7793, 1, 186, 28]
text_pipeline = lambda x:vocab(tokenizer(x))
label_pipeline = lambda x:label_name.index(x)
label_name = list(set(train_data[1].values[:]))
print(label_name)
['HomeAppliance-Control', 'Audio-Play', 'Other', 'Weather-Query', 'Music-Play', 'Travel-Query', 'TVProgram-Play', 'Alarm-Update', 'Video-Play', 'Calendar-Query', 'FilmTele-Play', 'Radio-Listen']

print(text_pipeline('我想看和平精英上战神必备技巧的游戏视频'))
print(label_pipeline('Video-Play'))
[2, 10, 13, 973, 1079, 146, 7724, 7574, 7793, 1, 186, 28]
8
# 生成数据批次和迭代器
from torch.utils.data import DataLoaderdef collate_batch(batch):label_list,text_list,offsets = [],[],[0]for (_text,_label) in batch:# 标签列表label_list.append(label_pipeline(_label))# 文本列表processed_text = torch.tensor(text_pipeline(_text),dtype = torch.int64)text_list.append(processed_text)# 偏移量(即语句的总词汇量)offsets.append(processed_text.size(0))label_list = torch.tensor(label_list,dtype = torch.int64)text_list = torch.cat(text_list)offsets = torch.tensor(offsets[:-1]).cumsum(dim=0) # 返回维度dim中输入元素的累计和return text_list.to(device),label_list.to(device),offsets.to(device)# 数据加载器,调用示例
dataloader = DataLoader(train_iter,batch_size = 8,shuffle = False,collate_fn = collate_batch)

c. 模型搭建与初始化

from torch import nnclass TextClassificationModel(nn.Module):def __init__(self,vocab_size,embed_dim,num_class):super(TextClassificationModel,self).__init__()self.embedding = nn.EmbeddingBag(vocab_size,  # 词典大小embed_dim,   # 嵌入维度sparse=False)self.fc = nn.Linear(embed_dim,num_class)self.init_weights()def init_weights(self):initrange = 0.5self.embedding.weight.data.uniform_(-initrange,initrange) # 初始化权重self.fc.weight.data.uniform_(-initrange,initrange)self.fc.bias.data.zero_()def forward(self,text,offsets):embedded = self.embedding(text,offsets)return self.fc(embedded)
# 初始化模型
num_class = len(label_name)
vocab_size = len(vocab)
em_size = 64
model = TextClassificationModel(vocab_size,em_size,num_class).to(device)

d. 训练函数

import timedef train(dataloader):size = len(dataloader.dataset) # 训练集的大小num_batches = len(dataloader)  # 批次数目, (size/batch_size,向上取整)train_acc,train_loss = 0,0 # 初始化训练损失和正确率for idx,(text,label,offsets) in enumerate(dataloader):# 计算预测误差predicted_label = model(text,offsets)   # 网络输出loss = criterion(predicted_label,label) # 计算网络输出和真实值之间的差距,label为真实值,计算二者差值即为损失# 反向传播optimizer.zero_grad() # grad属性归零loss.backward() # 反向传播torch.nn.utils.clip_grad_norm_(model.parameters(),0.1)optimizer.step() # 每一步自动更新# 记录acc与losstrain_acc += (predicted_label.argmax(1) == label).sum().item()train_loss  += loss.item()train_acc /= sizetrain_loss /= num_batchesreturn train_acc,train_loss

e. 评估函数

import timedef evaluate(dataloader):test_acc,test_loss,total_count = 0,0,0with torch.no_grad():for idx,(text,label,offsets) in enumerate(dataloader):# 计算预测误差predicted_label = model(text,offsets)loss = criterion(predicted_label,label)# 记录测试数据test_acc += (predicted_label.argmax(1) == label).sum().item()test_loss += loss.item()total_count += label.size(0)return test_acc/total_count,test_loss/total_count

f.拆分数据集运行模型

from torch.utils.data.dataset import random_split
from torchtext.data.functional import to_map_style_dataset
# 超参数
EPOCHS     = 10 # epoch
LR         = 5  # 学习率
BATCH_SIZE = 64 # batch size for trainingcriterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=LR)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1.0, gamma=0.1)
total_accu = None# 构建数据集
train_iter = custom_data_iter(train_data[0].values[:], train_data[1].values[:])
train_dataset = to_map_style_dataset(train_iter)split_train_, split_valid_ = random_split(train_dataset,[int(len(train_dataset)*0.8),int(len(train_dataset)*0.2)])train_dataloader = DataLoader(split_train_, batch_size=BATCH_SIZE,shuffle=True, collate_fn=collate_batch)valid_dataloader = DataLoader(split_valid_, batch_size=BATCH_SIZE,shuffle=True, collate_fn=collate_batch)
import copytrain_acc = []
train_loss = []
test_acc = []
test_loss = []best_acc = None # 设置一个最佳准确率,作为最佳模型的判别指标for epoch in range(1, EPOCHS + 1):epoch_start_time = time.time()model.train() # 切换为训练模式epoch_train_acc,epoch_train_loss = train(train_dataloader)model.eval() # 切换为测试模式epoch_test_acc,epoch_test_loss = evaluate(valid_dataloader)if best_acc is not None and best_acc > epoch_test_acc:scheduler.step()else:best_acc = epoch_test_accbest_model = copy.deepcopy(model)train_acc.append(epoch_train_acc)train_loss.append(epoch_train_loss)test_acc.append(epoch_test_acc)test_loss.append(epoch_test_loss)# 获取当前的学习率lr = optimizer.state_dict()['param_groups'][0]['lr']template = ('Epoch:{:2d},Train_acc:{:.1f}%,Train_loss:{:.3f},Test_acc:{:.1f}%,Test_loss:{:.3f},Lr:{:.2E}')print(template.format(epoch,epoch_train_acc*100,epoch_train_loss,epoch_test_acc*100,epoch_test_loss,lr))print('Done!')
Epoch: 1,Train_acc:63.8%,Train_loss:1.339,Test_acc:79.5%,Test_loss:0.012,Lr:5.00E+00
Epoch: 2,Train_acc:83.2%,Train_loss:0.592,Test_acc:84.8%,Test_loss:0.008,Lr:5.00E+00
Epoch: 3,Train_acc:88.2%,Train_loss:0.413,Test_acc:86.8%,Test_loss:0.007,Lr:5.00E+00
Epoch: 4,Train_acc:91.1%,Train_loss:0.313,Test_acc:87.6%,Test_loss:0.006,Lr:5.00E+00
Epoch: 5,Train_acc:93.3%,Train_loss:0.241,Test_acc:89.8%,Test_loss:0.006,Lr:5.00E+00
Epoch: 6,Train_acc:95.0%,Train_loss:0.189,Test_acc:89.8%,Test_loss:0.006,Lr:5.00E-01
Epoch: 7,Train_acc:96.7%,Train_loss:0.144,Test_acc:89.6%,Test_loss:0.006,Lr:5.00E-02
Epoch: 8,Train_acc:96.8%,Train_loss:0.139,Test_acc:89.6%,Test_loss:0.006,Lr:5.00E-03
Epoch: 9,Train_acc:96.8%,Train_loss:0.139,Test_acc:89.6%,Test_loss:0.006,Lr:5.00E-04
Epoch:10,Train_acc:96.8%,Train_loss:0.139,Test_acc:89.6%,Test_loss:0.005,Lr:5.00E-05
Done!

g. 结果可视化

epochs_range = range(EPOCHS)plt.figure(figsize=(12,3))
plt.subplot(1,2,1)plt.plot(epochs_range,train_acc,label='Training Accuracy')
plt.plot(epochs_range,test_acc,label='Test Accuracy')
plt.legend(loc = 'lower right')
plt.title('Training and Validation Accuracy')plt.subplot(1,2,2)
plt.plot(epochs_range,train_loss,label='Train Loss')
plt.plot(epochs_range,test_loss,label='Test Loss')
plt.legend(loc = 'lower right')
plt.title('Training and Validation Loss')
plt.show()


在这里插入图片描述

h. 测试指定数据

注意以下俩种测试方法,必须保证模型和数据在同样的设备上(GPU或CPU)

def predict(text, text_pipeline):with torch.no_grad():text = torch.tensor(text_pipeline(text))output = model(text, torch.tensor([0]))return output.argmax(1).item()# ex_text_str = "随便播放一首专辑阁楼里的佛里的歌"
ex_text_str = "还有双鸭山到淮阴的汽车票吗13号的"model = model.to("cpu")print("该文本的类别是:%s" %label_name[predict(ex_text_str, text_pipeline)])
该文本的类别是:Travel-Query

def predict(text, text_pipeline, model, device):model.eval()  # 切换为评估模式with torch.no_grad():# 将文本和偏移量张量都移动到相同的设备text = torch.tensor(text_pipeline(text)).to(device)offsets = torch.tensor([0]).to(device)output = model(text, offsets)return output.argmax(1).item()ex_text_str = "还有双鸭山到淮阴的汽车票吗13号的"# 确保模型在设备上
model = model.to(device)print("该文本的类别是:%s" % label_name[predict(ex_text_str, text_pipeline, model, device)])
该文本的类别是:Travel-Query

2. TextCNN(通用模型-待拓展)


3. Bert(高级模型-待拓展)


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

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

相关文章

C++STL初阶(7):list的运用与初步了解

在了解了vector之后&#xff0c;我们只需要简单学习List与vector不一样的接口即可 1.list的基本接口 1.1 iterator list中&#xff0c;与vector最大的区别就是迭代器由随机迭代器变成双向迭代器 string和vector中的迭代器都是随机迭代器&#xff0c;支持-等&#xff0c;而LIS…

达梦数据库 MPP集群搭建(带主备)

MPP集群搭建&#xff08;带主备&#xff09; 1.背景2.操作内容和要求3. 具体步骤3.1 搭建过程3.1.1 集群搭建3.1.2 准备工作3.1.2.1 初始化3.1.2.2 备份数据库 3.1.3 配置主库EP013.1.3.1 配置dm.ini3.1.3.2 配置dmmal.ini3.1.3.3 配置dmarch.ini3.1.3.4 配置dmmpp.ctl3.1.3.5 …

Seata 面试题及答案整理,最新面试题

Seata 是如何解决分布式事务问题的? Seata通过事务协调器、事务管理器和资源管理器三个核心组件来解决分布式事务问题。 1、事务协调器(TC): TC作为全局事务的协调者,负责维护全局和分支事务的状态,并协调全局提交或回滚。 2、事务管理器(TM): TM负责定义全局事务的范…

百度文心大模型4.0 Turbo面向企业开放 多款旗舰模型降价

在2024年世界人工智能大会期间&#xff0c;百度副总裁谢广军宣布了文心一言4.0Turbo模型对企业用户的全面开放&#xff0c;并介绍了其定价策略。文心一言4.0Turbo的输入定价为0.03元/千Tokens&#xff0c;输出定价为0.06元/千Tokens。谢广军指出&#xff0c;如果按照3:1的输入输…

ArcGIS Pro SDK (九)几何 7 多点

ArcGIS Pro SDK &#xff08;九&#xff09;几何 7 多点 文章目录 ArcGIS Pro SDK &#xff08;九&#xff09;几何 7 多点1 构造多点 - 从映射点的枚举2 构造多点 - 使用 MultipointBuilderEx3 修改多点的点4 从多点检索点、2D 坐标、3D 坐标 环境&#xff1a;Visual Studio 2…

Golang | Leetcode Golang题解之第263题丑数

题目&#xff1a; 题解&#xff1a; var factors []int{2, 3, 5}func isUgly(n int) bool {if n < 0 {return false}for _, f : range factors {for n%f 0 {n / f}}return n 1 }

Linux云计算 |【第一阶段】SERVICES-DAY4

主要内容&#xff1a; DHCP概述、PXE批量装机、配置PXE引导、Kickstart自动应答、Cobbler装机平台 一、DHCP服务概述及原理 DHCP动态主机配置协议&#xff08;Dynamic Host Configuration Protocol&#xff09;&#xff0c;由IETF&#xff08;Internet网络工程师任务小组&…

Ruby教程

Ruby是一种动态的、面向对象的、解释型的脚本语言&#xff0c;以其简洁和易读性而闻名。Ruby的设计哲学强调程序员的生产力和代码的可读性&#xff0c;同时也融合了功能性和面向对象编程的特性。 以下是一个基础的Ruby教程&#xff0c;涵盖了一些基本概念和语法&#xff1a; …

IMU提升相机清晰度

近期&#xff0c;一项来自北京理工大学和北京师范大学的团队公布了一项创新性的研究成果&#xff0c;他们将惯性测量单元&#xff08;IMU&#xff09;和图像处理算法相结合&#xff0c;显著提升了非均匀相机抖动下图像去模糊的准确性。 研究团队利用IMU捕捉相机的运动数据&…

通过 EMR Serverless Spark 提交 PySpark 流任务

在大数据快速发展的时代&#xff0c;流式处理技术对于实时数据分析至关重要。EMR Serverless Spark提供了一个强大而可扩展的平台&#xff0c;它不仅简化了实时数据处理流程&#xff0c;还免去了服务器管理的烦恼&#xff0c;提升了效率。本文将指导您使用EMR Serverless Spark…

巧用Vue3 composition api的计算属性实现扁平化tree连线

本示例节选自vue3最新开源组件实战教程大纲&#xff08;持续更新中&#xff09;的tree组件开发部分。将进一步把基于Vue3 composition api的computed计算属性特性应用到组件开发实战中&#xff0c;继续以最佳实践的方式呈现给大家。 下面我们要实现的是扁平化的dom结构所呈现的…

我去,怎么http全变https了

项目场景&#xff1a; 在公司做的一个某地可视化项目。 部署采用的是前后端分离部署&#xff0c;图片等静态资源请求一台minio服务器。 项目平台用的是http 图片资源的服务器用的是https 问题描述 在以https请求图片资源时&#xff0c;图片请求成功报200。 【现象1】: 继图…

IDEA性能优化方法解决卡顿

文章目录 前言一、可以采取以下措施&#xff1a;二、VM Options的参数解释1. 内存设置2. 性能调优3. GC&#xff08;垃圾回收&#xff09;调优4. 调试和诊断5. 其它设置6.设置 VM Options 的步骤&#xff1a; 总结 前言 我们在使用 IntelliJ IDEA的时候有时候会觉得卡顿&#x…

苹果电脑pdf合并软件 苹果电脑合并pdf 苹果电脑pdf怎么合并

在数字化办公日益普及的今天&#xff0c;pdf文件因其跨平台兼容性强、格式稳定等特点&#xff0c;已经成为工作、学习和生活中不可或缺的文件格式。然而&#xff0c;我们常常面临一个问题&#xff1a;如何将多个pdf文件合并为一个&#xff1f;这不仅有助于文件的整理和管理&…

Go解析JSON字符串到map或结构体

Go解析JSON字符串到map或结构体 解析JSON字符串到Go的map解析JSON字符串到Go的结构体 解析JSON字符串到Go的map package main import ( "encoding/json" "fmt" "log" ) func main() { // 假设这是你要解析的JSON字符串 jsonStr : {&qu…

阿里云服务器 篇三:提交搜索引擎收录

文章目录 系列文章推荐:为网站注册域名判断网站是否已被搜索引擎收录主动提交搜索引擎收录未查询到收录结果时,根据提示进行提交网站提交网站时一般需要登录账号主动提交网站可缩短爬虫发现网站链接时间,但不保证一定能够收录所提交的网站百度提交地址360搜索提交地址搜狗提…

最新!CSSCI(2023-2024)期刊目录公布!

【SciencePub学术】据鲁迅美术学院7月16日消息&#xff0c;近日&#xff0c;南京大学中国社会科学研究评价中心公布了中文社会科学引文索引&#xff08;CSSCI&#xff09;&#xff08;2023—2024&#xff09;数据库最新入选目录。 C刊一般指CSSCI来源期刊&#xff0c;即南大核心…

Python的列表操作有哪些

Python的列表操作非常丰富&#xff0c;包括列表的创建、元素的访问、修改、添加、删除、切片、排序等多个方面。以下是具体的列表操作&#xff1a; 一、列表的创建 使用方括号[]直接创建&#xff1a;可以直接在方括号中列出元素&#xff0c;元素之间用逗号分隔。例如&#xf…

Python 合并两个有序数组

Python 合并两个有序数组 正文 正文 题目说明如下&#xff1a; 这里我们直接让 nums1 的后 n 个数等于 nums2 数组&#xff0c;然后对 nums1 数组整体进行排序即可。 class Solution:def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:"…

​数据结构之初始二叉树(3)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 二叉树的基本操作 通过上篇文章的学习&#xff0c;我们简单的了解了二叉树的相关操作。接下来就是有…