mcpField
M
model-merging

model-merging

github.com/orchestra-research开发14.1k960 次安装19 周前更新
代码仓库

关于 model-merging

这是一份使用 mergekit 合并预训练模型的实践技能指南,面向模型开发者。它介绍多种合并方法、配置方式及结果评估流程。

主要功能

  1. 01加权线性合并与 SLERP
  2. 02任务算术、TIES 和 DARE 方法
  3. 03逐层与分词器合并
  4. 04基于 YAML 的合并配置
  5. 05基准评估与系数调优

适用场景

  1. 01融合数学与聊天能力
  2. 02组合多个任务专用模型
  3. 03无标注数据测试合并权重

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/orchestra-research/ai-research-skills --skill model-merging

安装后在 Claude Code 中输入/model-merging确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
coefficient-tuning.md
evaluation.md
examples.md
methods.md

详细介绍

模型合并:组合预训练模型

何时使用此技能

在以下情况下使用模型合并:

  • 组合多种能力,无需重新训练多个微调模型
  • 创建专用模型,融合特定领域的专业知识(数学 + 编码 + 聊天)
  • 提升性能,超越单个模型(基准测试中通常提升 5-10%)
  • 降低训练成本——无需 GPU,合并可在 CPU 上运行
  • 快速实验——几分钟内创建新的模型变体,而非耗费数天
  • 保留多种技能——合并时避免灾难性遗忘

成功案例:Marcoro14-7B-slerp(2024 年 2 月在 Open LLM Leaderboard 上排名第一),许多 HuggingFace 顶尖模型都使用了合并技术

工具:mergekit(Arcee AI)、LazyMergekit、Model Soup

安装

# Install mergekit
git clone https://github.com/arcee-ai/mergekit.git
cd mergekit
pip install -e .

# Or via pip
pip install mergekit

# Optional: Transformer library
pip install transformers torch

快速入门

简单线性合并
# config.yml - Merge two models with equal weights
merge_method: linear
models:
  - model: mistralai/Mistral-7B-v0.1
    parameters:
      weight: 0.5
  - model: teknium/OpenHermes-2.5-Mistral-7B
    parameters:
      weight: 0.5
dtype: bfloat16
# Run merge
mergekit-yaml config.yml ./merged-model --cuda

# Use merged model
python -m transformers.models.auto --model_name_or_path ./merged-model
SLERP 合并(最适合 2 个模型)
# config.yml - Spherical interpolation
merge_method: slerp
slices:
  - sources:
      - model: mistralai/Mistral-7B-v0.1
        layer_range: [0, 32]
      - model: teknium/OpenHermes-2.5-Mistral-7B
        layer_range: [0, 32]
parameters:
  t: 0.5  # Interpolation factor (0=model1, 1=model2)
dtype: bfloat16

核心概念

1. 合并方法

线性(Model Soup)

  • 对参数进行简单的加权平均
  • 速度快,适用于相似模型
  • 可合并 2 个或更多模型(w1 + w2 + ... = 1)

SLERP(球面线性插值)

  • 沿权重空间中的球面进行插值
  • 保持权重向量的模长
  • 最适合合并 2 个模型
  • 比线性插值更平滑
# SLERP formula
merged = (sin((1-t)*θ) / sin(θ)) * model1 + (sin(t*θ) / sin(θ)) * model2
# where θ = arccos(dot(model1, model2))
# t ∈ [0, 1]

任务算术

  • 提取“任务向量”(微调模型 - 基础模型)
  • 组合任务向量,并将其加到基础模型上
  • 适合合并多个专用模型(merged = base + α₁·tv₁ + α₂·tv₂)

TIES-Merging

  • 任务算术 + 稀疏化
  • 解决参数中的符号冲突
  • 最适合合并多个特定任务的模型

DARE(Drop And REscale)

  • 随机丢弃微调后的参数
  • 对剩余参数进行缩放
  • 减少冗余,同时保持性能
2. 配置结构
# Basic structure
merge_method: <method>  # linear, slerp, ties, dare_ties, task_arithmetic
base_model: <path>      # Optional: base model for task arithmetic

models:
  - model: <path/to/model1>
    parameters:
      weight: <float>   # Merge weight
      density: <float>  # For TIES/DARE

  - model: <path/to/model2>
    parameters:
      weight: <float>

parameters:
  # Method-specific parameters

dtype: <dtype>  # bfloat16, float16, float32

# Optional
slices:  # Layer-wise merging
tokenizer:  # Tokenizer configuration

合并方法指南

线性合并

最适合:简单的模型组合、等权重合并

merge_method: linear
models:
  - model: WizardLM/WizardMath-7B-V1.1
    parameters:
      weight: 0.4
  - model: teknium/OpenHermes-2.5-Mistral-7B
    parameters:
      weight: 0.3
  - model: NousResearch/Nous-Hermes-2-Mistral-7B-DPO
    parameters:
      weight: 0.3
dtype: bfloat16
SLERP 合并

最适合:两个模型、平滑插值

merge_method: slerp
slices:
  - sources:
      - model: mistralai/Mistral-7B-v0.1
        layer_range: [0, 32]
      - model: teknium/OpenHermes-2.5-Mistral-7B
        layer_range: [0, 32]
parameters:
  t: 0.5  # 0.0 = first model, 1.0 = second model
dtype: bfloat16

按层进行 SLERP:

merge_method: slerp
slices:
  - sources:
      - model: model_a
        layer_range: [0, 32]
      - model: model_b
        layer_range: [0, 32]
parameters:
  t:
    - filter: self_attn    # Attention layers
      value: 0.3
    - filter: mlp          # MLP layers
      value: 0.7
    - value: 0.5           # Default for other layers
dtype: bfloat16
任务算术

最适合:组合专用技能

merge_method: task_arithmetic
base_model: mistralai/Mistral-7B-v0.1
models:
  - model: WizardLM/WizardMath-7B-V1.1  # Math
    parameters:
      weight: 0.5
  - model: teknium/OpenHermes-2.5-Mistral-7B  # Chat
    parameters:
      weight: 0.3
  - model: ajibawa-2023/Code-Mistral-7B  # Code
    parameters:
      weight: 0.2
dtype: bfloat16
TIES-Merging

最适合:多个模型、解决冲突

merge_method: ties
base_model: mistralai/Mistral-7B-v0.1
models:
  - model: WizardLM/WizardMath-7B-V1.1
    parameters:
      density: 0.5  # Keep top 50% of parameters
      weight: 1.0
  - model: teknium/OpenHermes-2.5-Mistral-7B
    parameters:
      density: 0.5
      weight: 1.0
  - model: NousResearch/Nous-Hermes-2-Mistral-7B-DPO
    parameters:
      density: 0.5
      weight: 1.0
parameters:
  normalize: true
dtype: bfloat16
DARE 合并

最适合:减少冗余

merge_method: dare_ties
base_model: mistralai/Mistral-7B-v0.1
models:
  - model: WizardLM/WizardMath-7B-V1.1
    parameters:
      density: 0.5    # Drop 50% of deltas
      weight: 0.6
  - model: teknium/OpenHermes-2.5-Mistral-7B
    parameters:
      density: 0.5
      weight: 0.4
parameters:
  int8_mask: true  # Use int8 for masks (saves memory)
dtype: bfloat16

高级模式

逐层合并
# Different models for different layers
merge_method: passthrough
slices:
  - sources:
      - model: mistralai/Mistral-7B-v0.1
        layer_range: [0, 16]   # First half
  - sources:
      - model: teknium/OpenHermes-2.5-Mistral-7B
        layer_range: [16, 32]  # Second half
dtype: bfloat16
从合并模型创建 MoE
# Create Mixture of Experts
merge_method: moe
base_model: mistralai/Mistral-7B-v0.1
experts:
  - source_model: WizardLM/WizardMath-7B-V1.1
    positive_prompts:
      - "math"
      - "calculate"
  - source_model: teknium/OpenHermes-2.5-Mistral-7B
    positive_prompts:
      - "chat"
      - "conversation"
  - source_model: ajibawa-2023/Code-Mistral-7B
    positive_prompts:
      - "code"
      - "python"
dtype: bfloat16
分词器合并
merge_method: linear
models:
  - model: mistralai/Mistral-7B-v0.1
  - model: custom/specialized-model

tokenizer:
  source: "union"  # Combine vocabularies from both models
  tokens:
    <|special_token|>:
      source: "custom/specialized-model"

最佳实践

1. 模型兼容性
# ✅ Good: Same architecture
models = [
    "mistralai/Mistral-7B-v0.1",
    "teknium/OpenHermes-2.5-Mistral-7B",  # Both Mistral 7B
]

# ❌ Bad: Different architectures
models = [
    "meta-llama/Llama-2-7b-hf",  # Llama
    "mistralai/Mistral-7B-v0.1",  # Mistral (incompatible!)
]
2. 权重选择
# ✅ Good: Weights sum to 1.0
models:
  - model: model_a
    parameters:
      weight: 0.6
  - model: model_b
    parameters:
      weight: 0.4  # 0.6 + 0.4 = 1.0

# ⚠️  Acceptable: Weights don't sum to 1 (for task arithmetic)
models:
  - model: model_a
    parameters:
      weight: 0.8
  - model: model_b
    parameters:
      weight: 0.8  # May boost performance

无监督系数调优(无需标注数据)

无需手动搜索,可使用生成一致性:用多个候选系数进行合并,在一个小型无标注子集上生成响应,然后选择输出与相邻候选系数的输出最相似的系数。输出一致意味着合并区域稳定且性能良好(AdaMMS,arXiv:2503.23733)。

# Pseudocode — see references/coefficient-tuning.md for full implementation
candidates = [0.3, 0.4, 0.5, 0.6, 0.7]
for alpha in candidates:
    merged_paths[alpha] = merge_with_coefficient(alpha, model_a, model_b)
    responses[alpha]    = generate_responses(merged_paths[alpha], eval_prompts)

# Score each alpha by similarity to its neighbors (alpha ± 0.1)
best_alpha = max(candidates, key=lambda a: generation_consistency(a, responses))

完整算法、相似度指标、多系数搜索和端到端流水线,请参阅 references/coefficient-tuning.md。

3. 方法选择
# Choose merge method based on use case:

# 2 models, smooth blend → SLERP
merge_method = "slerp"

# 3+ models, simple average → Linear
merge_method = "linear"

# Multiple task-specific models → Task Arithmetic or TIES
merge_method = "ties"

# Want to reduce redundancy → DARE
merge_method = "dare_ties"
4. 密度调优(TIES/DARE)
# Start conservative (keep more parameters)
parameters:
  density: 0.8  # Keep 80%

# If performance good, increase sparsity
parameters:
  density: 0.5  # Keep 50%

# If performance degrades, reduce sparsity
parameters:
  density: 0.9  # Keep 90%
5. 按层合并

保留基础模型的第一层和最后一层(通常最好保持原样),并通过 merge_method: passthrough 和 slices 仅合并中间层——请参阅上文的逐层合并模式。

评估与测试

对合并模型进行基准测试
from transformers import AutoModelForCausalLM, AutoTokenizer

# Load merged model
model = AutoModelForCausalLM.from_pretrained("./merged-model")
tokenizer = AutoTokenizer.from_pretrained("./merged-model")

# Test on various tasks
test_prompts = {
    "math": "Calculate: 25 * 17 =",
    "code": "Write a Python function to reverse a string:",
    "chat": "What is the capital of France?",
}

for task, prompt in test_prompts.items():
    inputs = tokenizer(prompt, return_tensors="pt")
    outputs = model.generate(**inputs, max_length=100)
    print(f"{task}: {tokenizer.decode(outputs[0])}")
常见基准
  • Open LLM Leaderboard:通用能力
  • MT-Bench:多轮对话
  • MMLU:多任务准确率
  • HumanEval:代码生成
  • GSM8K:数学推理

生产部署

保存和上传
from transformers import AutoModelForCausalLM, AutoTokenizer

# Load merged model
model = AutoModelForCausalLM.from_pretrained("./merged-model")
tokenizer = AutoTokenizer.from_pretrained("./merged-model")

# Upload to HuggingFace Hub
model.push_to_hub("username/my-merged-model")
tokenizer.push_to_hub("username/my-merged-model")
对合并模型进行量化
# Quantize with GGUF
python convert.py ./merged-model --outtype f16 --outfile merged-model.gguf

# Quantize with GPTQ
python quantize_gptq.py ./merged-model --bits 4 --group_size 128

常见陷阱

  • 架构不匹配 — 只合并架构相同的模型(例如,不要混合 Llama 和 Mistral)。
  • 某个模型权重过高(例如,0.95 / 0.05)— 保持权重均衡,通常在 0.3–0.7 之间。
  • 跳过评估 — 部署前务必对合并后的模型进行基准测试(参见上文“评估与测试”部分)。

资源

另请参阅

  • references/methods.md - 深入了解合并算法
  • references/examples.md - 实际合并配置
  • references/evaluation.md - 基准测试与测试策略
  • references/coefficient-tuning.md - 通过生成一致性进行无监督系数搜索(AdaMMS,arXiv:2503.23733)

评论

支持 Markdown