LLM 微调实战:打造地面交通专业大模型

从数据构建到微调部署,手把手教你用 LoRA/QLoRA 微调开源 LLM 构建交通领域专家模型

引言

地面交通系统涉及信号控制、路径规划、交通仿真、事故预测等多个环节,传统基于规则或浅层学习的方法在泛化能力和上下文理解上存在明显瓶颈。将大语言模型(LLM)微调为交通领域专家,能够实现:

本文以开源 LLaMA/Qwen 系列为基座模型,介绍从零构建交通数据集到 LoRA 微调部署的完整流程。

一、数据构建:交通领域数据集

1.1 数据来源

数据类型来源说明
交通新闻/报告高德/百度交通 API、各地交警公开数据标注难度低,量大
交通事故描述事故报告、122报警记录脱敏数据需要专业标注
信号配时方案交警部门或仿真平台数据需结构化提取
交通仿真场景描述SUMO/Paramics 等仿真软件导出高价值,专业性强
交通学术论文(摘要)交通领域会议期刊(TRR、IEEE ITS)可做持续预训练

1.2 数据清洗与标注

# 示例:使用 LLM 做初步数据清洗与标注
import json

def clean_and_label_traffic_data(raw_text: str, label_model):
    """利用 LLM 对原始交通文本进行实体和意图标注"""
    prompt = f"""你是一位交通工程专家。请对以下文本进行标注,返回 JSON 格式:
    {{
        "entities": ["地点", "事件类型", "拥堵程度"...],
        "intent": "查询/控制/分析/报告",
        "summary": "一句话概括",
        "traffic_terms": ["信号灯", "交叉口", "拥堵"... ]
    }}

    文本:{raw_text}
    """
    response = label_model.chat(prompt)
    return json.loads(response)

1.3 Instruction-Tuning 数据格式

推荐使用 alpaca 格式或 sharegpt 格式:

{
  "instruction": "北京晚高峰东三环严重拥堵,有什么疏导建议?",
  "input": "当前路况:东三环双向车速 < 15km/h,持续时间 > 40min",
  "output": "根据当前态势,建议以下疏导方案:1) 将国贸桥至长虹桥段信号配时调整为..." 
}

1.4 数据配比

一个有效的交通领域微调数据集通常包含:

二、微调方法选择

2.1 全参数微调 vs 参数高效微调

方法参数量显存需求效果适用场景
全参数微调 (Full FT)100%A100 80G × 多卡最佳有充足算力
LoRA0.1%~1%单卡 24G 可行接近全参主流选择
QLoRA0.1%~1% (4-bit)单卡 16G 可行略低于 LoRA资源受限
Adapter-tuning1%~5%单卡 24G中等任务切换多

推荐:优先使用 QLoRA,在 16G 显存下即可完成 7B 模型的微调。

2.2 LoRA 核心原理

LoRA 在注意力层的 Q/K/V/O 矩阵旁添加低秩适配器:

# LoRA 核心公式
# W_orig: 原始预训练权重 (d × d)
# W_new = W_orig + ΔW = W_orig + BA
# B ∈ R^(d×r), A ∈ R^(r×d), r << d (低秩)
# 训练时只更新 B 和 A,冻结 W_orig

import torch
import torch.nn as nn

class LoRALinear(nn.Module):
    def __init__(self, original_layer: nn.Linear, rank: int = 4, alpha: float = 1.0):
        super().__init__()
        d_out, d_in = original_layer.weight.shape
        self.original = original_layer
        self.lora_A = nn.Parameter(torch.randn(rank, d_in) * 0.01)
        self.lora_B = nn.Parameter(torch.zeros(d_out, rank))
        self.scaling = alpha / rank
        
    def forward(self, x):
        return self.original(x) + (x @ self.lora_A.T @ self.lora_B.T) * self.scaling

2.3 交通领域适配器设计

针对交通场景,可以重点对以下层加 LoRA:

decoder_block.attn.q_proj      ← 语义理解(query 理解交通场景描述)
decoder_block.attn.k_proj      ← 关键实体(key 关联交通要素)
decoder_block.attn.v_proj      ← 知识记忆(value 存储交通规则)
decoder_block.mlp.gate_proj    ← 领域知识凝练

三、微调实战代码

3.1 环境准备

pip install transformers peft accelerate bitsandbytes trl
# 或使用 AxT >= 0.1 的统一命令:
pip install autotorch

3.2 QLoRA 微调脚本

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import torch

# 4-bit 量化配置
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

# 加载基座模型
model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen2-7B-Instruct",  # 或 LLaMA-3-8B
    quantization_config=bnb_config,
    device_map="auto",
    torch_dtype=torch.bfloat16,
)
model = prepare_model_for_kbit_training(model)

# LoRA 配置 — 针对交通领域重点调参
lora_config = LoraConfig(
    r=16,                      # 秩,越大效果越好但显存更高
    lora_alpha=32,             # 缩放因子
    target_modules=[            # 重点微调的模块
        "q_proj", "k_proj", "v_proj", "o_proj",
        "gate_proj", "up_proj", "down_proj"
    ],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 可训练参数: ~0.41% (仅 8.9M 参数)

# 训练配置
from transformers import TrainingArguments
training_args = TrainingArguments(
    output_dir="./checkpoints/traffic-llm",
    num_train_epochs=3,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,    # 有效 batch = 4×4=16
    optim="paged_adamw_32bit",
    learning_rate=2e-4,
    weight_decay=0.01,
    fp16=False,
    bf16=True,
    logging_steps=10,
    save_strategy="epoch",
    warmup_ratio=0.03,
    lr_scheduler_type="cosine",
)

3.3 交通领域特殊词表扩展

如果交通领域有大量专业术语(如 “交织区”、“信号相位”、“绿波带”),建议先扩展词表再微调:

from transformers import Tokenizer
from sentencepiece import sentencepiece_model_pb2

# 1. 收集交通术语
traffic_terms = [
    "信号相位", "绿波带", "交织区", "排队长度",
    "饱和流率", "延误时间", "路口渠化", "可变车道",
    "感应控制", "自适应配时", "区域协调控制"
]

# 2. 使用 sentencepiece 增量训练扩展词表
# 3. 用扩展词表重新 tokenize 数据集并微调

四、训练技巧与坑

4.1 灾难性遗忘防护

全参数微调时容易发生灾难性遗忘(模型遗忘通用能力),解决方案:

  1. 混入通用数据(20%):始终保留部分通用 QA 数据
  2. 使用 gamma 调度:参考 SwissArmyKnife 的渐进式解冻
  3. 设置较小的学习率:通常为预训练的 1/10 ~ 1/100

4.2 交通领域幻觉问题

交通领域对事实性要求高,LLM 容易一本正经地胡说八道。应对方法:

# RAG 增强:结合交通知识库检索
def traffic_rag_query(query: str, knowledge_base, llm):
    docs = knowledge_base.similarity_search(query, k=3)
    context = "\n".join([d.content for d in docs])
    
    prompt = f"""基于以下交通知识回答问题。如果信息不足,据实说明不知道。
    
    知识:{context}
    问题:{query}"""
    return llm.chat(prompt)

4.3 多模态扩展

如需处理交通图片(路况照片、仿真截图),可接入 LLaVAQwen-VL 系列做多模态微调:

# 以 LLaVA 为例:图像 + 交通文本联合微调
from llava.model.builder import load_pretrained_model
model, tokenizer, image_processor = load_pretrained_model("liuhaotian/llava-v1.6-7b")

五、评估与部署

5.1 评估指标

任务评估指标说明
交通问答BLEU-4 / ROUGE-L与专家答案对比
信号配时推荐自定义评分函数(延误降低率)需仿真环境验证
事故报告摘要BERTScore / G-Eval语义层面评估
领域知识测试交通领域 benchmark(自建)选择题/判断题

5.2 典型评估问题示例

{
  "question": "在某交叉口,晚高峰期间左转流量很大(280 pcu/h),对向直行流量为 600 pcu/h,
              该交叉口采用两相位控制,配时为 G40-Y3-R37。建议如何优化?",
  "expected": "建议增加左转专用相位或将配时调整为 G55-Y3-R32,以提高左转通行能力..."
}

5.3 部署

# 使用 vLLM 部署推理服务
from vllm import LLM, SamplingParams

llm = LLM(
    model="./checkpoints/traffic-llm/checkpoint-300",
    tensor_parallel_size=1,        # 单卡部署
    gpu_memory_utilization=0.90,
)
params = SamplingParams(temperature=0.3, max_tokens=512)

output = llm.generate(
    "晚高峰北京西直门桥拥堵,分析原因并给出疏导建议",
    params
)
print(output[0].outputs[0].text)

六、进阶方向


有任何问题或建议,欢迎通过博客留言交流!