Huggingface 实战 - 预测下一个词
文章目录
- 项目说明
- 代码实现
- 加载数据集
- 数据加载器
- 模型
- 测试函数
- 训练
项目说明
本文在 distilgpt2 模型的基础上微调,使用 glue/sst2 数据集,训练预测下一个词的模型。
本文根据视频修改:
蓝斯诺特 《七个实战任务,玩转自然语言处理,基于HuggingFace和PyTorch》
https://www.bilibili.com/video/BV1dU4y1C7so?p=2
源码地址:https://github.com/lansinuote/Huggingface_Task/blob/main/1.预测最后一个词.ipynb
代码实现
checkpoint = 'distilgpt2'from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained(checkpoint, use_fast=True)
tokenizer
'''
PreTrainedTokenizerFast(name_or_path='distilgpt2',
vocab_size=50257, model_max_len=1024, is_fast=True,
padding_side='right', truncation_side='right',
special_tokens={'bos_token': '<|endoftext|>', 'eos_token': '<|endoftext|>', 'unk_token': '<|endoftext|>'})
'''
测试 tokenizer
# 测试
text_arr = [' Creating new Models, Datasets or Spaces.', 'This model is a fine-tune checkpoint of DistilBERT, fine-tuned on SST-2. ']text_arr = ['hide new secretions from the parental units','contains no wit , only labored gags'
]
tokenizer.batch_encode_plus(text_arr)
'''
{'input_ids': [[24717, 649, 3200, 507, 422, 262, 21694, 4991], [3642, 1299, 645, 20868, 837, 691, 2248, 1850, 308, 3775]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]}
'''
加载数据集
# 加载数据集
from datasets import load_dataset, load_from_disk
dataset = load_dataset(path='glue', name='sst2')
查看数据
dataset
'''
DatasetDict({train: Dataset({features: ['sentence', 'label', 'idx'],num_rows: 67349})validation: Dataset({features: ['sentence', 'label', 'idx'],num_rows: 872})test: Dataset({features: ['sentence', 'label', 'idx'],num_rows: 1821})
})
'''dataset['train']
'''
Dataset({features: ['sentence', 'label', 'idx'],num_rows: 67349
})
'''dataset['train'][0]
'''
{'sentence': 'hide new secretions from the parental units ','label': 0,'idx': 0}
'''
处理数据
# 1、分词,同时删除多余的字段
def f(data):return tokenizer.batch_encode_plus(data['sentence'])dataset = dataset.map(f, batched=True, batch_size=1000, num_proc=4, remove_columns=['sentence', 'idx', 'label'])# 2、过滤掉长度小于8的句子; 准备拿第8个词,作为 label。
def f(data):return [len(i) > 8 for i in data['input_ids']] dataset = dataset.filter(f, batched=True, batch_size=1000, num_proc=4)# 3、截断句子,同时整理成模型需要的格式
def f(data):data['input_ids'] = [ i[:8] for i in data['input_ids'] ]data['attention_mask'] = [[1] * 8 ] * len(data['attention_mask'])# 在模型中处理了偏移量的问题,这里保持输入输出一致即可 data['labels'] = data['input_ids'].copy()return datadataset = dataset.map(f, batched=True, batch_size=1000, num_proc=4)
查看处理后的内容
dataset
'''
(DatasetDict({train: Dataset({features: ['input_ids', 'attention_mask', 'labels'],num_rows: 36125})validation: Dataset({features: ['input_ids', 'attention_mask', 'labels'],num_rows: 834})test: Dataset({features: ['input_ids', 'attention_mask', 'labels'],num_rows: 1683})}),
'''dataset['train'][0]
'''{'input_ids': [24717, 649, 3200, 507, 422, 262, 21694, 4991],'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1],'labels': [24717, 649, 3200, 507, 422, 262, 21694, 4991]})
'''
数据加载器
# 定义数据加载器
import torch
from transformers.data.data_collator import default_data_collatorloader = torch.utils.data.DataLoader(dataset=dataset['train'],batch_size = 8,collate_fn = default_data_collator,shuffle=True,drop_last=True,
)for i, data in enumerate(loader):breaklen(loader), data
'''
(4515,{'input_ids': tensor([[ 9099, 22590, 2644, 2809, 45070, 465, 1388, 11171],[ 1169, 38043, 710, 5369, 815, 299, 470, 307],[ 3798, 7916, 262, 14186, 1291, 37840, 286, 749],[ 64, 13526, 837, 1257, 837, 43211, 28680, 3807],[ 1169, 7110, 318, 1111, 542, 36207, 290, 537],[19188, 307, 2562, 329, 9188, 284, 21163, 340],[ 505, 286, 262, 614, 705, 82, 749, 19827],[ 270, 705, 82, 655, 7650, 1108, 329, 262]]),'attention_mask': 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, 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]]),'labels': tensor([[ 9099, 22590, 2644, 2809, 45070, 465, 1388, 11171],[ 1169, 38043, 710, 5369, 815, 299, 470, 307],[ 3798, 7916, 262, 14186, 1291, 37840, 286, 749],[ 64, 13526, 837, 1257, 837, 43211, 28680, 3807],[ 1169, 7110, 318, 1111, 542, 36207, 290, 537],[19188, 307, 2562, 329, 9188, 284, 21163, 340],[ 505, 286, 262, 614, 705, 82, 749, 19827],[ 270, 705, 82, 655, 7650, 1108, 329, 262]])})
'''
模型
# 定义模型
from transformers import AutoModelForCausalLM, GPT2Model# 自动模型,基本等同于下面手动实现的; 自动模型,官方会有很多健壮性的考虑。这里手动实现,追求简洁性。
# model = AutoModelForCausalLM.from_pretrained(checkpoint)import torch class Model(torch.nn.Module):def __init__(self):super().__init__()self.pretrained = GPT2Model.from_pretrained(checkpoint)self.fc = torch.nn.Linear(768, tokenizer.vocab_size, bias=False)parameters = AutoModelForCausalLM.from_pretrained(checkpoint)self.fc.load_state_dict(parameters.lm_head.state_dict() )self.criterion = torch.nn.CrossEntropyLoss()def forward(self, input_ids, attention_mask, labels=None):logits = self.pretrained(input_ids=input_ids, attention_mask=attention_mask, )logits = logits.last_hidden_statelogits = self.fc(logits)loss = Noneif labels is not None:shift_logits = logits[:, :-1].reshape(-1, tokenizer.vocab_size)shift_labels = logits[:, 1:].reshape(-1)# 将输入的 labels 和 输出的 logits 相互的做一个前后的偏移量,取相互交叉的部分来计算 lossloss = self.criterion(shift_logits, shift_labels)print('-- loss : ', loss, ' logits : ', logits)
查看模型
model = Model()# 统计模型参数量
print('-- ', sum(i.numel() for i in model.parameters() ) / 10000 )
# 12050.9952
测试函数
# 定义测试函数
# 在测试集合上计算预测的正确率 def test():model.eval()#数据加载器loader_test = torch.utils.data.DataLoader(dataset=dataset['test'],batch_size = 8,collate_fn = default_data_collator,shuffle=True,drop_last = True,)correct = 0total = 0for i, data in enumerate(loader_test):# 只计算最后一个词的正确率,这里先把最后一个词取出来label = data['input_ids'][:, -1].clone()# 从数据中抹除掉最后一个词,防止模型作弊data['input_ids'][:, -1] = 0# label就不需要了data['labels'][:, :] = 0with torch.no_grad():out = model(**data)# 只计算最后一个词的正确率,因为有偏移量的关系,这里取的是倒数第二个词out = out['logits'].argmax(dim=2)[:, -2]correct += (label==out).sum().item()total += 8if i % 10 == 0:print('-- ', i, label, out)if i == 50:breakprint('-- ', correct/total)for i in range(8):print(tokenizer.decode(data['input_ids'][i, :-1]) )print(tokenizer.decode(label[i]), tokenizer.decode(out[i]) )print()
训练
from transformers import AdamW
from transformers.optimization import get_scheduler'''
使用优化器 AdamW 而不是传统的 Adam 。AdamW 是 huggingface 提供的。
相比 pytorch 提供的 Adam,AdamW 被优化了。scheduler 可以随着训练的进行,不断调低 learning rate。帮助 loss 下降到更低的点。clip_grad_norm_ 提供了梯度的范数裁剪。让模型梯度范数保持在 1。这样可以防止梯度的过大或过小,帮助模型参数稳定的更新。'''def train():optimizer = AdamW(model.parameters(), lr=2e-5)scheduler = get_scheduler(name='linear', num_warmup_steps=0,num_training_steps=len(loader),optimizer=optimizer, )model.train() for i, data in enumerate(loader):out = model(**data)loss = out['loss']loss.backward()torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) optimizer.step()scheduler.step()optimizer.zero_grad()model.zero_grad() if i%50 == 0:labels = data['labels'][:, 1:]out = out['logits'].argmax(dim=2)[:, :-1]correct = (labels == out).sum().item()accuracy = correct / (8 * 7)lr = optimizer.state_dict()['param_groups'][0]['lr']print('-- ', i, loss.item(), accuracy, lr)torch.save(model, 'last_word.model')
伊织 2022-12-03(六)
Huggingface 实战 - 预测下一个词相关推荐
- 深入理解操作系统(12)第四章:处理器体系结构(4)Y86-64的流水线实现(包括:PIPE-处理器/预测下一个PC/分支预测/流水线冒险/暂停,转发避免冒险/PPE硬件结构及实现/CPI)
深入理解操作系统(12)第四章:处理器体系结构(4)Y86-64的流水线实现(包括:PIPE-处理器/预测下一个PC/分支预测/流水线冒险/暂停,转发避免冒险/PPE硬件结构及实现/CPI) 1. Y ...
- 中国程序员人数将增长50%,过半500强都要卖软件,边缘应用程序增长8倍丨IDC预测下一个五年...
郭一璞 发自 丽晶酒店 量子位 报道 | 公众号 QbitAI 最近,IDC发布了中国ICT(information and communications technology)市场十大预测. 发布之 ...
- NLP之Bi-LSTM(在长句中预测下一个单词)
Bi-LSTM 文章目录 Bi-LSTM 1.理论 1.1 基本模型 1.2 Bi-LSTM的特点 2.实验 2.1 实验步骤 2.2 实验模型 1.理论 1.1 基本模型 Bi-LSTM模型分为2个 ...
- lstm预测单词_下一个单词预测完整指南
lstm预测单词 As part of my summer internship with Linagora's R&D team, I was tasked with developing ...
- 【迁移学习】大数据时代下的迁移学习--- 机器学习的下一个前沿
文章内容索引: 什么是迁移学习? 为什么现在需要迁移学习? 迁移学习的定义 迁移学习的应用场景 迁移学习的应用 从模拟仿真中学习 适应新的领域场景 跨语言转化知识 迁移学习方法 使用预先训练的CNN得 ...
- 总忍不住想接话?原来是你的大脑在疯狂“脑补”下个词丨PNAS
萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 聊天.读书或听讲时,你有意识到自己正在疯狂"脑补"吗? 其实,你的大脑就像一个自动补全机一样,每时每刻都在猜别人要说什么. 不 ...
- 深度学习,使用RNN的NLP,您可以成为下一个莎士比亚吗?
是否想过智能键盘上的预测键盘之类的工具如何工作?在本文中,探讨了使用先验信息生成文本的想法.具体来说,将使用Google Colab上的递归神经网络(RNN)和自然语言处理(NLP),从16世纪文献中 ...
- 我的Serverless实战——引领云计算的下一个十年
前言:如今,越来越多的大厂企业开始大规模使用Serverless,处于变革中的开发者,大多已从观望状态转向尝试阶段,越来越多Serverless落地场景被解锁.作为基础研发底座,越来越多企业开始接受S ...
- R语言计算回归模型每个样本(观察、observation、sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用
R语言计算回归模型每个样本(观察.observation.sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用 目录
最新文章
- mcDropdown使用方法
- Vi非正常退出导致敏感信息泄露
- 3 个问题:MIT专家论述关于阻碍AutoML发展的障碍
- antd如何获取表单的值_antd 父组件获取子组件中form表单的值
- 30个数据可视化超级工具_Python5个数据可视化工具
- docker 容器重命名
- 《视频直播技术详解》系列之七:现代播放器原理
- Matlab基本数学应用
- 南京工业大学计算机研究生分数,2019南京工业大学研究生分数线汇总(含2016-2019历年复试)...
- 《易学Python》——第1章 为何学习Python 1.1 学习编程
- React 18 新特性
- 卷帘快门和全局快门的区别
- 生物细胞繁衍生存模拟仿真
- vs项目文件夹进行分类管理
- 企业文件加密系统 — 文件透明加密的优势和功能
- linux中zlib源码包安装
- 【HTML】常见的块元素,行内元素,行内块元素有哪些?
- GD32W515系列Wi-Fi MCU资料
- 四旋翼飞行器2——自己设计四旋翼飞行器的硬件准备和基础知识
- 计算机屏幕节省电,【火腿课堂】当FT8/FT4数字模式遇上电脑“屏幕保护程序或省电模式”时...