文章目录

  • 项目说明
  • 代码实现
    • 加载数据集
    • 数据加载器
    • 模型
    • 测试函数
    • 训练

项目说明

本文在 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 实战 - 预测下一个词相关推荐

  1. 深入理解操作系统(12)第四章:处理器体系结构(4)Y86-64的流水线实现(包括:PIPE-处理器/预测下一个PC/分支预测/流水线冒险/暂停,转发避免冒险/PPE硬件结构及实现/CPI)

    深入理解操作系统(12)第四章:处理器体系结构(4)Y86-64的流水线实现(包括:PIPE-处理器/预测下一个PC/分支预测/流水线冒险/暂停,转发避免冒险/PPE硬件结构及实现/CPI) 1. Y ...

  2. 中国程序员人数将增长50%,过半500强都要卖软件,边缘应用程序增长8倍丨IDC预测下一个五年...

    郭一璞 发自 丽晶酒店 量子位 报道 | 公众号 QbitAI 最近,IDC发布了中国ICT(information and communications technology)市场十大预测. 发布之 ...

  3. 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个 ...

  4. lstm预测单词_下一个单词预测完整指南

    lstm预测单词 As part of my summer internship with Linagora's R&D team, I was tasked with developing ...

  5. 【迁移学习】大数据时代下的迁移学习--- 机器学习的下一个前沿

    文章内容索引: 什么是迁移学习? 为什么现在需要迁移学习? 迁移学习的定义 迁移学习的应用场景 迁移学习的应用 从模拟仿真中学习 适应新的领域场景 跨语言转化知识 迁移学习方法 使用预先训练的CNN得 ...

  6. 总忍不住想接话?原来是你的大脑在疯狂“脑补”下个词丨PNAS

    萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 聊天.读书或听讲时,你有意识到自己正在疯狂"脑补"吗? 其实,你的大脑就像一个自动补全机一样,每时每刻都在猜别人要说什么. 不 ...

  7. 深度学习,使用RNN的NLP,您可以成为下一个莎士比亚吗?

    是否想过智能键盘上的预测键盘之类的工具如何工作?在本文中,探讨了使用先验信息生成文本的想法.具体来说,将使用Google Colab上的递归神经网络(RNN)和自然语言处理(NLP),从16世纪文献中 ...

  8. 我的Serverless实战——引领云计算的下一个十年

    前言:如今,越来越多的大厂企业开始大规模使用Serverless,处于变革中的开发者,大多已从观望状态转向尝试阶段,越来越多Serverless落地场景被解锁.作为基础研发底座,越来越多企业开始接受S ...

  9. R语言计算回归模型每个样本(观察、observation、sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用

    R语言计算回归模型每个样本(观察.observation.sample)的杠杆值(leverage)实战:如果一个样本的预测变量比其他样本的预测变量值更极端,那么被认为具有很高的杠杆作用 目录

最新文章

  1. mcDropdown使用方法
  2. Vi非正常退出导致敏感信息泄露
  3. 3 个问题:MIT专家论述关于阻碍AutoML发展的障碍
  4. antd如何获取表单的值_antd 父组件获取子组件中form表单的值
  5. 30个数据可视化超级工具_Python5个数据可视化工具
  6. docker 容器重命名
  7. 《视频直播技术详解》系列之七:现代播放器原理
  8. Matlab基本数学应用
  9. 南京工业大学计算机研究生分数,2019南京工业大学研究生分数线汇总(含2016-2019历年复试)...
  10. 《易学Python》——第1章 为何学习Python 1.1 学习编程
  11. React 18 新特性
  12. 卷帘快门和全局快门的区别
  13. 生物细胞繁衍生存模拟仿真
  14. vs项目文件夹进行分类管理
  15. 企业文件加密系统 — 文件透明加密的优势和功能
  16. linux中zlib源码包安装
  17. 【HTML】常见的块元素,行内元素,行内块元素有哪些?
  18. GD32W515系列Wi-Fi MCU资料
  19. 四旋翼飞行器2——自己设计四旋翼飞行器的硬件准备和基础知识
  20. 计算机屏幕节省电,【火腿课堂】当FT8/FT4数字模式遇上电脑“屏幕保护程序或省电模式”时...

热门文章

  1. idea 查看并设置快捷键
  2. 学校购买了若干台电计算机,某学校计划购买若干台电.doc
  3. 论文笔记--Goat: Fine-tuned LLaMA Outperforms GPT-4 on Arithmetic Tasks
  4. 【源码】红蓝配色图——从亮蓝色到白色再到亮红色
  5. invokeBeanFactoryPostProcessors浅析
  6. QObject源码浅析
  7. thinkpad笔记本uefi无法启动详细解决教程
  8. WiFi伴侣电脑版 v2.3.4 PC中文版
  9. 已备案域名购买,域名购买注意事项
  10. Python爬虫实现获取斗鱼主播信息