AI Research Skills 模型合并实战:基于生成一致性的无监督系数自动调优(AdaMMS 方法)
AI 技能人工智能大模型深度学习【免费下载链接】AI-Research-SKILLsComprehensive open-source library of AI research and engineering skills for any AI model. Package the skills and your claude code/codex/gemini agent will be an AI research agent with full horsepower. Maintained by Orchestra Research.项目地址https://gitcode.com/gh_mirrors/ai/AI-Research-SKILLs点击查看免费下载模型合并Model Merging能将多个微调模型的能力在无需重训的情况下融合但其效果高度依赖合并系数如 SLERP 的t、Task Arithmetic 的weight/lambda。本指南以仓库19-emerging-techniques/model-merging中的核心参考文档为基础系统讲解来自 CVPR 2025 论文 AdaMMS 的**生成一致性Generation Consistency**无监督系数选择方法仅需 50200 条无标签文本即可自动从候选系数中挑出最优值彻底摆脱人工试错与标注数据依赖。读完本文你将掌握从候选系数定义、批量合并、无标签推理到一致性评分与最优系数选取的完整可运行流水线并了解 ROUGE-L、BERTScore 等相似度度量的选型与多系数搜索的扩展方法。一、问题背景合并系数为什么难选主流的合并方法Task Arithmetic、TIES、DARE、SLERP都会暴露一个或多个标量系数例如weight、density、lambda、t它们对最终合并质量影响极大。仓库的 SKILL.md 明确给出了各种方法的配置结构其中 SLERP 用t控制插值位置0 取第一个模型、1 取第二个模型Task Arithmetic 用weight缩放任务向量TIES/DARE 还有density参数控制参数保留比例。传统的系数选择方式各有明显缺陷方法缺点人工经验/直觉不可靠依赖领域专家经验带评测集的网格搜索需要标注数据代价高N 次合并 × N 次评测贝叶斯优化每一轮 trial 都需要 ground-truth 信号生成一致性本文方法完全无监督、无需标签仅需少量无标注数据子集这也是模型合并进入生产环境前最常卡住的环节——evaluation.md 中强调合并后必须做完整评测但如果系数本身就选错了后面的评测与回归测试都建立在错误基础上。二、核心思想生成一致性Generation Consistency关键洞察当某个系数值接近最优时取邻近系数值合并出的模型会产出相似的输出——因为损失曲面在好的解附近是平滑的。相反在过差解附近系数过高或过低模型处于不稳定点输出会急剧发散。对于候选系数α定义一致性分数为ConsistencyScore(α) avg_similarity(outputs(α), outputs(α - δ)) avg_similarity(outputs(α), outputs(α δ))其中δ是小的步长如 0.1相似度在一小批无标签数据上计算。选择一致性分数最高的系数即为最优系数。这一思想与仓库中 methods.md 介绍的 SLERP 公式merged (sin((1-t)*θ)/sin(θ)) * model1 (sin(t*θ)/sin(θ)) * model2直接相关系数空间上的平滑性正是插值方法能在邻近点保持输出稳定性的前提。三、五步算法详解Step 1定义候选系数使用 NumPy 生成搜索网格。示例中搜索 SLERP 的t或 Task Arithmetic 的lambdaimport numpy as np # Example: searching over SLERP t or Task Arithmetic lambda alpha_min, alpha_max 0.2, 0.8 step 0.1 candidates np.arange(alpha_min, alpha_max step, step).tolist() # candidates [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]Step 2为每个候选系数合并模型利用 mergekit 的mergekit-yaml命令行工具为每个系数生成一个合并模型。文档示例同时给出了 SLERP 与 Task Arithmetic 两种 YAML 配置的构造方式import subprocess import json import os def merge_with_coefficient(alpha, model_a, model_b, output_dir, methodslerp): Merge models using mergekit with a specific coefficient. if method slerp: config { merge_method: slerp, slices: [{sources: [ {model: model_a, layer_range: [0, 32]}, {model: model_b, layer_range: [0, 32]} ]}], parameters: {t: alpha}, dtype: bfloat16 } elif method task_arithmetic: config { merge_method: task_arithmetic, base_model: model_a, # treat model_a as base models: [{model: model_b, parameters: {weight: alpha}}], dtype: bfloat16 } config_path f/tmp/merge_config_{alpha:.2f}.yaml import yaml with open(config_path, w) as f: yaml.dump(config, f) out_path os.path.join(output_dir, fmerged_alpha_{alpha:.2f}) subprocess.run( [mergekit-yaml, config_path, out_path, --cuda], checkTrue ) return out_path # Merge all candidates output_root /tmp/merge_candidates os.makedirs(output_root, exist_okTrue) merged_paths {} for alpha in candidates: path merge_with_coefficient(alpha, model_a_path, model_b_path, output_root) merged_paths[alpha] path这里生成的 SLERP 配置与 SKILL.md 中 Quick Start 的 SLERP 示例结构完全一致slicessourcesparameters.tTask Arithmetic 配置也与 SKILL.md 中base_modelmodels[].weight的写法对应。需要说明的是SLERP 要求两个模型同架构例如同为 Mistral 7B混合 Llama 与 Mistral 会导致失败这是 SKILL.md 中Common Pitfalls明确强调的前提。Step 3在无标签子集上推理只需少量约 50200 条无标签文本数据不需要任何标签。使用 HuggingFacetransformers逐候选模型批量生成回复from transformers import AutoModelForCausalLM, AutoTokenizer import torch def generate_responses(model_path, prompts, max_new_tokens128, batch_size8): Generate responses for all prompts using the merged model. tokenizer AutoTokenizer.from_pretrained(model_path) model AutoModelForCausalLM.from_pretrained( model_path, torch_dtypetorch.bfloat16, device_mapauto ) model.eval() all_responses [] for i in range(0, len(prompts), batch_size): batch prompts[i:i batch_size] inputs tokenizer(batch, return_tensorspt, paddingTrue, truncationTrue).to(model.device) with torch.no_grad(): outputs model.generate( **inputs, max_new_tokensmax_new_tokens, do_sampleFalse, # greedy for determinism pad_token_idtokenizer.eos_token_id ) decoded tokenizer.batch_decode(outputs[:, inputs[input_ids].shape[1]:], skip_special_tokensTrue) all_responses.extend(decoded) del model # free GPU memory before loading next torch.cuda.empty_cache() return all_responses # Small unlabeled evaluation prompts (no labels needed) eval_prompts [ Explain the concept of gradient descent., Write a Python function to find the maximum of a list., # ... 50-200 prompts total ] # Generate responses for each candidate all_responses {} for alpha in candidates: print(fGenerating responses for alpha{alpha:.2f} ...) all_responses[alpha] generate_responses(merged_paths[alpha], eval_prompts)注意两个实现细节一是do_sampleFalse使用贪心解码保证输出确定性使不同系数间的输出差异真实反映模型行为而非采样噪声二是每次推理后显式del model并torch.cuda.empty_cache()释放显存为加载下一个候选模型腾出空间。Step 4计算生成一致性分数将每个α的输出与其左右邻居α - δ、α δ的输出两两比较取平均相似度from rouge_score import rouge_scorer def text_similarity(text_a, text_b, metricrougeL): Compute similarity between two text strings. if metric rougeL: scorer rouge_scorer.RougeScorer([rougeL], use_stemmerFalse) score scorer.score(text_a, text_b) return score[rougeL].fmeasure elif metric token_overlap: tokens_a set(text_a.lower().split()) tokens_b set(text_b.lower().split()) if not tokens_a or not tokens_b: return 0.0 return len(tokens_a tokens_b) / len(tokens_a | tokens_b) def generation_consistency(alpha, all_responses, candidates, delta0.1, metricrougeL): Compute generation consistency for a given alpha. Compares model at alpha against its nearest neighbors: alpha - delta and alpha delta. responses_curr all_responses[alpha] neighbor_alphas [] left_alpha round(alpha - delta, 2) right_alpha round(alpha delta, 2) if left_alpha in all_responses: neighbor_alphas.append(left_alpha) if right_alpha in all_responses: neighbor_alphas.append(right_alpha) if not neighbor_alphas: return 0.0 # boundary case with no neighbors total_sim 0.0 count 0 for n_alpha in neighbor_alphas: responses_neighbor all_responses[n_alpha] pair_sims [ text_similarity(r_curr, r_neighbor, metricmetric) for r_curr, r_neighbor in zip(responses_curr, responses_neighbor) ] total_sim sum(pair_sims) / len(pair_sims) count 1 return total_sim / count # Compute consistency scores for all interior candidates consistency_scores {} for alpha in candidates: score generation_consistency(alpha, all_responses, candidates, delta0.1) consistency_scores[alpha] score print(falpha{alpha:.2f} consistency{score:.4f})这里的round(alpha - delta, 2)是为了规避浮点误差如 0.3 - 0.1 得到 0.19999999确保能命中all_responses中精确到两位小数的键。边界候选如 0.2 与 0.8只有一个邻居其分数是单侧的会被系统性低估这一点在后面的 Practical Tips 中会专门讨论。Step 5选择最佳系数取一致性分数最大的候选作为最优系数并可视化为一致性曲线best_alpha max(consistency_scores, keyconsistency_scores.get) print(f\nBest coefficient: alpha{best_alpha:.2f} (consistency{consistency_scores[best_alpha]:.4f})) # Optionally visualize import matplotlib.pyplot as plt alphas_sorted sorted(consistency_scores.keys()) scores_sorted [consistency_scores[a] for a in alphas_sorted] plt.figure(figsize(8, 4)) plt.plot(alphas_sorted, scores_sorted, markero) plt.axvline(best_alpha, colorred, linestyle--, labelfBest α{best_alpha:.2f}) plt.xlabel(Merge Coefficient (α)) plt.ylabel(Generation Consistency Score) plt.title(Unsupervised Coefficient Selection via Generation Consistency) plt.legend() plt.tight_layout() plt.savefig(consistency_curve.png, dpi150) plt.show()选出的最优模型路径即为merged_paths[best_alpha]可直接用于后续的正式评测参考 evaluation.md 中的 Open LLM Leaderboard、MT-Bench、MMLU、HumanEval 等基准测试流程。四、相似度度量选型生成一致性的核心是文本相似度计算文档给出三种方案按速度与质量权衡度量速度质量说明Token overlapJaccard快低适合快速原型验证ROUGE-L中中均衡之选安装rouge-scoreBERTScore慢高语义敏感度最高需要 GPUBERTScore 的批量实现如下适合需要更强语义判别的场景# BERTScore alternative (higher quality) from bert_score import score as bert_score def bertscore_similarity_batch(texts_a, texts_b, langen): P, R, F1 bert_score(texts_a, texts_b, langlang, verboseFalse) return F1.mean().item() # Replace text_similarity call with: # score bertscore_similarity_batch(responses_curr, responses_neighbor)选型建议快速迭代用 token overlap 或 ROUGE-L最终确认最优系数时可用 BERTScore 复验。三种度量在文档的generation_consistency函数中通过metric参数切换text_similarity已内置rougeL与token_overlap两种BERTScore 则通过替换调用实现。五、应用到不同合并方法SLERPt参数t取值范围为 [0.0, 1.0]应选取内部候选点以避免边界塌缩# Search t ∈ [0.0, 1.0]; interior candidates avoid boundary collapse candidates [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]Task Arithmetic / TIESlambda或weightlambda可以超过 1.0搜索范围应更宽# Lambda can exceed 1.0; search a wider range candidates [0.3, 0.5, 0.7, 1.0, 1.2, 1.5]这与 methods.md 中 TIES 的lambda_param语义一致——lambda是合并任务向量的缩放因子大于 1.0 意味着微调模型影响更强。同理TIES/DARE 的density参数默认 0.2范围 0.10.8也可以用同样的生成一致性框架扫描。多系数如两个模型不同权重当搜索二维系数空间w1与w2 1 - w1时由于w2由w1决定一维搜索即足够# 1D search: w1 ∈ [0.2, 0.8], w2 1 - w1 candidates [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8] # Map alpha - (alpha, 1-alpha) for the merge config对于更高维搜索3 个以上模型采用坐标轮换一致性优化每次固定其他系数、只优化一个def coordinate_wise_search(base_weights, coord_idx, candidates, all_responses_fn, delta0.1): Optimize one coefficient at a time, holding others fixed. best_score -1 best_alpha base_weights[coord_idx] for alpha in candidates: weights base_weights.copy() weights[coord_idx] alpha # Normalize if weights should sum to 1 weights [w / sum(weights) for w in weights] responses all_responses_fn(weights) score generation_consistency_from_responses(responses, delta) if score best_score: best_score score best_alpha alpha return best_alpha, best_score注意coordinate_wise_search是示意性代码——它调用的all_responses_fn对给定权重向量执行合并与生成和generation_consistency_from_responses需要你用上文 Step 24 的构建块自行组装。六、端到端流水线将五个步骤封装为一个可复用的函数import numpy as np from typing import List, Dict def unsupervised_coefficient_search( model_a: str, model_b: str, eval_prompts: List[str], method: str slerp, candidates: List[float] None, delta: float 0.1, similarity_metric: str rougeL, output_root: str /tmp/merge_candidates, max_new_tokens: int 128, ) - Dict: Unsupervised coefficient search using generation consistency. Args: model_a: Path or HuggingFace ID of first model (or base model). model_b: Path or HuggingFace ID of second model. eval_prompts: Small set of unlabeled prompts (50-200 recommended). method: Merge method (slerp, task_arithmetic, ties). candidates: List of coefficient values to search over. delta: Step size for neighbor comparison. similarity_metric: rougeL, token_overlap, or bertscore. output_root: Directory to store temporary merged models. max_new_tokens: Max tokens to generate per prompt. Returns: dict with best_alpha, best_path, scores, all_responses. if candidates is None: candidates [round(x, 2) for x in np.arange(0.2, 0.9, 0.1).tolist()] os.makedirs(output_root, exist_okTrue) # Step 1-2: Merge all candidates merged_paths {} for alpha in candidates: merged_paths[alpha] merge_with_coefficient(alpha, model_a, model_b, output_root, method) # Step 3: Generate responses all_responses {} for alpha in candidates: all_responses[alpha] generate_responses(merged_paths[alpha], eval_prompts, max_new_tokens) # Step 4: Score consistency scores {} for alpha in candidates: scores[alpha] generation_consistency(alpha, all_responses, candidates, delta, similarity_metric) # Step 5: Select best best_alpha max(scores, keyscores.get) return { best_alpha: best_alpha, best_path: merged_paths[best_alpha], scores: scores, all_responses: all_responses, } # Usage result unsupervised_coefficient_search( model_amistralai/Mistral-7B-v0.1, model_bteknium/OpenHermes-2.5-Mistral-7B, eval_promptseval_prompts, # ~100 unlabeled prompts methodslerp, candidates[0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], ) print(fBest coefficient: {result[best_alpha]}) print(fBest model path: {result[best_path]})这个端到端函数与 SKILL.md 中给出的无监督调优伪代码一一对应——该 Skill 文档将本方法定位为手动调参之外的无标签替代方案并在 Best Practices 一节直接指向references/coefficient-tuning.md获取完整算法。七、实用技巧与陷阱数据集选择任意目标领域的无标签文本均可。通常 50 个样本就足够超过 200 个样本收益递减。步长 δ搜索网格步长为 0.1 时用δ 0.1若采用更细网格如步长 0.05δ应同步设为 0.05。边界候选位于alpha_min或alpha_max的候选只有一个邻居其分数是单侧的、易被低估。建议从最终选择中排除或扩大搜索范围。计算成本总开销为 N 次合并 N 次推理。推理是瓶颈建议使用贪心解码和短输出以提速。以 N7 个候选、100 条提示词为例单 GPU 上通常耗时 1030 分钟。与 evaluation.md 中的完整基准评测相比这种小样本快速筛选的成本几乎可以忽略非常适合作为正式评测前的系数预选步骤。一致性曲线平坦若曲线没有明显峰值说明两个模型过于相似或差异过大。此时应优先调整 TIES/DARE 的density/dropout 参数再重新搜索。八、总结与扩展阅读生成一致性方法将系数选择从人工试错 标注评测转变为无标签小样本 邻近一致性在 SLERP、Task Arithmetic、TIES、DARE 等主流合并方法上均可直接套用且天然支持多系数坐标轮换搜索。它特别适合 Agent 自动化的模型合并场景——正如本仓库的设计目标让 AI Agent 自主完成从合并到调优的全流程。本仓库中与该文档配套的深度资料模型合并 Skill 主文档含合并方法选型、YAML 配置结构、DARE-TIES 与 MoE 合并等进阶模式合并方法深度剖析TIES 的 TRIM/ELECT/MERGE 三步、DARE 的随机丢弃与重缩放数学推导真实合并配置示例Marcoro14-7B-slerp、goliath-120b、领域专家模型等案例合并模型评测指南基准套件、能力保持率与回归测试方法可用于验证本文选出的最优系数。方法出处本方法源自 Du et al.,AdaMMS: Model Merging for Heterogeneous Multimodal Large Language Models with Unsupervised Coefficient OptimizationCVPR 2025原文提出的核心思想即以生成一致性作为无监督代理在无标注数据、无需人工搜索的前提下自动选择合并系数。所需依赖可通过pip install rouge-score、pip install bert-score安装合并工具使用 mergekit 的mergekit-yaml命令行详见 SKILL.md 的安装小节。赞分享AI 技能人工智能大模型深度学习【免费下载链接】AI-Research-SKILLsComprehensive open-source library of AI research and engineering skills for any AI model. Package the skills and your claude code/codex/gemini agent will be an AI research agent with full horsepower. Maintained by Orchestra Research.项目地址https://gitcode.com/gh_mirrors/ai/AI-Research-SKILLs点击查看免费下载相关推荐Hugging Face Skills 实战基于 HF Jobs 的 SFT 监督微调与模型发布指南Hugging Face Skills 实战基于 HF Jobs 的 SFT 监督微调与模型发布指南 本指南以 apps/quests/04_sft fine人工智能AI 技能/插件大模型AI 评测Phoenix AI 可观测性平台实战指南基于 OpenTelemetry 的 LLM 追踪、评估与生产监控AI-Research-SKILLsPhoenix AI 可观测性平台实战指南基于 OpenTelemetry 的 LLM 追踪、评估与生产监控AI Research SKILLs PhoeAI 技能人工智能大模型深度学习HUGE 图嵌入模型实战指南基于 TPU 的海量无监督图嵌入训练google-research/graph_embedding/hugeHUGE 图嵌入模型实战指南基于 TPU 的海量无监督图嵌入训练google research/graph_embedding/huge 导读 本文围绕人工智能深度学习NLP计算机视觉强化学习创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考