使用Colaboratory免费GPU资源微调Llama3-8b

Llama3微调过程

准备工作

Google Colaboratory

Google Colaboratory,也称为 Colab,是一个基于云的平台,允许用户编写和执行 Python 代码。 它为机器学习和数据分析任务提供了便利的环境,并内置了对 TensorFlow 等流行库的支持。

在Google 创建Colab笔记副本

  • 新建->更多->关联更多应用

image-20240605171618341

  • 搜索Google Colaboratory

image-20240605171558617

  • 安装 Colaboratory

image-20240605171745990

  • 再次新建 Google Colaboratory 文件

image-20240605171914405

  • 进入Colab笔记副本

image-20240605173617598

连接到T4 GPU

  • 更改运行时类型

image-20240605174816472

  • 选择T4

image-20240605174731452

连接到谷歌云盘

from google.colab import drive
drive.mount('/content/drive')

运行之后要弹出一个页面进行授权

下载Unsloth

unsloth是一个开源的大模型训练加速项目, 用它来微调 Llama 3、Mistral、Phi-3 和 Gemma 速度提高 2-5 倍,内存减少 80%

目前开源版本的 Unsloth,仅支持单机单卡训练,且仅支持 Llama2、Llama3、Mistral、Gemma、Zephyr、TinyLlama、Phi-3 等模型

%%capture
# Installs Unsloth, Xformers (Flash Attention) and all other packages!
!pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
!pip install --no-deps xformers trl peft accelerate bitsandbytes

下载预训练模型

from unsloth import FastLanguageModel
import torch
max_seq_length = 2048 
dtype = None 
load_in_4bit = True 

# 支持的预4位量化模型,可实现4倍更快的下载速度和无OOM。
fourbit_models = [
    "unsloth/mistral-7b-bnb-4bit",
    "unsloth/mistral-7b-instruct-v0.2-bnb-4bit",
    "unsloth/llama-2-7b-bnb-4bit",
    "unsloth/gemma-7b-bnb-4bit",
    "unsloth/gemma-7b-it-bnb-4bit", 
    "unsloth/gemma-2b-bnb-4bit",
    "unsloth/gemma-2b-it-bnb-4bit",
    "unsloth/llama-3-8b-bnb-4bit", 
] 

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/llama-3-8b-bnb-4bit",
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = load_in_4bit,
    # token = "hf_...", # 如果使用像meta-llama/Llama-2-7b-hf这样的门控模型,请使用其中一个
)

注意 : 这里运行之前要连接到T4 GPU, 否则会报cuda缺失错误

运行之后:

image-20240605175501190

设置LoRA训练参数

model = FastLanguageModel.get_peft_model(
    model,
    r = 16, # 选择任何大于0的数字!建议使用8、16、32、64、128
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
                      "gate_proj", "up_proj", "down_proj",],
    lora_alpha = 16,
    lora_dropout = 0, # 支持任何值,但等于0时经过优化
    bias = "none",    # 支持任何值,但等于"none"时经过优化
    # [NEW] "unsloth" 使用的VRAM减少30%,适用于2倍更大的批处理大小!
    use_gradient_checkpointing = "unsloth", # True或"unsloth"适用于非常长的上下文
    random_state = 3407,
    use_rslora = False,  # 我们支持排名稳定的LoRA
    loftq_config = None, # 以及LoftQ
)

什么是 LoRA?

LoRA 的核心思想是通过引入低秩矩阵的变化来代替对原始大矩阵的更新,从而减少训练过程中需要更新的参数数量。具体来说,在模型的某些权重矩阵中引入一个低秩分解(两个小矩阵的乘积),并只训练这些小矩阵,而不是原始的大矩阵。

数据准备

这里采用的是来自yahma的Alpaca数据集,这是原始Alpaca数据集的经过筛选的版本,包含了来自原始数据集中的52000条数据。可以用自己的数据准备替换此代码部分

alpaca_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.

### Instruction:
{}

### Input:
{}

### Response:
{}"""

EOS_TOKEN = tokenizer.eos_token # 必须添加EOS_TOKEN
def formatting_prompts_func(examples):
    instructions = examples["instruction"]
    inputs       = examples["input"]
    outputs      = examples["output"]
    texts = []
    for instruction, input, output in zip(instructions, inputs, outputs):
        # 必须添加EOS_TOKEN,否则生成将无法停止!
        text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN
        texts.append(text)
    return { "text" : texts, }
pass

from datasets import load_dataset
dataset = load_dataset("yahma/alpaca-cleaned", split = "train")
dataset = dataset.map(formatting_prompts_func, batched = True,)

运行之后:

image-20240605175810993

训练模型

参数设置

from trl import SFTTrainer  # SFTTrainer:来自 trl(用于大语言模型的低秩适应性训练的库),是一个用于训练模型的类。
from transformers import TrainingArguments # 来自 transformers 库,是一个包含训练参数的类。

trainer = SFTTrainer(
    model = model,  # model:预训练的语言模型。
    tokenizer = tokenizer, # tokenizer:对应的分词器
    train_dataset = dataset, # train_dataset:用于训练的文本数据集。
    dataset_text_field = "text", # dataset_text_field:数据集中包含文本的字段名称。
    max_seq_length = max_seq_length, # max_seq_length:每个输入序列的最大长度。
    dataset_num_proc = 2, # 数据处理时使用的进程数量,设置为 2 表示使用两个进程。
    packing = False, # 是否启用序列打包。打包可以提高短序列训练的效率,这里设置为 False。
    args = TrainingArguments(
        per_device_train_batch_size = 2, # 每个设备(如 GPU)上的训练批量大小,设置为 2
        gradient_accumulation_steps = 4,# 梯度累积步骤数,设置为 4。即每累计 4 个批次的梯度后才进行一次权重更新。
        warmup_steps = 5, # 学习率预热步骤数,设置为 5
        max_steps = 60, # 训练的最大步骤数,设置为 60
        learning_rate = 2e-4, # 初始学习率,设置为 2e-4
        fp16 = not torch.cuda.is_bf16_supported(), # 是否使用 16 位浮点数进行训练
        bf16 = torch.cuda.is_bf16_supported(), # 如果 GPU 支持 bf16,则使用 bf16
        logging_steps = 1, # 日志记录的步数间隔,设置为 1,即每步都记录日志
        optim = "adamw_8bit", # 优化器,设置为 adamw_8bit,表示使用 8 位精度的 AdamW 优化器,可以减少显存占用
        weight_decay = 0.01, # 权重衰减系数,设置为 0.01,用于防止过拟合
        lr_scheduler_type = "linear", # 学习率调度器类型,设置为 linear,表示线性调度
        seed = 3407, # 随机种子,设置为 3407,用于确保结果的可重复性。
        output_dir = "outputs", # 输出目录,训练生成的模型和日志会保存在这个目录下
    ),
)

显示当前内存状态

gpu_stats = torch.cuda.get_device_properties(0)
start_gpu_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
max_memory = round(gpu_stats.total_memory / 1024 / 1024 / 1024, 3)
print(f"GPU = {gpu_stats.name}. 最大内存 = {max_memory} GB.")
print(f"{start_gpu_memory} GB of 内存剩余。")
  • 输出

image-20240605180217554

开始训练

trainer_stats = trainer.train()

运行之后:

image-20240605182659016

运行模型

# alpaca_prompt = Copied from above
FastLanguageModel.for_inference(model) # Enable native 2x faster inference
inputs = tokenizer(
[
    alpaca_prompt.format(
        "Continue the fibonnaci sequence.", # instruction
        "1, 1, 2, 3, 5, 8", # input
        "", # output - leave this blank for generation!
    )
], return_tensors = "pt").to("cuda")

outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
tokenizer.batch_decode(outputs)

连接对话

# alpaca_prompt = Copied from above
FastLanguageModel.for_inference(model) # Enable native 2x faster inference
inputs = tokenizer(
[
    alpaca_prompt.format(
        "Continue the fibonnaci sequence.", # instruction
        "1, 1, 2, 3, 5, 8", # input
        "", # output - leave this blank for generation!
    )
], return_tensors = "pt").to("cuda")

from transformers import TextStreamer
text_streamer = TextStreamer(tokenizer)
_ = model.generate(**inputs, streamer = text_streamer, max_new_tokens = 128)

保存模型

  • 获取当前的保存的地址
import os
current_path = os.getcwd()
model.save_pretrained("lora_model") # 本地保存
print(f"保存地址 {current_path}/lora_model")
  • 将模型保存为预训练的GGUF格式
if True: model.save_pretrained_gguf("model", tokenizer, quantization_method = "q4_k_m")

运行后:

image-20240605191455492

生成的模型移动到谷歌云

import shutil

source_path = '/content/model-unsloth.Q4_K_M.gguf'
destination_path = '/content/drive/MyDrive/'

# 移动文件,内容有点大需要点时间
shutil.move(source_path, destination_path)
print("请使用谷歌云MyDrive中下载该内容")

运行后:

image-20240605192100443

查看模型

image-20240605192125976

LM Studio

导入微调后的模型

image-20240606112704431

使用微调后的模型

image-20240606112616928

问题记录

  • GPU 计算能力不够

image-20240605180526918

原因 :

之前安装的 PyTorch 版本与 xFormers 编译时使用的 PyTorch 版本不匹配

解决办法:

  • 重新安装xformers
pip uninstall xformers -y
!pip install --no-deps xformers trl peft accelerate bitsandbytes
  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Llama3-8b是一个开源的聊天机器人模型,可以用于自然语言处理和对话生成任务。如果您希望进行私有化部署,可以按照以下步骤进行操作: 1. 获取源代码:首先,您需要从Llama3-8b的开源代码库中获取源代码。您可以在GitHub上找到该项目,并将其克隆到本地。 2. 环境配置:在进行私有化部署之前,您需要配置适当的环境。确保您的系统满足所需的软件和硬件要求,并安装必要的依赖项。 3. 数据准备:为了训练和使用Llama3-8b模型,您需要准备相应的数据集。这可能包括对话数据、语料库等。确保数据集的质量和多样性,以提高模型的性能。 4. 模型训练:使用准备好的数据集,您可以开始训练Llama3-8b模型。根据您的需求和资源情况,您可以选择在单个GPU或多个GPU上进行训练。训练过程可能需要一定的时间和计算资源。 5. 模型部署:一旦训练完成,您可以将Llama3-8b模型部署到私有环境中。这可能涉及将模型加载到服务器或云平台,并设置相应的API接口供其他应用程序调用。 6. 安全性和隐私保护:在进行私有化部署时,确保采取适当的安全措施来保护用户数据和系统安全。这可能包括数据加密、访问控制、身份验证等。 7. 持续优化和更新:私有化部署后,您可以根据实际需求对Llama3-8b模型进行持续优化和更新。这可能包括增加新的训练数据、微调模型参数等。 希望以上步骤对您进行Llama3-8b的私有化部署提供了一些指导。如果您有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值