編集者注:大規模言語モデル技術の急速な発展に伴い、モデル融合は低コストかつ高性能なモデル構築の新たなアプローチとなっています。本稿では、Maxime Labonneがmergekitライブラリを用いた4つのモデル融合手法(SLERP、TIES、DARE、passthrough)を解説します。設定例とケーススタディを通して、これらのアルゴリズムの原理と実用的な動作を詳細に解説します。 著者の主張の中心となるのは、完全に新しいモデルをトレーニングするのと比べて、既存のモデルを融合することで、より低い計算コストで同様またはより良い結果を達成できるという点です。 本稿では、モデル融合によって生成された高性能なMarcoro14-7B-slerpモデルを紹介します。このモデルは、Open LLMリーダーボードとNousResearchベンチマークの両方において、そのパラメータ範囲においてトップクラスのパフォーマンスを示しました。このケーススタディは、モデル融合の高い費用対効果に関する著者らの主張を裏付けています。しかしながら、モデル融合には、トレーニングデータの汚染や、様々なベンチマークリーダーボードにおけるスコアの過大評価といった限界もあります。本稿では、モデル融合の手法とエンジニアリング手法に関する詳細なガイドを提供し、AI実践者にとって貴重な知見を提供します。
著者 | マキシム・ラボンヌ 編纂者:岳陽 著者による画像 モデルマージとは、2つ以上の大規模言語モデル(LLM)を1つのモデルに統合する手法です。これは比較的新しい実験的なアプローチであり、低コスト(GPU不要)で新しいモデルを作成できます。驚くべきことに、この手法は非常に効果的であり、Open LLMリーダーボード[1]で多くの最先端モデルを生み出しています。 このチュートリアルでは、mergekit [2]ライブラリを用いてこの手法を実装します。具体的には、4つのモデル融合手法を概説し、関連する設定例を示します。その後、mergekitを用いて、Open LLMリーダーボード(2024年2月1日)で最高のパフォーマンスを示したモデル、Marcoro14–7B-slerp [3]を作成します。 関連するコードはGitHub[4]とNotebook[5]にアップロードされています。個人的には、mergekitを簡単に実行するためにLazyMergekit[6]プロジェクトの使用をお勧めします。 この記事をレビューしてくれたmergekitライブラリの作者であるCharles Goddard[7]に特に感謝します。 著者による画像 01 🤝 融合アルゴリズムこのセクションでは、mergekitライブラリに現在実装されている4つのモデル融合手法に焦点を当てます。他にも線形[8]やタスク算術[9]などの手法があることに注意してください。モデル融合に関する論文にご興味があれば、Hugging Face [10]に関する優れた論文集をお読みになることをお勧めします。 1.1 SLERP 球面線形補間(SLERP)は、2つのベクトル間の滑らかで一貫性のある補間手法です。この手法は、変化率を一定に保ち、ベクトルが存在する球面空間の幾何学的特性を維持します。 SLERPが従来の線形補間法よりも優れている理由はいくつかあります。例えば、高次元空間では、線形補間は補間ベクトルの大きさ(振幅)の減少(つまり重みの大きさの減少)につながる可能性があります。さらに、重みの方向の変化は、重みの大きさの変化よりも、より意味のある情報を表す場合が多いです(例えば、特徴学習や表現において)。 SLERP は次の手順で実装されます。 - 入力ベクトルは、その大きさが単位(1)になるように正規化されます。このステップにより、ベクトルは大きさではなく方向を表すことが保証されます。
- これらのベクトル間の角度はドット積を使用して計算されます。
- ベクトルがほぼ平行の場合、効率性を向上させるため、デフォルトで線形補間が使用されます。2つの入力ベクトル間の角度が大きい場合、SLERPは補間係数t(補間係数tは0から1の間の値で、補間の度合いを指定します。t=0は最初のベクトルのみを使用し、t=1は2番目のベクトルのみを使用し、0から1の間の値は2つのベクトルの混合度合いを表します)とベクトル間の角度に基づいてスケール係数を計算します。
- これらの係数は元のベクトルに重み付けするために使用され、その後合計されて補間ベクトルが得られます。
SLERPは現在最も人気のあるモデル融合手法ですが、一度に2つのモデルしか融合できません。しかし、Mistral-7B-Merge-14-v0.1[11]に示されているように、複数のモデルを階層的に融合することは可能です。 設定例: スライス:
- 出典:
- モデル: OpenPipe/mistral-ft-optimized-1218
レイヤー範囲: [0, 32]
- モデル: mlabonne/NeuralHermes-2.5-Mistral-7B
レイヤー範囲: [0, 32]
マージ方法: slerp
ベースモデル: OpenPipe/mistral-ft-optimized-1218
パラメータ:
t:
- フィルター: self_attn
値: [0, 0.5, 0.3, 0.7, 1]
- フィルター: mlp
値: [1, 0.5, 0.7, 0.3, 0]
- 値: 0.5
データ型: bfloat16 これは、モデルの各層にSLERPを適用して全体的なモデル融合を完了する、典型的なSLERP構成です。補間係数tには、一連の勾配値を入力することに注意してください。自己注意層とMLP層のパラメータには、OpenPipe/mistral-ft-optimized-1218[12]とmlabonne/NeuralHermes-2.5-Mistral-7B[13]の異なる組み合わせを使用します。 最終的に訓練されたモデルはHugging Face Hubのmlabonne/NeuralPipe-7B-slerp[14]で見つけることができます。 1.2 同点 TIES-Mergingは、Yadavらによって本論文[15]で導入されました。TIES-Mergingは、複数のタスク固有のモデルを単一のマルチタスクモデルに効率的に統合することを目的としています。これは、モデル融合における2つの主要な問題を解決します。 - モデルパラメータの冗長性:特定のタスクにおいて、モデル内の冗長なパラメータを識別し、排除することができます。具体的には、モデルのファインチューニングにおいて、モデルパラメータの変化に焦点を当て、ファインチューニング中に発生した変化を分類し、モデルのパフォーマンスに最も大きな影響を与える上位k%の変化を選択し、変化が少ない、またはパフォーマンスへの影響が小さい変化は無視します。
- モデルパラメータの符号に不一致が生じます。異なるモデルが同じパラメータに対して相反する調整を提案すると、矛盾が生じます。TIES-Mergingは、すべてのモデルにおいて最も重要な変化の方向を表す統一された符号ベクトルを作成することで、これらの矛盾を解決します。
TIES-Merging は次の 3 つのステップで構成されます。 - トリム: 最も重要なパラメータ (密度パラメータ) の一部のみを保持し、残りをゼロにリセットすることで、特定のタスク モデル内の冗長なパラメータを削減します。
- 選択符号: モデル内のどの変化の方向 (正または負) が最も重要または支配的であるかを識別することにより、異なるモデル間の符号の競合を解決するための統一された符号ベクトルが作成されます。
- 分離マージ:マージ処理では、以前に作成された統合シンボルベクトルと一致するパラメータ値のみが考慮され、これらの値の平均が計算されます。元のパラメータ値がゼロだったケースは、平均計算時に考慮されません。
SLERP とは異なり、TIES は複数のモデルを一度にマージできます。 設定例: モデル:
- モデル: ミストラライ/Mistral-7B-v0.1
# ベースモデルにはパラメータは必要ありません
- モデル: OpenPipe/mistral-ft-optimized-1218
パラメータ:
密度: 0.5
重量: 0.5
- モデル: mlabonne/NeuralHermes-2.5-Mistral-7B
パラメータ:
密度: 0.5
重量: 0.3
merge_method: タイ
ベースモデル: ミストラライ/ミストラル-7B-v0.1
パラメータ:
正規化: true
データ型: float16 この構成では、Mistral-7Bをベースモデルとして用いて差分重みを計算します。mistral-ft-optimized-1218(50%)[12]とNeuralHermes-2.5-Mistral-7B(30%)[13]の2つのモデルを融合し、正規化します。ここでの「density」パラメータは、各モデルのパラメータの50%のみを保持することを意味します(残りの半分はベースモデルから取得されます)。 設定内の重みの合計は1ではありませんが、normalize: trueパラメータによって内部的に自動的に正規化されることに注意してください。この設定は、OpenHermes-2.5-neural-chat-7b-v3-1-7B[16]の著者らが提供したパラメータに着想を得ています。 最終的に訓練されたモデルはHugging Face Hubのmlabonne/NeuralPipe-7B-ties[17]で見つけることができます。 1.3 挑戦 DARE[18]はYuら(2023)によって提案され、TIESと同様のアプローチを採用していますが、主に2つの違いがあります。 - プルーニング:DARE は、微調整された重みをランダムに元の値(ベース モデルの重み)にリセットします。
- 再スケーリング:DAREは、モデル出力の期待値がほぼ一定になるように重みを再スケーリングします。スケーリング係数を用いて、2つ(またはそれ以上)のモデルの再スケーリングされた重みをベースモデルの重みに加算します。
Mergekit はこのメソッドを、TIES を使用する (dare_ties) または TIES を使用しない (dare_linear) という 2 つの方法で実装します。 設定例: モデル:
- モデル: ミストラライ/Mistral-7B-v0.1
# ベースモデルにはパラメータは必要ありません
- モデル: サミールファマ/SamirGPT-v1
パラメータ:
密度: 0.53
重量: 0.4
- モデル: abacusai/Slerp-CM-mist-dpo
パラメータ:
密度: 0.53
重量: 0.3
- モデル: EmbeddedLLM/Mistral-7B-Merge-14-v0.2
パラメータ:
密度: 0.53
重量: 0.3
merge_method: dare_ties
ベースモデル: ミストラライ/ミストラル-7B-v0.1
パラメータ:
int8_mask: true
データ型: bfloat16 この設定例では、dare_tiesを使用して、Mistral-7Bに基づく3つの異なるモデルをマージしました。今回は重みの合計を1にしました(合計は0.9~1.1の範囲である必要があります)。密度パラメータは論文で提案されている値(<0.5)よりもわずかに高く設定されていますが、一貫してより良い結果が得られるようです(この議論[19]を参照)。 これはHugging Face Hubのmlabonne/Daredevil-7B[20]で見つけることができます。これは本論文で最も優れたマージモデルであり、Marcoro14-7B-slerpよりも優れています。 1.4 パススルーパススルー法は、これまでの手法とは大きく異なります。異なるLLMのモデル層を連結することで、通常とは異なるパラメータ数を持つモデルを生成できます(例えば、7Bパラメータのモデルを2つ組み合わせることで、9Bパラメータのモデルを生成できます)。これらのモデルは、「フランケンマージ」または「フランケンシュタインモデル」と呼ばれることがよくあります。 この技術は非常に実験的ですが、2つのLlama 2 70Bモデルを融合して作られたgoliath-120bなど、印象的なモデルの作成に成功しています。最近発表されたSOLAR-10.7B-v1.0でも同じアイデアが採用されており、論文ではこの技術は「深度アップスケーリング」と呼ばれています。 設定例: スライス:
- 出典:
- モデル: OpenPipe/mistral-ft-optimized-1218
レイヤー範囲: [0, 32]
- 出典:
- モデル: mlabonne/NeuralHermes-2.5-Mistral-7B
レイヤー範囲: [24, 32]
merge_method: パススルー
データ型: bfloat16 結果として得られるフランケンマージモデルには、最初のモデルの32層すべてと、2番目のモデルの8層が追加されます。これにより、合計40層、899億個のパラメータを持つフランケンマージが作成されます。この構成は、GML-Mistral-merged-v1[21]に触発されています。 最終モデルはHugging Face Hubのmlabonne/NeuralPipe-9B-merged [22]でご覧いただけます。 02 💻 独自のモデルを統合するこのセクションでは、mergekit ライブラリを使用してモデル フュージョン構成を読み込み、実行し、結果のモデルを Hugging Face Hub にアップロードします。 まず、次のようにソース コードから直接 mergekit をインストールします。 !git クローン https://github.com/cg123/mergekit.git
!cd mergekit && pip install -q -e . 以下のコードブロックでは、YAML形式のモデル融合設定を読み込みます。融合後のモデル名もここで指定しておき、後で使用します。前のセクションから任意の設定をコピー&ペーストできます。 今回は、Marcoroni-7B-v3[23]とMistral-7B-Merge-14-v0.1[24]という2つの異なるモデルを使用し、SLERP法を用いてモデルフュージョンを実行します。設定はyamlファイルとして保存され、model fusionコマンドの入力として使用されます。 yamlをインポートする
MODEL_NAME = "Marcoro14-7B-slerp"
yaml_config = """
スライス:
- 出典:
- モデル: AIDC-ai-business/Marcoroni-7B-v3
レイヤー範囲: [0, 32]
- モデル: EmbeddedLLM/Mistral-7B-Merge-14-v0.1
レイヤー範囲: [0, 32]
マージ方法: slerp
ベースモデル: AIDC-ai-business/Marcoroni-7B-v3
パラメータ:
t:
- フィルター: self_attn
値: [0, 0.5, 0.3, 0.7, 1]
- フィルター: mlp
値: [1, 0.5, 0.7, 0.3, 0]
- 値: 0.5
データ型: bfloat16
「」
# 設定をyamlファイルとして保存する
open('config.yaml', 'w', encoding="utf-8") を f として実行します:
f.write(yaml_config) モデル融合コマンドを実行するには、次のパラメータを使用します。 - –copy-tokenizer は、ベースモデルからトークナイザーをコピーするために使用されます。
- `--allow-crimes` オプションと `--out-shard-size` オプションを使用すると、モデルを小さなシャードに分割して、メモリが限られた CPU で計算を実行できるようになります。
- `--lazy-unpickle` オプションは、実験的な遅延 unpickler メカニズムを有効にして、メモリ使用量を削減します。
さらに、一部のモデルでは --trust_remote_code パラメータが必要になる場合があります (Mistral-7B では必要ありません)。 このコマンドは、モデル融合構成にリストされているすべてのモデルの重みをダウンロードし、選択したモデル融合方法を実行します (これには約 10 分かかります)。 # モデルをマージする
!mergekit-yaml config.yaml マージ --copy-tokenizer --allow-crimes --out-shard-size 1B --lazy-unpickl モデルはマージされ、マージディレクトリに保存されました。アップロードする前に、モデルのマージ操作を再現するために必要な情報を含むREADMEファイルを作成できます。次のコードブロックはJinjaテンプレートを定義し、モデルのマージ設定からデータを自動的に入力します。 !pip インストール -qU huggingface_hub
huggingface_hub から ModelCard、ModelCardData をインポート
jinja2からテンプレートをインポート
ユーザー名 = "mlabonne"
テンプレートテキスト = """
---
ライセンス: apache-2.0
タグ:
- マージ
- マージキット
- レイジーマージキット
{%- モデル内のモデル %}
- {{ モデル }}
{%- 終了 %}
---
# {{ モデル名 }}
{{ model_name }} は、[mergekit](https://github.com/cg123/mergekit) を使用して次のモデルをマージしたものです。
{%- モデル内のモデル %}
* [{{ モデル }}](https://huggingface.co/{{ モデル }})
{%- 終了 %}
## 🧩 設定
```yaml
{{- yaml_config -}}
「」
「」
# Jinjaテンプレートオブジェクトを作成する
jinja_template = テンプレート(template_text.strip())
# 設定からモデルのリストを取得する
データ = yaml.safe_load(yaml_config)
データ内に「models」がある場合:
models = [data["models"][i]["model"]、i が range(len(data["models"])) 内にある場合、"parameters" が data["models"][i]] 内にある場合
データ内のelif「パラメータ」:
models = [data["slices"][0]["sources"][i]["model"]、i が range(len(data["slices"][0]["sources"]))] 内の場合
elif はデータを「スライス」します:
models = [data["slices"][i]["sources"][0]["model"] for i in range(len(data["slices"]))]
それ以外:
例外を発生させます("yaml 設定にモデルまたはスライスが見つかりません")
# テンプレートに記入する
コンテンツ = jinja_template.render(
model_name=モデル名,
モデル=モデル、
yaml_config=yaml_config、
ユーザー名=ユーザー名、
)
# モデルカードを保存する
カード = ModelCard(コンテンツ)
card.save('merge/README.md') モデル カードができたので、フォルダー全体を HuggingFace Hub にプッシュできます。 google.colabからユーザーデータをインポートする
huggingface_hubからHfApiをインポート
ユーザー名 = "mlabonne"
# Google Colabのシークレットタブで定義されています
api = HfApi(トークン=userdata.get("HF_TOKEN"))
api.create_repo(
repo_id=f"{ユーザー名}/{モデル名}",
リポジトリタイプ="モデル"
)
api.upload_folder(
repo_id=f"{ユーザー名}/{モデル名}",
フォルダパス="マージ",
) このモデルは現在、Hugging Face Hubのmlabonne/Marcoro14–7B-slerp[25]で公開されています。別のノートブックでは、以下のコードを使って、無料のT4 GPUでこのモデルを実行してみることができます。 !pip install -qU トランスフォーマーを加速する
トランスフォーマーからAutoTokenizerをインポート
輸入変圧器
輸入トーチ
モデル = "mlabonne/Marcoro14-7B-slerp"
messages = [{"role": "user", "content": "大規模言語モデルとは何ですか?"}]
トークナイザー = AutoTokenizer.from_pretrained(モデル)
プロンプト = トークナイザー.apply_chat_template(
メッセージ、
トークン化=False、
add_generation_prompt=True
)
パイプライン = トランスフォーマー.パイプライン(
「テキスト生成」、
モデル=モデル、
torch_dtype=torch.float16、
device_map="自動",
)
出力 = パイプライン(プロンプト、max_new_tokens=256、do_sample=True、温度=0.7、top_k=50、top_p=0.95) LLM に「大規模言語モデルとは何か」という質問を投げかけたところ、次のような出力が得られました。 大規模言語モデルは、膨大な量のテキストデータで学習された人工知能(AI)システムの一種です。人間のような言語を理解し、生成するように設計されており、文や文書内で次にどのような単語やフレーズが続くかを予測します。これらのモデルは、複雑なアルゴリズムとニューラルネットワークアーキテクチャを用いてデータから学習し、時間の経過とともにパフォーマンスを向上させます。よく知られている大規模言語モデルには、OpenAIのGPT-3やGoogleのBERTなどがあります。 融合モデルは良さそうですが、より包括的な評価が必要です。このタイプの汎用モデルには、興味深いベンチマークがいくつかあります。 - Chatbot Arena[26]は、人間の投票によってLLMのリーダーボードを作成しています。人々が様々な言語モデルのパフォーマンスに投票し、Eloアルゴリズムを用いてこれらのモデルをランク付けします。
- MT-bench[26]はGPT-4を審査員として使用し、一連の複数ラウンドの質問に対するモデルの応答を評価します。
- NousResearchベンチマークスイート[27]は、AGIEVAL、GPT4ALL、TruthfulQA、Bigbenchの4つのベンチマークテストをコンパイルしています。GPT4ALLには、HellaSwag、OpenBookQA、Winogrande、ARC-Easy、ARC-Challenge、BoolQ、PIQAが含まれています。
- Open LLM Leaderboard[28]は、ARC、HellaSwag、MMLU、Winogrande、GSM8K、TruthfulQAの6つのベンチマークをまとめています。
残念ながら、このモデルをChatbot Arenaに提出することはできません。ただし、Open LLM LeaderboardとNousResearchベンチマークを使用して評価することは可能です。 このモデルをOpen LLMリーダーボード[28]に提出したところ、70億パラメータモデルの中で最高の評価を得ました。詳細のスクリーンショットを以下に示します。 著者による画像 Open LLMリーダーボードの問題は、これらのベンチマークが公開されていることです。つまり、テストデータを使って言語モデルを学習することで、より良い結果を得ることができるということです。これらの最良モデルを統合することで、モデルが汚染される可能性もあります。Marcoro14-7B-slerpは汚染されていたと断言できます。この統合に使用されたモデルの一部は、これらの評価テストセットで学習された可能性が高いです。リーダーボードで優れたパフォーマンスを発揮するモデルではなく、最高のモデルを作成したい場合は、非統合モデルのみを使用して独自の統合モデルを作成することをお勧めします。 そのため、Open LLM Leaderboardだけに頼ることはできません。NousResearchベンチマークスイートでは、🧐 LLM AutoEval [29] を使用して評価スコアを自動計算しました。以下は、高性能なOpenHermes-2.5-Mistral-7B [30]と比較した結果です。 著者による画像 このモデルと比較して、すべてのベンチマークで大幅な改善を達成しました。NousResearchベンチマークスイートは、Open LLM Leaderboard(ARC-Challenge、TruthfulQA、HellaSwag、Winogrande)と一部の評価タスクを共有している点にご注意ください。私の知る限り、Bigbenchは完全に異なる唯一のベンチマークです(そうでない場合は、元のリンクから著者にお問い合わせください)。ただし、このモデル融合に使用したモデルの1つは、Bigbenchの評価データセットで学習された可能性があります。 03 要約この記事では、LLMを融合する4つの異なる手法を紹介します。SLERP、TIES、DARE、パススルーの仕組みを詳しく説明し、関連する設定例を示します。最後に、SLERP法とmergekitライブラリを用いてMarcoro14–7B-slerpを学習し、Hugging Face Hubにアップロードしました。Open LLM Leaderboard(このリストで最も優れた7Bモデル)とNousResearchという2つのベンチマークスイートで優れたパフォーマンスを達成しました。 読んでくれてありがとう! 終わり
|