Gemma2–2B 在 Colab 上的微调完整指南
简介
直到去年,开源大型语言模型的能力和效果主要都逊于其闭源的同类模型。目前,开源正在推动向一个新时代的转型。
谷歌于2024年6月发布了最新的顶级开源模型Gemma 2。这些模型提供270亿(27B)和90亿(9B)参数两种版本。自发布以来,27B版本迅速成为LMSYS Chatbot Arena排行榜上最突出的开源模型之一。事实上,它在实际对话中已经超过了参数量是其两倍多的流行模型。
Gemma 2 2B 是 Gemma 家族中一种新的 20 亿参数模型变体。它兼具强大的性能和效率,并且内置了安全改进。
在本文中,我们将使用 unsloth 并进行微调以提取合并收购信息。我们已经使用类似的方法与 Llama 3 进行了尝试。
未进行微调的结果
### 安装 Unsloth、Xformers(Flash Attention)和其他所有包!
!pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
!pip install --no-deps "xformers<0.0.27" "trl<0.9.0" peft accelerate bitsandbytes
### 安装 Flash Attention 2 以支持软上限
import torch
if torch.cuda.get_device_capability()[0] >= 8:
!pip install --no-deps packaging ninja einops "flash-attn>=2.6.3"
### 加载模型和分词器
from unsloth import FastLanguageModel
import torch
max_seq_length = 2048 # 选择任何值!我们内部自动支持 RoPE Scaling!
dtype = None # None 用于自动检测。Float16 用于 Tesla T4,V100,Bfloat16 用于 Ampere+
load_in_4bit = True # 使用 4bit 量化以减少内存使用。可以设为 False。
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/gemma-2-2b-bnb-4bit",
max_seq_length = max_seq_length,
dtype = dtype,
load_in_4bit = load_in_4bit,
)
### 指令格式
alpaca_prompt = """下面是一个描述任务的指令,附带一个提供更多上下文的输入。编写一个适当完成请求的响应。
### 指令:
{}
### 输入:
{}
### 响应:
{}"""
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
### mna 新闻和指令
mna_news_input = """HCL Technologies 已完成对德国 IT 咨询公司 Gesellschaft für Banksysteme GmbH(“GBS”)51% 股权的收购。收购于 2022 年 1 月 5 日完成。"""
mna_news_instruction1 = """收购日期是什么。请精确回答"""
mna_news_instruction2 = """哪个公司是收购方。请精确回答"""
FastLanguageModel.for_inference(model) # 启用原生 2 倍更快的推理
inputs = tokenizer(
[
alpaca_prompt.format(
mna_news_instruction1,
mna_news_input,
"", # 输出 - 生成时留空!
)
], return_tensors = "pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]
### 输出:收购日期是 2022 年 1 月 5 日。<eos>
inputs = tokenizer(
[
alpaca_prompt.format(
mna_news_instruction2,
mna_news_input,
"", # 输出 - 生成时留空!
)
], return_tensors = "pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]
### 输出:HCL Technologies<eos>
结果非常令人印象深刻,但正如我们在第一次输出中看到的,“收购日期是2022年01月05日。”,我们只想提取日期。有多种方法可以做到这一点,但我们将借助微调来完成。
微调后的结果
### 数据集替换为自己的数据集
import pandas as pd
from pprint import pprint
list_ds =[
{"instruction":"获取收购日期", "input":"Peak Performance Corporation 收购 Power Forward Corporation 的日期为 28/Jul/2022", "output":"28/Jul/2022"},
{"instruction":"获取收购日期", "input":"纽约 - Empire Innovations Inc,一家领先的科技集团,宣布计划于 01MARCH2025 收购 Unique Ventures LLC,一家专注于颠覆性创业公司的知名风险投资公司", "output":"01MARCH2025"},
{"instruction":"哪一家公司是收购方", "input":"Peak Performance Corporation 收购 Power Forward Corporation 的日期为 28/Jul/2022", "output":"Peak Performance Corporation"},
{"instruction":"哪一家公司是收购方", "input":"Prime Solutions Group 通过战略合并收购 Dynamic Solutions Inc", "output":"Prime Solutions Group"},
]
pprint(list_ds)
# 安装 Unsloth、Xformers(Flash Attention)和其他所有包
!pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
!pip install --no-deps "xformers<0.0.27" "trl<0.9.0" peft accelerate bitsandbytes
# 安装 Flash Attention 2 以支持软上限
import torch
if torch.cuda.get_device_capability()[0] >= 8:
!pip install --no-deps packaging ninja einops "flash-attn>=2.6.3"
### 微调
from unsloth import FastLanguageModel
import torch
max_seq_length = 1024 # 选择任何值!我们内部自动支持 RoPE Scaling
dtype = None # None 表示自动检测。Float16 适用于 Tesla T4,V100,Bfloat16 适用于 Ampere+
load_in_4bit = True # 使用 4bit 量化以减少内存使用。可以设置为 False
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/gemma-2-2b-bnb-4bit",
max_seq_length = max_seq_length,
dtype = dtype,
load_in_4bit = load_in_4bit,
# token = "hf_...", # 如果使用受保护的模型如 meta-llama/Llama-2-7b-hf,请使用 token
)
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" 使用 30% 更少的 VRAM,适合 2 倍更大的批处理大小!
use_gradient_checkpointing = "unsloth", # True 或 "unsloth" 用于非常长的上下文
random_state = 3407,
use_rslora = False, # 我们支持秩稳定的 LoRA
loftq_config = None, # 以及 LoftQ
)
alpaca_prompt = """下面是一个描述任务的指令,以及提供进一步上下文的输入。请编写一个适当完成请求的响应。
### 指令:
{}
### 输入:
{}
### 响应:
{}"""
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
import datasets
import pandas as pd
# 从字典数组创建数据集
df = pd.DataFrame(list_ds)
dataset = datasets.Dataset.from_pandas(df)
# 打印数据集
print(dataset)
dataset = dataset.map(formatting_prompts_func, batched = True,)
print(dataset)
from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported
trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
dataset_text_field = "text",
max_seq_length = max_seq_length,
dataset_num_proc = 2,
packing = False, # 可以使短序列的训练速度提高 5 倍
args = TrainingArguments(
per_device_train_batch_size = 2,
gradient_accumulation_steps = 4,
warmup_steps = 5,
# num_train_epochs = 1, # 设置此值以进行一次完整的训练
max_steps = 60,
learning_rate = 2e-4,
fp16 = not is_bfloat16_supported(),
bf16 = is_bfloat16_supported(),
logging_steps = 1,
optim = "adamw_8bit",
weight_decay = 0.01,
lr_scheduler_type = "linear",
seed = 3407,
output_dir = "outputs",
),
)
#### 实际训练
trainer_stats = trainer.train()
##### 结果
FastLanguageModel.for_inference(model)
mna_news_input = """HCL Technologies 已完成对德国 IT 咨询公司 Gesellschaft für Banksysteme GmbH (“GBS”) 51% 股权的收购。收购日期为 2022 年 1 月 5 日。"""
mna_news_instruction1 = """获取收购日期。请精确回答"""
mna_news_instruction2 = """哪一家公司是收购方。请精确回答"""
inputs = tokenizer(
[
alpaca_prompt.format(
mna_news_instruction1,
mna_news_input,
"", # 输出 - 生成时留空!
)
], return_tensors = "pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]
### 输出 : January 05, 2022<eos>
### 上面的结果非常好,正是我们想要的
inputs = tokenizer(
[
alpaca_prompt.format(
mna_news_instruction2,
mna_news_input,
"", # 输出 - 生成时留空!
)
], return_tensors = "pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
tokenizer.batch_decode(outputs)[0].split("\n\n### 响应:\n")[1].split("\n\n### 解释:\n")[0]
### 输出 : HCL Technologies<eos>
结论
我们通过微调得到了精确的结果。太棒了。使用T4和仅20亿参数的模型,效果更令人惊叹。
Colab ::COLAB:: 翻译为
COLAB::
这里保持了原始的双冒号格式,但由于直接翻译会有些不自然,建议直接保留原始格式或根据具体使用场景调整。如果必须翻译,可以理解为“谷歌协同”或“谷歌协作”,但根据上下文,这里可能更适合保留原始格式。
Google ColabEdit 描述colab.research.google.com Google ColabEdit 描述colab.research.google.com點擊查看更多內容
為 TA 點贊
評論
評論
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
正在加載中
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦