来自保姆级教程,用PyTorch和BERT进行文本分类

一、bert

bert模型的下载:去抱抱脸网站bert-base-cased at main下载预训练模型,下载对应的这三个文件,这里下载的是pytorch版本

下载后放入对应文件夹,是这样的:

验证bert能不能调用成功:

from transformers import BertModel,BertTokenizer
BERT_PATH = './bert-base-cased'
tokenizer = BertTokenizer.from_pretrained(BERT_PATH)
print(tokenizer.tokenize('I have a good time, thank you.'))
bert = BertModel.from_pretrained(BERT_PATH)
print('load bert model over')['I', 'have', 'a', 'good', 'time',
',', 'thank', 'you', '.']
load bert model over

BertTokenizer解析:BertTokenizer将数据处理成bert需要的格式

from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-cased')
example_text = 'I will watch Memento tonight'
bert_input = tokenizer(example_text,padding='max_length', max_length = 10, truncation=True,return_tensors="pt")
# ------- bert_input ------
print(bert_input['input_ids'])
print(bert_input['token_type_ids'])
print(bert_input['attention_mask'])tensor([[  101,   146,  1209,  2824,  2508,26173,  3568,   102,     0,     0]])
tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
tensor([[1, 1, 1, 1, 1, 1, 1, 1, 0, 0]])

BertTokenizer参数:

  • padding:将每个sequence填充到指定的最大长度。
  • max_length: 每个sequence的最大长度。本示例中我们使用 10,但对于本文实际数据集,我们将使用 512,这是 BERT 允许的sequence 的最大长度。
  • truncation:如果为True,则每个序列中超过最大长度的标记将被截断。
  • return_tensors:将返回的张量类型。由于我们使用的是 Pytorch,所以我们使用pt;如果你使用 Tensorflow,那么你需要使用tf

BertTokenizer输出:bert_input

  • input_ids,它是每个 token 的 id 表示,101代表[CLS],102代表[SEP],0代表[PAD]
  • token_type_ids,它是一个 binary mask,用于标识 token 属于哪个 sequence。如果我们只有一个 sequence,那么所有的 token 类型 id 都将为 0。对于文本分类任务,token_type_ids是 BERT 模型的可选输入参数。
  • attention_mask,它是一个 binary mask,用于标识 token 是真实 word 还是只是由填充得到。如果 token 包含 [CLS]、[SEP] 或任何真实单词,则 mask 将为 1。如果 token 只是 [PAD] 填充,则 mask 将为 0

二、定义模型

bert的输出送入一层全连接层,再通过一层relu层

from torch import nn
from transformers import BertModel
import torchclass BertClassifier(nn.Module):def __init__(self, dropout=0.5):super(BertClassifier, self).__init__()#self.bert = BertModel.from_pretrained('bert-base-cased')self.bert = BertModel.from_pretrained('/home/jiqiboyi03/chenpp/bert-classification/bert-base-cased')self.dropout = nn.Dropout(dropout)self.linear = nn.Linear(768, 7)self.relu = nn.ReLU()def forward(self, input_id, mask):_, pooled_output = self.bert(input_ids= input_id, attention_mask=mask,return_dict=False)# print(pooled_output.size())#[batch_size,768] CLS的向量dropout_output = self.dropout(pooled_output)linear_output = self.linear(dropout_output)final_layer = self.relu(linear_output)return final_layer

输入input_ids和mask的格式应该是:以batch_size=2为例,input_ids应该是二维的,mask二维三维都可以

input_id=torch.tensor([[ 101,   178,   112,   173,  1176,   170,   189,  3624,  3043,  1121,17496,  1396, 11305,  1106,  1207, 26063,  4661,  1664, 26645,   102],[  101,  1110,  1175,   170, 20811,  3043,  1121, 10552,  4121,  1106,21718,  1179,   175,  4047, 21349,  2528,   102,     0,     0,     0]])
mask=torch.tensor([[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]]])

三、数据预处理

import torch
import numpy as np
from transformers import BertTokenizer
import torch.utils.data as databert_path='/home/jiqiboyi03/chenpp/bert-classification/bert-base-cased'
tokenizer = BertTokenizer.from_pretrained(bert_path)
labels={'AddToPlaylist':0,'BookRestaurant':1,'GetWeather':2,'PlayMusic':3,'RateBook':4,'SearchCreativeWork':5,'SearchScreeningEvent':6}class Dataset(data.Dataset):def __init__(self, df):self.labels = [labels[label] for label in df['category']]self.texts = [tokenizer(text,padding='max_length',max_length = 20,truncation=True,return_tensors="pt")for text in df['text']]def classes(self):return self.labelsdef __len__(self):return len(self.labels)def get_batch_labels(self, idx):# Fetch a batch of labelsreturn np.array(self.labels[idx])def get_batch_texts(self, idx):# Fetch a batch of inputsreturn self.texts[idx]def __getitem__(self, idx):batch_texts = self.get_batch_texts(idx)batch_y = self.get_batch_labels(idx)return batch_texts, batch_y

其中df的格式应该是:

{'category': ['PlayMusic', .....],
'text': ['open groove shark and play native us',..... }

四、训练

from torch.optim import Adam
from tqdm import tqdm
from snips_process import Dataset
import torch
import torch.utils.data as data
import torch.nn as nn
import matplotlib.pyplot as pltdef train(model, train_data, val_data, learning_rate, epochs):# 通过Dataset类获取训练和验证集train, val = Dataset(train_data), Dataset(val_data)# DataLoader根据batch_size获取数据,训练时选择打乱样本train_dataloader = torch.utils.data.DataLoader(train, batch_size=32, shuffle=True)val_dataloader = torch.utils.data.DataLoader(val, batch_size=32)# 判断是否使用GPUuse_cuda = torch.cuda.is_available()device = torch.device("cuda" if use_cuda else "cpu")# 定义损失函数和优化器criterion = nn.CrossEntropyLoss()optimizer = Adam(model.parameters(), lr=learning_rate)train_loss=[]train_acc=[]val_loss=[]val_acc=[]EPOCH=[]if use_cuda:model = model.cuda()criterion = criterion.cuda()# 开始进入训练循环for epoch_num in range(epochs):# 定义两个变量,用于存储训练集的准确率和损失total_acc_train = 0total_loss_train = 0# 进度条函数tqdmfor train_input, train_label in tqdm(train_dataloader):train_label = train_label.to(device)#1维mask = train_input['attention_mask'].to(device)input_id = train_input['input_ids'].squeeze(1).to(device)# print("input_id size:",input_id.size())#[32,20]# print("mask size:",mask.size())# 通过模型得到输出output = model(input_id, mask)#[32,21]# 计算损失batch_loss = criterion(output, train_label)total_loss_train += batch_loss.item()# 计算精度acc = (output.argmax(dim=1) == train_label).sum().item()total_acc_train += acc# 模型更新model.zero_grad()batch_loss.backward()optimizer.step()# ------ 验证模型 -----------# 定义两个变量,用于存储验证集的准确率和损失total_acc_val = 0total_loss_val = 0# 不需要计算梯度with torch.no_grad():# 循环获取数据集,并用训练好的模型进行验证for val_input, val_label in val_dataloader:# 如果有GPU,则使用GPU,接下来的操作同训练val_label = val_label.to(device)mask = val_input['attention_mask'].to(device)input_id = val_input['input_ids'].squeeze(1).to(device)output = model(input_id, mask)batch_loss = criterion(output, val_label)total_loss_val += batch_loss.item()acc = (output.argmax(dim=1) == val_label).sum().item()total_acc_val += acctrain_loss.append(total_loss_train / len(train_data['text']))train_acc.append(total_acc_train / len(train_data['text']))val_loss.append(total_loss_val / len(val_data['text']))val_acc.append(total_acc_val / len(val_data['text']))EPOCH.append(epoch_num+1)print(f'''Epochs: {epoch_num + 1} | Train Loss: {total_loss_train / len(train_data['text']): .3f} | Train Accuracy: {total_acc_train / len(train_data['text']): .3f} | Val Loss: {total_loss_val / len(val_data['text']): .3f} | Val Accuracy: {total_acc_val / len(val_data['text']): .3f}''')print("saving bert model......")torch.save(model.state_dict(),'../bert-base-cased/bert_trained_snips_full.pt')#画图plt.plot(EPOCH,train_loss,'b',label='train_loss')plt.plot(EPOCH, train_acc,'g',label='train_acc')plt.plot(EPOCH, val_loss, 'r', label='val_loss')plt.plot(EPOCH, val_acc, 'c', label='val_acc')plt.show()

注:train_data即数据预处理中的df,经过DataLoader会加一维batch_size,变成3维,但是bert的输入得是2维,因此经过了squeeze(1)操作

五、验证

from snips_process import Dataset,df_test
import torch
from model import BertClassifier
import torch.utils.data as datadef evaluate(model, test_data):test = Dataset(test_data)length=len(test_data['text'])test_dataloader = torch.utils.data.DataLoader(test, batch_size=2)use_cuda = torch.cuda.is_available()device = torch.device("cuda" if use_cuda else "cpu")if use_cuda:model = model.cuda()total_acc_test = 0with torch.no_grad():for test_input, test_label in test_dataloader:test_label = test_label.to(device)mask = test_input['attention_mask'].to(device)input_id = test_input['input_ids'].squeeze(1).to(device)output = model(input_id, mask)acc = (output.argmax(dim=1) == test_label).sum().item()total_acc_test += accprint(f'Test Accuracy: {total_acc_test / length: .3f}')

Bert实现意图分类相关推荐

  1. 搜索引擎——用户搜索意图的理解及其难点解析,本质是利用机器学习用户的意图分类...

    用户搜索意图的理解及其难点解析 搜索引擎涉及的技术非常的繁复,既有工程架构方面的,又有算法策略方面的.综合来讲,一个搜索引擎的技术构建主要包含三大部分: 对 query 的理解 对内容(文档)的理解 ...

  2. 【NLP】Kaggle从零到实践:Bert中文文本分类

    Bert是非常强化的NLP模型,在文本分类的精度非常高.本文将介绍Bert中文文本分类的基础步骤,文末有代码获取方法. 步骤1:读取数据 本文选取了头条新闻分类数据集来完成分类任务,此数据集是根据头条 ...

  3. 【PaddleNLP实战】对话意图分类方案

    基于预训练模型ERNIE 3.0 和CrossWOZ数据的意图识别分类任务 AI Studio平台默认安装了Paddle和PaddleNLP,并定期更新版本. 如需手动更新Paddle,可参考飞桨安装 ...

  4. Bert实战--文本分类(一)

    使用Bert预训练模型进行文本分类 bert做文本分类,简单来说就是将每句话的第一个位置加入了特殊分类嵌入[CLS].而该[CLS]包含了整个句子的信息,它的最终隐藏状态(即,Transformer的 ...

  5. Rasa实体抽取和意图分类之DIETClassifier

    Rasa实体抽取和意图分类之DIETClassifier rasa\nlu\classifiers\diet_classifier.py DIETClassifier训练模型是diet_classif ...

  6. 基于维基百科的用户意图分类

    关于"用户查询意图分类(识别)",在很久以前就开始关注了,最近开始阅读一些文章.前期得文章中,多半在特征抽取中,提到的都是用其他得资源比如查询日志比较多.今天偶然读了一篇文章,以一 ...

  7. Pytorch Bert+BiLstm文本分类

    文章目录 前言 一.运行环境 二.数据 三.模型结构 四.训练 五.测试及预测 前言 昨天按照该文章(自然语言处理(NLP)Bert与Lstm结合)跑bert+bilstm分类的时候,没成功跑起来,于 ...

  8. 深度学习 一 :使用BERT做 NLP分类任务

    文章目录 前言 什么是BERT? 它与其他机器学习算法的不同之处 代码示例 开始设置 准备数据 训练模型 做一个预测 鸣谢!!!! 前言 ****Bert的原理资料已经很多这里不多陈述,仅仅用一个实际 ...

  9. 二分类问题:基于BERT的文本分类实践!附完整代码

    Datawhale 作者:高宝丽,Datawhale优秀学习者 寄语:Bert天生适合做分类任务.文本分类有fasttext.textcnn等多种方法,但在Bert面前,就是小巫见大巫了. 推荐评论展 ...

最新文章

  1. ORA-32004错误的解决方法
  2. 利用FreeNas创建AFP共享
  3. c语言指针写鞍点,c语言——鞍点
  4. Debian下搭建Samba CTDB集群。
  5. transforms.Compose()函数
  6. java实现邮件发送, 抄送及多附件发送
  7. python模块heapq之简单学习使用
  8. 僵尸进程与孤儿进程(精简易懂,直接要害)
  9. html背景半透明 字不变,css实现背景半透明文字不透明的效果示例
  10. 【项目管理】开发方法和生命周期绩效域管理
  11. Zynga和Unity:独家奖励广告
  12. hadoop+Spark实战基于大数据技术之电视收视率企业项目实战
  13. 上海证券交易所-债券品种介绍
  14. 高仿微信抢红包动画特效
  15. do_syscall_64 函数
  16. Web设计网站软件推荐
  17. 【力扣】6. Z 字形变换
  18. HTTP访问控制(CORS) 跨域访问
  19. Filter过滤器的生命周期和工作原理
  20. 修改 jq weui cityPicker.js原来的值

热门文章

  1. 图形化界面的Xmind用例转excel工具
  2. ClipperLib库使用说明
  3. 使用了却报错值没有使用_使用没有
  4. 程序人生(一) 初生牛犊
  5. 常见的电脑蓝屏代码和解决方法
  6. 【shell笔记】Linux Shell脚本编程入门知识点全面涵盖
  7. IOS开发系列—Objective-C之内存管理
  8. 怎样健康喝水 这样喝水有助我们的健康
  9. 去哪儿旅行携程旅行淘宝旅行移动端产品分析报告
  10. Java 合并、拆分PPT幻灯片