見出し画像

mergekit を使用してLLMをマージする

以下の記事が面白かったので、かるくまとめました。

Merge Large Language Models with mergekit


1. モデルのマージ

モデルのマージは、2つ以上のLLMを1つのモデルに結合する手法です。これは、新しいモデルを安価に作成するための比較的新しく実験的な方法です (GPUは必要ありません)。モデルのマージは驚くほどうまく機能し、 「Open LLM Leaderboard」に多くの最先端のモデルが生成されました。

このチュートリアルでは、「mergekit」を使用して独自のモデル「Marcoro14-7B-slerp」を作成します。このモデルは、「Open LLM Leaderboard」 (02/01/23) で最高のパフォーマンスを誇るモデルになりました。

コードは「GitHub」および「Google Colab」で入手できます。「mergekit」を簡単に実行するには、自動化されたノートブック「LazyMergekit」を使用することをお勧めします。

2. マージアルゴリズム

「mergekit」に実装されている、4つのマージアルゴリズムを紹介します。「linear」や「Task Arithmetic」など、他の手法もあることに注意してください。モデルのマージに関する論文に興味がある場合は、この優れたコレクションをおすすめします。

2-1. SLERP

SLERP」(Spherical Linear Interpolation) は、2つのベクトル間を滑らかに補間するために使用される方法です。一定の変化率を維持し、ベクトルが存在する球状空間の幾何学的特性を保存します。

従来の線形補間よりも「SLERP」を優先する理由はいくつかあります。たとえば、高次元空間では、線形補間により、補間されたベクトルの大きさが減少する可能性があります。さらに、重みの方向の変化は、多くの場合、変化の大きさよりも意味のある情報を表します。

「SLERP」の実装手順は、次のとおりです。

(1) 入力ベクトルを単位長に正規化し、大きさではなく方向を表すようにする。
(2) これらの内積を使用して、これらのベクトル間の角度を計算。
(3) ベクトルがほぼ同一線上にある場合、効率を高めるためにデフォルトで線形補間が行われる。それ以外の場合、「SLERP」は内挿係数t( t=0= 最初のベクトルの 100%、t=1= モデル2の100%) とベクトル間の角度に基づいてスケール係数を計算。
(4) これらの係数を使用して元のベクトルを重み付けし、それらを合計して補間されたベクトルを取得。

「SLERP」は現在最も一般的な結合方法ですが、一度に結合できるのは2つのモデルのみに制限されています。「Mistral-7B-Merge-14-v0.1」に示すように、複数のモデルを階層的に結合することは可能です。

・構成例

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

これは古典的な「SLERP」構成であり、両方のモデルのすべてのレイヤーに適用されます。補間係数 t の値の勾配を入力することに注意してください。セルフアテンションレイヤーとMLPレイヤーのパラメータでは、「OpenPipe/mistral-ft-optimized-1218」と「mlabonne/NeuralHermes-2.5-Mistral-7B」のさまざまな組み合わせが使用されます。他のレイヤーは2つのモデルを 50/50 で混合したものです。

最終モデルは、「mlabonne/NeuralPipe-7B-slerp」にあります。

2-2. TIES

Yadavらによってこの論文で紹介された「TIES」は、複数のタスク固有のモデルを1つのマルチタスクモデルに効率的にマージするように設計されています。これは、モデルの結合における2つの主要な課題に対処します。

・モデル パラメータの冗長性 : タスク固有のモデル内の冗長なパラメータを特定して削除。これは、ファインチューニング中に行われた変更に焦点を当て、上位k%の最も重要な変更を特定し、残りを破棄することによって実現。
・パラメータ記号間の不一致 : 異なるモデルが同じパラメータに対して反対の調整を提案する場合、矛盾が発生。「TIES-Merging」は、すべてのモデルにわたって最も支配的な変化の方向を表す統一された符号ベクトルを作成することで、これらの競合を解決。

「TIES」は次の3ステップに分かれています。

(1) Trim : 最も重要なパラメータ (密度パラメータ) の一部のみを保持し、残りをゼロにリセットすることにより、タスク固有のモデルの冗長性を削減。
(2) Elect Sign : 累積的な大きさの点で最も支配的な方向 (正または負) に基づいて統一された符号ベクトルを作成することにより、異なるモデル間での符号の競合を解決。
(3) Disjoint Merge : ゼロ値を除いて、統一符号ベクトルと一致するパラメータ値を平均。

「TIES」は一度に複数のモデルをマージできます。

・構成例

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

この構成では、デルタウェイトを計算するためのベースモデルとして「Mistral-7B」を使用します。同じ2つのモデル、「mistral-ft-optimized-1218」(50%) と「NeuralHermes-2.5-Mistral-7B」 (30%) を正規化してマージします。ここでの密度は、各モデルのパラメータの 50% のみを保持していることを意味します (残りの半分は基本モデルから取得されます)。

設定では重みの合計が1に等しくないことに注意してください。ただし、normalize: trueパラメータによって内部的に重みが自動的に正規化されます。この構成は、「OpenHermes-2.5-neural-chat-7b-v3-1-7B」の作成者によって提供されたパラメータからインスピレーションを得ています。

最終モデルは、「mlabonne/NeuralPipe-7B-ties」 にあります。

2-3. DARE

Yuらによって導入された「DARE」は、「TIES」に似たアプローチを用いているが、2つの主な違いがあります。

・Pruning : ファインチューニングされた重みをランダムに元の値 (ベース モデルの値) にリセット。
・Rescaling : DARE は、モデル出力の期待値をほぼ変更しないように重みを再スケーリング。両方 (またはそれ以上) のモデルの再スケーリングされた重みを、スケール係数を使用してベース モデルの重みに追加。

「mergekit」によるこのメソッドの実装には、「TIES」の符号選択ステップあり (dare_ties) となし (dare_linear) の2つの形式があります。

・構成例

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

この構成では、dare_tiesを使ってMistral-7Bに基づく3つの異なるモデルをマージします。今回は、合計が1になる重みを選びました (合計は0.9から1.1の間になるはず)。密度パラメータは論文で推奨されている値(<0.5)より少し高いが、その方が一貫して良い結果が得られるようです(この議論を参照)。

これは、「mlabonne/Daredevil-7B」で見つけることができます。これは、この記事の中で最高のマージ モデルでもあり、「Marcoro14-7B-slerp」よりも優れています。

2-4. Passthrough

「Passthrough」はこれまでのものとは大きく異なります。異なるLLMのレイヤーを連結することで、エキゾチックな数のパラメータを持つモデルを作り出すことができます (2つの7Bモデルで9Bモデルを作るなど)。このようなモデルは、しばしば「frankenmerges」または「Frankenstein models」と呼ばれています。

この手法は非常に実験的ですが、 2 つのLlama2-70B モデルを使用した「goliath-120b」のような印象的なモデルを作成することができました。最近リリースされた「SOLAR-10.7B-v1.0」も、論文で深度アップスケーリングと呼ばれる同じアイデアを使用しています。

・構成例

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

結果の「frankenmerge」には、最初のモデルの32レイヤーすべてと、2番目のモデルの8つの追加レイヤーが含まれます。これにより、合計40のレイヤーと8.99Bのパラメータを持つ「frankenmerge」が作成されます。この構成は「GML-Mistral-merged-v1」からインスピレーションを得ています。

最終モデルは、「mlabonne/NeuralPipe-9B-merged」にあります。

3. 独自モデルのマージ

はじめに、「mergekit」をインストールします。

!git clone https://github.com/cg123/mergekit.git
!cd mergekit && pip install -q -e .

次のブロックでは、マージ設定をyaml形式で読み込みます。前節の設定をここにコピー&ペーストできます。

今回は、 「Marcoroni-7B-v3」と「Mistral-7B-Merge-14-v0.1」の2つの異なるモデルを使用し、「SLERP」でマージします。

import yaml

MODEL_NAME = "Marcoro14-7B-slerp"
yaml_config = """
slices:
  - sources:
      - model: AIDC-ai-business/Marcoroni-7B-v3
        layer_range: [0, 32]
      - model: EmbeddedLLM/Mistral-7B-Merge-14-v0.1
        layer_range: [0, 32]
merge_method: slerp
base_model: AIDC-ai-business/Marcoroni-7B-v3
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
"""

# Save config as yaml file
with open('config.yaml', 'w', encoding="utf-8") as f:
    f.write(yaml_config)

次のパラメータを使用してマージを実行します。

・--copy-tokenizer : 基本モデルからトークナイザーをコピー
・--allow-crimes--out-shard-size : モデルを小さなシャードに分割し、RAM の少ないCPUで計算できるようにする。
・--lazy-unpickle : 実験的なlazy unpickleを有効にしてメモリ使用量を削減。

一部のモデルでは--trust_remote_codeが必要になる場合もあります (「Mistral-7B」では必要ありません)。

このコマンドは、マージ設定にリストされているモデルの重みをダウンロードし、マージを実行します (所要時間は約10分)。

# Merge models
!mergekit-yaml config.yaml merge --copy-tokenizer --allow-crimes --out-shard-size 1B --lazy-unpickle



この記事が気に入ったらサポートをしてみませんか?