大模型微调入门(Transformers + Pytorch)

目标

输入:你是谁?

输出:我们预训练的名字。

训练

为了性能好下载小参数模型,普通机器都能运行。

下载模型

python 复制代码
# 方式1:使用魔搭社区SDK 下载
# down_deepseek.py
from modelscope import snapshot_download
model_dir = snapshot_download('deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B')

# 方式2:git lfs 
# 需要提前安装git大文件存储 git-lfs
# 在线查看 https://www.modelscope.cn/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
git lfs install
git clone https://www.modelscope.cn/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B.git

训练模型

python 复制代码
# finetune_deepseek.py
from datasets import Dataset
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
    Trainer,
    DataCollatorForLanguageModeling
)

# 加载模型和分词器
model_name = "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True)

# 准备训练数据
train_data = [
    {
        "question": "你是谁?",
        "answer": "我是黄登峰。"
    },
    {
        "question": "你的名字是什么?",
        "answer": "黄登峰"
    },
    {
        "question": "你是做什么的?",
        "answer": "我是深圳一家公司打工的牛马程序员。"
    },
    # 在这里添加更多的问答对
]

test_data = [
    {
        "question": "你的名字是什么?",
        "answer": "我的名字是黄登峰。"
    }
]
def format_instruction(example):
    """格式化输入输出对"""
    return f"Human: {example['question']}\n\nAssistant: {example['answer']}"

# 转换数据格式
train_formatted_data = [{"text": format_instruction(item)} for item in train_data]
test_formatted_data = [{"text": format_instruction(item)} for item in test_data]
train_dataset = Dataset.from_list(train_formatted_data)
test_dataset = Dataset.from_list(test_formatted_data)

# 数据预处理函数
def preprocess_function(examples):
    return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=512)

# 对数据集进行预处理
train_tokenized_dataset = train_dataset.map(
    preprocess_function,
    batched=True,
    remove_columns=train_dataset.column_names
)

test_tokenized_dataset = test_dataset.map(
    preprocess_function,
    batched=True,
    remove_columns=test_dataset.column_names
)
output_dir = "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B_CUSTOM"

# 训练参数设置
training_args = TrainingArguments(
    output_dir=output_dir,
    num_train_epochs=3,
    per_device_train_batch_size=4,
    save_steps=100,
    save_total_limit=2,
    learning_rate=2e-5,
    weight_decay=0.01,
    logging_dir="./logs",
    logging_steps=10,
)

# 创建训练器
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_tokenized_dataset,
    eval_dataset=test_tokenized_dataset,
    data_collator=DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False),
)

# 开始训练
trainer.train()

# 保存模型
trainer.save_model()
# 保存tokenizer
tokenizer.save_pretrained(output_dir)

模型格式

训练后的模型输出格式是Hugging Face格式,vllm 可以直接使用,ollama,llama.cpp默认是GGUF格式。

bash 复制代码
# 需要用llama.cpp仓库的convert_hf_to_gguf.py脚本来转换
git clone https://github.com/ggerganov/llama.cpp.git
pip install -r llama.cpp/requirements.txt
# 如果不量化,保留模型的效果
python llama.cpp/convert_hf_to_gguf.py ./DeepSeek-R1-Distill-Qwen-1.5B  --outtype f16 --verbose --outfile DeepSeek-R1-Distill-Qwen-1.5B.gguf
# 如果需要量化(加速并有损效果),直接执行下面脚本就可以
python llama.cpp/convert_hf_to_gguf.py ./DeepSeek-R1-Distill-Qwen-1.5B  --outtype q8_0 --verbose --outfile DeepSeek-R1-Distill-Qwen-1.5B.gguf

验证

python 复制代码
# test_model.py
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

def generate_response(prompt, model, tokenizer, max_length=512):
    # 将输入格式化为训练时的格式
    formatted_prompt = f"Human: {prompt}\n\nAssistant:"
    
    # 对输入进行编码
    inputs = tokenizer(formatted_prompt, return_tensors="pt", padding=True, truncation=True)
    
    # 生成回答
    with torch.no_grad():
        outputs = model.generate(
            inputs.input_ids,
            max_length=max_length,
            num_return_sequences=1,
            temperature=0.7,
            do_sample=True,
            pad_token_id=tokenizer.pad_token_id,
            eos_token_id=tokenizer.eos_token_id,
        )
    
    # 解码输出
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
    
    # 提取Assistant的回答部分
    response = response.split("Assistant:")[-1].strip()
    return response

def main():
    # 加载微调后的模型和分词器
    model_path = "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B_CUSTOM"
    tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
    model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True)
    
    # 准备测试问题
    test_questions = [
        "你是谁?",
        "你的名字是什么?",
        "你是做什么的?",
    ]
    
    # 测试模型回答
    print("开始测试模型回答:")
    print("-" * 50)
    for question in test_questions:
        print(f"问题: {question}")
        response = generate_response(question, model, tokenizer)
        print(f"回答: {response}")
        print("-" * 50)

if __name__ == "__main__":
    main()
相关推荐
传说故事18 分钟前
【论文阅读】MotuBrain: An Advanced World Action Model for Robot Control
论文阅读·人工智能·具身智能·wam
北京耐用通信42 分钟前
全域适配工业场景耐达讯自动化Modbus TCP 转 PROFIBUS 网关轻松实现以太网与现场总线互通
网络·人工智能·网络协议·自动化·信息与通信
火山引擎开发者社区1 小时前
TRAE × 火山引擎 Supabase:为你的 AI 应用装上“数据引擎”
人工智能
小a彤1 小时前
GE 在 CANN 五层架构中的位置
人工智能·深度学习·transformer
前端若水1 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
Upsy-Daisy1 小时前
AI Agent 项目学习笔记(八):Tool Calling 工具调用机制总览
人工智能·笔记·学习
企学宝2 小时前
企学宝5月专题课程丨《OpenClaw AI 智能体实战营:从零基础部署到全场景自动化落地》
人工智能·ai·企业培训
冬奇Lab2 小时前
让 AI Agent 更可靠:Harness Engineering 与多 Agent 系统工程实践
人工智能·llm·agent
放下华子我只抽RuiKe52 小时前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架
想你依然心痛2 小时前
HarmonyOS 6(API 23)实战:基于悬浮导航、沉浸光感与HMAF的“文思智脑“——PC端AI智能体沉浸式智能写作工作台
人工智能·ar·harmonyos·ai写作