“ 从去年12月份开始融合的模型就疯狂刷榜,medium上一个老哥写了个博客,可以学习一下了,本文不全是翻译,因为原博客没有覆盖所有的mergekit算法
https://towardsdatascience.com/merge-large-language-models-with-mergekit-2118fb392b54
https://github.com/cg123/mergekit
https://arxiv.org/pdf/2306.01708.pdf
TIES-Merging 方法解决了模型融合过程中的两个主要问题:
- 冗余参数值的干扰(Interference from Redundant Parameters): 在微调过程中,许多模型参数可能会发生变化,但这些变化对模型性能的影响可能非常小。当合并这些模型时,这些冗余的参数值可能会干扰那些对性能有显著影响的参数。TIES-Merging 通过修剪这些冗余参数值来减少这种干扰,从而保留那些对性能有实质性贡献的参数。
- 参数符号不一致的干扰(Interference from Sign Disagreement): 不同的微调模型可能会对同一参数产生相反的更新(即正负号不一致)。简单地对这些参数值进行平均可能会导致性能下降,因为合并后的参数值可能无法正确反映任何单一模型的更新方向。TIES-Merging 通过Elect每个参数的最终符号来解决这个问题,确保合并后的参数值在所有模型中保持一致的符号方向。
TIES-Merging分为以下三个步骤:
- 修剪(Trim): 在这一步中,TIES-Merging 对于每个任务的参数变化(任务向量)进行修剪,只保留那些在微调过程中变化幅度较大的参数值。具体来说,它会根据参数值的大小来保留前k%的参数,并将剩余的参数值重置为0(或恢复到预训练模型的初始值)。这样,可以消除那些对性能影响不大的冗余参数,减少它们在合并过程中可能带来的干扰。
- 选举(Elect): 在修剪参数后,可能会存在一些参数在不同模型中具有相反的符号(正负号不一致)。为了解决这个问题,TIES-Merging 会创建一个聚合的选举符号向量,这个向量会根据每个参数在不同模型中总的正负方向变化来决定最终的符号。对于每个参数,它会计算所有模型中该参数值的总和(正向和负向),然后选择总和绝对值较大的方向作为该参数的最终符号。
- 不相交合并(Disjoint Merge): 在确定了每个参数的最终符号后,TIES-Merging 会进行不相交合并。对于每个参数,它会计算那些与最终符号一致的模型的参数值的平均值。这样,只有那些在所有模型中都具有相同符号的参数值会被考虑在内,从而避免了符号不一致导致的干扰。
TIES一次可以合并多个模型,mergekit的configuration示例:
models:
- model: mistralai/Mistral-7B-v0.1
# no parameters necessary for base model
- model: OpenPipe/mistral-ft-optimized-1218
parameters:
density: 0.5
weight: 0.5
- model: mlabonne/NeuralHermes-2.5-Mistral-7B
parameters:
density: 0.5
weight: 0.3
merge_method: ties
base_model: mistralai/Mistral-7B-v0.1
parameters:
normalize: true
dtype: float16
Task Arithmetic 是一种模型编辑方法,它通过任务向量(task vectors)来调整预训练模型的行为。任务向量代表了从预训练模型到特定任务微调后模型的权重变化。这种方法允许通过简单的算术操作(如加法、减法和取反)来组合这些任务向量,从而实现模型行为的精确控制。以下是 Task Arithmetic 的核心流程:
- 任务向量创建:
- 对于每个任务,首先从预训练模型(如CLIP或T5)中初始化权重(记为θpre)。
- 然后,对模型进行特定任务的微调(fine-tuning),得到微调后的模型权重(记为θft)。
- 任务向量τ是由微调后的权重减去预训练权重得到的,即τ = θft - θpre。
- 任务向量操作:
- 取反(Negation):对任务向量τ取反(τnew = -τ),这会降低模型在目标任务上的性能,同时对控制任务的性能影响较小。
- 加法(Addition):将两个或多个任务向量相加(τnew = τ1 + τ2 + ...),这可以创建一个多任务模型,或者在单个任务上提高性能。
- 任务类比(Task Analogies):当任务之间存在类比关系(如“A is to B as C is to D”),可以通过组合三个任务的任务向量来提高第四个任务的性能,即使没有第四个任务的训练数据。
- 模型权重更新:
- 通过将任务向量与预训练模型的初始权重进行元素级加法操作(θnew = θpre + λτnew),其中λ是一个可调整的缩放因子,来更新模型权重。
- 缩放因子λ通常通过验证集来确定,以确保合并后的模型在验证集上的性能。
- 性能评估:
- 在目标任务和控制任务上评估模型的性能,以确保编辑操作(如忘记特定任务或提高多任务性能)是有效的。
球面线性插值(SLERP)是一种用于在两个向量之间平滑插值的方法。它保持恒定的变化速率,并保留向量所在的球面空间的几何特性。
有几个原因可以选择SLERP而不是传统的线性插值。例如,在高维空间中,线性插值可能会导致插值向量的大小减小(即减小权重的比例)。此外,权重方向的变化通常代表更有意义的信息(如特征学习和表示),而不是变化的大小。
slerp步骤如下:
- 将输入向量归一化为单位长度,确保它们表示的是方向而不是大小。
- 使用它们的点积计算这些向量之间的角度。
- 如果向量几乎共线,为了效率,默认为线性插值。否则,根据插值因子 t(t=0 表示 100% 使用第一个向量,t=1 表示 100% 使用第二个向量)和向量之间的角度,计算 SLERP 的比例因子。
- 这些因子用于加权原始向量,然后求和以获得插值向量。
SLERP目前是最热的合并方法,但它只能一次合并两个模型。
slices:
- sources:
- model: OpenPipe/mistral-ft-optimized-1218
layer_range: [0, 32]
- model: mlabonne/NeuralHermes-2.5-Mistral-7B
layer_range: [0, 32]
merge_method: slerp
base_model: OpenPipe/mistral-ft-optimized-1218
parameters:
t:
- filter: self_attn
value: [0, 0.5, 0.3, 0.7, 1]
- filter: mlp
value: [1, 0.5, 0.7, 0.3, 0]
- value: 0.5
dtype: bfloat16
DARE(Drop And REscale)是一种用于减少语言模型(LMs)在监督微调(SFT)过程中产生的delta参数冗余的简单方法。在模型合并的上下文中,DARE作为一个预处理步骤,帮助整合多个任务特定的微调模型(SFT LMs)的参数,从而创建一个单一的模型,该模型具备所有微调模型的能力。以下是DARE在模型合并流程中的步骤:
- 应用DARE到每个微调模型:
- 对于每个基于相同预训练骨架的微调模型,首先应用DARE操作来减少delta参数的冗余。这包括随机丢弃一些delta参数(根据一个特定的丢弃率p),并将剩余的参数按比例1/(1-p)进行缩放。
- 合并参数:
- 使用DARE处理后的模型参数,可以采用现有的模型合并技术来整合这些参数。例如,可以使用平均合并(Average Merging)、任务算术(Task Arithmetic)、Fisher合并(Fisher Merging)、RegMean或TIES-Merging等方法。
- 创建合并模型:
- 通过上述合并方法,将多个任务特定的微调模型的参数合并成一个单一的模型。这个合并模型将继承所有原始模型的能力,而不需要额外的训练或GPU资源。
- 评估合并模型:
- 在合并模型完成后,可以在各种任务上评估其性能,以验证DARE在减少参数冗余和提高模型合并效果方面的有效性。
DARE的关键优势在于它能够在不显著影响模型性能的前提下,大幅减少delta参数的数量。这使得模型合并过程更加高效,因为合并后的模型可以更轻松地处理来自多个任务的输入,同时保持或甚至提高在这些任务上的性能。
models:
- model: mistralai/Mistral-7B-v0.1
# No parameters necessary for base model
- model: samir-fama/SamirGPT-v1
parameters:
density: 0.53
weight: 0.4
- model: abacusai/Slerp-CM-mist-dpo
parameters:
density: 0.53
weight: 0.3
- model: EmbeddedLLM/Mistral-7B-Merge-14-v0.2
parameters:
density: 0.53
weight: 0.3
merge_method: dare_ties
base_model: mistralai/Mistral-7B-v0.1
parameters:
int8_mask: true
dtype: bfloat16
Passthrough方法与之前的方法有显著的不同。通过连接来自不同LLM的层,它可以产生具有异类参数数量的模型(例如,使用两个7B参数模型构建9B模型)。社区经常将这些模型称为“frankenmerges”或“Frankenstein模型”。
slices:
- sources:
- model: OpenPipe/mistral-ft-optimized-1218
layer_range: [0, 32]
- sources:
- model: mlabonne/NeuralHermes-2.5-Mistral-7B
layer_range: [24, 32]
merge_method: passthrough
dtype: bfloat16