DeepSpeed-Chat トレーニング用のカスタム モデルとデータ

この記事では、DS-Chat コードで Facebook オプト以外の他の事前トレーニング済みモデルを使用する方法と、特定のドメインまたはアプリケーション向けに大規模なモデルをトレーニングするためにモデル トレーニング用のカスタム データを準備して使用する方法を説明します。

ビデオ アドレス: DeepSpeed-Chat は独自のモデルとデータを使用して ChatGPT をトレーニングします。

この章の主な内容は次のとおりです。

  • 実験設定の紹介: 今回の実験の設定とその理由を紹介し、AI技術を学ぶ際の参考にしていただければ幸いです。

  • モデルを置き換える方法: DS-Chat で使用される事前トレーニング済みモデルを置き換える方法と、独自の事前トレーニング済みモデルを DS-Chat に統合する方法を紹介します。

  • データの準備とデータの置き換え方法: モデルのトレーニングに必要なデータ形式、データ形式の変換など、独自のデータセットを準備する方法を紹介します。DS-Chat モデルのトレーニングで独自のデータセットを使用する方法。

上記の内容が、特定のアプリケーション シナリオにより適した大規模なモデルをトレーニングするために、DS-Chat でさまざまなモデルとデータ セットを使用する方法をより深く理解するのに役立つことを願っています。

現在、NLP 分野の多くのモデルと公開データが Huggingface で見つけることができます。DS-Chat ツールも Huggingface のモデルとデータを使用しています。したがって、この章の内容は主に Huggingface のモデルとデータに基づいています。

1 実験セットアップ: モデルとデータ

【ビデオ解説を見る】

この章の実験は主に LLMZoo を参照して設定されています。
GitHub - FreedomIntelligence/LLMZoo: ⚡LLM Zoo は、大規模な言語モデルのデータ、モデル、評価ベンチマークを提供するプロジェクトです。⚡

1.1 このモデルを選んだ理由は何ですか?

このモデルを選択した主な理由は 2 つあります。

  • モデルとデータは両方とも公開されており、関連記事が参照可能です。
  • このモデル (Phoenix-inst-chat-7b) は中国のデータに対して非常に優れたパフォーマンスを発揮します。

モデルやデータの公開、関連記事の紹介により、公開モデルの性能を最大限に再現することができ、運用が正しいかどうかの確認が容易になります。

このビデオの作成時点では、7B スケールの Phoenix-inst-chat-7b モデルは中国のデータで非常に優れたパフォーマンスを示しています。以下は著者らによる評価結果であり、ChatGPTやBaidu-Wenxinなどの非常に大規模なモデルとはある程度の差はあるものの、7Bパラメータスケールモデルにおいては依然として非常に優れたパフォーマンスを示していることがわかります。6B パラメータを使用した ChatGLM のパフォーマンスは優れているようですが、そのトレーニング データは公開されていません。

資格のある学生は、このモデルの再現を目指し、大規模モデルのトレーニング手法を学ぶことができます。

以下の表はGPT-4によるモデルの評価です。

モデル 比率
Phoenix-inst-chat-7b 対 ChatGPT 85.2%
Phoenix-inst-chat-7b 対 ChatGLM-6b 94.6%
Phoenix-inst-chat-7b vs. Baidu-Wenxin 96.8%
Phoenix-inst-chat-7b vs. MOSS-moon-003-sft 109.7%
Phoenix-inst-chat-7b vs. BELLE-7b-2m 122.7%
フェニックス-インスタント-チャット-7b vs. チャイニーズ-アルパカ-7b 135.3%
フェニックス-インスタント-チャット-7b vs. チャイニーズ-アルパカ-13b 125.2%

以下は手動評価の結果です

モデル 勝つ ネクタイ 失う
フェニックス vs. ChatGPT 12 35 53
フェニックス vs. チャットGLM-6b 36 11 53
フェニックス vs. バイドゥ・ウェンシン 29 25 46
フェニックス vs. BELLE-7b-2m 55 31 14
フェニックス vs. チャイニーズアルパカ-13b 56 31 13

1.2 事前トレーニング済みモデル

現在、LLMZoo でリリースされているモデルは 2 種類あります。主に中国に偏った Phoenix-inst-chat-7b モデルを指します。このモデルのトレーニングに使用される事前トレーニング モデルは、BLOOMZ-7b1-mt です。この 7B モデルは現在の OpenAI モデルよりもはるかに小さいですが、それでも非常に大規模なモデルです。このモデルをトレーニングするには、トレーニング用に数十の GPU が必要です。

学習の初期段階では、パラメーターの少ない BLOOMZ-560M モデルを使用することをお勧めします。このモデルは小さいですが、パラメーターを調整して継続的に最適化することで、LLM トレーニングの関連知識とスキルを効果的に学習できます。

この小さなモデルでコードがスムーズに実行された後、資格のある学生は、より多くのハードウェア リソースを使用して 7B スケールのモデルをトレーニングできるようになります。もちろん、複数のノードでトレーニングする方法を習得するには、現時点では DeepSpeed について詳しく知る必要があります。

関連する事前トレーニング済みモデルは次のとおりです。

  • BLOOMZ-7b1-mt: Phoenix-inst-chat-7b で使用される事前トレーニング済みモデル。Huggingface の名前は bigscience/bloomz-7b1-mt です。トレーニングには約 48 個の 32G GPU が必要です。
  • BLOOMZ-560M: 学習モデル、bigscience/bloomz-560m は、単一の 24G GPU でトレーニングできます。

参考: さまざまな構成に必要な GPU リソース:

モデル 最小GPU量 バッチサイズ バッチサイズ(デバイス) max_seq_len 状態
ブルームズ-7b1-mt 48(6x8,32g) 48×8×1 8 512 通常のトレーニング
ブルームズ-560m 1(32G) 2 2 512 通常のトレーニング

1.3 トレーニングデータ

LLMZoo のモデル トレーニング データは、FreedomIntelligence/phoenix-sft-data-v1 という名前で Huggingface で公開されています。このトレーニング データには、指示や会話の種類を含む合計 473,000 件のレコードが含まれています。このうち、指示型は 267,000 件、会話型は 198,000 件となっています。データは中国語 (113,000 レコード) や英語 (51,000 レコード) を含む複数の言語をカバーしており、合計 40 以上の言語が含まれています。

このデータをダウンロードします。次のリンクから直接ダウンロードできます:
https://huggingface.co/datasets/FreedomIntelligence/phoenix-sft-data-v1/resolve/main/data.json

データの詳細については、https: //arxiv.org/abs/2304.10453を参照してください。

2 代替機種

【ビデオ解説を見る】

DS-chat のデフォルトのトレーニングでは、Huggingface 形式に基づいたモデルとデータが使用されるため、Huggingface ベースの BLOOMZ モデルへの切り替えは非常に簡単で、model_name_or_path パラメーターを使用するモデルに変更するだけです。
注: モデル アーキテクチャとカプセル化クラスの影響により、Huggingface のすべてのモデルを直接使用できるわけではありません。たとえば、GLM モデルを DS-Chat で直接使用することはできません。

ここでは、BLOOMZ-560M モデルを例に、DS-Chat での BLOOMZ モデルの使用方法を紹介します。

以下は、  run1.3b.sh model_name_or_path を bigscience/bloomz-560m に変更して、この事前トレーニング済みモデルを使用するように変更されたスクリプトです。

deepspeed --num_gpus 1 main.py \
   --data_path Dahoas/rm-static \
   --model_name_or_path bigscience/bloomz-560m \
   --gradient_accumulation_steps 8 --lora_dim 128 --zero_stage $ZERO_STAGE \
   --per_device_train_batch_size 8 --per_device_eval_batch_size 8 \
   --deepspeed --output_dir $OUTPUT 2>&1 | tee $OUTPUT/training.log

注: 上記の設定のビデオ メモリは約 30G を消費します。per_device_train_batch_size と per_device_eval_batch_size を調整して、ビデオ メモリの使用量を減らすことができます。

モデルのインポートは 3 つの部分に分けることができます。

  • トークナイザーをインポートします: AutoTokenizer.from_pretrained(...)
  • model_config の入力: AutoConfig.from_pretrained(...)
  • モデルの入力: AutoModelForCausalLM.from_pretrained(...)

実装の詳細については、次のコードを参照してください。

from utils.model.model_utils import create_hf_model
tokenizer = AutoTokenizer.from_pretrained(args.model_name_or_path,
                                          fast_tokenizer=True)
model = create_hf_model(AutoModelForCausalLM,
                        args.model_name_or_path,
                        tokenizer,
                        ds_config,
                        disable_dropout=args.disable_dropout)

create_hf_model 関数の実装コードは次のとおりです。

def create_hf_model(model_class,
                    model_name_or_path,
                    tokenizer,
                    ds_config=None,
                    rlhf_training=False,
                    disable_dropout=False):
    model_config = AutoConfig.from_pretrained(model_name_or_path)
    if disable_dropout:
        model_config.dropout = 0.0
    # Note: dschf is defined in function scope to avoid global effects
    # https://huggingface.co/docs/transformers/main_classes/deepspeed#nontrainer-deepspeed-integration
    if ds_config is not None and ds_config["zero_optimization"]["stage"] == 3:
        dschf = HfDeepSpeedConfig(ds_config)
    else:
        dschf = None
    if rlhf_training:
        # the weight loading is handled by create critic model
        model = model_class.from_config(model_config)
    else:
        model = model_class.from_pretrained(
            model_name_or_path,
            from_tf=bool(".ckpt" in model_name_or_path),
            config=model_config)

    model.config.end_token_id = tokenizer.eos_token_id
    model.config.pad_token_id = model.config.eos_token_id
    model.resize_token_embeddings(int(8 *math.ceil(len(tokenizer) / 8.0)))  
    # make the vocab size multiple of 8

    return model

BLOOMZ シリーズのモデルを使用する場合、モデルのインポート コードを変更する必要はありません。ただし、GLM など他のモデルを使用している場合は、DS-Chat でモデルを直接インポートできないため、上記のコードを調整する必要があります。

よくある問題:

  • トレーニング中にメモリ不足が発生します:
    対策: バッチサイズを減らします。パラメーターを追加したり --per_device_train_batch_size 1 --per_device_eval_batch_size 1
    、パラメーターを変更したりできます。--max_seq_len 255

  • Huggingface からダウンロードされたモデル、ローカル保存場所:
    デフォルトの場所は次の~/.cache/huggingface/hub ディレクトリです。

  • 独自のモデルを使用するには?
    パラメータを model_name_or_path ローカル パスに設定するだけです。
    モデル フォルダーに  2 つのファイル「tokenizer_config.json と 」があるかどうかを確認する必要があることに注意してください (DS-Chat はモデルを保存するときにこれら 2 つのファイルを保存しません)。tokenizer.json

3 データを置き換える

【ビデオ解説を見る】

大規模モデルの重要な開発作業は、タスク固有のデータを使用してモデルをさらに最適化することです。通常、関連タスクのデータを使用して最適化されたモデルは、ターゲット タスクでのパフォーマンスが向上します。DS-Chat ツールでのモデル トレーニングに独自のデータを使用する手順は、次の 3 つの手順に分けることができます。

  1. データを準備し、JSON 形式などの特定の形式でデータを整理します。
  2. data_utils.py と raw_datasets.py のコードを変更して、新しいデータのサポートを追加します。
  3. トレーニング シェル スクリプトで新しいデータを設定し、モデルのトレーニングを開始します。

3.1 データの準備方法

データを準備する前に、まずモデルのトレーニングに必要なデータ形式を理解する必要があります。raw_datasets.py コードを見ることで、トレーニング中に使用されるデータ形式を理解できます。以下は、コードに実装されたデータ読み取りタイプの 1 つの例です。

class HelloSimpleAIHC3ChineseDataset(PromptRawDataset):
    def get_prompt(self, sample):
        if sample['question'] is not None:
            return " Human: " + sample['question'] + " Assistant:"
        return None

    def get_chosen(self, sample):
        if sample['human_answers'][0] is not None:
            return " " + sample['human_answers'][0]
        return None

    def get_prompt_and_chosen(self, sample):
        if sample['question'] is not None and sample['human_answers'][
                0] is not None:
            return " Human: " + sample['question'] + " Assistant: " + sample[
                'human_answers'][0]
        return None

    def get_rejected(self, sample):
        ...
    def get_prompt_and_rejected(self, sample):
        ...

上記のコードから、このデータには 3 つのデータ形式 (プロンプト、回答、拒否) と、それらの組み合わせ (プロンプト + 回答およびプロンプト + 拒否) があることがわかります。したがって、訓練データの最も基本的な内容は、即時、回答、拒否です。

次に、data_utils.py ファイルの 141 行目から学びます。

  • ステージ 1 では、get_prompt_and_chosen() を呼び出してトレーニング データを読み取ります。したがって、ステージ 1 のトレーニングを実行する場合は、プロンプトと回答を準備する必要があります。

  • ステージ 2 では、get_prompt_and_chosen と get_prompt_and_rejected が呼び出され、報酬モデルをトレーニングするためのデータが読み取られます。つまり、この部分にはプロンプト、回答、および拒否されたデータが必要です。

  • ステージ 3 では get_prompt のみが呼び出されるため、ステージ 3 のトレーニングを実行するにはプロンプトのみが必要です。

LLMZoo モデルでのモデルのトレーニングはステージ 1 と似ているため、準備する必要があるデータにはプロンプトと回答が含まれているだけです。

データの読み取りを容易にするために、phoenix-sft-data-v1 データをフォーマットしました。以下はそのデータの JSON の例です。

[
  {
    "id": "0",
    "type": "Instruction",
    "from_human": "假设你是一位Airbnb房主。... \n",
    "from_gpt": "很抱歉,作为AI语言模型,我无法检查您的Airbnb列表。"
  },
  {
    "id": "1",
    "type": "Instruction",
    "from_human": "假设你是一位翻译。... \n",
    "from_gpt": "\"Al dente\" means cooking the ..."
  }
]

このうち、from_human はプロンプト、from_gpt はアンサーです。次に、独自のデータがある場合は、上記の形式に従ってデータを準備できます。

3.2 データを読み取るようにコードを変更する

【ビデオ解説を見る】

次に、カスタム データを読み取るためにコードを変更する方法について説明します。DS-Chat は複数の形式でデータ読み取りメソッドを提供し、独自のデータ形式に似たデータ読み取りクラスを選択して変更できます。または、いずれかの形式を直接選択し、その形式に合わせてデータを準備することで、コードの修正量を減らすことができます。

コードの変更には次のものが含まれます (変更プロセスについてはビデオを参照してください)。

  • data_utils.pyの新しいコンテンツ
    : 新しいデータ クラスのオブジェクトとインターフェイスを定義する必要があります。
  • raw_datasets.pyの新しいコンテンツ
    : 新しいデータ読み取りクラスを定義します。load_dataset のローカル データ読み取りメソッド: self.raw_datasets =load_dataset(path="/home/data/", data_files="yourData.json")。
  • Run1.3b.sh
    の変更: 独自のデータベース名を使用するように設定します。

モデルのトレーニング プロセス中に、データベース名を使用して data_utils.py のデータ読み取りクラスを呼び出すことによって、データ読み取りオブジェクトが初期化されます。次に、raw_datasets.py ファイル内で、load_dataset が初めて呼び出されるときに、load_dataset は JSON ファイルを arrow 形式に変換し、cache_dir ディレクトリにキャッシュします。次回データが再度読み取られるとき、キャッシュされた arrow ファイルが直接読み取られます。

注:
分散トレーニングを使用している場合は、最初に単一の GPU プロセスを使用してデータ部分をキャッシュすることをお勧めします。これは、分散トレーニング中に、特にデータ量が比較的大きい場合に、複数のプロセスがデータをキャッシュするとエラーが発生する可能性があるためです。状況。

また、DS-Chat はデータに対して 2 番目のローカル データ キャッシュを実行するため、ハード ドライブ上の追加のストレージ スペースを占有する可能性があることにも注意してください。また、この方法は、データ量が比較的大きい場合には、過剰なメモリ消費にもつながります。この問題は現在正式に解決中です。具体的な情報については、以下のリンクを参照してください。学習フェーズでは、少数のサンプルを使用するか、マルチ GPU トレーニングを使用して、この問題を軽減できます。
機能リクエスト: LazyPromptDataset を DeepSpeedChat に追加 · 問題 #450 · microsoft/DeepSpeedExamples · GitHub

データ呼び出し処理
次にコード修正処理を行います。コードを変更する場合は、次の呼び出しプロセスを参照して変更を加えることができます。

- File: step1_supervised_finetuning/main.py: 
  - Line 224 (train_dataset, eval_dataset = create_prompt_dataset() 
    - File: /training/utils/data/data_utils.py
      - Line 268: train_dataset, eval_dataset = create_dataset()
      - Line 212: raw_dataset = get_raw_dataset()
        - Line 20:def get_raw_dataset(): 
            return raw_datasets.Wangrui6ZhihuKOLDataset()
            - File: training/utils/data/raw_datasets.py
              - Line 307: class Wangrui6ZhihuKOLDataset(PromptRawDataset)
      
      - Line 220: train_dataset = create_dataset_split()
        - Line 141: if train_phase == 1:
            chosen_sentence = raw_dataset.get_prompt_and_chosen()

よくある問題

  • Q/A 1: エラー例外: 現在の損失スケールはすでに最小になっています - これ以上スケールを減らすことはできません 実行を終了しています
    問題の説明: トレーニング プロセス中に、上記のエラーが発生する場合があります。この問題は通常、モデルのトレーニングが不安定であることが原因で発生するため、トレーニングの安定性を高めるためにバッチ サイズを増やすことをお勧めします。バッチ サイズを増やすと、ビデオ メモリの使用量が増加します。別の方法としては、複数の GPU を使用するか、gradient_accumulation_steps を設定して、バッチ サイズを増やす効果を得ることができます。
    それでも問題が解決しない場合は、float32 を使用してみてください (通常は nan エラーの場合)。

  • Q/A 2: DS-Chat プログラムの一時データの削除に注意してください
    。デフォルトでは、次のようなデータが複数回キャッシュされます。

    • Huggingface のマップ操作などのデータのキャッシュでは、データが自動的にキャッシュされます (プログラムの変更により再キャッシュが発生する可能性があるため、古いキャッシュ ファイルを削除するように注意してください)。
    • load_dataset は、json データを arrow データ形式に自動的にキャッシュします。
    • DS-Chat はデータをローカル マシンにキャッシュします: traindata-xxxx.pt  evaldata-xxx.pt ファイルはローカル マシンの /tmp/data_files/ ディレクトリにあり、データ インデックス ファイル (*.npy) も含まれています。
  • Q/A 3: 分散トレーニング中のデータ読み取りエラー
    データのload_dataset部分を単一のGPUで個別に実行し、基本的なデータ処理をキャッシュしてからマルチノード分散トレーニングを開始することをお勧めします。

  • Q/A 4: データ量が多い場合、マシンのメモリ使用量を削減し、
    データを適切に分割する方法 (対応するコードの調整が必要)。
    動的呼び出しが使用できます。公式の解決策は解決中です。最新の進捗状況については、以下のリンクを参照してください:機能リクエスト: LazyPromptDataset を DeepSpeedChat に追加 · 問題 #450 · Microsoft/DeepSpeedExamples · GitHub

  • Q/A 5: ローカル データが変更された後、再トレーニングすると、データは変更前と同じままになります。これは、
    DS-Chat のデータ キャッシュが原因です。ローカル上のキャッシュ ファイルを手動で削除する必要があります。 machine:
    デフォルトのキャッシュ ディレクトリ: /tmp /data_files/、このディレクトリを削除してトレーニングを再開できます。

参考文献

おすすめ

転載: blog.csdn.net/chaishen10000/article/details/131311777