DARE:Drop and Rescale模型合并
1. 概述
DARE(Drop And REScale)1 是一种通过稀疏化Delta参数来减少模型合并干扰的方法。其核心思想是:大多数Delta参数在微调后变化很小,可以安全地丢弃。
2. 核心思想
2.1 Delta参数
Delta参数编码了微调过程中学到的知识。
2.2 稀疏化动机
实验观察表明:1
- 约 70-90% 的Delta参数接近于零
- 这些「微小变化」在合并时可能引入噪声
- 丢弃它们可以减少任务间干扰
3. DARE算法
3.1 Drop操作
随机将比例 的Delta参数设为零:
其中 是随机数。
def drop_delta(delta, drop_ratio=0.9):
"""Drop操作:随机丢弃比例drop_ratio的Delta参数"""
mask = torch.rand_like(delta) > drop_ratio
return delta * mask3.2 Rescale操作
由于丢弃了大部分参数,需要对剩余参数进行缩放以保持数学期望一致:
这确保了:
def rescale_delta(delta, drop_ratio=0.9):
"""Rescale操作:补偿Drop造成的期望变化"""
return delta / (1 - drop_ratio)3.3 完整流程
def dare(task_vector, drop_ratio=0.9):
"""
DARE: Drop And REScale
Args:
task_vector: Delta参数 (theta_finetune - theta_pretrain)
drop_ratio: 要丢弃的参数比例
"""
dropped = drop_delta(task_vector, drop_ratio)
rescaled = rescale_delta(dropped, drop_ratio)
return rescaled4. 与TIES的对比
| 维度 | DARE | TIES |
|---|---|---|
| 稀疏化方式 | 随机丢弃 | 基于幅度阈值 |
| 符号处理 | 保留原符号 | 符号投票统一 |
| 参数选择 | 概率性 | 确定性 |
| 理论基础 | 期望保持 | 实验验证 |
4.1 互补性
DARE和TIES可以结合使用:
def ties_dare_merge(pretrain, task_vectors, delta=1.0, drop_ratio=0.8):
"""
TIES + DARE 组合方法
"""
# Step 1: TIES Trim
trimmed = [trim_task_vector(tv, delta) for tv in task_vectors]
# Step 2: Elect Signs
elected = elect_signs(trimmed)
# Step 3: DARE Drop & Rescale
merged_delta = torch.zeros_like(pretrain)
for tv in trimmed:
masked = tv * (torch.sign(tv) == elected).float()
merged_delta += dare(masked, drop_ratio)
return pretrain + merged_delta5. 理论分析
5.1 期望保持性质
DARE的Rescale操作确保了合并后模型在统计意义上保持一致:
这对于一阶近似是合理的。
5.2 方差变化
丢弃参数后,方差会发生变化:
实际上,由于丢弃的是接近零的参数,有效方差变化更小。
6. 超参数选择
6.1 Drop Ratio
推荐值及效果:
| 效果 | 适用场景 | |
|---|---|---|
| 0.5 | 保守,保留较多参数 | 低干扰任务 |
| 0.7 | 平衡 | 一般场景 |
| 0.9 | 激进,减少干扰 | 高干扰任务 |
6.2 自适应Drop Ratio
可以根据参数重要性动态调整:
def adaptive_dare(task_vector, base_ratio=0.8):
"""自适应DARE:根据参数幅度调整drop ratio"""
abs_tv = task_vector.abs()
importance = abs_tv / abs_tv.sum()
# 重要性高的参数使用较低的drop ratio
drop_ratio = base_ratio * (1 - importance)
drop_ratio = drop_ratio.clamp(0.5, 0.95)
mask = torch.rand_like(task_vector) > drop_ratio
return (task_vector * mask) / (1 - drop_ratio.mean())7. 大规模实验结果
DARE在大规模LLM合并上表现优异:1
| 模型 | 原始 | TIES | DARE | TIES+DARE |
|---|---|---|---|---|
| LLaMA-7B | 65.2 | 68.5 | 69.1 | 71.3 |
| LLaMA-13B | 68.1 | 70.2 | 71.0 | 72.8 |
| Mistral-7B | 70.5 | 72.1 | 72.8 | 74.2 |
8. 实践指南
8.1 完整合并流程
def full_merge(
pretrain_model,
finetune_models, # List of fine-tuned models
weights, # Merge weights
method='ties_dare',
ties_delta=1.0,
dare_ratio=0.8
):
"""
完整的模型合并流程
Args:
pretrain_model: 预训练基准模型
finetune_models: 微调后的模型列表
weights: 各模型的权重
method: 'dare', 'ties', 'ties_dare'
ties_delta: TIES修剪阈值
dare_ratio: DARE丢弃比例
"""
# 计算任务向量
task_vectors = [
(finetune.state_dict() - pretrain_model.state_dict())
for finetune in finetune_models
]
if method == 'dare':
merged_delta = sum(
w * dare(tv, dare_ratio)
for w, tv in zip(weights, task_vectors)
)
elif method == 'ties':
merged_delta = ties_merge(pretrain_model.state_dict(), task_vectors, ties_delta)
else: # ties_dare
merged_delta = ties_dare_merge(
pretrain_model.state_dict(),
task_vectors,
ties_delta,
dare_ratio
)
merged_state = pretrain_model.state_dict()
for key in merged_state:
merged_state[key] += merged_delta[key]
return merged_state8.2 评估建议
- 单任务评估:验证每个原始任务的性能保留
- 冲突度量:计算任务间的干扰程度
- 集成对比:与模型集成方法比较效率