第N4周:中文文本分类——Pytorch实现

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

数据集:train

 一.加载数据

import torch
import torch.nn as nn
import torchvision
from torchvision import transforms,datasets
import os,PIL,pathlib,warnings
 
warnings.filterwarnings("ignore")
 
 
device = torch.device("cuda"if torch.cuda.is_available() else"cpu")
device

#获取数据
import pandas as pd
train_data = pd.read_csv('D:/BaiduNetdiskDownload/train.csv',sep='\t',header=None)
train_data.head()

 

#构建数据的迭代器
def coustom_data_iter(texts,labels):
    for x,y in zip(texts,labels):
        yield x,y
        
train_iter = coustom_data_iter(train_data[0].values[:],train_data[1].values[:])

 二.数据处理

1.构建词典

from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
import jieba 
 
tokenizer =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>"])

vocab(['随便','播放','一','首','歌','我'])
out:[173, 4, 181, 0, 108, 2]
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)


print(text_pipeline('我想看'))
print(label_pipeline('HomeAppliance-Control'))

创建了两个lambda函数,一个用于将文本转换成词汇索引,另一个用于将标签文本转换成它们在label_name列表中的索引。

除了一般使用def声明的函数外,Python中还支持lambda匿名函数,可以在任何场合替代def函数。
匿名函数,通常指的是运行时临时创建的,没有显示命名的函数,它允许快速定义简单的函数。

语法

lambda arguments :expression

lambda argument1,argument2...,argumentn : expression using arguments

        lambda 是关键字
  arguments是参数,可以是0个或多个,用逗号分割
  expression是一个表达式,描述了函数的返回值

lambda关键字用于创建小巧的匿名函数。lambda a, b: a+b 函数返回两个参数的和。Lambda 函数可用于任何需要函数对象的地方。在语法上,匿名函数只能是单个表达式。在语义上,它只是常规函数定义的语法糖。与嵌套函数定义一样,lambda 函数可以引用包含作用域中的变量。

优点:

  简洁:lambda表达式可以快速定义简单的函数,无需使用def语句。
  匿名:由于lambda表达式没有正式的函数名称,因此它们是匿名的,可以用于需要短生命周期函数的情况。
  轻量级:lambda表达式只包含一个表达式,因此它们占用内存空间较小,适合用于小型任务。
  可嵌套:Lambda表达式可以嵌套在其他函数或代码块中使用,使代码更加紧凑。

缺点:
  只能包含一个表达式:Lambda表达式只能包含一个表达式,这意味着它们不能包含多个语句或复杂逻辑。
  调试困难:由于Lambda表达式通常很短,因此很难在调试时设置断点和查看执行流程。
  不支持变量定义:Lambda表达式不能定义变量,只能使用已存在的变量。这意味着它们在处理复杂逻辑时可能会受到限制。
  性能问题:Lambda表达式可能在性能方面不如使用def语句定义的函数。由于它们通常是轻量级的,因此可能不会进行优化。

2.生成数据批次和迭代器

from torch.utils.data import DataLoader
 
def 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)
    
    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)

collate_batch函数用于处理数据加载器中的批次。它接收一个批次的数据,处理它,并返回适合模型训练的数据格式。在这个函数内部,它遍历批次中的每个文本和标签对,将标签添加到label_list,将文本通过text_pipeline函数处理后转换为tensor,并添加到text_list。

三.模型构建

1.搭建模型

from torch import nn
 
class 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.5
        self.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)

Embedding 层 (nn.EmbeddingBag):

通过 nn.EmbeddingBag 定义了一个嵌入层,用于将文本数据嵌入到低维空间中。
vocab_size 参数指定词典的大小,embed_dim 参数指定嵌入的维度,sparse=False 表示不使用稀疏张量。
全连接层 (nn.Linear):

使用 nn.Linear 定义了一个全连接层,将嵌入后的文本表示映射到最终的类别分数。
输入维度为 embed_dim,输出维度为 num_class(类别的数量)。
初始化权重 (init_weights):

在模型初始化时调用,用于初始化 Embedding 层和全连接层的权重和偏置。
使用均匀分布初始化权重,偏置值被归零。
前向传播 (forward):

接受文本数据 text 和对应的偏移量 offsets 作为输入。
使用 Embedding 层将文本嵌入到低维空间,通过调用 self.embedding(text, offsets) 实现。
将嵌入后的文本表示传递给全连接层,得到最终的类别分数。

2.初始化模型

num_class = len(label_name)
vocab_size = len(vocab)
em_size = 64
model = TextClassificationModel(vocab_size,em_size,num_class).to(device)

3.定义训练和评估函数

import time
 
def train(dataloader):
    model.train()
    total_acc,train_loss,total_count =0,0,0
    log_interval = 50
    start_time =time.time()
    
    for idx,(text,label,offsets) in enumerate(dataloader):
        
        predicted_label = model(text,offsets)
        
        optimizer.zero_grad()
        loss= criterion(predicted_label,label)
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(),0.1)
        optimizer.step()
    
        total_acc +=(predicted_label.argmax(1)==label).sum().item()
        train_loss += loss.item()
        total_count += label.size(0)
        
        if idx % log_interval == 0 and idx >0:
            elapsed = time.time() - start_time
            print('| epoch {:1d}|{:4d}/{:4d} batches'
                  '| train_acc {:4.3f} train_loss{:4.5f}'.format(epoch,idx,len(dataloader),
                                             total_acc/total_count,train_loss/total_count))
            total_acc,train_loss,total_count = 0,0,0
            start_time =time.time()
 
def evaluate(dataloader):
    model.eval()
    total_acc,train_loss,total_count = 0,0,0
    
    with torch.no_grad():
        for idx, (text,label,offsets) in enumerate(dataloader):
            predicted_label =model(text,offsets)
            
            loss = criterion(predicted_label,label)
            
            total_acc +=(predicted_label.argmax(1) == label).sum().item()
            train_loss +=loss.item()
            total_count +=label.size(0)
            
    return total_acc/total_count,train_loss/total_count

train 和 evaluate分别用于训练和评估文本分类模型。

·训练函数 train 的工作流程如下:将模型设置为训练模式。初始化总准确率、训练损失和总计数变量。记录训练开始的时间。遍历数据加载器,对每个批次:进行预测、清零优化器的梯度、计算损失(使用一个损失函数,例如交叉熵)、反向传播计算梯度、通过梯度裁剪防止梯度爆炸、执行一步优化器更新模型权重、更新总准确率和总损失、每隔一定间隔,打印训练进度和统计信息。

·评估函数 evaluate 的工作流程如下:将模型设置为评估模式、初始化总准确率和总损失、不计算梯度(为了节省内存和计算资源)、遍历数据加载器,对每个批次:进行预测、计算损失、
更新总准确率和总损失、返回整体的准确率和平均损失。

四、训练模型 

1.拆分数据集并运行模型

from torch.utils.data.dataset import random_split
from torchtext.data.functional import to_map_style_dataset
 
EPOCHS = 10
LR = 5
BATCH_SIZE= 64
 
 
criterion = 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 = coustom_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)
for epoch in range(1,EPOCHS + 1):
    epoch_start_time =time.time()
    train(train_dataloader)
    val_acc,val_loss = evaluate(valid_dataloader)
    
    lr= optimizer.state_dict()['param_groups'][0]['lr']
    
    if total_accu is not None and total_accu > val_acc:
        scheduler.step()
    else:
        total_accu = val_acc
    print('-'* 69)
    print('|epoch {:1d} |time: {:4.2f}s | '
          'valid_acc{:4.3f} valid_loss{:4.3f} | lr{:4.6f}'.format(epoch,
                                       time.time()- epoch_start_time,
                                       val_acc,val_loss,lr))
    print('-'* 69)

2.测试数据

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="还有双鸭山到淮阴的汽车票吗13号的"
 
model =model.to("cpu")
print("该文本的类别是:%s"%label_name[predict(ex_text_str,text_pipeline)])

该文本的类别是:Travel-Query

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电脑连接爱快iKuai软路由之后,网卡没有正常获取到IP,无法访问爱快路由管理页?

前言 上一次咱们说到在爱快控制台上设置/辨认lan口&#xff0c;设置完成之后&#xff0c;其他的一些设置就需要在爱快iKuai软路由的管理页面上设置。 有些小伙伴会发现&#xff0c;当电脑连接上爱快软路由的lan口之后&#xff0c;电脑并没有正常获取到ip&#xff0c;导致无法访…

DNS域名解析的分离解析

一.DNS介绍 DNS域名解析是一种将域名转换为IP地址的服务&#xff0c;在互联网上访问网站时&#xff0c;输入的通常是网站的域名&#xff0c;而计算机在通信时则使用IP地址。因此&#xff0c;DNS域名解析就是将用户输入的域名解析为对应的IP地址&#xff0c;以便计算机能够找到并…

Spark-广播变量详解

Spark概述 Spark-RDD概述 1.为什么会需要广播变量&#xff1f; 广播变量是为了在分布式计算环境中有效地向集群中的所有节点广播大型只读数据集而设计的。 在分布式环境中&#xff0c;通常会遇到需要在所有节点上使用相同的数据集的情况&#xff0c;但是将这些数据集复制到每个…

留学培训行业PaaS应用系统架构的设计与实践

随着留学需求的增长和教育培训市场的不断扩大&#xff0c;留学培训行业正面临着越来越多的挑战和机遇。在这个背景下&#xff0c;利用PaaS&#xff08;Platform as a Service&#xff09;平台来构建留学培训行业的应用系统架构&#xff0c;将成为提升服务质量和效率的重要手段。…

【热门话题】一文带你读懂公司是如何知道张三在脉脉上发了“一句话”的

按理说呢&#xff0c;A公司和脉脉属于不同的平台&#xff0c;而且脉脉上大家可以匿名发言&#xff0c;所以&#xff0c;即便我坐在你边上&#xff0c;我发了一句话上去&#xff0c;你也不知道是谁发的。但通过一些技术&#xff0c;我们却可以分析出&#xff0c;公司是如何知道张…

路由聚合和VRRP技术

实验拓扑图&#xff1a; 实验需求 1、内网IP地址使用172.16.0.0/16 2、SW1和SW2之间互为备份&#xff1b; 3、VRRP/stp/vlan/eth-trunk均使用&#xff1b; 4、所有pc均通过DHCP获取IP地址&#xff1b; 5、ISP只配置IP地址&#xff1b; 6、所有电脑可以正常访问ISP路由器环…

《2024中国AI大模型产业图谱1.0版》重磅发布

‍ 数据猿出品 本次“数据猿2024年度三大媒体策划活动——《2024中国数据智能产业图谱1.0版》”正式发布。下一次版本迭代将于2024年7月底发布2024年2.0版&#xff0c;敬请期待&#xff0c;欢迎报名。 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着科技的飞速发展&#…

在vue中实现下载文件功能

实际操作为&#xff0c;在表格中 我们可以获取到文件的id&#xff0c;通过插槽就可以实现 <template #default"scope"><el-button type"text" click"handleDown(scope.row)"><span>下载</span></el-button> </…

吃透1850道真题和解析备考AMC8和AMC(1020240524持续发布)

多做真题&#xff0c;吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一&#xff0c;通过做真题&#xff0c;可以帮助孩子找到真实竞赛的感觉&#xff0c;而且更加贴近比赛的内容&#xff0c;可以通过真题查漏补缺&#xff0c;更有针对性的补齐知识的短板。 今天我们继续…

善用KEGG数据库挖掘目的基因

有关KEGG的分析在很多已发表的论文中都十分常见&#xff0c;涉及到的方向也很广泛&#xff0c;比如&#xff1a;代谢组、表观组、转录组等等。通常得到相关的基因集或者代谢物后&#xff0c;我们都希望能够快速了解它们的蛋白功能和涉及的调控机制&#xff0c;从而进一步锁定接…

Substrate 优秀学员专访|从前端到高级测试工程师,他坚定奔赴 Web3 红海

4 月 29 日&#xff0c;第 14 期「Substrate 区块链开发入门课」课程圆满毕业收官&#xff0c;课程涌现了新一批优秀毕业学员&#xff0c;他们即将带着自己在课程中学习的新知识、新经验&#xff0c;奔赴 Web3 行业各个赛道。在这些学员中&#xff0c;有这样一位开发实力突出、…

线上研讨会 | 探索非标自动化产线行业的数转智改之路

报名链接&#xff1a; 2024 达索系统工业大发展在线研讨会 (tbh5.com)

2024电工杯A题保姆级分析完整思路+代码+数据教学

2024电工杯A题保姆级分析完整思路代码数据教学 A题题目&#xff1a;园区微电网风光储协调优化配置 接下来我们将按照题目总体分析-背景分析-各小问分析的形式来 总体分析&#xff1a; 题目要求对园区微电网进行风光储协调优化配置&#xff0c;具体涉及三个园区&#xff08…

Python魔法学院:PySpider篇——网络世界的探险与征服

Hi&#xff0c;我是阿佑&#xff0c;迎来到Python魔法学院&#xff0c;今天阿佑要带大家学习的是PySpider篇——一门让你在网络世界中探险与征服的魔法课程。从环境搭建到高级功能应用&#xff0c;再到性能优化&#xff0c;每一个章节都是成为数据大师的必经之路&#xff01; 文…

深度学习之基于YOLOV5的口罩检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着全球公共卫生事件的频发&#xff0c;口罩成为了人们日常生活中不可或缺的一部分。在公共场所&am…

Nacos 微服务管理

Nacos 本教程将为您提供Nacos的基本介绍&#xff0c;并带您完成Nacos的安装、服务注册与发现、配置管理等功能。在这个过程中&#xff0c;您将学到如何使用Nacos进行微服务管理。下方是官方文档&#xff1a; Nacos官方文档 1. Nacos 简介 Nacos&#xff08;Naming and Confi…

Qt for Android 乱码问题

java文件乱码 导致编译失败 使用notepad等查看java文件的编码&#xff0c; 修改成utf-8&#xff0c;否则会因为乱码编译失败&#xff0c; 记住是utf8不是utf8-bom. 做如下修改确保utf8文件不被修改掉。 编译时错误显示的是乱码 如果开发其他乱码再改回&#xff0c; 原本是Sys…

Q-Learning学习笔记-李宏毅

introduction 学习的并不是policy&#xff0c;而是学习critic&#xff0c;critic用来评价policy好还是不好&#xff1b;一种critic&#xff1a;state value function V π ( s ) V^\pi(s) Vπ(s)是给定一个policy π \pi π&#xff0c;在遇到state s s s之后累积的reward的…

docker所在磁盘空间不足 迁移数据

1.查看原始目录docker info | grep "Docker Root Dir" 一般在/var/lib/docker 2.停止docker service docekr stop 3.移动数据 注意 移动前不要创建docker目录&#xff01; mv /var/lib/docker /home/docker 4.进入目录查看是否与原始目录相同&#xff0c;确认一…

操作系统总结(2)

目录 2.1 进程的概念、组成、特征 &#xff08;1&#xff09;知识总览 &#xff08;2&#xff09;进程的概念 &#xff08;3&#xff09;进程的组成—PCB &#xff08;4&#xff09;进程的组成---程序段和数据段 &#xff08;5&#xff09;程序是如何运行的呢&#xff1f…