「インテルCPU上での安定したディフューションモデルのファインチューニング」
Stable fine-tuning of diffusion models on Intel CPUs
拡散モデルは、テキストのプロンプトから写真のようなリアルな画像を生成するというその驚異的な能力によって、生成型AIの普及に貢献しました。これらのモデルは現在、合成データの生成やコンテンツ作成などの企業のユースケースに取り入れられています。Hugging Faceハブには、5,000以上の事前学習済みのテキストから画像へのモデルが含まれています。Diffusersライブラリと組み合わせることで、実験や画像生成ワークフローの構築がこれまで以上に簡単になりました。
Transformerモデルと同様に、Diffusionモデルをファインチューニングしてビジネスニーズに合ったコンテンツを生成することができます。初期のファインチューニングはGPUインフラストラクチャー上でのみ可能でしたが、状況は変わってきています!数か月前、インテルはSapphire Rapidsというコードネームの第4世代のXeon CPUを発売しました。Sapphire Rapidsは、ディープラーニングワークロードのための新しいハードウェアアクセラレータであるIntel Advanced Matrix Extensions (AMX)を導入しています。私たちはすでにいくつかのブログ記事でAMXの利点を実証しています:NLP Transformerのファインチューニング、NLP Transformerの推論、およびStable Diffusionモデルの推論。
この投稿では、Intel Sapphire Rapids CPUクラスター上でStable Diffusionモデルをファインチューニングする方法を紹介します。わずかな例の画像のみを必要とするテキスト反転という技術を使用します。たった5つの画像だけです!
さあ、始めましょう。
- 「PythonのリストとNumPyの配列:メモリレイアウトとパフォーマンスの利点についての詳細な調査」
- 「2023年7月のAIボイスチェンジャーツールのトップ10」
- フルスケールのゲームプレイ:「ドラゴンズドグマ:ダークアリズン」がGeForce NOWに登場
クラスターのセットアップ
Intelの友人たちが、最新のIntelプロセッサとパフォーマンス最適化されたソフトウェアスタックを使用したIntel®最適化デプロイメント環境でのワークロードの開発と実行を行うためのサービスプラットフォームであるIntel Developer Cloud(IDC)にホストされた4つのサーバーを提供してくれました。
各サーバーには、2つのIntel Sapphire Rapids CPUが搭載されており、物理コア数56個、スレッド数112個で動作しています。以下はlscpu
の出力です:
アーキテクチャ:x86_64
CPUの動作モード:32ビット、64ビット
アドレスサイズ:物理52ビット、仮想57ビット
バイトオーダー:リトルエンディアン
CPU数:224
オンラインCPUリスト:0-223
ベンダーID:GenuineIntel
モデル名:Intel(R) Xeon(R) Platinum 8480+
CPUファミリー:6
モデル:143
コアあたりのスレッド数:2
ソケットあたりのコア数:56
ソケット数:2
ステッピング:8
CPUの最大周波数:3800.0000
CPUの最小周波数:800.0000
BogoMIPS:4000.00
フラグ:fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_per fmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cat_l2 cdp_l3 invpcid_single intel_ppin cdp_l2 ssbd mba ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local split_lock_detect avx_vnni avx512_bf16 wbnoinvd dtherm ida arat pln pts hwp hwp_act_window hwp_epp hwp_pkg_req avx512vbmi umip pku ospke waitpkg avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq la57 rdpid bus_lock_detect cldemote movdiri movdir64b enqcmd fsrm md_clear serialize tsxldtrk pconfig arch_lbr amx_bf16 avx512_fp16 amx_tile amx_int8 flush_l1d arch_capabilities
まず、nodefile
内のサーバーのIPアドレスをリストアップしましょう。最初の行はプライマリサーバーを指します。
cat << EOF > nodefile
192.168.20.2
192.168.21.2
192.168.22.2
192.168.23.2
EOF
分散トレーニングにはプライマリと他のノード間でパスワードレスのssh
が必要です。プロセスに慣れていない場合、以下の記事が参考になります。
次に、各ノードで新しい環境を作成し、ソフトウェアの依存関係をインストールします。特に、Intelの2つのライブラリをインストールします。分散通信を管理するoneCCLと、Sapphire Rapidsに存在するハードウェアアクセラレーション機能を活用するためのIntel Extension for PyTorch(IPEX)です。また、高性能メモリ割り当てライブラリであるlibtcmalloc
をインストールするためにgperftools
も追加します。
conda create -n diffuser python==3.9
conda activate diffuser
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip3 install transformers accelerate==0.19.0
pip3 install oneccl_bind_pt -f https://developer.intel.com/ipex-whl-stable-cpu
pip3 install intel_extension_for_pytorch
conda install gperftools -c conda-forge -y
次に、各ノードでdiffusersリポジトリをクローンし、ソースからインストールします。
git clone https://github.com/huggingface/diffusers.git
cd diffusers
pip install .
次に、diffusers/examples/textual_inversion
内の微調整スクリプトにIPEXを追加します。IPEXをインポートし、U-NetとVariable Auto Encoderモデルを最適化します。すべてのノードに適用されていることを確認してください。
diff --git a/examples/textual_inversion/textual_inversion.py b/examples/textual_inversion/textual_inversion.py
index 4a193abc..91c2edd1 100644
--- a/examples/textual_inversion/textual_inversion.py
+++ b/examples/textual_inversion/textual_inversion.py
@@ -765,6 +765,10 @@ def main():
unet.to(accelerator.device, dtype=weight_dtype)
vae.to(accelerator.device, dtype=weight_dtype)
+ import intel_extension_for_pytorch as ipex
+ unet = ipex.optimize(unet, dtype=weight_dtype)
+ vae = ipex.optimize(vae, dtype=weight_dtype)
+
# We need to recalculate our total training steps as the size of the training dataloader may have changed.
num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps)
if overrode_max_train_steps:
最後のステップはトレーニング画像のダウンロードです。理想的には共有NFSフォルダを使用しますが、簡単のために各ノードに画像をダウンロードします。すべてのノードで同じディレクトリにあることを確認してください(/home/devcloud/dicoo
)。
mkdir /home/devcloud/dicoo
cd /home/devcloud/dicoo
wget https://huggingface.co/sd-concepts-library/dicoo/resolve/main/concept_images/0.jpeg
wget https://huggingface.co/sd-concepts-library/dicoo/resolve/main/concept_images/1.jpeg
wget https://huggingface.co/sd-concepts-library/dicoo/resolve/main/concept_images/2.jpeg
wget https://huggingface.co/sd-concepts-library/dicoo/resolve/main/concept_images/3.jpeg
wget https://huggingface.co/sd-concepts-library/dicoo/resolve/main/concept_images/4.jpeg
以下は画像です:
システムのセットアップが完了しました。トレーニングジョブの設定を行いましょう。
ファインチューニングジョブの設定
Accelerateライブラリを使用すると、分散トレーニングを非常に簡単に実行できます。各ノードで実行し、簡単な質問に答える必要があります。
ここでは、プライマリノードのスクリーンショットを示します。他のノードでは、ランクを1、2、3に設定する必要があります。その他の回答はすべて同じです。
最後に、プライマリノードで環境を設定する必要があります。これは、ファインチューニングジョブが開始されると他のノードに伝播されます。最初の行は、すべてのノードが実行されるローカルネットワークに接続されたネットワークインターフェースの名前を設定します。これには、適切な情報を取得するためにifconfig
を使用して適応する必要があるかもしれません。
export I_MPI_HYDRA_IFACE=ens786f1
oneccl_bindings_for_pytorch_path=$(python -c "from oneccl_bindings_for_pytorch import cwd; print(cwd)")
source $oneccl_bindings_for_pytorch_path/env/setvars.sh
export LD_PRELOAD=${LD_PRELOAD}:${CONDA_PREFIX}/lib/libiomp5.so
export LD_PRELOAD=${LD_PRELOAD}:${CONDA_PREFIX}/lib/libtcmalloc.so
export CCL_ATL_TRANSPORT=ofi
export CCL_WORKER_COUNT=1
export MODEL_NAME="runwayml/stable-diffusion-v1-5"
export DATA_DIR="/home/devcloud/dicoo"
ファインチューニングジョブを起動する準備が整いました。
モデルのファインチューニング
ノードリストに記載されたノード間で分散通信を設定するmpirun
を使用して、ファインチューニングジョブを起動します。16つのタスク(-n
)を4つのタスクごとに実行します(-ppn
)。Accelerate
は、すべてのタスクを対象に分散トレーニングを自動的に設定します。
ここでは、約5分かかる200ステップのトレーニングを行います。
mpirun -f nodefile -n 16 -ppn 4 \
accelerate launch diffusers/examples/textual_inversion/textual_inversion.py \
--pretrained_model_name_or_path=$MODEL_NAME --train_data_dir=$DATA_DIR \
--learnable_property="object" --placeholder_token="<dicoo>" --initializer_token="toy" \
--resolution=512 --train_batch_size=1 --seed=7 --gradient_accumulation_steps=1 \
--max_train_steps=200 --learning_rate=2.0e-03 --scale_lr --lr_scheduler="constant" \
--lr_warmup_steps=0 --output_dir=./textual_inversion_output --mixed_precision bf16 \
--save_as_full_pipeline
ビジーなクラスタのスクリーンショットです。
トラブルシューティング
分散トレーニングは難しい場合があります、特にこの分野に初めて取り組む場合は。単一ノードでのわずかな設定ミスが最も起こりやすい問題です:依存関係の不足、異なる場所に保存されたイメージなどです。
トラブルメーカーを素早く特定するには、各ノードにログインしてローカルでトレーニングを行います。まず、プライマリノードと同じ環境を設定し、次のコマンドを実行します。
python diffusers/examples/textual_inversion/textual_inversion.py \
--pretrained_model_name_or_path=$MODEL_NAME --train_data_dir=$DATA_DIR \
--learnable_property="object" --placeholder_token="<dicoo>" --initializer_token="toy" \
--resolution=512 --train_batch_size=1 --seed=7 --gradient_accumulation_steps=1 \
--max_train_steps=200 --learning_rate=2.0e-03 --scale_lr --lr_scheduler="constant" \
--lr_warmup_steps=0 --output_dir=./textual_inversion_output --mixed_precision bf16 \
--save_as_full_pipeline
トレーニングが正常に開始されたら、それを停止して次のノードに移動します。すべてのノードでトレーニングが正常に開始された場合は、プライマリノードに戻り、ノードファイル、環境、およびmpirun
コマンドを再確認してください。心配しないで、問題は見つかります 🙂
ファインチューニングされたモデルで画像を生成する
5分間のトレーニングの後、モデルはローカルに保存されます。私たちはバニラのdiffusers
パイプラインを使ってそれをロードし、予測することができます。しかし、代わりにOptimum IntelとOpenVINOを使用してモデルを最適化しましょう。前の投稿で説明したように、これにより単一のCPUで5秒未満で画像を生成することができます!
pip install optimum[openvino]
ここでは、モデルをロードし、静的な形状に最適化して保存します:
from optimum.intel.openvino import OVStableDiffusionPipeline
model_id = "./textual_inversion_output"
ov_pipe = OVStableDiffusionPipeline.from_pretrained(model_id, export=True)
ov_pipe.reshape(batch_size=5, height=512, width=512, num_images_per_prompt=1)
ov_pipe.save_pretrained("./textual_inversion_output_ov")
次に、最適化されたモデルをロードし、5つの異なる画像を生成して保存します:
from optimum.intel.openvino import OVStableDiffusionPipeline
model_id = "./textual_inversion_output_ov"
ov_pipe = OVStableDiffusionPipeline.from_pretrained(model_id, num_inference_steps=20)
prompt = ["a yellow <dicoo> robot at the beach, high quality"]*5
images = ov_pipe(prompt).images
print(images)
for idx,img in enumerate(images):
img.save(f"image{idx}.png")
以下は生成された画像です。モデルがdicoosがメガネをかけていることを学ぶのに5つの画像しか必要としなかったことは印象的です!
もしよければ、モデルをさらにファインチューニングすることもできます。ここでは、3,000ステップのモデル(約1時間のトレーニング)によって生成された素晴らしい例をご覧ください。
結論
Hugging FaceとIntelのおかげで、Xeon CPUサーバーを使用してビジネスニーズに適した高品質な画像を生成することができます。これらは、GPUなどの専用ハードウェアよりも一般的に手頃な価格で広く利用可能です。Xeon CPUは、ウェブサーバーからデータベースまで、他のプロダクションタスクに簡単に再利用できるため、ITインフラストラクチャの柔軟性に優れた選択肢です。
以下は始めるためのリソースです:
- Diffusersのドキュメント
- Optimum Intelのドキュメント
- Intel IPEXのGitHub
- IntelとHugging Faceの開発者リソース
- Intel Developer Cloud、AWS、およびGCP上のSapphire Rapidsサーバー
ご質問やフィードバックがあれば、Hugging Faceフォーラムでお待ちしております。
お読みいただきありがとうございました!
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles