大模型用model.generate 直接产生文本的id以及获得模型生成文本概率的方法

使用模型的 generate 方法

当使用大型语言模型(如 GPT-2、GPT-3、BERT 等)的 generate 方法直接产生文本时,通常返回的是文本的 token ID 序列。为了获得每个 token 的生成概率,你需要使用模型的 logits 输出。logits 是模型在softmax层之前的输出,表示模型对每个可能的下一个 token 的置信度。通过对这些 logits 应用softmax函数,可以得到概率分布。

使用 logits 和 softmax 函数

以下是一个简化的例子,展示如何在使用 generate 方法时获得生成每个 token 的概率:

import torch
from transformers import GPT2LMHeadModel, GPT2Tokenizer

# 加载预训练模型和分词器
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2LMHeadModel.from_pretrained('gpt2')

# 编码输入文本
input_text = "The quick brown fox"
input_ids = tokenizer.encode(input_text, return_tensors='pt')

# 生成文本,同时获取logits
outputs = model.generate(input_ids, max_length=20, output_scores=True, return_dict_in_generate=True)

# 提取logits
logits = outputs.scores

# 计算概率
probs = [torch.softmax(log, dim=-1) for log in logits]

# 获取生成文本的token ID和对应的概率
generated_ids = outputs.sequences
for i, token_id in enumerate(generated_ids[0][len(input_ids[0]):]):
    token_prob = probs[i][0, token_id].item()
    print(f"Token ID: {token_id}, Probability: {token_prob}")

在这个例子中,generate 方法的参数 output_scores=True 使得模型返回生成每个 token 时的 logits。通过对 logits 应用softmax函数,我们可以得到每个 token 的生成概率。

注意事项
  • 输出概率是针对每个单独生成的 token 的,并且是在给定之前所有 token 的条件下的概率。
  • 生成的概率是自回归模型中每步的条件概率,而不是整个序列的联合概率。
  • 如果使用的是 Hugging Face 的 transformers 库,确保安装了最新版本,因为不同版本的 generate 方法参数可能会有所不同。

上面示例使用时可能会出现问题,下面是一个自己项目中的示例:

#!/usr/bin/python
# encoding: utf-8

import torch
# Load via Huggingface Style
from transformers import AutoTokenizer
from mplug_owl.modeling_mplug_owl import MplugOwlForConditionalGeneration
from mplug_owl.processing_mplug_owl import MplugOwlImageProcessor, MplugOwlProcessor
import time
#from peft import PeftModel
from PIL import Image

# 记录开始时间
device = torch.device('cuda:0')
print("hahahahah1  ",device)
start_time = time.time()
# 效果最好
# pretrained_ckpt = 'checkpoint-epoch5-step3600'
src_pwd_path = "soat_nlp"
pretrained_ckpt = src_pwd_path + '/checkpoint-epoch20-final'

model = MplugOwlForConditionalGeneration.from_pretrained(
    pretrained_ckpt,
    torch_dtype=torch.bfloat16,
##    device_map="auto"
)


print("hahahahah1  ",model.device)
device = "cuda:0"
model.to(device)
print("hahahahah2  ",model.device)
image_processor = MplugOwlImageProcessor.from_pretrained(pretrained_ckpt)
tokenizer = AutoTokenizer.from_pretrained(pretrained_ckpt)
processor = MplugOwlProcessor(image_processor, tokenizer)
print("load model done")

print(model)
# 记录结束时间
end_time = time.time()

# 计算耗时
elapsed_time = end_time - start_time

# 打印耗时
print("代码耗时:{:.2f}秒".format(elapsed_time))

# We use a human/AI template to organize the context as a multi-turn conversation.
# <image> denotes an image placehold.
prompts = [
'''
Human: 现在你是一个AI模型,请根据我的提示信息,直接输出已定义好格式的答案。\nAI: ''']

# The image paths should be placed in the image_list and kept in the same order as in the prompts.
# We support urls, local file paths and base64 string. You can custom the pre-process of images by modifying the mplug_owl.modeling_mplug_owl.ImageProcessor
image_list = ["26520_0.jpg", "4381_0.jpg"]


# generate kwargs (the same in transformers) can be passed in the do_generate()
generate_kwargs = {
    'do_sample': True,
    'top_k': 5,
    'max_length': 400
}

images = [Image.open(src_pwd_path + _) for _ in image_list]
inputs = processor(text=prompts, images=images, return_tensors='pt')
inputs = {k: v.bfloat16() if v.dtype == torch.float else v for k, v in inputs.items()}
inputs = {k: v.to(model.device) for k, v in inputs.items()}
print(inputs)
with torch.no_grad():
    outputs = model.generate(**inputs, **generate_kwargs)


# 计算概率
probs = torch.stack(outputs.scores, dim=1).softmax(-1)

# 获取生成文本的token ID和对应的概率
generated_ids = outputs.sequences.tolist()
sentence = tokenizer.decode(generated_ids[0], skip_special_tokens=True)

sent_prob = probs[0][0][generated_ids[0][1]].item()

print(sentence,sent_prob)

# # let's stack the logits generated at each step to a tensor and transform
# # logits to probs
# probs = torch.stack(outputs.scores, dim=1).softmax(-1)  # -> shape [3, 15, vocab_size]


# for idx,prob in enumerate(probs[0][0]) :
#     if prob > 1e-5:
#         print(idx,prob)

其中,模型最后的输出也需要对应的修改:

outputs = self.language_model.generate(

inputs_embeds=inputs_embeds,

# 新增两行

output_scores=True,

return_dict_in_generate=True,

# input_ids=input_ids,

attention_mask=attention_mask,

**generate_kwargs,

)

就可以正常调用了。

已知token id,如何获取对应的文本:tokenizer = AutoTokenizer.from_pretrained(pretrained_ckpt)

从 Token ID 获取对应的文本

若要从已知的 token ID 获取对应的文本,你需要使用加载的 tokenizer 对象的 decode 方法。以下是如何操作的步骤:

  1. 加载预训练的 tokenizer。
  2. 使用 decode 方法将 token ID 转换为文本。
from transformers import AutoTokenizer

# 加载预训练的 tokenizer
pretrained_ckpt = 'your_pretrained_checkpoint'
tokenizer = AutoTokenizer.from_pretrained(pretrained_ckpt)

# 假设你有一个 token ID 列表
token_ids = [101, 1037, 2143, 102]  # 示例 token ID

# 使用 decode 方法将 token ID 转换为文本
text = tokenizer.decode(token_ids)

print(text)

在这个例子中,token_ids 是一个包含 token ID 的列表。tokenizer.decode 方法接受这个列表,并返回对应的文本字符串。pretrained_ckpt 应该被替换为你实际使用的预训练模型的检查点名称。

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是使用 PaddleNLP 模块建立 GPT-2 文本生成模型的代码示例: ```python import paddle import paddle.nn.functional as F from paddlenlp.transformers import GPT2Model, GPT2ForPretraining # 加载 GPT-2 预训练模型 model = GPT2Model.from_pretrained('gpt2-medium-en') # 定义文本生成模型 class GPT2Generator(paddle.nn.Layer): def __init__(self, decoder): super().__init__() self.decoder = decoder def forward(self, input_ids, position_ids=None, attention_mask=None): # 使用 GPT-2 的 decoder 生成文本 output = self.decoder(input_ids, position_ids=position_ids, attention_mask=attention_mask) return output # 加载 GPT-2 预训练模型的 decoder 部分作为文本生成模型的主体部分 decoder = model.transformer generator = GPT2Generator(decoder) # 定义生成文本方法 def generate_text(model, prompt, max_len=50, temperature=1.0): model.eval() # 将 prompt 转换为 token_ids token_ids = model.tokenizer.encode(prompt) token_ids = paddle.to_tensor(token_ids).unsqueeze(0) # 生成文本 for i in range(max_len): output = model(token_ids) logits = output.logits[:, -1, :] / temperature probs = F.softmax(logits, axis=-1) next_token = paddle.multinomial(probs, num_samples=1) token_ids = paddle.concat([token_ids, next_token], axis=-1) # 将生成的 token_ids 转换为文本 generated_text = model.tokenizer.decode(token_ids.numpy().squeeze().tolist()) return generated_text # 测试文本生成模型 generated_text = generate_text(model=generator, prompt='PaddlePaddle is', max_len=20, temperature=0.7) print(generated_text) ``` 代码中使用了 PaddleNLP 模块中的 `GPT2Model` 和 `GPT2ForPretraining` 类,分别表示 GPT-2 预训练模型和 GPT-2 文本生成模型。首先加载 GPT-2 预训练模型,然后使用其 decoder 部分作为文本生成模型的主体部分。代码中还定义了一个 `generate_text` 方法,用于生成文本。在方法中,首先将 prompt 转换为 token_ids,然后使用文本生成模型生成文本,最后将生成的 token_ids 转换为文本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

samoyan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值