用Unsloth微调Gemma-3
当大家都在竞相构建基于 ChatGPT 的应用程序时,精明的开发人员正在悄悄发现这个新轻量级 Gemma-3 的微调能力,这是一个隐藏的宝石,可以将通用人工智能转化为你的专业数字专家。
通过本文,你将学习如何将通用的 Gemma 3 模型转化为专门化、领域特定的 LLM。
1、Gemma 3简介
谷歌发布了一款名为 Gemma 3 的全新模型,具有 270 亿个参数。Gemma 是一系列轻量级、最先进的开源模型,这些模型是基于与 Gemini 模型相同的研发和技术构建的。Gemma 3 专为开发人员构建可以在从手机到工作站的任何地方运行的 AI 应用程序而设计,支持超过 35 种语言,并能够处理文本、图像和短视频。
根据公司的博客文章,它是“世界上最好的单加速器模型”,在单 GPU 主机上超越了 Meta 的 Llama、DeepSeek 和 OpenAI 的 o1-preview 和 o3-mini-high。对于一个旨在保持精简的模型来说,这非常令人印象深刻。
与谷歌的专有 Gemini 模型不同,Gemmi 3 是开源的。 这意味着它是任何人都可以使用和访问的。 它有四种尺寸:10 亿、40 亿、120 亿和 270 亿个参数——适合各种需求!
通过微调模型,我们可以使其以更专业化和更领域特定的方式回答问题。凭借 Gemma 3 最佳的单加速器结果,它成为几乎所有涉及低可用计算或部署项目的优秀选择。
在这篇文章中,我们将深入探讨如何使用 Python 和 Unsloth 对 Gemma-3 模型进行微调。通过本文,你将学习如何使用任何数据集对模型进行微调,并将其合并并保存到 Hugging Face Hub。
尽管微调是一项计算密集的任务,但本文尝试通过利用通常可获得的资源(例如 Google 的 Colab 笔记本)使其尽可能易于访问。
2、前提条件和设置
在我们真正开始微调 LLM 之前,这里有一些关于技术前提或设置要求的简要说明。
用于微调 LLM 的 Python 库和框架包括:
unsloth
,该包使像 Llama-3、Mistral、Phi-4 和 Gemma 这样的大型语言模型的微调速度提高 2 倍,内存使用减少 70%,并且不会降低准确性!你可以在这里了解更多 https://docs.unsloth.ai/。torch
,这是深度学习的基础构建块,基于 PyTorch。它提供了一个类似于 NumPy 的强大张量库,但具有 GPU 加速的优势,这对于处理 LLM 来说至关重要。transformers
是一个功能强大且流行的自然语言处理 (NLP) 开源库。它提供了广泛的状态-of-the-art 预训练模型的易用接口。由于预训练模型是任何微调任务的基础,此包有助于轻松访问已训练的模型。- Python 中的
trl
包是专门为 强化学习 (RL) 设计的变压器模型专用库。它建立在 Hugging Face 的transformers
库之上,利用其优势,使使用变压器进行强化学习更加容易和高效。
3、计算要求
微调是一种技术,可以在不进行完全参数训练的情况下使 LLM 的响应更加结构化和领域特定。
然而,微调较大的 LLM 仍然对大多数普通计算机硬件来说不可行,因为所有可训练参数以及实际的 LLM 都存储在 GPU 的虚拟 RAM (vRAM) 中,而 LLM 的巨大规模构成了实现这一点的主要障碍。
因此,为了本文的目的,我们将微调一个小一点的 LLM,即 Gemma-3-it,它有 43 亿个参数。这个 LLM 至少需要 8–12 GB 的 vRAM,为了使它对所有人都可访问,我们将使用 Google Colab 的免费 T4 GPU,它有 15 GB 的 vRAM。
4、数据准备策略
为了微调 LLM,我们需要结构化的任务特定数据。有许多数据准备策略,无论是从社交媒体平台、网站、书籍还是研究论文中抓取数据。
对于这篇文章,我们将使用 Hugging Face 的 datasets 库来加载 Hugging Face Hub 中的数据。我们将使用 Hugging Face 的 mlabonne/FineTome-100k
数据集,你可以在这里探索该数据集。
5、Python 实现
5.1 安装包
要在 Google Colab 中安装包,你必须在内核中运行以下命令,——
# 在 Google Colab 笔记本中安装包
!pip install --no-deps bitsandbytes accelerate xformers==0.0.29.post3 peft trl triton cut_cross_entropy unsloth_zoo
!pip install sentencepiece protobuf datasets huggingface_hub hf_transfer
!pip install --no-deps unsloth
# 安装最新版本的 Hugging Face 用于 Gemma-3!
!pip install --no-deps git+https://github.com/huggingface/transformers@v4.49.0-Gemma-3
如果你有一台性能良好的 GPU,并且愿意在本地机器上执行微调任务,那么过程相当简单。只需在终端中运行以下命令即可安装包,——
pip install unsloth
# 安装最新版本的 Hugging Face 用于 Gemma-3!
pip install --no-deps git+https://github.com/huggingface/transformers@v4.49.0-Gemma-3
5.2 初始化模型和分词器
我们将使用 unsloth
包来加载预训练模型,因为它提供了有用的技术,可以加快 LLM 的下载和微调。
初始化模型和分词器的代码如下,——
from unsloth import FastModel
import torch
model, tokenizer = FastModel.from_pretrained(
model_name = "unsloth/gemma-3-4b-it",
max_seq_length = 2048,
load_in_4bit = True, # 使用 4 位量化以减少内存
load_in_8bit = False, # 更准确,但使用 2 倍内存
full_finetuning = False, # 执行全微调
# token = "<YOUR_HF_TOKEN>", # 如果使用受限制的模型
)
- 使用
unsloth
提供的FastModel.from_pretrained()
方法从 Hugging Face Hub 加载预训练的 Gemma3 模型。 - 第一个传递的参数是
model_name
,即unsloth/gemma-3–4b-it
,它是 指令训练的、40 亿参数 版本的 Gemma3 模型,非常适合我们的目的。 - 通过设置
max_seq_length
,我们可以处理模型的序列长度,允许模型处理长度为2048
个标记的输入序列。它也会影响模型的性能、内存使用和准确性。 load_in_4bit
参数用于……在 4 位精度 下量化模型,以减少内存使用,同时你可以将load_in_8bit
设置为True
(前提是你的 GPU 支持),因为它会提高准确性但会增加 两倍的内存成本。full_finetuning
标志设置为False
,这启用了 参数高效微调 (PEFT) 而不是更新所有模型参数。
5.3 添加 LoRA 适配器
我们将向预训练的 Gemma3 模型添加 LoRA 矩阵,这将有助于微调模型的响应。通过 unsloth
,整个过程只需几行代码即可完成。
以下是具体操作方法:
model = FastModel.get_peft_model(
model,
finetune_vision_layers = False, # 关闭以仅处理文本!
finetune_language_layers = True, # 应保持开启!
finetune_attention_modules = True, # 注意力模块对 GRPO 很有用
finetune_mlp_modules = True, # 应始终开启!
r = 16, # 较大值会提高准确性,但也可能过拟合
lora_alpha = 16,
lora_dropout = 0,
bias = "none",
random_state = 3407,
)
代码解释如下:
FastModel.get_peft_model()
方法通过unsloth
对传递的基模型应用了 参数高效微调 (PEFT),该模型是之前初始化的 Gemma3。- 使用
unsloth
,我们可以在加载 PEFT 模型时显式设置微调视觉层和语言层的参数,以提高效率。 - 我们禁用了视觉层的微调(
finetune_vision_layers=False
),并启用了语言层(finetune_language_layers=True
)、注意力模块(finetune_attention_modules=True
)和 MLP 模块(finetune_mlp_modules=True
),以实现更好的性能。 - 参数
r
(秩)控制了 LoRA 适应矩阵 的大小,较大的值可以提高准确性但可能导致过拟合。lora_alpha
是一个缩放因子,通常设置为或高于r
。 - 我们设置了
lora_dropout=0
,表示不应用丢弃,并且bias="none"
表示我们不微调偏置。 - 设置
random_state=3407
可确保在微调过程中获得一致且可重复的结果。
5.4 加载 Gemma3 的聊天模板
chat_template
表示多轮对话的骨架,用于确保模型能够正确区分系统、用户和助手的消息。
它有助于维护对话流程和上下文,这对基于聊天的微调和推理非常重要。通过使用聊天模板,可以增强对话型模型(如 Gemma3
)的响应质量。
Gemma3 的 chat_template
是这样的:
<bos><start_of_turn>user
Hello!<end_of_turn>
<start_of_turn>model
Hey there!<end_of_turn>
以下是使用 unsloth
加载 Gemma3 聊天模板的方法:
from unsloth.chat_templates import get_chat_template
tokenizer = get_chat_template(
tokenizer,
chat_template = "gemma-3",
)
- 这里我们指定了
chat_template
为gemma-3
,并传入了我们为预训练模型加载的分词器。对于其他聊天模板,您可以参考 这里。
5.5 数据准备
现在,我们在预训练的 Gemma3 模型上设置了 LoRA 适配器后,可以转向构建用于训练模型的数据结构。
我们将使用 mlabonne/FineTome-100k
数据集进行模型微调,并通过 Hugging Face 加载数据集。在这里,我们仅限于训练数据,而没有加载完整的 100k 行。
要加载数据集,请执行以下代码:
from datasets import load_dataset
dataset = load_dataset("mlabonne/FineTome-100k", split = "train")
现在,我们需要标准化数据结构以匹配基于聊天的微调所需的格式,例如处理“用户”和“助手”等角色。
要标准化数据集,请执行以下代码:
from unsloth.chat_templates import standardize_data_formats
dataset = standardize_data_formats(dataset)
标准化数据集后,我们需要在整个数据集上应用聊天模板,以便用于微调。
要将聊天模板应用于数据集,请执行以下代码:
def act(examples):
texts = tokenizer.apply_chat_template(examples["conversations"])
return { "text" : texts }
pass
dataset = dataset.map(act, batched = True)
在这里,我们创建了一个函数 act()
,它将使用 分词器 的 apply_chat_template()
方法,并将结果附加到数据集中的新列 text
中。通过使用 .map()
,我们对每一批数据应用 apply_chat_template()
函数,从而转换整个数据集。
5.6 训练模型
现在我们已经有了结构化的数据和带有 LoRA 适配器的模型,我们可以开始训练模型了。
为了训练模型,我们需要初始化一些超参数,这些参数将促进训练过程,并在一定程度上影响模型的准确性。
我们将使用 SFTTrainer
和超参数来初始化一个 trainer
。
from trl import SFTTrainer, SFTConfig
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
eval_dataset = None,
args = SFTConfig(
dataset_text_field = "text", # 数据集中用于训练的结构化字段
per_device_train_batch_size = 2, # 每个设备每批处理的样本数
gradient_accumulation_steps = 4, # 在反向传播之前累积梯度的步数
warmup_steps = 5, # 训练开始时逐步增加学习率的步数
# num_train_epochs = 1, # 设置为完整训练一次
max_steps = 30, # 总共要执行的训练步数
learning_rate = 2e-4, # 训练期间更新权重的学习率
logging_steps = 1, # 日志记录训练指标的频率(以步为单位)
optim = "adamw_8bit", # 优化器
weight_decay = 0.01, # 防止过拟合的正则化技术
lr_scheduler_type = "linear", # 控制学习率衰减
seed = 3407,
report_to = "none", # 日志记录平台,也可以是 'wandb'
),
)
代码解释如下:
trl
库中的SFTTrainer
用于在自定义数据集上微调大型语言模型。它支持诸如梯度累积、混合精度优化等技术,非常适合指令微调、对话生成和领域特定的 LLM 适应任务。- 在 SFTTrainer 中,我们传递了迄今为止准备好的模型、分词器和训练数据集,并将评估数据集设置为 None,以满足我们的用例需求。
当我们实例化了 trainer 并声明了其超参数后,我们可以使用一种优化技术来改进模型的输出质量,同时避免过度拟合用户提示或不必要的上下文。
通过 unsloth
,这个过程变得非常简单直观:
from unsloth.chat_templates import train_on_responses_only
trainer = train_on_responses_only(
trainer,
instruction_part = "<start_of_turn>user\n",
response_part = "<start_of_turn>model\n",
)
- 这里我们使用了
unsloth
的train_on_responses_only
方法,只训练助手的输出,忽略用户输入的损失。这有助于提高微调的准确性! - 参数
instruction_part
("<start_of_turn>user\n"
) 标识用户的输入或提示。 - 参数
response_part
("<start_of_turn>model\n"
) 标记模型的响应,允许训练器专注于微调这部分内容。
现在,我们完成了所有设置,模型已准备好进行训练,启动训练的代码如下:
trainer_stats = trainer.train()
这将在每个步骤中在内核中打印训练损失,如下所示:
5.7 推理微调后的模型
现在,我们已经完成了模型的训练,接下来只需推断微调后的模型以评估其响应。
推断模型的代码如下:
from unsloth.chat_templates import get_chat_template
# 初始化带有 chat_template 的分词器
tokenizer = get_chat_template(
tokenizer,
chat_template = "gemma-3",
)
# 定义用户的提示
messages = [{
"role": "user",
"content": [{
"type" : "text",
"text" : "继续这个序列:1, 1, 2, 3, 5, 8,",
}]
}]
# 将聊天模板应用于用户的提示
text = tokenizer.apply_chat_template(
messages,
add_generation_prompt = True, # 必须添加以生成
)
# 从模型生成提示的输出
outputs = model.generate(
**tokenizer([text], return_tensors = "pt").to("cuda"),
max_new_tokens = 64, # 增加以生成更长的输出!
# 推荐的 Gemma-3 设置!
temperature = 1.0, top_p = 0.95, top_k = 64,
)
# 解码生成的输出为文本
tokenizer.batch_decode(outputs)
- 在这里,为了推断模型,我们初始化了分词器以处理 gemma3 聊天格式的对话。
messages
是一个列表,其中提到的角色为"user"
,"text"
包含用户的提示。
5.8 保存微调后的模型
这个步骤完成了整个微调模型的过程,现在我们可以将微调后的模型保存下来以供推理或未来使用。
我们还需要与模型一起保存分词器。以下是将完整的微调模型保存到本地系统的方法。
model.save_pretrained_merged("gemma-3-4b-Maxime-Labonne-FineTuned", tokenizer)
- 在这里,我们将微调模型的名称指定为
gemma-3–4b-Maxime-Labonne-FineTuned
,但您可以选择自己的名称。
要将模型推送到 Hugging Face Hub,可以使用以下命令:
model.push_to_hub("<Your_HF_Account>/<Model_Name>", token = "YOUR_HF_TOKEN")
tokenizer.push_to_hub("<Your_HF_Account>/<Model_Name>", token = "YOUR_HF_TOKEN")
- 使用此方法,最终的微调模型将以 LoRA 适配器的形式保存在 Hugging Face Hub 上。
6、结束语
本文讨论的主要要点如下:
- 大型语言模型(LLM)在最朴素的术语中只是深度学习架构(如 Transformer)的美丽实现,它被训练了大量语言文本数据。
- Gemma 3 是为开发人员构建可以在从手机到工作站运行的 AI 应用程序而设计的,支持超过 35 种语言,并能够处理文本、图像和短视频。
- 微调一个 LLM 是通过向模型提供一些任务特定的数据来定制其响应以适应特定用途的过程,从而提高其准确性并使其响应更加专注和领域特定。
chat_template
表示用于对多轮对话进行分词的骨架,以确保模型正确区分系统、用户和助手消息。- 我们使用的主 Python 库和框架是
unsloth
、torch
、transformers
和trl
。此外,我们还讨论了微调 LLM 的计算需求。 - 我们构建了数据集以有效微调模型,然后使用 SFTTrainer 对其进行了训练。
- 我们还将 LoRA 适配器或矩阵与预训练模型合并,以便将其推送到 Hugging Face Hub。
原文链接:Google’s Gemma-3 Fine-Tuning Made Simple: Create Custom AI Models with Python and Unsloth
汇智网翻译整理,转载请标明出处