之前我写过一篇
Sakana也好,Jamba也罢,其实都是模型合并的一种比较好的项目实践,今天我们可以讨论一下普通开发者是否能像做一个项目一样,合并多个模型,达到自己想要的效果(GPU的连载后面写,东西太多,再给2篇也不知道能不能写完
)
不同于Sakana和Jamba,从头开始design模型的各个layer来进行合并,这种特别工程化的项目,大多数的开发者和小型团队,是不具备这样的能力的,说个最简单的,百分之99的人都不知道每一个层的权重分布到底是干啥的,这需要大量的实验数据和理论支撑。
如果不想像这两个项目做的这么细,其实也有现成的一些算法来支撑模型合并,其实最简单的就是两个同架构模型的权重做加权平均,有效果但是有限,比较好用的其他算法这里举两个例子。
SLERP:
这个大家应该不陌生,就是字面上的SLERP(Spherical linear interpolation),球面线性插值,一般插值可能平面就够了,但是带旋转,特别是向量方向太分散的LLM里面,肯定球面要好,描述要准(右图)
从线性代数的角度去琢磨这个事,如果两个单位四元数之间进行插值,左图的线性插值,得到的四元数一定不是单位四元数,旋转的插值应该等长的,所以显然右图球面插值更为合理。
基础理论就这样了,也没啥可说的。
模型的角度上操作
1- 模型1和模型2有两个权重(那必然是向量来表达)
2- 归一化成一个球面
3- 计算他们的夹角θ
4- 然后做加权求和,得到你要的新的插值向量
SLERP的特点,因为球面norm吗,所以合并贼平滑,也能最大化保留每个模型的独特的特征和能力。
但是它也只能合并2个模型,好几个一起,它不支持,属于1v1选手。
TIES:
传统的模型合并,如果是不同模型参数之间的合并,就会有干扰,尤其模型多了,干扰幅度就会大,这个也好理解,不同向量之间互相拉扯。
TIES解决了什么问题呢?
1- 首先它就是剪,它调出对模型影响最大的参数,小小不严的就干掉了,减少冗余。
2- 不同模型之间难免有参数冲突,它有个协商过程,确认哪些合并,冲突大的就不合并了
3- 最后确认了,才合并商定一致的参数(比如方向,符号)
TIES已被证明在各种设置下优于几种现有的merge方法。它有效地解决了干扰问题,尤其是符号干扰。增强了合并模型的整体性和稳定性。
我们拿两个模型印证一下合并。
本次我们用mergekit工具来做这个事
先配置yaml文件,做些基本配置
models:
/aml/merge/mistral7b # 基础模型
- model: /aml/merge/wizardmath7b #能力模型
parameters:
density: 0.5
weight:
- filter: mlp
value: 0.5
- value: 0
merge_method: ties #应用的方法
base_model: /aml/merge/mistral7b
parameters:
normalize: true
int8_mask: true
dtype: float16
开始合并
mergekit-yaml merge.yaml ./merge_mistal_math --allow-crimes --copy-tokenizer --out-shard-size 1B --write-model-card --lazy-unpickle --cuda
可以看到因为选择了TIES有冲突的它合不了的layer,都给你打印在log上了,这是TIES的特点。
合并完成的模型
现在就得到了一个拥有数学能力加强的mistral模型了
,全程没训练,因为我开了cuda,所以合并的更快,大概2分钟,如果你用CPU其实10分钟以内也能合并完毕了。