模型合并技术实践:融合多个模型的智慧
引言 你有一个擅长编程的模型和一个擅长数学的模型,能不能得到一个两者都擅长的模型?模型合并(Model Merging)就是解决这个问题——将多个专门化模型的能力融合到一个模型中。 2026年,模型合并已经成为构建通用模型的重要技术。 一、合并方法 1.1 简单权重平均 def simple_average(models): """简单权重平均""" avg_state = {} for key in models[0].state_dict(): avg_state[key] = sum(m.state_dict()[key] for m in models) / len(models) return avg_state 简单但可能不是最优——不同模型的权重可能在不同方向上优化。 1.2 SLERP(球面线性插值) def slerp(t, v0, v1): """球面线性插值""" v0_norm = v0 / v0.norm() v1_norm = v1 / v1.norm() omega = torch.acos(torch.clamp(v0_norm @ v1_norm, -1, 1)) so = torch.sin(omega) if so < 1e-6: return (1-t)*v0 + t*v1 return torch.sin((1-t)*omega)/so * v0 + torch.sin(t*omega)/so * v1 def merge_slerp(model_a, model_b, t=0.5): """SLERP合并""" merged = {} for key in model_a.state_dict(): merged[key] = slerp(t, model_a.state_dict()[key], model_b.state_dict()[key]) return merged 1.3 TIES def ties_merge(models, base_model, density=0.5): """TIES合并: Trim, Elect Sign, Disjoint Merge""" # 1. 计算每个模型相对于base的delta deltas = [m.state_dict() - base_model.state_dict() for m in models] # 2. Trim: 只保留每个delta中top-k的参数 for delta in deltas: for key in delta: threshold = torch.quantile(delta[key].abs(), 1 - density) delta[key] = torch.where(delta[key].abs() > threshold, delta[key], 0) # 3. Elect Sign: 投票决定每个参数的符号 merged = {} for key in base_model.state_dict(): signs = sum(torch.sign(d[key]) for d in deltas) elected_sign = torch.sign(signs) # 4. Disjoint Merge: 只保留与选举符号一致的delta,取平均 consistent = [] for delta in deltas: mask = torch.sign(delta[key]) == elected_sign consistent.append(torch.where(mask, delta[key], 0)) merged[key] = base_model.state_dict()[key] + sum(consistent) / max(1, sum(elected_sign != 0)) return merged 1.4 DARE def dare_merge(model_a, model_b, base_model, drop_rate=0.9): """DARE: Drop And REscale""" delta_a = model_a.state_dict() - base_model.state_dict() delta_b = model_b.state_dict() - base_model.state_dict() merged = {} for key in base_model.state_dict(): # 随机丢弃大部分delta mask_a = (torch.rand_like(delta_a[key]) > drop_rate).float() mask_b = (torch.rand_like(delta_b[key]) > drop_rate).float() # 重新缩放 dropped_a = delta_a[key] * mask_a / (1 - drop_rate) dropped_b = delta_b[key] * mask_b / (1 - drop_rate) # 合并 merged[key] = base_model.state_dict()[key] + dropped_a + dropped_b return merged 二、层级合并 不同层使用不同的合并策略: ...