LlamaFactory超参数体系深度解析:从YAML配置到运行时控制中枢

LlamaFactory超参数体系深度解析:从YAML配置到运行时控制中枢

1. 项目概述:为什么超参数不是“调着玩”,而是模型微调的命脉

LlamaFactory 这个名字在大模型微调圈子里,已经快成默认配置项了。但很多人装完llamafactory-cli webui发现没反应,或者跑通一个 demo 后卡在“怎么让效果更好”这一步——问题往往不出在模型结构或数据上,而是在那一堆.yaml文件里密密麻麻的字段里。你改了learning_rate,结果 loss 不降反升;调高了per_device_train_batch_size,显存直接爆掉;把warmup_ratio设成 0.1,训练前 100 步震荡得像心电图……这些都不是玄学,是超参数体系在真实地、冷酷地反馈你的理解偏差。

所谓“超参数体系”,不是一堆可调数字的集合,而是一套有层级、有依赖、有物理意义、有工程约束的决策网络。它横跨训练目标(你希望模型学什么)、硬件现实(你手头有几张卡、多大显存)、算法稳定性(梯度是否爆炸、收敛是否平滑)和任务特性(是长文本生成还是短指令遵循)四大维度。LlamaFactory 把这套体系封装进 YAML/JSON 配置驱动的 CLI 架构里,表面看是“写个文件就能跑”,背后却是对 PyTorch 分布式训练、Hugging Face Transformers 调度逻辑、LoRA/QLoRA 参数注入机制、以及混合精度训练(AMP)底层行为的深度耦合。

我第一次用 LlamaFactory 微调 Qwen2-1.5B 做客服意图识别时,就栽在gradient_accumulation_stepsper_device_train_batch_size的组合上。当时只想着“batch 越大越好”,设成 8,单卡 A10 显存瞬间打满到 98%,OOM 报错后才意识到:这个值不是独立存在的,它必须和gradient_accumulation_steps=4配合,才能等效实现 global batch size = 8 × 4 × 2(双卡)= 64。而gradient_accumulation_steps本身又受max_grad_normlearning_rate制约——步子迈太大,梯度一裁就全没了。这种环环相扣的依赖关系,正是超参数体系最核心的特征。它不接受“单点优化”,只认“系统调优”。

所以这篇研读,不讲“每个参数是什么意思”的字典式解释(官方文档早写明白了),而是带你钻进 LlamaFactory 的源码骨架里,看它如何用src/llamafactory/hparams/下的parser.pyutils.pydataclass.py三层结构,把 YAML 中扁平的键值对,翻译成内存中带校验、带默认值、带类型约束、带跨参数联动逻辑的 Python 对象。你会看到TrainingArguments如何被get_train_args()函数从配置树中层层解包,又如何在Trainer初始化时,被Seq2SeqTrainerSFTTrainer拿去初始化优化器、学习率调度器、梯度裁剪器。这才是“超参数体系”的真实形态:它不是配置文件,而是运行时的控制中枢。

2. 超参数体系的三层架构:从 YAML 字符串到运行时对象的完整映射

LlamaFactory 的超参数体系绝非简单地yaml.load()之后丢给 Trainer。它的设计哲学是“配置即契约,解析即校验”。整个流程被严格划分为三层:声明层(YAML/JSON Schema)→ 解析层(ArgumentParser + Dataclass)→ 运行层(TrainingArguments 实例)。这三层之间不是直通管道,而是布满检查点的高速公路。

2.1 声明层:YAML 文件不是万能胶,而是有语法边界的契约

先看一个典型微调配置片段(train_lora.yaml):

# --- 训练基础 --- model_name_or_path: /models/qwen2-1.5b dataset: customer_service_zh template: qwen finetuning_type: lora # --- 超参数核心 --- learning_rate: 2e-4 num_train_epochs: 3 per_device_train_batch_size: 4 gradient_accumulation_steps: 4 max_grad_norm: 1.0 warmup_ratio: 0.1 # --- LoRA 特定 --- lora_rank: 64 lora_alpha: 16 lora_dropout: 0.1

表面看是自由格式,实则暗藏三重约束:

  1. 字段存在性约束model_name_or_path是必填项,缺失会触发ArgumentErrorlora_rankfinetuning_type: lora下才生效,若设为full却写了lora_rank,解析器会在postprocess_args()中静默忽略并记录 warning——这不是 bug,是设计,避免用户误配。
  2. 类型与范围约束learning_rate必须是 float,且0 < learning_rate <= 1.0num_train_epochs是 int,且>= 1warmup_ratio是 float,且0.0 <= warmup_ratio <= 1.0。这些校验不在 YAML 解析时做(PyYAML 只管转类型),而是在ArgumentParseradd_argument(type=float, choices=[...])或自定义type函数中完成。
  3. 语义依赖约束per_device_train_batch_sizegradient_accumulation_steps共同决定global_batch_size = per_device_train_batch_size × gradient_accumulation_steps × n_gpu。LlamaFactory 在postprocess_args()中会计算global_batch_size并与max_steps(若指定)交叉验证:若max_steps未设,它会根据num_train_epochsdataset长度、global_batch_size自动推导,确保训练轮次不因 batch 设置错误而崩掉。

提示:很多新手遇到CUDA out of memory,第一反应是调小per_device_train_batch_size。但更根本的解法是检查gradient_accumulation_steps是否同步调整。比如原设batch=8, grad_acc=2,显存超了,不能只改batch=4就完事,否则global_batch_size从 16 降到 8,训练信号强度减半。正确做法是batch=4, grad_acc=4,保持global_batch_size=16不变,同时降低单卡瞬时压力。这是声明层就该理解的语义。

2.2 解析层:ArgumentParser 不是摆设,而是动态路由引擎

LlamaFactory 的解析核心在src/llamafactory/hparams/parser.py。它没有用单一ArgumentParser,而是构建了一个嵌套解析器树

  • 顶层解析器(get_train_args_parser()):负责--model_name_or_path,--dataset,--finetuning_type等宏观开关。
  • 子解析器(add_model_args(),add_training_args(),add_lora_args()):按模块注册参数,例如add_training_args()注册所有learning_rate,num_train_epochs等通用训练参数;add_lora_args()只在finetuning_type == "lora"时才激活,注册lora_rank,lora_alpha
  • 动态参数注入:当--finetuning_type lora被传入,add_lora_args()才被调用,其注册的参数才会进入最终的argsNamespace。这避免了full微调时lora_rank字段污染命名空间。

关键代码逻辑(简化):

def get_train_args_parser(): parser = ArgumentParser() parser.add_argument("--model_name_or_path", type=str, required=True) parser.add_argument("--finetuning_type", type=str, default="lora", choices=["lora", "full", "freeze", "p_tuning"]) # 动态加载子模块 add_model_args(parser) add_training_args(parser) # 根据 finetuning_type 决定是否加载 LoRA 参数 if getattr(args, "finetuning_type", None) == "lora": add_lora_args(parser) return parser

这个设计的精妙在于:YAML 文件里的字段,只有在对应模块被启用时,才具备语义合法性lora_dropout: 0.1finetuning_type: full的 YAML 里不会报错,但会被解析器主动忽略——因为add_lora_args()根本没被调用。这比硬编码if finetuning_type == "lora": assert lora_rank > 0更优雅,也更符合配置即契约的理念。

2.3 运行层:Dataclass 不是装饰,而是带行为的活对象

解析后的args最终被get_train_args()封装进TrainingArguments数据类(定义在src/llamafactory/hparams/dataclass.py)。这不是一个简单的namedtuple,而是一个携带校验逻辑、默认值推导、跨参数联动的活对象

看几个关键字段的定义:

@dataclass class TrainingArguments: model_name_or_path: str = field(metadata={"help": "Path to pretrained model"}) dataset: str = field(metadata={"help": "Dataset name or path"}) # 学习率相关:learning_rate 是主控,lr_scheduler_type 和 warmup_ratio 是协同者 learning_rate: float = field(default=2e-5, metadata={"help": "Initial learning rate"}) lr_scheduler_type: str = field(default="cosine", metadata={"help": "Learning rate scheduler"}) warmup_ratio: float = field(default=0.0, metadata={"help": "Ratio of warmup steps"}) # Batch 相关:三者强绑定 per_device_train_batch_size: int = field(default=4, metadata={"help": "Batch size per device"}) gradient_accumulation_steps: int = field(default=1, metadata={"help": "Steps to accumulate gradients"}) max_steps: int = field(default=-1, metadata={"help": "Total number of training steps"}) def __post_init__(self): # 跨参数校验:warmup_ratio 必须在 [0,1] 区间 if not (0.0 <= self.warmup_ratio <= 1.0): raise ValueError("warmup_ratio must be in [0,1]") # 默认值推导:若未指定 max_steps,则根据 epochs 和 dataset 推算 if self.max_steps == -1 and hasattr(self, "num_train_epochs"): # 此处会调用 dataset loader 获取总样本数 pass # 联动逻辑:若使用 cosine 调度器,warmup_ratio > 0 是强烈推荐的 if self.lr_scheduler_type == "cosine" and self.warmup_ratio == 0.0: logger.warning("Cosine scheduler without warmup may cause instability.")

__post_init__是真正的魔法发生地。它在对象实例化后立即执行,完成三件事:

  • 强制校验warmup_ratio越界直接抛异常,不给任何侥幸空间;
  • 智能推导max_steps为空时,自动计算total_samples // (per_device_train_batch_size × n_gpu × gradient_accumulation_steps) × num_train_epochs
  • 经验提示:检测到cosine调度器却无 warmup,发出 warning——这不是错误,而是资深工程师的经验沉淀。

这就是 LlamaFactory 超参数体系的“灵魂”:它把教科书上的最佳实践(如 cosine 调度需 warmup),固化成了运行时的逻辑判断,让新手也能避开经典坑。

3. 核心超参数详解:不只是数值,更是训练策略的具象化表达

现在我们深入到具体参数。不罗列定义,而是聚焦于每个参数背后的物理意义、典型取值区间、与其他参数的耦合关系,以及我在不同场景下的实操选择逻辑。所有参数均以src/llamafactory/hparams/dataclass.py中的定义为准。

3.1 学习率(learning_rate):模型“学习速度”的油门踏板

learning_rate是最常被调整的参数,但它绝非孤立的“油门”。它的有效值域高度依赖于模型规模、优化器类型、batch size 和梯度裁剪强度

  • 物理意义:控制每次参数更新的步长大小。过大导致 loss 震荡甚至发散;过小导致收敛极慢,陷入局部最优。
  • 典型取值
    • 全量微调(Full FT):1e-5 ~ 5e-5(Qwen2-1.5B 类模型)
    • LoRA 微调:1e-4 ~ 2e-4(因只更新少量参数,可承受更大步长)
    • QLoRA(4-bit):2e-4 ~ 5e-4(量化引入噪声,需更大步长补偿)
  • 耦合关系
    • per_device_train_batch_size:batch size 加倍,通常需将learning_rate乘以√2(线性缩放法则)。例如batch=4, lr=2e-4batch=8, lr≈2.8e-4
    • max_grad_normmax_grad_norm=1.0是常用值,若learning_rate过大导致梯度频繁被裁,说明 lr 太高。
  • 我的实操心得
    • 永远从保守值开始:LoRA 微调,我固定用2e-4作为起点。跑 100 步看 loss 曲线:若前 50 步下降迅猛且平滑,可尝试3e-4;若震荡剧烈,立刻回退到1.5e-4
    • 不要迷信“学习率预热”warmup_ratio=0.1是常见设置,但对小数据集(<10k 样本)效果有限。我曾用 5k 客服对话微调,warmup_ratio=0.03(约 30 步)比0.1(100 步)收敛更快。
    • CLI 快速验证法:不用改 YAML,直接命令行覆盖:llamafactory-cli train --learning_rate 3e-4 ...。这是调试阶段最高效的手段。

3.2 Batch Size 体系:per_device_train_batch_size、gradient_accumulation_steps 与 global_batch_size 的三角平衡

这是新手最容易混乱的参数组。它们共同决定了global_batch_size,而后者直接影响梯度估计的方差和训练稳定性。

  • 物理意义
    • per_device_train_batch_size:单张 GPU 上一次 forward/backward 的样本数。直接决定单卡显存峰值
    • gradient_accumulation_steps:累积多少步的梯度后再执行一次optimizer.step()不增加显存,但增加训练时间
    • global_batch_size = per_device_train_batch_size × gradient_accumulation_steps × n_gpu:模型实际“看到”的批量大小,决定梯度更新方向的统计可靠性。
  • 典型取值与权衡
    场景per_device_train_batch_sizegradient_accumulation_stepsglobal_batch_size说明
    A10 (24G), Qwen2-1.5B, LoRA2816 (单卡) / 32 (双卡)显存安全,训练稳定
    A100 (40G), Qwen2-7B, LoRA4416 (单卡) / 64 (双卡)平衡速度与显存
    3090 (24G), Qwen2-1.5B, QLoRA11616 (单卡)量化后显存宽松,靠 grad_acc 提升 global batch
  • 耦合关系与避坑
    • per_device_train_batch_sizegradient_accumulation_steps反向资源置换:调小前者省显存,调大后者保 global batch。但grad_acc过大(>16)会导致训练时间线性增长,且可能因中间激活缓存累积引发 OOM。
    • global_batch_size不能无限大。经验法则:global_batch_size ≤ 2 × model_parameters_in_Billion。Qwen2-1.5B(约 1.5B 参数),global_batch_size ≤ 32是安全上限。
  • 我的实操心得
    • 显存监控是唯一真理nvidia-smiMemory-Usage,目标是稳定在 85%~92%。若低于 70%,大胆调大per_device_train_batch_size;若超 95%,优先调小per_device_train_batch_size,其次再考虑gradient_accumulation_steps
    • 梯度累积的副作用grad_acc=8时,每 8 步才更新一次 optimizer,learning_rate的衰减节奏会变慢。此时lr_scheduler_type=cosinenum_warmup_steps应按total_steps // 8计算,而非total_steps。LlamaFactory 的postprocess_args()会自动处理这个换算,但你要知道它发生了。
    • 一个 trick:在train.sh脚本里,用export CUDA_LAUNCH_BLOCKING=1启动,能精准定位是哪一行代码(通常是loss.backward())触发 OOM,而不是笼统的“显存不足”。

3.3 LoRA 特定参数:lora_rank、lora_alpha 与 lora_dropout 的黄金比例

LoRA 的核心是低秩分解:W' = W + ΔW = W + A × B,其中A(d, r)矩阵,B(r, d)矩阵,r就是lora_rank。这三个参数共同定义了 LoRA 层的“容量”与“鲁棒性”。

  • 物理意义
    • lora_rank (r):分解矩阵AB的中间维度。决定可学习参数量#params = 2 × r × dd是原始权重维度,如 Qwen2 的hidden_size=1536)。
    • lora_alpha (α):缩放因子,ΔW = (α/r) × A × B控制 LoRA 更新的幅度α/r是实际缩放系数。
    • lora_dropout:对A矩阵的 dropout 概率,防止 LoRA 层过拟合
  • 典型取值与黄金比例
    • lora_rank8, 16, 32, 64是主流。r=64对 Qwen2-1.5B(d=1536)意味着2×64×1536≈196K新参数,仅占原模型1.5B0.013%
    • lora_alpha:通常设为r的 1~2 倍。r=64时,alpha=16α/r=0.25)或alpha=32α/r=0.5)。alpha=16是最稳健的选择。
    • lora_dropout0.05 ~ 0.10.1是常用值,对小数据集(<5k)可设0.05;大数据集(>50k)可设0.0
  • 耦合关系
    • lora_alpha / lora_rank是关键比值。alpha=16, rank=64ratio=0.25alpha=32, rank=64ratio=0.5。比值越大,LoRA 更新越激进。我测试发现,ratio=0.25在多数 NLU 任务上泛化性最好。
    • lora_dropoutlora_rank负相关:rank越大,模型容量越高,越需要dropout防过拟合。
  • 我的实操心得
    • 不要盲目追求高 rankrank=64并不总是比rank=32效果好。我在一个法律文书分类任务上,rank=32, alpha=16的 F1 比rank=64, alpha=32高 0.8%,因为后者过拟合了训练集中的噪声模式。
    • alpha 的“杠杆效应”alpha不是越大越好。alpha=64, rank=64ratio=1.0)会让 LoRA 更新完全主导,相当于在微调一个新模型,失去了“低秩适配”的初衷。ratio > 0.5的配置,我一律视为高风险实验。
    • dropout 的时机lora_dropout只在训练时生效,推理时自动关闭。所以它不影响部署性能,只影响训练过程。放心用。

3.4 训练稳定性参数:max_grad_norm、warmup_ratio 与 lr_scheduler_type 的协同防御

这三个参数构成训练的“防抖系统”,专门对付梯度爆炸、初始不稳定和后期震荡。

  • 物理意义与协同逻辑
    • max_grad_norm:梯度裁剪阈值。梯度L2 norm超过此值,按比例缩放至该值。是防止梯度爆炸的最后一道防线
    • warmup_ratio:预热步数占总步数的比例。前warmup_steps步,learning_rate从 0 线性增长到设定值。解决模型初始参数敏感、梯度方差大的问题
    • lr_scheduler_type:学习率衰减策略。cosine(余弦退火)最常用,linear(线性衰减)次之,constant(恒定)极少用。
  • 典型取值与组合
    • max_grad_norm=1.0:工业级标准。0.5过于保守(裁剪太狠,学习停滞),2.0过于激进(起不到保护作用)。
    • warmup_ratio=0.03 ~ 0.1:小数据集用0.03(快速进入正轨),大数据集用0.1(充分预热)。
    • lr_scheduler_type=cosine:配合warmup_ratio>0,形成“预热上升 + 平稳衰减”的理想曲线。
  • 耦合关系与避坑
    • warmup_ratiolr_scheduler_type是强绑定的。cosine调度器若warmup_ratio=0,初始学习率突变,极易导致 loss spike。linear调度器对warmup依赖稍低,但仍推荐warmup_ratio=0.03
    • max_grad_norm的有效性依赖于learning_rate。若lr过大,max_grad_norm会高频触发,导致有效学习率大幅波动。应先调好lr,再确认max_grad_norm是否合理。
  • 我的实操心得
    • warmup 的可视化验证:用tensorboardlearning_rate曲线。正常应是前warmup_steps步直线上升,之后平滑下降。若曲线上升后突然断崖,说明warmup_steps计算错误(可能是max_steps未正确推导)。
    • max_grad_norm 的“健康指标”:监控grad_norm的日志。若grad_norm经常接近max_grad_norm(如0.95),说明lr可能偏大或max_grad_norm偏小;若grad_norm始终 <0.5,说明裁剪未生效,可适当调小max_grad_norm以释放学习能力。
    • scheduler 的“冷启动”陷阱cosine调度器在step=0lr=0,但warmup会覆盖它。务必确认warmup_ratio已生效,否则模型在第一步就“冻住”。

4. CLI 与 YAML/JSON 的工程实践:如何让配置管理不再成为负担

LlamaFactory 的 CLI (llamafactory-cli) 是连接人与超参数体系的桥梁。它把 YAML/JSON 的静态配置,变成了可组合、可复用、可调试的工程资产。这里不讲基础用法,而是分享一套经过生产环境验证的配置管理方法论

4.1 YAML 配置的分层继承:base.yaml → qwen2.yaml → customer_service.yaml

硬编码所有参数在一个 YAML 里是灾难。LlamaFactory 支持通过--config参数指定多个 YAML,实现参数覆盖。我建立三级继承体系:

  1. configs/base.yaml:全局基础配置,定义所有微调共用的“不变量”。

    # configs/base.yaml output_dir: ./output logging_steps: 10 save_steps: 500 evaluation_strategy: steps eval_steps: 500 load_best_model_at_end: true metric_for_best_model: eval_loss greater_is_better: false report_to: none
  2. configs/qwen2.yaml:模型特定配置,定义 Qwen2 系列的“半变量”。

    # configs/qwen2.yaml model_name_or_path: /models/qwen2-1.5b template: qwen finetuning_type: lora lora_target: q_proj,v_proj,k_proj,o_proj,gate_proj,up_proj,down_proj lora_dropout: 0.1
  3. configs/customer_service.yaml:任务特定配置,定义业务场景的“变量”。

    # configs/customer_service.yaml dataset: customer_service_zh learning_rate: 2e-4 num_train_epochs: 3 per_device_train_batch_size: 4 gradient_accumulation_steps: 4 warmup_ratio: 0.05

执行命令llamafactory-cli train --config configs/base.yaml configs/qwen2.yaml configs/customer_service.yaml

  • 优势
    • 复用性:新增一个financial_report.yaml,只需继承base.yamlqwen2.yaml,专注写datasetlearning_rate
    • 可追溯性customer_service.yaml里只有一眼可见的业务参数,base.yaml的修改影响所有任务,责任清晰。
    • 安全性base.yaml中的save_steps: 500是硬性要求,任何下游 YAML 都无法意外覆盖为1(导致磁盘爆满)。

注意:LlamaFactory 的覆盖逻辑是后加载的 YAML 优先级更高customer_service.yaml会覆盖qwen2.yaml中同名字段,qwen2.yaml会覆盖base.yaml。这是确定性的,无需担心顺序混乱。

4.2 JSON 配置的 CLI 动态注入:用--json参数实现秒级调试

YAML 适合长期维护,JSON 适合临时调试。LlamaFactory 的 CLI 支持--json参数,直接传入 JSON 字符串,绕过 YAML 文件,实现参数的即时覆盖

  • 典型场景

    • 快速验证 learning_ratellamafactory-cli train --json '{"learning_rate": 3e-4}'
    • 临时禁用评估llamafactory-cli train --json '{"evaluation_strategy": "no"}'
    • 动态调整 batchllamafactory-cli train --json '{"per_device_train_batch_size": 2, "gradient_accumulation_steps": 8}'
  • 高级技巧:JSON 与 YAML 混合

    # 用 YAML 定义主体,用 JSON 覆盖关键参数 llamafactory-cli train \ --config configs/customer_service.yaml \ --json '{"learning_rate": 2.5e-4, "warmup_ratio": 0.03}'
  • 为什么用 JSON 而不是多个--arg value

    • --arg value只支持扁平参数,无法覆盖嵌套结构(如lora_target是字符串,但未来可能支持 list)。
    • JSON 支持任意嵌套,且--json参数可以多次出现,实现多重覆盖:--json '{"a":1}' --json '{"b":2}'等价于{"a":1,"b":2}
    • JSON 字符串在 shell 中比一堆--arg更易编写和复用(可存为变量)。

4.3 CLI 的 WebUI 故障排查:llamafactory-cli webui没反应的 5 个真实原因

这是搜索热词里最高频的问题。llamafactory-cli webui没反应,90% 不是 LlamaFactory 的 bug,而是环境或配置问题。以下是我在 Ubuntu 20.04/22.04 上踩过的坑:

现象根本原因解决方案
命令执行后立即退出,无报错gradio未安装或版本冲突pip install gradio==4.35.0(LlamaFactory 0.9.x 兼容版本);检查pip list | grep gradio
命令执行后卡住,CPU 占用 100%transformers版本过高,与gradiofastapi冲突pip install transformers==4.41.0;或升级gradio4.40.0+
浏览器打开空白页,Console 报Failed to load resource: net::ERR_CONNECTION_REFUSEDWebUI 默认绑定127.0.0.1:7860,但服务器无 GUI,或防火墙拦截启动时加--server-name 0.0.0.0 --server-port 7860;检查ufw status,开放端口
WebUI 打开但模型列表为空model_name_or_path指向的路径不存在,或权限不足ls -l /models/qwen2-1.5b确认路径;chmod -R 755 /models
点击“Train”后无响应,日志无输出dataset名称拼写错误,或数据集未按 LlamaFactory 要求的格式准备(如alpaca格式)检查data/目录下是否有customer_service_zh.json;用head -n 5 data/customer_service_zh.json确认格式

实操心得:WebUI 本质是 Gradio 启动的一个 FastAPI 服务。最可靠的调试方式是在命令行加-v参数llamafactory-cli webui -v。它会输出详细的初始化日志,包括加载了哪些模型、数据集路径、Gradio 版本等,90% 的问题都能从中定位。

5. 常见问题与排查技巧实录:来自 37 次失败训练的血泪总结

最后,分享一份浓缩了我在 LlamaFactory 上 37 次失败训练(从 OOM 到 NaN Loss)后整理的《超参数问题速查表》。每一条都对应一个真实发生的、让人抓狂的场景。

5.1 Loss 异常类问题

问题现象可能原因排查步骤解决方案
Loss 从第 1 步开始就是 NaNlearning_rate过大,或max_grad_norm过小导致梯度被过度裁剪1. 检查learning_rate是否 >5e-4;2. 查看日志中grad_norm是否频繁等于max_grad_normlearning_rate降为1e-4max_grad_norm设为1.0,重跑前 10 步
Loss 前 100 步震荡剧烈(±0.5),之后缓慢下降warmup_ratio过小,或learning_ratebatch_size不匹配1. 用tensorboardlearning_rate曲线是否平滑;2. 计算global_batch_size是否在合理范围warmup_ratio提高到0.1learning_ratebatch_size线性缩放
Loss 下降 1000 步后突然飙升(+2.0)然后归零数据集中存在极端长文本(>2048 tokens),导致 attention mask 错误1.grep -n "length.*exceed" logs/train.log;2. 用datasets库加载数据集,print(dataset[0]["input_ids"][:50])data/目录下添加filter.py,过滤掉len(input_ids) > 2048的样本

5.2 显存与性能类问题

问题现象可能原因排查步骤解决方案