Unsloth 微调 构建自己的大模型 没有GPU也能微调

这次我们使用unsloth框架来微调模型,将模型微调成一个垂直领域的模型

先说问题

复制代码
This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

从 Python 3.11 开始,一些 Debian/Ubuntu 系统默认启用保护机制------目的是保护系统级的 Python 环境

这个问题主要是 系统不再允许使用 pip 直接安装全局包

我们需要用虚拟环境安装

复制代码
sudo apt update
sudo apt install python3-venv

根目录执行
python3 -m venv .venv

然后再根目录会生成一个.venv/ 的文件夹

安装时指定环境目录

复制代码
.venv/bin/pip3 install 包名  
.venv/bin/python3 脚本.py
于是安装就变成了
.venv/bin/pip3 install unsloth

也可以使用激活python环境来安装,这样就不用指定目录,但是记得安装完要关闭环境

复制代码
source .venv/bin/activate
pip3 install 包名

python3 脚本.py
deactivate
安装CPU版PyTorch
复制代码
官方安装 一般比较慢
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
国内镜像安装
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu -i https://pypi.tuna.tsinghua.edu.cn/simple
如果需要指定特殊版本
pip3 install torch==2.4.0+cpu torchvision==0.19.0+cpu torchaudio==2.4.0 --index-url https://download.pytorch.org/whl/cpu

验证CPU安装成功

bash 复制代码
python3 -c "import torch; print(f'Version: {torch.__version__}'); print(f'CUDA Available: {torch.cuda.is_available()}'); print(f'CUDA Build: {torch.version.cuda}'); x = torch.rand(2,2); print(f'Device: {x.device}')"
大概输出
Version: 2.4.0+cpu
CUDA Available: False
CUDA Build: None
Device: cpu
如果出现的是
PyTorch Version: 2.14.1+cu130   这个cu130意思是CUDA 13.0 的 GPU 加速版本
需要重新安装CPU版本的PyTorch

安装unsloth

复制代码
pip3 install --upgrade pip
pip3 install unsloth unsloth_zoo

如果设备没有GPU,使用CPU进行微调,则会出现以下问题

复制代码
    raise NotImplementedError("Unsloth cannot find any torch accelerator? You need a GPU.")
NotImplementedError: Unsloth cannot find any torch accelerator? You need a GPU.

只使用CPU进行微调,需要这样安装unsloth

bash 复制代码
pip3 install --upgrade pip
apt-get update && apt-get install -y git
pip3 install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git" -U
pip3 install bitsandbytes==0.44.0 --force-reinstall
如果安装不成功,使用以下方法
pip3 install --upgrade pip
git clone https://github.com/unslothai/unsloth.git
cd unsloth
pip3 install ".[colab-new]" --no-deps
pip3 install ".[cpu]"
pip3 install trl==0.12.2 peft==0.13.2 accelerate==1.2.1 bitsandbytes==0.44.0

bitsandbytes 在CPU模式下必须使用0.44.2或更低版本

高版本(如0.45+)移除了CPU支持,会导致 ImportError: cannot import name 'MatmulLtState' 如遇此错,请降级

复制代码
强制重装
pip3 install bitsandbytes==0.44.0 --force-reinstall

如果依然出现这个错误,需要重装CPU版本的PyTorch,说明安装时候是GPU版本

bash 复制代码
    raise NotImplementedError("Unsloth cannot find any torch accelerator? You need a GPU.")
NotImplementedError: Unsloth cannot find any torch accelerator? You need a GPU.

验证安装成功

python 复制代码
python3 -m unsloth

能看到版本和欢迎信息就说明核心部分已经就绪

微调

python 复制代码
#引入依赖
from unsloth import FastLanguageModel, is_bfloat16_supported
from transformers import TrainingArguments
from trl import SFTTrainer
from datasets import load_dataset
#加载模型
max_seq_length = 8192 # 模型处理文本的最大长度
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "ckpts/qwen-1.5b",
max_seq_length = max_seq_length,
dtype=None, # 自动检测合适的类型
load_in_4bit = True,
# device_map="balanced" # 多卡训练时均衡分布模型权重,默认为sequential
)

垂直领域举例

娱乐运势模型

python 复制代码
# 定义训练数据格式化字符串模板
train_prompt_style="""请遵循指令回答用户问题。
在回答之前,请仔细思考问题,并创建一个逻辑连贯的思考过程,以确保回答准确无误。
### 指令:
你是一位精通八字算命、紫微斗数、风水、易经卦象、塔罗牌占卜、星象、面相手相和运势预测等方面的算命大师。
请回答以下算命问题。
### 问题:
{}
### 回答:
<think>{}</think>
{}
"""
# 加载数据集
dataset = load_dataset("data/fortune-telling", split="train")
def formatting_data(examples):
    questions = examples["Question"]
    cots = examples["Complex_CoT"]
    responses = examples["Response"]
    texts = []
    for q, c, r in zip(questions, cots, responses):
        text = train_prompt_style.format(q, c, r) + tokenizer.eos_token
        texts.append(text)
    return {"text": texts}
dataset = dataset.map(formatting_data, batched=True)
添加 LoRA 权重
model = FastLanguageModel.get_peft_model(
model,
r = 16, # Rank of the LoRA matrix
target_modules = ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj",], # Layers to apply LoRA to
lora_alpha = 16, # LoRA alpha value
lora_dropout = 0, # Supports any, but = 0 is optimized,防止过拟合,0 表示不drop任何参数
bias = "none",    # Supports any, but = "none" is optimized
use_gradient_checkpointing = "unsloth", # True or "unsloth" for very long context
random_state = 3407,
use_rslora = False,  # We support rank stabilized LoRA
loftq_config = None, # And LoftQ
)
#定义 trainer
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, # Can make training 5x faster for short sequences.
args = TrainingArguments(
per_device_train_batch_size = 2, # 每个GPU上的batch size
gradient_accumulation_steps = 4, # 梯度累积步数
warmup_steps = 10,
# max_steps = 200, # 最大训练步数
num_train_epochs=3, # 训练轮数 和 max_steps 二选一
learning_rate = 2e-4, # 学习率,默认值是 2.0e-5
fp16 = not is_bfloat16_supported(),
bf16 = is_bfloat16_supported(),
logging_steps = 2,
output_dir = "outputs",
optim = "adamw_8bit",
seed = 3407,
),
)
#开始训练
train_stats = trainer.train()
#模型保存
model.save_pretrained("ckpts/lora_model")
tokenizer.save_pretrained("ckpts/lora_model")
#注:这里只会保存 LoRA 权重,在adapter_config.json会指定原始模型位置

Unsloth 会根据加载的模型和设备情况自动选择 GPU 数量。

默认 device_map="sequential",只有当单卡显存不够时,才占用其他卡

如果 device_map="balanced",会占用所有卡,并均衡分布模型权重

python 复制代码
# 模型测试
# 加载模型
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "ckpts/lora_model",
    max_seq_length = max_seq_length,
    load_in_4bit = True,
)
FastLanguageModel.for_inference(model)
question = '1995年七月初十生,今年是2025年,了解未来五年的运势'
inputs = tokenizer([prompt_style.format(question)], return_tensors='pt', max_length=max_seq_length).to("cuda")
outputs = model.generate(inputs['input_ids'], attention_mask=inputs['attention_mask'], max_length=max_seq_length, use_cache=True)
answer = tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
print(answer)

如果单卡放不下模型权重,会报错,因为模型权重切分了,但 inputs 并没有切分

这篇文章写的有点复杂,而且由于只是用CPU进行微调,所以在匹配上会出现各种各样的问题

如果大家有任何问题,欢迎留言讨论

相关推荐
高山有多高1 小时前
【Linux笔记】IO模型
linux
不会就选b2 小时前
Linux之TCP理论<1>
linux·运维·服务器
冬奇Lab2 小时前
LLM 驱动的自动化测试系列(06):移动端自动化(二)——DroidRun/Mobilerun 的角色级模型拆分
人工智能·测试
冬奇Lab2 小时前
一天一个开源项目(第230篇):HandRaw-Style —— 把 327 种手绘风格、165 种排版、36 种配色编号化,让 AI 画图不再每次都飘
人工智能·开源·资讯
罗西的思考2 小时前
从陶哲轩的访谈看:AI 数学研究方法论 & 给其它行业的启示
人工智能
学...2 小时前
软件学报 2023 论文《面向复杂约束优化问题的进化算法综述》阅读笔记
人工智能·ga·cmop
小π军2 小时前
操作系统面试题
java·linux·服务器
倔强的石头1063 小时前
应用账号最小权限实践:读写账号、报表账号、运维账号分层
java·运维·开发语言
传人once3 小时前
页面中心圆圈放大效果如何写
开发语言·javascript·ecmascript