【大模型-驯化】一文教会你bert、qwen、llama等模型对结果进行概率控制问题

【大模型-驯化】一文教会你bert、qwen、llama等模型对结果进行概率控制问题
 
本次修炼方法请往下查看
在这里插入图片描述

🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地!
🎇 相关内容文档获取 微信公众号
🎇 相关内容视频讲解 B站

🎓 博主简介:AI算法驯化师,混迹多个大厂搜索、推荐、广告、数据分析、数据挖掘岗位 个人申请专利40+,熟练掌握机器、深度学习等各类应用算法原理和项目实战经验

🔧 技术专长: 在机器学习、搜索、广告、推荐、CV、NLP、多模态、数据分析等算法相关领域有丰富的项目实战经验。已累计为求职、科研、学习等需求提供近千次有偿|无偿定制化服务,助力多位小伙伴在学习、求职、工作上少走弯路、提高效率,近一年好评率100%

📝 博客风采: 积极分享关于机器学习、深度学习、数据分析、NLP、PyTorch、Python、Linux、工作、项目总结相关的实用内容。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


下滑查看解决方法

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  

🎯 1.问题介绍

  大模型的发展使得之前的nlp相关任务:文本分类、实体抽取、文本生成、文本理解等任务都在由bert预训练模型向gpt模型进行过渡,具体的之前用bert进行文本分类的任务都可以通过gpt进行sft来得到微调的最终结果,在通过bert进行文本分类的过程中,我们可以对bert的输出结果softmax进行阈值的分析和选择来确定最终召回和精确率,但是在gpt方式微调的过程中,由于gpt是每次预测未来一个字的概率,因此,和之前的bert分类直接取每个类别的概率的最大值有较大的区别,本次博客教大家如何通过gpt系列模型进行预测,然后通过某个字的概率来调整最终的召回和精确:

💡 2. 问题分析

💡 2. 1 bert模型做分类得出相关的概率值

  通过bert进行微调分类效果,通常是通过对bert的最终softmax中某个类别的概率的最大值最为我们最终的结果,因此,如果是通过bert进行分类的话,只需要得到最终一层的softmax的结果的概率值,然后,调整概率值的阈值就可以调整最终的准召,具体的代码如下所示:

import torch
from transformers import XLMRobertaTokenizer, XLMRobertaModel
import pandas as pd

# 指定模型和分词器的路径
model_path = "huggingface/robert"
tokenizer = XLMRobertaTokenizer.from_pretrained(model_path)
model = XLMRobertaModel.from_pretrained(model_path)
# 确定设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)

# 准备输入数据
def get_result(texts):
    inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
    inputs = {k: v.to(device) for k, v in inputs.items()}

    # 获取嵌入
    model.eval()
    with torch.no_grad():
        outputs = model(**inputs, output_hidden_states=True)
        # 选择最后一层的隐藏状态
        last_hidden_states = outputs.hidden_states[-1]
    embeddings = last_hidden_states.mean(dim=1)  # 沿序列长度维度取平均
    # 转换为DataFrame
    embeddings_df = pd.DataFrame(embeddings.cpu().numpy())
    return embeddings_df


data=pd.read_excel("./dataset.xlsx")
data = data[['opcode_text','full_graph_content', 'label']]
data['text'] = data.apply(lambda x: str(x['opcode_text'])[:261] + str(x['full_graph_content'])[:261], axis=1)
df = None 
for i, (v, label) in enumerate(zip(data['text'].tolist(), data['label'].tolist())):
    if i == 0:
        df = get_result([v])
        df['label'] = label
    else:
        tmp_df = get_result([v])
        tmp_df['label'] = label
        df = pd.concat([df, tmp_df])

df.to_csv('all_embedding.csv', sep=',', index=False)

   我们最终得到的向量的维度是bert输出的512维的向量维度,如果想要得到softmax对应的每个类别的概率,具体的代码如下所示:

def model_predict():
    """
        模型预测
    """
    bert_config = BertConfig.from_pretrained('../bert-base-chinese')
    model = BertClassifier(bert_config, 2)
    # 加载训练好的模型
    model.load_state_dict(torch.load('best_model.pkl', map_location=torch.device('cpu')))
    model.eval()
    tokenizer = BertTokenizer.from_pretrained('../bert-base-chinese')
    print('进行预测过程!!!!!')
    while True:
        text = input('Input: ')
        token = tokenizer(text, add_special_tokens=True, padding='max_length', truncation=True, max_length=512)
        input_ids = token['input_ids']
        attention_mask = token['attention_mask']
        token_type_ids = token['token_type_ids']

        input_ids = torch.tensor([input_ids], dtype=torch.long)
        attention_mask = torch.tensor([attention_mask], dtype=torch.long)
        token_type_ids = torch.tensor([token_type_ids], dtype=torch.long)

        predicted = model(
            input_ids,
            attention_mask,
            token_type_ids,
        )
        pred_label = torch.argmax(predicted, dim=1)

        print('Label:', pred_label)

  有了上述的softamx的输出后,我们可以取最大的概率最为我们最终类别的概率,然后在通过调整概率的阈值来控制最终模型的准召情况

💡 2. 2 gpt模型做分类得出相关的概率值

  对于gpt系列的模型,比如qwen、llama等模型,他们的输出是一个token的输出,每次都是输出每个字的概率,这种情况,我们可以根据最终的输出的label进行判断,比如通过qwen进行微调后的分类模型标签为:心情很好,心情很不好,那么这个时候我们可以通过去判断第4个token是还是来判断最终模型输出的分类是那个,当然这里需要注意的是,gpt对输入进行切词的时候并不是一个字一个字的切分的,而是一个token切分的,因此,可能会有两个字为一个token的情况,因此,可以将gpt的输出token和对应的概率和向量都打印出来,这个还有一个需要注意的是,gpt的输出是所有词典的token的概率输出,因此是一个很大的向量,具体的代码如下所示:

# A100 14G memory
import numpy as np 
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_path = "=qwen2_5-14b-instruct/v4-20241016-163008/checkpoint-1872"
prompt_info = "xxxxxx"
input_query = "xx:啊喂你好师傅外卖到了开门吧\n用户:喂\nxx:好了\n骑手:嗯好嘞\n"
device = "cuda:7"

messages = [
    {"role": "system", "content": prompt_info},
    {"role": "user", "content": input_query}
]

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype="auto",
    device_map=device
    )
tokenizer = AutoTokenizer.from_pretrained(model_path)

text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True)
model_inputs = tokenizer([text], return_tensors="pt").to(device)
generated_ids = model.generate(
    model_inputs.input_ids,
    do_sample=False,
    max_new_tokens=512,
    return_dict_in_generate=True,
    temperature=2,
    # output_logits=True
    output_scores=True
)
# output_prob(model,generated_ids,model_inputs,tokenizer)
generated_tokens = [
    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids.sequences)
]

for tokens, logits in zip(generated_tokens[0], generated_ids.scores):
    print(tokens, tokenizer.decode(tokens), np.max(torch.softmax(logits, dim=1).tolist()[0]), 
          torch.softmax(logits, dim=1).tolist()[0][tokens.item()])

transition_scores = model.compute_transition_scores(
    generated_ids.sequences, generated_ids.scores, normalize_logits=True
)
# print(transition_scores)

response = tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)[0]

print(response)
print(generated_ids.scores)
print(generated_ids)

# 输出通过概率
# pred = -1
# for idx, score in enumerate(generated_ids.scores):
#     prob = torch.softmax(score, dim=1).tolist()[0]
#     print(prob)
#     for idx_word,p in enumerate(prob):
#         if idx==3 and idx_word==67338:                   
#             pred = p


输出结果:
tensor(100855, device='cuda:7') a 1.0
tensor(44934, device='cuda:7') b 1.0
tensor(38342, device='cuda:7') c 0.9999998807907104
tensor(104953, device='cuda:7') de 1.0
tensor(99512, device='cuda:7') f 1.0
tensor(102737, device='cuda:7') g 1.0
tensor(20412, device='cuda:7') h 1.0
tensor(100855, device='cuda:7') i 1.0
tensor(44934, device='cuda:7') j 1.0
tensor(99531, device='cuda:7') kl 1.0
tensor(151645, device='cuda:7') <|im_end|> 1.0
tensor([[ 0.0000e+00,  0.0000e+00, -1.1921e-07,  0.0000e+00,  0.0000e+00,
          0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,  0.0000e+00,
          0.0000e+00]], device='cuda:7')
abcdefghijkl
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

算法驯化师

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

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

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

打赏作者

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

抵扣说明:

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

余额充值