关于训练gpt-2的思路

2,384 阅读4分钟

知识积累

  1. Train GPT-2 in your own language 2.Text Generation with Pretrained GPT2 Using PyTorch

  2. 手把手教你用Pytorch-Transformers

  3. How to generate text

  4. 基于transformers的自然语言处理(NLP)入门

  5. 微调模型 Fine-tune a pretrained model

  6. Huggingface🤗NLP笔记4 该作者的代码位置 8. GPT-2

9.Huggingface🤗NLP笔记8:使用PyTorch来微调模型「初级教程完结撒花❀❀」

10.simpleAi index 11. Huggingface Transformer教程 12. GPT-2 使用指南:从Finetune到部署

13.GPT2-Pytorch with Text-Generator

  1. 部署到flask中
  2. 微调GPT-2 使用pytorch 16.翻译后 翻译15 这个可以用来复现代码

17 预训练模型专题_GPT2_模型代码学习笔记 pytorch 版本

  1. 微调finetune-gpt2xl

数据集

训练集数据=原始数据 标签数据=下一个字符

image.png

使用trainer API 进行模型的训练

这里的 使用 pytorch 、 tf 、keras 等的训练过程还有有差别的、

主要是选择模型 和 对 文本数据的向量化

GPT2LMHeadModel类、GPT2Model类

#!/usr/bin/env Python
# coding=utf-8

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

# 初始化GPT2模型的Tokenizer类.
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# 初始化GPT2模型, 此处以初始化GPT2LMHeadModel()类的方式调用GPT2模型.
model = GPT2LMHeadModel.from_pretrained('gpt2')
# model.config.use_return_dict = None
# print(model.config.use_return_dict)

# GPT模型第一次迭代的输入的上下文内容, 将其编码以序列化.
# 同时, generated也用来存储GPT2模型所有迭代生成的token索引.
generated = tokenizer.encode("The Manhattan bridge")
# 将序列化后的第一次迭代的上下文内容转化为pytorch中的tensor形式.
context = torch.tensor([generated])
# 第一次迭代时还无past_key_values元组.
past_key_values = None

for i in range(30):

    '''
    此时模型model返回的output为CausalLMOutputWithPastAndCrossAttentions类,
    模型返回的logits以及past_key_values对象为其中的属性,
    CausalLMOutputWithPastAndCrossAttentions(
            loss=loss,
            logits=lm_logits,
            past_key_values=transformer_outputs.past_key_values,
            hidden_states=transformer_outputs.hidden_states,
            attentions=transformer_outputs.attentions,
            cross_attentions=transformer_outputs.cross_attentions,
        )
'''

    output = model(context, past_key_values=past_key_values)
    past_key_values = output.past_key_values
    # 此时获取GPT2模型计算的输出结果hidden_states张量中第二维度最后一个元素的argmax值, 得出的argmax值即为此次GPT2模型迭代
    # 计算生成的下一个token. 注意, 此时若是第一次迭代, 输出结果hidden_states张量的形状为(batch_size, sel_len, n_state);
    # 此时若是第二次及之后的迭代, 输出结果hidden_states张量的形状为(batch_size, 1, n_state), all_head_size=n_state=nx=768.
    token = torch.argmax(output.logits[..., -1, :])

    # 将本次迭代生成的token的张量变为二维张量, 以作为下一次GPT2模型迭代计算的上下文context.
    context = token.unsqueeze(0)
    # 将本次迭代计算生成的token的序列索引变为列表存入generated
    generated += [token.tolist()]

# 将generated中所有的token的索引转化为token字符.
sequence = tokenizer.decode(generated)
sequence = sequence.split(".")[:-1]
print(sequence)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/9/16 8:46
# @Author  : 结尾!!!
# @File    : 简易版GPT.py



# https://blog.csdn.net/weixin_38241876/article/details/109764619
import torch
from transformers import GPT2Tokenizer, GPT2LMHeadModel
# 可选:如果您想了解发生的信息,请按以下步骤logger
import logging

logging.basicConfig(level=logging.INFO)
# 加载预训练模型(权重)
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
# 编码输入
text = "Who was Jim Henson ? Jim Henson was a"
indexed_tokens = tokenizer.encode(text)
# 转换为PyTorch tensor
tokens_tensor = torch.tensor([indexed_tokens])
# 让我们看看如何使用GPT2LMHeadModel生成下一个跟在我们的文本后面的token:
# 加载预训练模型(权重)
model = GPT2LMHeadModel.from_pretrained('gpt2')
# 将模型设置为评估模式
# 在评估期间有可再现的结果这是很重要的!
model.eval()
# 如果你有GPU,把所有东西都放在cuda上
tokens_tensor = tokens_tensor.to('cuda')
model.to('cuda')
# 预测所有标记
with torch.no_grad():
    outputs = model(tokens_tensor)  # [1, 11, 50257],[2, 1, 12, 11, 64]
    predictions = outputs[0]
# 得到预测的下一个子词(在我们的例子中,是“man”这个词)
predicted_index = torch.argmax(predictions[0, -1, :]).item()
predicted_text = tokenizer.decode(indexed_tokens + [predicted_index])
# assert predicted_text == 'Who was Jim Henson? Jim Henson was a man'
# 每个模型架构(Bert、GPT、GPT-2、Transformer XL、XLNet和XLM)的每个模型类的示例,可以在文档中找到。
# 使用过去的GPT-2
# 以及其他一些模型(GPT、XLNet、Transfo XL、CTRL),使用past或mems属性,这些属性可用于防止在使用顺序解码时重新计算键/值对。它在生成序列时很有用,因为注意力机制的很大一部分得益于以前的计算。
#
# 下面是一个使用带past的GPT2LMHeadModel和argmax解码的完整工作示例(只能作为示例,因为argmax decoding引入了大量重复):

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

tokenizer = GPT2Tokenizer.from_pretrained("gpt2") # 分词器
model = GPT2LMHeadModel.from_pretrained('gpt2')

generated = tokenizer.encode("The Manhattan bridge")
context = torch.tensor([generated])
past = None

for i in range(100):
    output, past = model(context, past=past)
    token = torch.argmax(output[..., -1, :])

    generated += [token.tolist()]
    context = token.unsqueeze(0)

sequence = tokenizer.decode(generated)

print(sequence)
```
```