LLM - 读取 Lora 模型进行文本生成

news2025/1/11 14:12:43

目录

一.引言

二.Lora 模型文本生成

1.模型读取

1.1 AutoModelForCausalLM.from_pretrained

1.2  PeftModel.from_pretrained

2.文本生成

2.1 Tokenizer

2.2 model.generate

3.输出实践

三.总结


一.引言

前面介绍了使用 Baichuan7B 从样本生成到 Lora 模型微调和存储的流程,本文介绍基于 Lora 得到的微调模型进行文本生成,从而实现 QA 样本到 Lora 微调到预测的全链路。由于是学习途中,所以本文也会尽可能解释每一个 API 每一个参数,有问题欢迎大家指出交流~

二.Lora 模型文本生成

1.模型读取

为了在预测时体验 Lora 前后模型效果的变化,所以我们同时加载原始 Baichuan7B 和微调后的 Baichuan7B。

from peft import PeftModel
from transformers import AutoTokenizer, AutoModel
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
import contextlib
import time
autocast = contextlib.nullcontext

# 加载原始 LLM
model_path = "/model/baichuan-7B"

load_st = time.time()
model = AutoModelForCausalLM.from_pretrained(
model_path, load_in_8bit=False, trust_remote_code=True,
device_map="auto" # 模型不同层会被自动分配到不同GPU上进行计算)
)
load_end = time.time()
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
# 原始 LLM 安装上 Lora 模型
lora_model = PeftModel.from_pretrained(model, "weights/simple_lora_by_baichuan-7B").half()
load_lora_end = time.time()
print("Load Ori Model: %s Load Lora Model: %s" % (cost(load_st, load_end), cost(load_end, load_lora_end)))

下面简单了解下加载原始模型和加载 Lora 模型的 API。

1.1 AutoModelForCausalLM.from_pretrained

AutoModelForCausalLM.from_pretrained 方法是用于从预训练模型加载一个自回归语言模型的快捷方式,这里我们给定了四个参数:

• model_path - 模型地址,原生的读取 Baichuan 即可,Lora 读取训练得到的 weights 下的地址

• load_in_8bit - 设置为 True 时,预训练模型的权重参数会以更低的精度 [8位] 进行存储,从而减少了模型所需的内存空间。

• trust_remote_code - 该参数指示系统在执行远程或外部代码时如何处理安全性和信任性。

• device_map - 在分布式计算环境中,可以使用 "device_map" 参数将不同的任务分配给不同的计算节点或处理器,并利用并行计算来加速整体计算过程。这里使用 auto 自定选择。

除此之外,官方还内置了很多常用的 LM,我们可以通过关键字直接下载加载:

from transformers import AutoModelForCausalLM

# 从预训练模型加载自回归语言模型
model = AutoModelForCausalLM.from_pretrained(
    "gpt2",
    cache_dir="./cache",
    from_tf=False,
    force_download=False,
    resume_download=True,
    use_auth_token=False
)

• pretrained_model_name_or_path - 指定要加载的预训练模型的名称或路径。

• config - 可选参数,可以传递一个预训练模型的配置对象(如GPTConfig)。如果没有提供,将自动从pretrained_model_name_or_path中加载。

• cache_dir - 可选参数,用于指定缓存目录地址。

• from_tf - 可选参数,如果设置为True,则从TensorFlow模型转换而来。

• force_download - 可选参数,如果设置为True,则强制从模型Hub下载模型。

• resume_download - 可选参数,如果设置为True,则在下载过程中断后继续下载

• user_auth_token - 可选参数,如果设置为True,并且你的Hugging Face账户已经配置了token,那么将使用token进行认证。 

1.2  PeftModel.from_pretrained

   @classmethod
    def from_pretrained(
        cls,
        model: PreTrainedModel,
        model_id: Union[str, os.PathLike],
        adapter_name: str = "default",
        is_trainable: bool = False,
        config: Optional[PeftConfig] = None,
        **kwargs: Any,
    ):

• model - 初始化模型,通过 ~transformers.PreTrainedModel.from_pretrained 加载而来

• model_id - 在 HF 托管的 Lora 模型 id 或者 Lora 训练后通过 save_pretrained 保存的路径地址

daapter_name - 要加载的适配器的名称。这对于加载多个适配器非常有用。

• is_trainable - 适配器是否应可训练。如果为“False”,适配器将被冻结并用于推理。

• config - 要使用的配置对象,而不是自动加载的配置。此配置对象与“model_id”和“kwargs”互斥。一般在调用“from_pretrained”之前加载。

Tips:

config 即 peft.PeftConfig 上文 Lora 训练时我们已经介绍了其中的参数,最主要的是低秩 rank r。

peft_config = LoraConfig(
        task_type=TaskType.CAUSAL_LM, # 因果语言模型可以被看作是自回归语言模型的一种扩展,在每个时间步上,它不仅考虑之前的文本序列,还>考虑了未来可能出现的单词信息,从而更好地捕捉语句的因果结构。
        inference_mode=False,
        r=finetune_args.lora_rank,
        lora_alpha=32,
        lora_dropout=0.1,
        target_modules = ["W_pack"] # 把model打印出来,找跟attention相关的模块
    )
 
# 获取 Lora 微调模型
model = get_peft_model(model, peft_config)

 推理阶段我们一般直接加载 Base 模型和 Lora 参数即可,Lora 微调时需要设置 peft.PeftConfig。

2.文本生成

while True:
    inputText = input("请输入信息 [输入'q'退出]\n")
    if inputText == 'q':
        print("Exit!")
        break
    else:
        time_st = time.time()
        inputs = tokenizer(inputText + "\n", return_tensors='pt')
        inputs = inputs.to('cuda:0')
        time_token = time.time()
        ori_pred = model.generate(**inputs, max_new_tokens=512, do_sample=True)
        ori_answer = tokenizer.decode(ori_pred.cpu()[0], skip_special_tokens=True)
        time_ori = time.time()
        lora_pred = lora_model.generate(**inputs, max_new_tokens=512, do_sample=True)
        lora_answer = tokenizer.decode(lora_pred.cpu()[0], skip_special_tokens=True)
        time_lora = time.time()
        print("原始输出:")
        print(ori_answer)
        print('Lora输出:')
        print(lora_answer)
        print("Total Cost: %s Token Cost: %s Ori Cost: %s Lora Cost: %s" % (cost(time_st, time_lora), cost(time_st, time_token), cost(time_token, time_ori), cost(time_ori, time_lora)))

为了可以单次加载多次使用,这里采用 While True 的形式,主要使用 tokenizer 对原始输入进行 token 编码,其次使用 model.generate 进行文本生成,最后用 tokenizer.encode 变成我们可以看懂的语言。为了对比前后差距,我们采用原 Baichuan7B 和 Lora 后的 Baichuan7B 进行人工对比。这里简单了解诶下 tokenizer 和 generate 的参数。

2.1 Tokenizer

tokenizer return_tensors='pt' 代表返回 PyTorch 类的张量。我们可以从 tokenizer 后的 Inputs 获取 input_ids 和 attention_mask 作为 PyTorch 向量。

input="你好,今天天气不错!"
print(tokenizer(input + "\n", return_tensors='pt'))
=>
{'input_ids': tensor([[ 9875, 31213,    72,  3482,  6971,  6891,    80,     5]]), 
 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1]])}

2.2 model.generate

在 model.generate 方法中,我们主要使用了 max_new_token 和 do_sample 参数

• max_new_token

前者从字面意思就可以看出其含义指定了生成的文本中允许的最大新标记数目。文本会一直生成直到满足下面条件之一: 达到 max_length 限制或生成的文本中新增的 token 数目超过了 max_new_token。该参数和 max_length 主要用于控制生成文本的长度。

• do_sample

该参数决定了是否采用采样策略生成文本。当设置为 True 时,模型将根据概率分布随机选择下一个标记,当设置为 False 时,模型将选择概率最高的下一个标记。通过设置 do_sample = True,我们可以增加生成文本的多样性。

下面给出一个常用的文本生成示例,其中给出了不同参数的含义:

# 使用generate方法生成文本
output = model.generate(
    input_ids=input_ids,  # 输入的token张量
    max_length=100,       # 生成文本的最大长度
    num_return_sequences=5,  # 返回多个生成序列
    max_new_tokens=20,    # 允许的最大新标记数目
    do_sample=True,       # 使用采样策略
)

# 处理生成的输出
for generated_sequence in output:
    generated_text = tokenizer.decode(generated_sequence, skip_special_tokens=True)
    print(generated_text)

Tips:

上述 While True 函数虽然是持续输出,但是每次输出是单调独立的,每一次输出不会考虑过去的输入,即没有记忆性,不考虑 History。

3.输出实践

• 原始样本

{"q": "请计算:39 * 0 = 什么?", "a": "这是简单的乘法运算,39乘以0得到的是0"}
{"q": "题目:51/186的答案是什么?", "a": "这是简单的除法运算,51除以186大概为0.274"}
{"q": "鹿妈妈买了24个苹果,她想平均分给她的3只小鹿吃,每只小鹿可以分到几个苹果?", "a":"鹿妈妈买了24个苹果,平均分给3只小鹿吃,那么每只
小鹿可以分到的苹果数就是总苹果数除以小鹿的只数。\n24÷3=8\n每只小鹿可以分到8个苹果。所以,答案是每只小鹿可以分到8个苹果。"}
{"q": "请计算:39 * 0 = 什么?", "a": "这是简单的乘法运算,39乘以0得到的是0"}
{"q": "题目:51/186的答案是什么?", "a": "这是简单的除法运算,51除以186大概为0.274"}
{"q": "鹿妈妈买了24个苹果,她想平均分给她的3只小鹿吃,每只小鹿可以分到几个苹果?", "a": "鹿妈妈买了24个苹果,平均分给3只小鹿吃,那么每>只小鹿可以分到的苹果数就是总苹果数除以小鹿的只数。\n24÷3=8\n每只小鹿可以分到8个苹果。所以,答案是每只小鹿可以分到8个苹果。"}
{"q": "请计算:39 * 0 = 什么?", "a": "这是简单的乘法运算,39乘以0得到的是0"}
{"q": "题目:51/186的答案是什么?", "a": "这是简单的除法运算,51除以186大概为0.274"}
{"q": "鹿妈妈买了24个苹果,她想平均分给她的3只小鹿吃,每只小鹿可以分到几个苹果?", "a": "鹿妈妈买了24个苹果,平均分给3只小鹿吃,那么每>只小鹿可以分到的苹果数就是总苹果数除以小鹿的只数。\n24÷3=8\n每只小鹿可以分到8个苹果。所以,答案是每只小鹿可以分到8个苹果。"}

• 输出示例

我们的训练样本简单的复制了几次 demo 样本,可以看到模型在经过 lora 微调后,可以大致描述清楚,但是存在重复输出的问题。

三.总结

结合前面的样本生成和 Lora 训练,这里我们实现了样本-训练-生成的全链路。有兴趣的同学可以简单尝试该 demo。这一版从样本和训练整体来说都比较简单,后续有时间会更新下带 History 样本的模型微调示例。

QA 数据准备与 DataSet 构建

Lora 微调预训练模型

训练数据构造解析

Lora 微调遇到的问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/753768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

磁盘擦写次数计算

1.让机器能有外网 2,安装工具 sudo apt-get install smartmontools 3,输入查询命令 sudo smartctl -x /dev/sda |egrep Device Model|User Capacity|Sector Size|173|Logical Sectors Written|Percentage Used Endurance Indicator 4,计算擦写次数 计算方法:25…

hadoop启动无法启动datanode或者namenode

首先进入hadoop安装目录下例如: 再进入dfs目录下,没有出现在hdfs-site.xml配置的data或者name cd data/current vim VERSION 打开VERSION文件复制:clusterID下的内容 将内容复制到name中的VERSION。再进行重启Hadoop

常见的前端安全以及常规安全策略

1、CSRF:跨站请求伪造(Cross-site request forgery); 原理: (1) 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A; (2&#xff…

mapping文件目录生成修改

参考文章: gradle编译完成Copy mapping文件 - 简书 (jianshu.com) 第一步:在app的build.gradle中做如下配置: android {android.applicationVariants.all {variant ->def buildType variant.buildType.nametasks.all {def mappingDir …

米尔基于STM32MP135核心板,助力充电桩发展

随着电动车的普及和人们环保意识的增强,充电桩作为电动车充电设备的重要一环,充电桩行业正迅速发展,消费市场的大量应用也造就市场的需求量不断增长。因此,产品的功能、可靠性、安全性等要求也变得尤为重要,而采用传统…

Leetcode---353周赛

周赛题目 2769. 找出最大的可达成数字 2770. 达到末尾下标所需的最大跳跃次数 2771. 构造最长非递减子数组 2772. 使数组中的所有元素都等于零 一、找出最大的可达成数字 这题就是简单的不能在简单的简单题, 题目意思是:给你一个数num和操作数t&…

智能分析网关V2有抓拍告警但无法推送到EasyCVR,是什么原因?

我们在此前的文章中也介绍了关于智能分析网关V2接入EasyCVR平台的操作步骤,感兴趣的用户可以查看这篇文章:在EasyCVR新版本v3.3中,如何正确接入智能分析网关V2? 智能分析网关V2是基于边缘AI计算技术,可对前端摄像头采…

机器学习 day27(反向传播)

导数 函数在某点的导数为该点处的斜率,用height / width表示,可以看作当w增加ε,J(w,b)增加k倍的ε,则k为该点的导数 反向传播 tensorflow使用反向传播来自动计算神经网络模型中的导数

中国区域地面气象要素驱动数据集(1979-2018)

中国区域地面气象要素驱动数据集(1979-2018) 摘要 中国区域地面气象要素驱动数据集,包括近地面气温、近地面气压、近地面空气比湿、近地面全风速、地面向下短波辐射、地面向下长波辐射、地面降水率共7个要素。数据为NETCDF格式,时…

Redis_非关系型数据库

一、 Redis介绍 1.NoSQL 也叫Not Only SQL(不仅仅是SQL, 不用 sql语言操作的数据库), 一般指非关系型数据库 关系型数据库: 以数据库表为单位存储,表与表之间存在某种关系 非关系型数据库: 数据与数据之间没有关系, 数据就是以键值对的形式存储, 通过键获取到值 在互联网发展中…

cjson的内存泄漏案例

1、当我们使用下面这些创建json对象时,需要用cJSON_Delete();释放,(当然,释放父JSON对象后,子JSON对象也会被释放) 2、多次释放同一内存空间 在recv_write_property函数中的data,在Equipment_re…

Unity游戏源码分享-Unity5.4.1打砖块游戏Breakout_Game_Starter_Kit

Unity5.4.1打砖块游戏Breakout_Game_Starter_Kit 童年的回忆 项目地址:https://download.csdn.net/download/Highning0007/88042779Unity游戏源码分享-

ViDeNN: Deep Blind Video Denoising

ViDeNN: Deep Blind Video Denoising 摘要 We propose ViDeNN: a CNN for Video Denoising without prior knowledge on the noise distribution (blind denoising). The CNN architecture uses a combination of spatial and temporal filtering, learning to spatially deno…

【Java 泛型方法】泛型方法的定义和使用,泛型的通配符和泛型的上下限,泛型的注意事项

博主&#xff1a;_LJaXi Or 東方幻想郷 专栏&#xff1a; Java | 从跨平台到跨行业 开发工具&#xff1a;IntelliJ IDEA Java 泛型方法 泛型方法 ❓需求| 泛型的通配符 | 上限 | 下限 |泛型擦除 ⛔基本数据类型问题 泛型方法 ❓ [修饰符] <类型变量, 类型变量...> [返回…

内容过多,超出部分以省略号“...”显示

效果图如图所示&#xff1a; 1.第一种实现方法&#xff0c;使用纯css实现&#xff08;ps&#xff1a;此方式必须给元素设置宽度&#xff0c;否则可能无效果&#xff09;&#xff0c;代码如下&#xff1a; html代码 <!-- 超过长度&#xff0c;用省略号实现&#xff0c;css的…

相交链表——力扣160

题目描述 法一&#xff09;哈希表 class Solution{ public:ListNode* getIntersectionNode (ListNode* headA, ListNode* headB){unordered_set<ListNode*> st;ListNode* temp headA;while(temp){st.insert(temp);temp temp->next;}temp headB;while(temp){if(st.c…

DES加密解密 Feistel算法网络结构 详讲

文章目录 简单知识导入&#xff1a;具体过程&#xff1a;IP置换&#xff08; 64 − > 64 64->64 64−>64&#xff09;轮函数--E扩展置换&#xff08; 32 − > 48 32->48 32−>48&#xff09;轮函数--与子密钥异或&#xff08; 48 − > 48 48->48 48−&…

【Matlab】智能优化算法_人工大猩猩部队优化算法GTO

【Matlab】智能优化算法_人工大猩猩部队优化算法GTO 1.背景介绍2.数学模型2.1 勘探阶段2.2 开采阶段2.2.1 跟随银背2.2.2 成年女性比赛 3.文件结构4.算法流程图5.伪代码6.详细代码及注释6.1 boundaryCheck.m6.2 GTO.m6.3 initialization.m6.4 main.m6.5 ObjectiveFunction.m 7.…

LabVIEW开发惯性测量系统

LabVIEW开发惯性测量系统 惯性导航系统是通过将惯性传感器直接绑定在载体主体上来完成制导和导航任务的系统。所以惯性测量系统主要是动态静态地测试陀螺仪和加速度计的性能。测试点和计算点数众多&#xff0c;对测试速度和精度要求高。基于上述特点&#xff0c;基于虚拟仪器软…

Web自动化 —— Selenium元素定位与防踩坑

1. 基本元素定位一 from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By # selenium Service("../../chromedriver.exe") # driver webdriver.Chrome(serviceService) # driver.…