【实战教程】结合自定义损失函数采用LoRA微调Llama3-8B

准备工作

  • 准备特定场景微调数据1000左右的量级作为训练集,300左右的数据作为测试集(最好是英文版),数据集的格式示例如下:
// 判别式分类任务
[
	{
   
   
		"instrcution": "# Goal\nYou are a senior python programmer, please check is there any risk of endless loop in the code snippet.\n#code\n```python\nint n = 0\nwhile n < 100:\ns = get_token();\n```",
		"input": "",
		"output": "{\"label\":1}"
	},	
	//...
]
//文本生成式任务
[
	{
   
   
		"instrcution": "# Goal\nYou are a senior python programmer, please write a binary search algorithm.",
		"input": "",
		"output": "def binary_search(arr, target):\nleft = 0\nright = len(arr) - 1\nwhile left <= right:\nmid = left + (right - left) // 2\nif arr[mid] == target:\n.   return mid\nelif arr[mid] > target:\nright = mid - 1\nelse:\nleft = mid + 1\nreturn -1"
	},	
	//...
]
# unsloth是一个比较轻量级的框架,适合开发者从0-1自定义微调路径
# 本实战教程是基于unsloth框架的
https://github.com/unslothai/unsloth
# 里面有很多微调教程、量化的大模型、数据集可参考使用

# 其他主流微调框架,功能全面,可视化完善
# https://github.com/huggingface/trl
# https://github.com/OpenAccess-AI-Collective/axolotl
# https://github.com/hiyouga/LLaMA-Factory
# https://github.com/modelscope/swift
# ...还有很多其他框架,百花齐放
  • python环境准备:
    查看系统GPU配置信息:
import torch
major_version, minor_version = torch.cuda.get_device_capability()
print(major_version)

根据配置信息安装指定的包

# major_version>=8时,GPU环境一般为Ampere, Hopper GPUs (RTX 30xx, RTX 40xx, A100, H100, L40)等,需要根据以下语句安装环境
pip3 install --no-deps packaging ninja einops flash-attn xformers trl peft accelerate bitsandbytes
# major_version<8时,GPU环境一般为(V100, Tesla T4, RTX 20xx)等,需要根据以下语句安装环境
pip3 install --no-deps xformers trl peft accelerate bitsandbytes

导包如果报错的话,大概率是包版本的冲突,如果重装一些包还是存在冲突,实在解决不了,就新建一个conda环境,按提示一个一个装

LoRA微调

  • step1:样本转换,json转换至jsonl的脚本cover_alpaca2jsonl.py
import argparse
import json
from tqdm import tqdm


def format_example(example: dict) -> dict:
    context = f"Instruction: {
     
     example['instruction']}\n"
    if example.get("input"):
        context += f"Input: {
     
     example['input']}\n"
    context += "Answer: "
    target = example["output"]
    return {
   
   "context": context, "target": target}


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--data_path", type=str, default="data/train_data/samples_train_llama.json")
    parser.add_argument("--save_path", type=str, default="data/train_data/samples_train_llama.jsonl")

    args = parser.parse_args()
    with open(args.data_path) as f:
        examples = json.load(f)

    with open(args.save_path, 'w') as f:
        for example in tqdm(examples, desc="formatting.."):
            f.write(json.dumps(format_example(example)) + '\n')


if __name__ == "__main__":
    main()
  • step2:生产tokenize文件夹,为后续自定义损失函数做数据准备,脚本tokenize_dataset_rows.py
import argparse
import json
from tqdm import tqdm

import datasets
import transformers
import os


def preprocess(tokenizer, config, example, max_seq_length, version):
    if version == 'v1':
        prompt = example["context"]
        target = example["target"]
        prompt_ids = tokenizer.encode(prompt, max_length=max_seq_length, truncation=True)
        target_ids = tokenizer.encode(
            target,
            max_length=max_seq_length,
            truncation=True,
            add_special_tokens=False)
        input_ids = prompt_ids + target_ids + [config.eos_token_id]
        return {
   
   "input_ids": input_ids, "seq_len": len(prompt_ids)}

    if version == 'v2':
        query = example["context"]
        target = example["target"]
        history = None
        prompt = tokenizer.build_prompt(query, history)

        a_ids = tokenizer.encode(text=prompt, add_special_tokens=True, truncation=True,
                                 max_length=max_seq_length)
        b_ids = tokenizer.encode(text=target, add_special_tokens=False, truncation=True,
                                 max_length=max_seq_length)

        input_ids = a_ids + b_ids + [tokenizer.eos_token_id]

        return {
   
   "input_ids": input_ids, "seq_len": len(a_ids)}


def read_jsonl(path, max_seq_length, base_model_path, version='v1', skip_overlength=False):

    tokenizer = transformers.AutoTokenizer.from_pretrained(
        base_model_path, trust_remote_code=True)
    config = transformers.AutoConfig.from_pretrained(
        base_model_path, trust_remote_code=True, device_map='auto')
    with open(path, "r") as f:
        for line in tqdm(f.readlines()):
            example = json.loads(line)
            # feature = preprocess(tokenizer, config, example, max_seq_length)
            feature = preprocess(tokenizer, config, example, max_seq_length, version)
            if skip_overlength and len(feature[
<think>好的,我现在需要帮助用户了解如何对Llama3-8B模型进行微调。首先,我需要回忆一下微调大模型的一般步骤,确保没有遗漏关键点。用户提到的模型是Llama3-8B-Chinese-Chat,所以可能需要处理中文数据。 首先,环境准备。通常需要安装深度学习的框架,比如PyTorch,以及相关的库,如Transformers、Accelerate、Peft等。可能还需要考虑使用Hugging Face的生态系统,因为模型是在他们的平台上提供的。这里需要确认用户是否已经具备这些环境,或者是否需要指导他们安装。 接下来是数据准备。用户需要收集或准备与下游任务相关的中文数据集。数据格式可能需要符合指令微调的要求,比如指令-输入的配对。例如,对于对话任务,可能需要类似“问题-回答”的结构。数据预处理可能包括分词、格式化等步骤,确保数据与模型兼容。这里可能需要提醒用户注意数据质量和多样性,避免过拟合。 然后是模型加载。使用Hugging Face的AutoModelForCausalLM和AutoTokenizer来加载预训练模型和分词器。需要确保模型路径正确,可能需要从指定的Hugging Face仓库下载,比如shenzhi-wang/Llama3-8B-Chinese-Chat。此外,考虑到显存限制,可能需要使用量化技术或LoRA等参数高效微调方法。这部分需要解释LoRA的作用,以及如何配置它来减少训练时的资源消耗。 训练配置部分,用户需要设置训练参数,比如学习率、批次大小、训练轮数等。可能需要推荐使用Hugging Face的Trainer类来简化训练流程。同时,使用Accelerate库来处理分布式训练或混合精度训练,这对显存有限的用户来说很重要。需要提醒用户根据硬件调整per_device_train_batch_size,避免OOM错误。 开始训练阶段,需要确保数据、模型和训练循环正确连接。训练过程中监控损失函数和评估指标,防止过拟合。这部分可能需要用户定期保存检查点,以便恢复训练或评估模型性能。 最后是模型评估与应用。训练完成后,用户需要在验证集或测试集上评估模型表现。保存微调后的模型,并提供加载和使用的示例代码。可能还需要建议用户进行多轮迭代,逐步优化模型。 在相关问题的部分,需要考虑用户可能遇到的后续问题,比如数据处理、参数调整、资源不足的解决方案,以及微调后的部署问题。这些问题需要覆盖整个微调流程的各个方面,帮助用户全面了解可能遇到的挑战和解决方法。 需要确保回答符合用户的要求,使用中文,结构清晰,并且正确应用LaTeX格式。同时,引用部分要正确指向提供的参考链接。最后,检查是否有遗漏的步骤或错误的信息,确保回答的准确性和实用性。</think>以下是对Llama3-8B模型进行微调的步骤指南,采用模块化结构说明: ### 一、环境准备 1. 安装基础框架: ```bash pip install torch transformers accelerate peft ``` 2. 推荐使用支持QLoRA的库(降低显存需求): ```bash pip install bitsandbytes datasets ``` ### 二、数据准备 1. **格式要求**: - 建议使用JSON格式的指令数据集 - 示例结构: ```json {"instruction": "解释量子纠缠", "input": "", "output": "量子纠缠是指..."} {"instruction": "翻译成英文", "input": "今天天气晴朗", "output": "Today is sunny"} ``` 2. **数据处理技巧**: - 中文文本需通过模型的tokenizer进行子词分词 - 使用`max_length=512`进行序列截断 - 建议数据集规模:1万-10万条指令数据 ### 三、模型加载(含优化配置) ```python from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "shenzhi-wang/Llama3-8B-Chinese-Chat" model = AutoModelForCausalLM.from_pretrained( model_name, load_in_4bit=True, # 4bit量化 device_map="auto" ) tokenizer = AutoTokenizer.from_pretrained(model_name) ``` ### 四、训练配置(使用QLoRA) ```python from peft import LoraConfig lora_config = LoraConfig( r=8, lora_alpha=32, target_modules=["q_proj", "v_proj"], # 选择注意力层的投影矩阵 lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) # 训练参数设置示例 training_args = TrainingArguments( output_dir="./output", per_device_train_batch_size=2, gradient_accumulation_steps=4, learning_rate=2e-5, num_train_epochs=3, fp16=True ) ``` ### 五、训练执行 ```python from transformers import Trainer trainer = Trainer( model=model, args=training_args, train_dataset=tokenized_dataset, data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False) ) trainer.train() ``` ### 六、保存与使用 1. **模型保存**: ```python model.save_pretrained("./finetuned_llama3") ``` 2. **推理示例**: ```python inputs = tokenizer("请解释相对论:", return_tensors="pt") outputs = model.generate(**inputs, max_length=200) print(tokenizer.decode(outputs[0])) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值