2024工作周期安排
2024项目整体规划
沐曦测试(已完成)
沐曦性能测试研究
沐曦Benchmark相关测试
沐曦模型适配表
2024-02-26沐曦沟通报告
智能打标
数据打标服务Json样例
智能打标寒武纪大模型思路
业务层优先级排序
智能打标流程图
打标API接口文档
图像内容识别
其他
申报项目文本段落
研发链相关资料文档
国产GPU虚拟化培训介绍
大模型比赛
相关资料
智能填单_填单 启动命令
2024私人规划
ChatGPT API账号记录
公众号相关资料
基于 Docker 的深度学习环境:入门篇
ollama
Ollama
ReFT
ReFT AI论文笔记
ReFT概要
分布式对齐搜索 DAS
不是每个人都开始使用 ReFT 吗?
ReFT 微调Llama3
ReFT 算法详解
-
+
首页
ReFT 微调Llama3
# 介绍 参数高效微调 (PEFT) 方法旨在通过仅涉及几个参数的权重更新来调整大型语言模型。尽管如此,之前关于可解释性的大多数研究表明,表示包含大量的语义信息,这意味着编辑表示可能是一个更有效的选择。这就是 Representation Finetuning (ReFT) 方法的用武之地。事实上,LoReFT(ReFT 系列的一部分)是现有 PEFT 的直接替代品,并且学习的干预措施比以前最先进的 PEFT 高 **10 到 50 倍**。 在这方面,**Zhengxuan Wu 等人的**论文表明,当前最先进的 PEFT 的标志是它们修改权重而不是表示。但是,他们的工作表明,编辑表示可能是比权重更新更强大、更高效的替代方案。 # ReFT (表示微调) 在进入 ReFT 之前,我们首先需要理解 **Representations** 的含义。我们知道语言模型会产生标记序列的上下文化表示。给定一个 n 个输入标记 x = (x1, . . . . , xn) 的序列,模型首先将这些标记嵌入到一个表示列表中。然后,模型层将第 j 个隐藏表示 h (j) 列表作为前一个隐藏表示 h (j−1) 列表的函数 连续计算。每个隐藏的表示都是一个向量。LM 使用最终的隐藏表示来生成其预测。 **ReFT 的动机**源于**基于干预的模型可解释性**的概念,它强调改变表示而不是权重。这个概念基于**线性表示假说,该假说**指出概念被编码在神经网络表示的线性子空间中。 在本文中[,他们](https://arxiv.org/pdf/2404.03592)决定使用**分布式交换干预**操作来制作一种新的参数高效方法,用于使语言模型适应下游任务。如果您想更深入地了解这个概念,请随时参考他们的[**论文**](https://arxiv.org/pdf/2404.03592)。 # PyReFT [**PyReFT**](https://github.com/stanfordnlp/pyreft/tree/main) 是一个表示微调 (ReFT) 库,支持通过可训练的干预来调整内部语言模型表示。Pyreft 具有更少的微调参数和更强大的性能,可以提高微调效率,降低微调成本,同时为研究自适应参数的可解释性打开大门。 Pyreft 支持: - 使用 ReFT 微调 HuggingFace 上的任何预训练 LM - 通过配置设置 ReFT 超参数 - 轻松将微调结果分享到 HuggingFace # 使用 PyReFT 微调 Llama-3 由于缺乏计算资源,我在 teknium/OpenHermes-2.5 数据集的 10k 子集上对 Llama-3-8b 进行了 1 个时期的微调。请随意在完整的数据集上试用。 # 安装依赖项 第一步是安装 Pyreft 库。如果已安装,将导入 pyreft。 ``` try: import pyreft except ModuleNotFoundError: !pip install git+https://github.com/stanfordnlp/pyreft.git ``` Pip 安装最新版本的 transformers 或支持 llama-3 的版本。此外,您还需要 bitsandbytes 库。 ``` !pip install -q git+https://github.com/huggingface/transformers !pip install -q bitsandbytes ``` 确保您的 huggingface 可以访问封闭的 Llama-3 模型,并且您必须登录您的 huggingface 帐户。请使用下面的代码片段。 ``` from huggingface_hub import notebook_login notebook_login() ``` # Load Model 和 Tokenizer 下一步是设置用于训练的提示模板。由于我们将使用基本模型,因此我们需要添加特殊标记,以便模型可以学习停止并且不要继续生成文本。使用下面的代码片段加载 model 和 tokenizer。 ``` import torch, transformers, pyreft device = "cuda" prompt_no_input_template = """<|begin_of_text|><|start_header_id|>user<|end_header_id|>%s<|eot_id|><|start_header_id|>assistant<|end_header_id|>""" model_name_or_path = "meta-llama/Meta-Llama-3-8B" model = transformers.AutoModelForCausalLM.from_pretrained( model_name_or_path, torch_dtype=torch.bfloat16, device_map=device, trust_remote_code=True) # # get tokenizer tokenizer = transformers.AutoTokenizer.from_pretrained( model_name_or_path, model_max_length=2048, padding_side="right", use_fast=False) tokenizer.pad_token = tokenizer.eos_token ``` # 为 ReFT FineTuning 准备模型 为模型设置 pyreft 配置,然后使用 pyreft.get_reft_model() 方法让模型准备好进行表示微调。对于配置,我们将在第 15 层对最后一个提示令牌的残差流应用单个 rank-4 LoReFT 干预。 ``` # get reft model reft_config = pyreft.ReftConfig(representations={ "layer": 8, "component": "block_output", "low_rank_dimension": 4, "intervention": pyreft.LoreftIntervention(embed_dim=model.config.hidden_size, low_rank_dimension=4)}) reft_model = pyreft.get_reft_model(model, reft_config) reft_model.set_device("cuda") reft_model.print_trainable_parameters() ``` # 准备数据集 准备数据集以进行微调。我使用了 OpenHermes-2.5 数据集的 10k 子集。由于 Reft Trainer 希望数据采用特定格式,因此我们将使用 pyreft.make_last_position_supervised_data_module() 来准备数据。 ``` dataset_name = "teknium/OpenHermes-2.5" from datasets import load_dataset dataset = load_dataset(dataset_name, split="train") dataset = dataset.select(range(10_000)) data_module = pyreft.make_last_position_supervised_data_module( tokenizer, model, [prompt_no_input_template % row["conversations"][0]["value"] for row in dataset], [row["conversations"][1]["value"] for row in dataset]) ``` # 开始培训 现在我们将为 pyreft 设置 training args。ReftTrainerForCausalLM() 的 API 请求。请根据 ypur 自己的用例和计算资源随意更改它。我将只训练 1 个 epoch 的模型。我尝试集成 wandb,但我认为目前 wandb 的集成存在问题。 ``` # train training_args = transformers.TrainingArguments( per_device_train_batch_size = 4, gradient_accumulation_steps = 8, warmup_steps = 100, num_train_epochs = 1, learning_rate = 5e-4, bf16 = True, logging_steps = 1, optim = "paged_adamw_32bit", weight_decay = 0.0, lr_scheduler_type = "cosine", output_dir = "outputs", report_to=[] ) trainer = pyreft.ReftTrainerForCausalLM(model=reft_model, tokenizer=tokenizer, args=training_args, **data_module) _ = trainer.train() ``` 完成训练后,将干预块保存到目录中。 ``` reft_model.save( save_directory="./reft_to_share", ) ``` # 推理 要进行推理,请将 device 设置为 cuda。加载基本模型并通过将干预模块与其合并来准备 reft 模型。然后将 reft 模型转移到 cuda,否则将无法进行推理。 ``` import torch, transformers, pyreft device = "cuda" model_name_or_path = "meta-llama/Meta-Llama-3-8B" model = transformers.AutoModelForCausalLM.from_pretrained( model_name_or_path, torch_dtype=torch.bfloat16, device_map=device) reft_model = pyreft.ReftModel.load( "Syed-Hasan-8503/Llama-3-openhermes-reft", model, from_huggingface_hub=True ) reft_model.set_device("cuda") ``` 设置您选择的指令并运行下面的代码片段。**恭喜!** 您刚刚推断了您的第一个 REFT 微调模型。 ``` instruction = "A rectangular garden has a length of 25 feet and a width of 15 feet. If you want to build a fence around the entire garden, how many feet of fencing will you need?" # tokenize and prepare the input prompt = prompt_no_input_template % instruction prompt = tokenizer(prompt, return_tensors="pt").to(device) base_unit_location = prompt["input_ids"].shape[-1] - 1 # last position _, reft_response = reft_model.generate( prompt, unit_locations={"sources->base": (None, [[[base_unit_location]]])}, intervene_on_prompt=True, max_new_tokens=512, do_sample=True, eos_token_id=tokenizer.eos_token_id, early_stopping=True ) print(tokenizer.decode(reft_response[0], skip_special_tokens=True)) ```
yg9538
2024年12月9日 16:22
237
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码