mistral-finetune
は、Mistral モデルのメモリ効率とパフォーマンスの高い微調整を可能にする軽量コードベースです。これは、ほとんどの重みが凍結され、低ランクの行列摂動の形で追加の重みの 1 ~ 2% のみがトレーニングされるトレーニング パラダイムである LoRA に基づいています。
最大限の効率を得るには、A100 または H100 GPU を使用することをお勧めします。コードベースはマルチ GPU、単一ノードのトレーニング セットアップ向けに最適化されていますが、7B などの小規模なモデルの場合は 1 つの GPU で十分です。
注記
このリポジトリの目標は、Mistral モデルを微調整するためのシンプルでガイド付きのエントリポイントを提供することです。そのため、これはかなり意見が強く (特にデータ形式に関して)、複数のモデル アーキテクチャやハードウェア タイプにわたって網羅的であることを目的としていません。より一般的なアプローチについては、torchtune などの他の優れたプロジェクトをチェックしてください。
13.08.2024 : Mistral Large v2 がmistral-finetune
と互換性を持つようになりました。
他のモデルと比較して低い学習率を使用することをお勧めします。たとえば、lr=1e-6 はほとんどの場合に適切に機能します。
Mistral-Large v2 の微調整には、モデル サイズが大きいため、大幅に多くのメモリが必要になります。現時点では、 seq_len
8192 以下に設定します
ここから 123B 命令をダウンロードし、 model_id_or_path
ダウンロードしたチェックポイント ディレクトリに設定します。
19.07.2024 : ミストラル ニモは、 mistral-finetune
と互換性がありました。
7B v3 と同じハイパーパラメータを使用することをお勧めします。
Mistral-Nemo の微調整には、語彙サイズが大きくなり、CE 損失のピーク メモリ要件が急増するため、現在さらに多くのメモリが必要です (すぐに改善された CE 損失をここに追加します)。現時点では、 seq_len
16384 以下に設定します
pip install --upgrade mistral-common
実行して、Tekkenizer ( >=1.3.1
) をサポートするバージョンを取得します。
ここから 12B Base または Instruct をダウンロードし、 model_id_or_path
ダウンロードしたチェックポイント ディレクトリに設定します。
Mistral LoRA の微調整を開始するには、次の手順に従います。
このリポジトリのクローンを作成します。
cd $HOME && git clone https://github.com/mistralai/mistral-finetune.git
必要な依存関係をすべてインストールします。
cd mistral-finetune pip install -r requirements.txt
ここからダウンロードできる公式ミストラル モデルの 1 つを微調整することをお勧めします。
モデル | リンク | チェックサム |
---|---|---|
7BベースV3 | 7Bベース | 0663b293810d7571dad25dae2f2a5806 |
7B 命令 v3 | 7B 命令 v3 | 80b71fcb6416085bcb4efad86dfb4d52 |
8x7B ベース V1 | 8x7B ベース | (HFリンク) |
8x7B 命令 V1 | 8x7B 命令 | 8e2d3930145dc43d3084396f49d38a3f |
8x22 命令 V3 | 8x22 命令 | 471a02a6902706a2f1e44a693813855b |
8x22B ベース V3 | 8x22B ベース | a2fa75117174f87d1197e3a4eb50371a |
12B 指示する | 12B 指示(ミストラル・ニモ) | 296fbdf911cb88e6f0be74cd04827fe7 |
12Bベース | 12 ベース (ミストラル-ニモ) | c5d079ac4b55fc1ae35f51f0a3c0eb83 |
ミストラルラージ2 | 123B 命令 (大 v2) | fc602155f9e39151fba81fcaab2fa7c4 |
重要なお知らせ: 8x7B Base V1 および 8x7B Instruct V1 の場合、微調整する前に、v3 トークナイザーを使用して語彙サイズを 32768 に拡張する必要があります。このプロセスの詳細な手順については、「モデル拡張」セクションを参照してください。
たとえば、7B ベースのモデルをダウンロードするには、次のコマンドを実行できます。
mkdir -p ~/${HOME}/mistral_modelscd ${HOME} && wget https://models.mistralcdn.com/mistral-7b-v0-3/mistral-7B-v0.3.tar tar -xf misstral-7B-v0.3.tar -C misstral_models
必ずトレーニング スクリプトを変更し、ダウンロードしたフォルダーへのパスをmodel_id_or_path
として追加してください。
たとえば、 $HOME/mistral_models/7B
への絶対パスを含めるように example/7B.yaml を変更します。
model_id_or_path: "/Users/johndoe/mistral_models/7B"
効果的なトレーニングを保証するために、 mistral-finetune
はトレーニング データの形式に関する厳格な要件があります。
すべてのデータ ファイルは jsonl 形式のファイルで保存する必要があります。
次の 2 種類のデータ ファイルを構築できます。
事前学習データは、 "text"
キーに格納されているプレーン テキスト データに対応します。例えば:
{"テキスト": "ドキュメント n°1 に含まれるテキスト"} {"テキスト": "ドキュメント n°2 に含まれるテキスト"}
現在、データに続く 2 つの異なるタイプの命令がサポートされています。
Instruct : "messages"
キーにリスト形式で格納される会話データ。各リスト項目は、 "content"
キーと"role"
キーを含む辞書です。 "role"
は「user」、「assistant」、「system」のいずれかの文字列です。損失は、「役割」 == 「アシスタント」の場合にのみ計算されます。例えば:
{ "メッセージ": [ { "role": "user", "content": "ドキュメント n°1 に含まれるユーザー インタラクション n°1" }、 { "role": "アシスタント", "content": "ドキュメント n°1 に含まれるボット インタラクション n°1" }、 { "role": "user", "content": "ドキュメント n°1 に含まれるユーザー インタラクション n°2" }、 { "role": "アシスタント", "content": "ドキュメント n°1 に含まれるボット インタラクション n°2" } ] } { "メッセージ": [ { "role": "user", "content": "ドキュメント n°2 に含まれるユーザー インタラクション n°1" }、 { "role": "アシスタント", "content": "ドキュメント n°2 に含まれるボット インタラクション n°1" }、 { "role": "user", "content": "ドキュメント n°2 に含まれるユーザー インタラクション n°2" }、 { "role": "アシスタント", "content": "ドキュメント n°2 に含まれるボット インタラクション n°2", "weight": 0, # n°2 ではトレーニングしない }、 { "role": "user", "content": "ドキュメント n°2 に含まれるユーザー インタラクション n°3" }、 { "role": "アシスタント", "content": "ドキュメント n°2 に含まれるボット インタラクション n°3" } ] }
関数呼び出し: "messages"
キーにリスト形式で格納された会話データ。各リスト項目は、 "role"
と"content"
または"tool_calls"
キーを含む辞書です。 "role"
は「user」、「assistant」、「system」、「tool」のいずれかの文字列です。損失は、「役割」 == 「アシスタント」の場合にのみ計算されます。
注: 関数呼び出しでは、 "tool_calls"
の"id"
と"tool_call_id"
は、ランダムに生成された正確に 9 文字の文字列です。ここで行うように、データ準備スクリプトでこれを自動的に生成することをお勧めします。
例えば:
{ "メッセージ": [ { "role": "system", "content": "あなたは、ユーザーを支援するために次の機能にアクセスできる便利なアシスタントです。必要に応じて機能を使用できます。" }、 { "role": "user", "content": "「聞く」という単語のアナグラムを生成するのを手伝ってくれませんか?" }、 { "役割": "アシスタント"、"ツール呼び出し": [ { "id": "TX92Jm8Zi", "type": "function", "function": { "name": "generate_anagram", "arguments": "{"word": "listen"}" } } ] }、 { "role": "tool", "content": "{"anagram": "silent"}", "tool_call_id": "TX92Jm8Zi" }、 { "role": "アシスタント", "content": "単語「聞く」のアナグラムは「沈黙」です。" }、 { "role": "user", "content": "それはすごいですね! "race" という単語のアナグラムを生成できますか?" }、 { "役割": "アシスタント"、"ツール呼び出し": [ { "id": "3XhQnxLsT"、"type": "function"、"function": { "name": "generate_anagram"、"arguments": "{"word": "race"}" } } ] } ]、「ツール」: [ { "type": "function", "function": { "name": "generate_anagram", "description": "指定された単語のアナグラムを生成", "parameters": { "type": "object", " property": { "word": { "type": "string", "description": "アナグラムを生成する単語" } }, "必須": [ "単語" ] } } } ] }
トレーニングの実行を開始する前に、データセットが正しくフォーマットされていることを確認し、トレーニング時間の見積もりを取得する必要があります。これを行うには、./utils/validate_data スクリプトを使用します。
この手順は、データが正しくフォーマットされていることを確認するために重要であることに注意してください。
次の命令でモデルをトレーニングする簡単な例を見てみましょう。
Ultachat_200k のチャンクをロードする
データ フォルダーを作成し、そのフォルダーに移動します。
cd $HOME && mkdir -p data && cd $HOME/data
データを Pandas データフレームにロードします。
注: pandas と pyarrow がインストールされていることを確認してください ( pip install pandas pyarrow
)。
パンダを pddf = pd.read_parquet('https://huggingface.co/datasets/HuggingFaceH4/ultrachat_200k/resolve/main/data/test_gen-00000-of-00001-3d4cd8309148a71f.parquet') としてインポートします。
train と eval に分割
df_train=df.sample(frac=0.95,random_state=200)df_eval=df.drop(df_train.index)
データをjsonlに保存する
df_train.to_json("ultrachat_chunk_train.jsonl", orient="レコード", Lines=True)df_eval.to_json("ultrachat_chunk_eval.jsonl", orient="レコード", Lines=True)
トレーニング yaml を変更して、ultrachat データセットを含め、yaml を確認します。
example/7B.yaml を変更して、 $HOME/data/ultrachat_chunk_train.jsonl
への絶対パスと、トレーニング用のデータセット混合重みと評価用の$HOME/data/ultrachat_chunk_eval.jsonl
を含めます。
data: instruct_data: "/Users/johndoe/data/ultrachat_chunk_train.jsonl" eval_instruct_data: "/Users/johndoe/data/ultrachat_chunk_eval.jsonl"
これで、トレーニング yaml を検証して、データが正しくフォーマットされていることを確認し、トレーニング時間の推定値を取得できるようになりました。
cd $HOME/mistral-finetune python -m utils.validate_data --train_yaml example/7B.yaml
完了すると、次の多くのエラーを含むエラー レポートが表示されます。
The data in line 1412 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user The data in line 1413 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user The data in line 1414 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user The data in line 1415 of dataset /Users/johndoe/data/ultrachat_chunk_eval.jsonl is incorrectly formatted. Expected last role to be one of: [assistant] but got user
多くの会話は「ユーザー」ロールで終了するようですが、「アシスタント」メッセージでのみトレーニングするため、不必要にデータを処理することになるため、これは不必要です。
./utils/reformat_data.py を使用してデータを修正できます。
cd $HOME/mistral-finetune python -m utils.reformat_data $HOME/data/ultrachat_chunk_train.jsonl python -m utils.reformat_data $HOME/data/ultrachat_chunk_eval.jsonl
いくつかのサンプルがスキップされることがわかります。
トレーニングステップ数が変更される可能性があります
データセットを修正したら、スクリプトを再度実行します
cd $HOME/mistral-finetune python -m utils.validate_data --train_yaml example/7B.yaml
データ入力とトレーニング パラメーターの概要を取得する必要があります。
Train States -------------------- { "expected": { "eta": "00:52:44", "data_tokens": 25169147, "train_tokens": 131072000, "epochs": "5.21", "max_steps": 500, "data_tokens_per_dataset": { "/Users/johndoe/data/ultrachat_chunk_train.jsonl": "25169147.0" }, "train_tokens_per_dataset": { "/Users/johndoe/data/ultrachat_chunk_train.jsonl": "131072000.0" }, "epochs_per_dataset": { "/Users/johndoe/data/ultrachat_chunk_train.jsonl": "5.2" } }, }
max_steps
500 に設定すると、データセットを約 5 回反復することになりますが、これは妥当ですが、少し多すぎる可能性があります。 8xH100 クラスターで 30 分しかかからない推奨設定を以下に示します。
次に、関数呼び出しでモデルを微調整するためのより高度な使用例を見てみましょう。関数呼び出しでは、データが上で説明した形式である必要があります。例を見てみましょう。
Glaive 関数呼び出しデータセットのチャット形式バージョンをロードする
データ フォルダーを作成し、そのフォルダーに移動します。
cd $HOME && mkdir -p data && cd $HOME/data
データを Pandas データフレームにロードします。
注: pandas と pyarrow がインストールされていることを確認してください ( pip install pandas pyarrow
)。
import pandas as pddf = pd.read_parquet('https://huggingface.co/datasets/Locutusque/function-calling-chatml/resolve/main/data/train-00000-of-00001-f0b56c6983b4a78f.parquet')
train と eval に分割
df_train=df.sample(frac=0.95,random_state=200)df_eval=df.drop(df_train.index)
データをjsonlに保存する
df_train.to_json("glaive_train.jsonl", orient="レコード", Lines=True)df_eval.to_json("glaive_eval.jsonl", orient="レコード", Lines=True)
データセットを再フォーマットする
ご覧のとおり、データセットは必要な関数呼び出し形式に従っていないため、再フォーマットする必要があります。特に、 "from"
名前を"user"
に変更し、余分な"n"
文字を削除する必要があります。このデータセットでは、 ./utils/reformat_data_glaive.py
を利用できます。
cd $HOME/mistral-finetune python -m utils.reformat_data_glaive $HOME/data/glaive_train.jsonl python -m utils.reformat_data_glaive $HOME/data/glaive_eval.jsonl
このコマンドを実行すると、ほとんどのサンプルが正しい形式であることが確認されます。
注: すべての種類のデータセットに対して機能する再フォーマット スクリプトを作成することは不可能です。データセットが上記の必須形式に従っていない場合は、おそらく、再フォーマット スクリプトを自分で作成する必要があります (ここでは、mistral-chat または chat-gpt があなたの親友です!)。
データセットを検証する
これで、 example/7B.yaml
のdata.instruct_data
とdata.eval_instruct_data
$HOME/data/glaive_train.jsonl
と$HOME/data/glaive_eval.jsonl
にそれぞれ設定することで、データセットを検証できるようになりました。
再フォーマットされたデータセットにはまだエラーがいくつかありますが、 --create_corrected
で削除できます。このため、次のように--create_corrected
を必ず追加してください。
cd $HOME/mistral-finetune python -m utils.validate_data --train_yaml example/7B.yaml --create_corrected
このコマンドを実行すると、いくつかのエラーが表示され、2 つの新しいデータセット$HOME/data/glaive_train.jsonl.corrected
および$HOME/data/glaive_eval.jsonl.corrected
が保存されます。必ずexample/7B.yaml
内のこれら 2 つのデータセットを使用して、コマンドを再度実行してください。これで、データセットが正しくフォーマットされるはずです。
データセット検証セクションに従った後、トレーニングを開始できます。トレーニングを高速化するには、max_steps を 300 のみに設定することをお勧めします。必ずrun_dir
実験フォルダーに定義し、オプションでwandb_project
ログ用の Weights & Biases プロジェクトに設定してください。例:
max_steps: 300 run_dir: "/Users/johndoe/ultra_chat_test" wandb.project: ultra_chat
オプションで、 wandb
設定することもできます
トレーニング設定を保存してトレーニングを開始してください。 --nproc-per-node
使用可能な GPU の数に設定してください。
cd $HOME/mistral-finetune torchrun --nproc-per-node 8 --master_port $RANDOM -m train example/7B.yaml
ウルトラ チャットのトレーニングには 8xH100 ノードで約 30 分かかり、結果の重みにより MT ベンチ スコアは約 6.3 になるはずです。
glaive のトレーニングには 8xH100 ノードで約 1 時間かかり、結果として得られる重みは関数呼び出しに適切に機能するはずです。
サンプルのmistral-finetune/examples/7B
学習率、重み減衰などの適切なパラメータが定義されていますが、これらの設定をユースケースに合わせてカスタマイズすることをお勧めします。
通常、トレーニング設定には次のパラメータを入力する必要があります。
model_id_or_path
トレーニングを開始するモデルを定義します。これは、事前トレーニングされたモデルまたはローカル モデル ディレクトリへのパスにすることができます。
run_dir
トレーニング チェックポイントとメトリクスが保存されるディレクトリを定義します。
seq_len
トレーニング用のシーケンスの長さを定義します。これは、モデルが処理する入力シーケンスの最大長です。トレーニング効率を最大化するために、サンプルはseq_len
の長さに達するようにパックされます。
batch_size
GPU ごとに使用されるトレーニング サンプルの数を定義します。注: すべての GPU にわたる全体的な有効なbatch_size (トークン単位) は、 num_gpus
x batch_size
x seq_len
に等しくなります。
max_steps
トレーニング ステップの最大数を定義します。これは、トレーニング プロセスが実行される反復の合計数です。トレーニング シナリオの特定のニーズに基づいて調整できます。トレーニング中に確認されるトークンの総数は、 max_steps
x num_gpus
x batch_size
x seq_len
です。
optim.lr
学習率を定義します。これは、オプティマイザーの初期学習率です。
optim.weight_decay
重みの減衰を定義します。重み減衰は、大きな重みにペナルティを与えることで過学習を防ぐために使用される正則化手法です。 0.1 のままにすることをお勧めします。
optim.pct_start
学習率のウォームアップ フェーズで使用される合計トレーニング ステップのうち、学習率が減少し始める前の割合を定義します。 PyTorchのOneCycleLRのpct_startに相当します。
lora.rank
LoRA (Low-Rank Adaptation) アダプターのサイズを定義します。 LoRA で使用される低ランク分解のランクを調整する 64 以下を推奨します。
seed
初期化およびデータ シャッフル/サンプリング用のランダム シードを定義します。シードを設定すると、結果の再現性が保証されます。
log_freq
ロギングの頻度を定義します。これは、トレーニング メトリクスをログに記録する頻度 (ステップ単位) を指定します。
data.instruct_data
、トレーニングに使用される命令データへのパスです。このフィールドには、上で説明した形式で 1 つまたは複数のデータ ソースを入力する必要があります。各データ ソースは、jsonl ファイルへのパス、または jsonl ファイルを含むディレクトリへのパスのいずれかで、その後にこのデータセットの重要性を定義する重み付けが続く必要があります:
。例: data.instruct_data: "/path/to/data1.jsonl:5.,/path/to/data2.jsonl:1.,/path/to/dir_of_jsonls:1."
data.data
上で説明した形式の追加の事前トレーニング データへのオプションのパスです。このフィールドは空白のままにできることに注意してください。
data.eval_instruct_data
は、 eval_freq
ステップごとに相互検証を実行するための評価指示データへのオプションのパスです。相互検証メトリクスは、 loss
とperplexity
として表示されます。
eval_freq
、モデルを評価する頻度 (ステップ単位) を定義します。これは、検証セット上でモデルが評価される間隔を指定します。
no_eval
は中間評価を有効または無効にするフラグです。 False に設定すると、トレーニング中の定期的な評価が有効になります。
ckpt_freq
、チェックポイントを保存する頻度 (ステップ単位) を定義します。モデルの状態を保存する間隔を指定します。
save_adapters
、トレーニングされた LoRA チェックポイントのみを保存するか、トレーニングされた LoRA をベース モデルに直接マージして保存するかを定義します。注: save_adapters=False
を設定する場合は、モデル全体を 1 つのプロセスに保存するのに十分な CPU および GPU メモリがあることを確認してください (通常、これは 7B モデルでのみ可能です)。
wandb.key
ロギング用の Weights & Biases (wandb) API キーを渡すために使用されます。これにより、トレーニング メトリクスを wandb ダッシュボードに記録できるようになります。
wandb.project
wandb プロジェクト名を定義します。これは、トレーニングの実行が wandb インターフェイスに記録される場所です。
モデルがトレーニングされたら、推論で試してみる必要があります。ミストラル推論の使用をお勧めします。
mistral_inference
正しくインストールされていることを確認してください。
pip install mistral_inference
lora.safetensors
$HOME/ultra_chat_test/checkpoints/checkpoint_000300/consolidated/lora.safetensors
に保存されていると仮定すると、次のように、 mistral_inference
使用してモデルとチャットできます。
misstral-chat /mnt/slow/runs/patrick/mistral-finetune/7B/ --max_tokens 256 --temperature 1.0 --instruct --lora_path $HOME/ultra_chat_test/checkpoints/checkpoint_000300/consolidated/lora.safetensors
トレーニングの実行を監視および視覚化できるように、重みとバイアスの明示的なサポートが追加されました。この統合により、さまざまなメトリクスをログに記録し、実験を簡単に追跡できるようになります。
mistral-finetune
で重みとバイアスを使用するには、次の手順に従います。
ウェイトとバイアスをインストールします。
wandb
ライブラリがインストールされていることを確認してください。 pip を使用してインストールできます。
pip インストールワンデータベース
トレーニングが開始されたら、wandb プロジェクト ダッシュボードにアクセスして、進行状況をリアルタイムで監視できます。トレーニング損失、評価損失、学習率などを含むすべての指標がログに記録され、視覚化されます。
wandb の使用方法の詳細については、重みとバイアスのドキュメントを参照してください。
重要: v3 トークナイザーと互換性のあるミストラル モデルのみを微調整できることに注意してください。これにより、モデルの語彙サイズは 32000 ではなく 32768 になります。ただし、語彙サイズ 32000 の古いバージョンを簡単に拡張して、語彙サイズを持たせることはできます。以下を使用して 32768 の
python -m utils.extend_model_vocab --original_model_ckpt /folder/to/old/model --extended_model_ckpt /folder/to/extended/model
拡張機能が機能したら、 /folder/to/extended/model
に新しく作成されたモデル チェックポイントを使用して微調整できます。
MoE を微調整するベスト プラクティスは何ですか?
MoE モデルを微調整する場合、パフォーマンスのばらつきが大きくなることがわかります。異なるシードを使用して MoE モデルを微調整すると、パフォーマンスに大きなばらつきが生じる可能性があることは珍しいことではありません。密なモデルではそのような大きな分散は観察されませんでした。したがって、MoE モデルに対して同じ微調整プロセスの複数のインスタンスを実行し、最もパフォーマンスが高いものを選択することをお勧めします。
モデルのトレーニング プロセス中に使用されるトークンの数を確認するにはどうすればよいですか?
次のスクリプトを使用して確認できます: https://github.com/mistralai/mistral-finetune/blob/main/utils/validate_data.py。このスクリプトは、.yaml トレーニング ファイルを入力として受け取り、モデルがトレーニングされているトークンの数を返します。
CUDA のメモリ不足エラーが発生した場合はどうすればよいですか?
考えられる解決策の 1 つは、GPU あたりのバッチ サイズを減らすことです。バッチ サイズはseq_len
batch_size
に等しくなります。試しに、 batch_size
1 に設定し、 seq_len
減らしてください。 .yaml ファイルでbatch_size
とseq_len
定義できます。