实战Llama3

369 阅读7分钟

实战 Llama 3

今天有时间,我们来实测一下,如何玩转Llama 3 。

这里我就挑选比较重要的一些部分来说,想要看完整版的请移步到文章末尾。

Llama-3 8b 用疯狂的 15 万亿代币进行训练! Llama-2 是 2 万亿。

1%%capture
2import torch
3# 获取CUDA设备的能力,主要版本和次要版本
4major_version, minor_version = torch.cuda.get_device_capability()
5
6# 安装适用于Colab环境的unsloth包的特定版本,该版本解决了与torch 2.2.1的兼容性问题
7!pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
8
9# 根据CUDA设备的主要版本选择要安装的软件包
10if major_version >= 8:
11    # 如果CUDA主要版本大于等于8,则安装适用于新GPU架构(如Ampere、Hopper等)的软件包
12    !pip install --no-deps packaging ninja einops flash-attn xformers trl peft accelerate bitsandbytes
13else:
14    # 如果CUDA主要版本小于8,则安装适用于旧GPU架构(如V100、Tesla T4、RTX 20xx)的软件包
15    !pip install --no-deps xformers trl peft accelerate bitsandbytes
16pass  # 此处的pass关键字是为了保持语法完整性,实际上在Jupyter Notebook中,它不需要被执行
1# 设置模型相关的参数
2from unsloth import FastLanguageModel
3import torch
4max_seq_length = 2048  # 可自选!我们内部自动支持RoPE Scaling!
5dtype = None  # 自动检测。Tesla T4, V100使用Float16,Ampere+使用Bfloat16
6load_in_4bit = True  # 使用4bit量化以减少内存使用。可以设为False。
7
8# 我们支持的4bit预量化模型,下载速度提高4倍,且不会出现内存不足的情况。
9fourbit_models = [
10    "unsloth/mistral-7b-bnb-4bit",
11    "unsloth/mistral-7b-instruct-v0.2-bnb-4bit",
12    "unsloth/llama-2-7b-bnb-4bit",
13    "unsloth/gemma-7b-bnb-4bit",
14    "unsloth/gemma-7b-it-bnb-4bit",  # Gemma 7b的Instruct版本
15    "unsloth/gemma-2b-bnb-4bit",
16    "unsloth/gemma-2b-it-bnb-4bit",  # Gemma 2b的Instruct版本
17    "unsloth/llama-3-8b-bnb-4bit",  # [NEW] 15 Trillion token的Llama-3
18]  # 更多模型参见https://huggingface.co/unsloth
19
20# 从预训练模型加载FastLanguageModel和对应的tokenizer
21model, tokenizer = FastLanguageModel.from_pretrained(
22    model_name="unsloth/llama-3-8b-bnb-4bit",
23    max_seq_length=max_seq_length,
24    dtype=dtype,
25    load_in_4bit=load_in_4bit,
26    # token="hf_...",  # 如果使用如meta-llama/Llama-2-7b-hf等门控模型,则使用一个token
27)	

参数:

  • model: 基础语言模型,将对此模型进行PEFT fine-tuning。
  • r: LoRA方法中的空间维度参数。选择大于0的整数,建议值包括8, 16, 32, 64, 128。
  • target_modules: 需要应用LoRA更新的模块列表。
  • lora_alpha: LoRA方法中的另一个重要参数,控制低秩近似的效果。
  • lora_dropout: 应用于LoRA参数的dropout比例。为优化,默认设置为0。
  • bias: 指定是否在LoRA更新中使用偏置。"none"表示不使用。
  • use_gradient_checkpointing: 是否启用梯度检查点以节省内存。"unsloth"模式进一步优化内存使用。
  • random_state: 用于模型初始化的随机状态,确保实验可复现性。
  • use_rslora: 是否使用排名稳定的LoRA方法进行更新。
  • loftq_config: LoftQ的配置,用于进一步的参数量化和压缩。

返回:

  • model: 经过PEFT fine-tuning处理的模型实例。
1model = FastLanguageModel.get_peft_model(
2    model,
3    r = 16, # Choose any number > 0 ! Suggested 8, 16, 32, 64, 128
4    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
5                      "gate_proj", "up_proj", "down_proj",],
6    lora_alpha = 16,
7    lora_dropout = 0, # Supports any, but = 0 is optimized
8    bias = "none",    # Supports any, but = "none" is optimized
9    # [NEW] "unsloth" uses 30% less VRAM, fits 2x larger batch sizes!
10    use_gradient_checkpointing = "unsloth", # True or "unsloth" for very long context
11    random_state = 3407,
12    use_rslora = False,  # We support rank stabilized LoRA
13    loftq_config = None, # And LoftQ
14)
1# 定义一个格式化提示信息的函数
2# 参数 examples 是一个包含指令、输入和输出的字典
3# 返回一个包含格式化后文本的字典
4alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
5
6### Instruction:
7{}
8
9### Input:
10{}
11
12### Response:
13{}"""
14
15EOS_TOKEN = tokenizer.eos_token # 必须添加 EOS_TOKEN,以避免生成过程无限进行
16
17def formatting_prompts_func(examples):
18    instructions = examples["instruction"] # 指令列表
19    inputs       = examples["input"]       # 输入列表
20    outputs      = examples["output"]      # 输出列表
21    texts = []
22    for instruction, input, output in zip(instructions, inputs, outputs):
23        # 为每个指令、输入和输出生成格式化的文本,并添加 EOS_TOKEN
24        text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN
25        texts.append(text)
26    return { "text" : texts, } # 返回包含所有格式化文本的字典
27
28# 加载数据集
29from datasets import load_dataset
30dataset = load_dataset("yahma/alpaca-cleaned", split = "train")
31# 对数据集应用 formatting_prompts_func 函数,进行预处理
32dataset = dataset.map(formatting_prompts_func, batched = True,)

最关键的一步来了,开始训练

1# 初始化一个SFTTrainer用于模型训练
2# SFTTrainer是用于序列标注任务的训练器,封装了训练和评估的逻辑
3from trl import SFTTrainer
4from transformers import TrainingArguments
5
6# 创建SFTTrainer实例
7trainer = SFTTrainer(
8    model = model,  # 要训练的模型
9    tokenizer = tokenizer,  # 用于文本分词的工具
10    train_dataset = dataset,  # 训练数据集
11    dataset_text_field = "text",  # 数据集中文本字段的名称
12    max_seq_length = max_seq_length,  # 最大序列长度
13    dataset_num_proc = 2,  # 数据集加载时的进程数
14    packing = False,  # 是否使用序列打包以提高训练速度,对于短序列有效
15    args = TrainingArguments(
16        per_device_train_batch_size = 2,  # 每个设备的训练批次大小
17        gradient_accumulation_steps = 4,  # 累积梯度计算的步数
18        warmup_steps = 5,  # 预热步数
19        max_steps = 60,  # 最大训练步数
20        learning_rate = 2e-4,  # 学习率
21        fp16 = not torch.cuda.is_bf16_supported(),  # 是否使用半精度训练,取决于硬件支持
22        bf16 = torch.cuda.is_bf16_supported(),  # 是否使用BFloat16训练,取决于硬件支持
23        logging_steps = 1,  # 每多少步打印一次日志
24        optim = "adamw_8bit",  # 优化器选择
25        weight_decay = 0.01,  # 权重衰减
26        lr_scheduler_type = "linear",  # 学习率调度器类型
27        seed = 3407,  # 随机种子
28        output_dir = "outputs",  # 输出目录
29    ),
30)
1# 使用FastLanguageModel进行推理加速
2FastLanguageModel.for_inference(model) # 启用原生2倍加速推理
3
4# 准备输入数据
5inputs = tokenizer(
6[
7    alpaca_prompt.format(
8        "Continue the fibonnaci sequence.", # 给出的指令是继续斐波那契数列
9        "1, 1, 2, 3, 5, 8", # 输入的初始数列
10        "", # 生成的输出留空
11    )
12], return_tensors = "pt").to("cuda") # 将输入数据转换为适合模型的格式并移动到CUDA设备上
13
14# 生成输出
15outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True) # 生成最多64个新令牌,使用缓存加速
16tokenizer.batch_decode(outputs) # 解码输出结果
1# 使用FastLanguageModel进行推理加速
2FastLanguageModel.for_inference(model) # 启用原生2倍加速推理
3
4# 准备输入数据,这里使用tokenizer对输入文本进行编码
5inputs = tokenizer(
6[
7    alpaca_prompt.format(
8        "Continue the fibonnaci sequence.", # 给出的指令是继续斐波那契数列
9        "1, 1, 2, 3, 5, 8", # 输入的初始斐波那契数列
10        "", # 生成输出时留空
11    )
12], return_tensors = "pt").to("cuda") # 返回tensor类型的数据,并转移到CUDA设备上
13
14# 引入TextStreamer用于流式生成文本
15from transformers import TextStreamer
16text_streamer = TextStreamer(tokenizer) # 创建文本流处理器
17
18# 使用模型生成文本,这里使用了streamer参数以支持流式生成
19_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 128)
20# max_new_tokens参数限制了一次生成的新token数量,用于控制生成文本的长度

当然我把colab的代码共享出来了,你可以直接访问查看

colab.research.google.com/drive/1ImsC…

原创声明:本文为本人原创作品,首发于AI ONES wuxiongwei.com,如果转载,请保留本文链接,谢谢。