# CogVideoX

CogVideoX は、プロンプトに沿った一貫性のある動画を生成することに特化したテキストから動画への変換モデルです。この目的を達成するために、いくつかの方法を用いています。

- 空間的・時間的に動画を圧縮し、圧縮率と動画の精度を向上させる3次元変分オートエンコーダー

- テキストと動画をアラインメントするために役立つエキスパートのtransformerブロックと、空間的・時間的に正確な動画をキャプチャおよび生成するための3Dフルアテンションモジュール。

動画指示次元の実際のテストでは、CogVideoXは、一貫したテーマ、動的な情報、一貫した背景、オブジェクト情報、滑らかなモーション、色、シーン、外観スタイル、時間的スタイルにおいて良好な効果を示す一方、人間のアクション、空間的な関係、複数のオブジェクトについては良好な結果を得られないことが判明しました。

Diffusersによるファインチューニングは、これらの不良な結果を補うのに役立ちます。

## データ準備

トレーニングスクリプトは、2つの形式のデータを受け入れます。

最初の形式は小規模なトレーニングに適しており、2番目の形式はCSV形式を使用しています。CSV形式は、大規模なトレーニングにおけるストリーミングデータにより適しています。今後、Diffusersは`<Video>`タグをサポートする予定です。

### 小規模なフォーマット

1つのファイルに改行区切りのプロンプトを、もう1つのファイルに改行区切りの動画データへのパス（`--instance_data_root`で指定するパスからの相対パスである必要があります）を格納する2つのファイルです。より理解を深めるために、例を見てみましょう。

`--instance_data_root` を `/dataset` に指定し、このディレクトリに `prompts.txt` と `videos.txt` が含まれていると仮定します。

`prompts.txt` ファイルには、改行で区切られたプロンプトを含める必要があります:

```
A black and white animated sequence featuring a rabbit, named Rabbity Ribfried, and an anthropomorphic goat in a musical, playful environment, showcasing their evolving interaction.
A black and white animated sequence on a ship's deck features a bulldog character, named Bully Bulldoger, showcasing exaggerated facial expressions and body language. The character progresses from confident to focused, then to strained and distressed, displaying a range of emotions as it navigates challenges. The ship's interior remains static in the background, with minimalistic details such as a bell and open door. The character's dynamic movements and changing expressions drive the narrative, with no camera movement to distract from its evolving reactions and physical gestures.
...
```

`videos.txt` ファイルには、動画ファイルへのパスを1行ずつ記載する必要があります。なお、パスは `--instance_data_root` ディレクトリからの_相対パス_である必要があります。

```
videos/00000.mp4
videos/00001.mp4
...
```

全体として、`tree` コマンドをデータセットのルートディレクトリで実行した場合、データセットは次のようになります。

```
/dataset
├── prompts.txt
├── videos.txt
├── videos
    ├── videos/00000.mp4
    ├── videos/00001.mp4
    ├── ...
```

この形式を使用する場合、`--caption_column` は `prompts.txt` であり、`--video_column` は `videos.txt` である必要があります。

### ストリーム形式

単一のCSVファイルを使用できます。この例では、`metadata.csv`ファイルがあるものとします。期待される形式は以下の通りです。

```
<CAPTION_COLUMN>,<PATH_TO_VIDEO_COLUMN>
"""A black and white animated sequence featuring a rabbit, named Rabbity Ribfried, and an anthropomorphic goat in a musical, playful environment, showcasing their evolving interaction.""","""00000.mp4"""
"""A black and white animated sequence on a ship's deck features a bulldog character, named Bully Bulldoger, showcasing exaggerated facial expressions and body language. The character progresses from confident to focused, then to strained and distressed, displaying a range of emotions as it navigates challenges. The ship's interior remains static in the background, with minimalistic details such as a bell and open door. The character's dynamic movements and changing expressions drive the narrative, with no camera movement to distract from its evolving reactions and physical gestures.""","""00001.mp4"""
...
```

この場合、`--instance_data_root` は動画が保存されている場所を指定し、`--dataset_name` はローカルフォルダへのパス、または Hub にホストされている [load_dataset](https://huggingface.co/docs/datasets/main/en/package_reference/loading_methods#datasets.load_dataset) 互換のデータセットを指定します。Minecraft のゲームプレイ動画が `https://huggingface.co/datasets/my-awesome-username/minecraft-videos` にあると仮定すると、`my-awesome-username/minecraft-videos` を指定する必要があります。

この形式を使用する場合、`--caption_column` は `<CAPTION_COLUMN>` であり、`--video_column` は `<PATH_TO_VIDEO_COLUMN>` である必要があります。

CSV形式に限定されるわけではありません。`load_dataset`メソッドが、基本的な`<PATH_TO_VIDEO_COLUMN>`と`<CAPTION_COLUMN>`を読み込むためのファイル形式をサポートしている限り、任意の形式で問題ありません。動画データの読み込みのために、こうしたデータセットの整理作業が必要になる理由は、`load_dataset`がすべての種類の動画形式を完全にサポートしていないためです。

> [!NOTE]
> CogVideoX は、動画生成において、長く詳細な LLM 拡張プロンプトと組み合わせることで最も優れたパフォーマンスを発揮します。動画の前処理として、まず VLM を使用してサマリーを生成し、その後 LLM を使用してプロンプトを拡張することを推奨します。上記のキャプションを生成するには、[MiniCPM-V-26](https://huggingface.co/openbmb/MiniCPM-V-2_6) と [Llama-3.1-8B-Instruct](https://huggingface.co/meta-llama/Meta-Llama-3.1-8B-Instruct) を使用しています。この処理の非常にシンプルで最小限の例は、[こちら](https://gist.github.com/a-r-r-o-w/4dee20250e82f4e44690a02351324a4a)で確認できます。プロンプト拡張の公式推奨ツールは [ChatGLM](https://huggingface.co/THUDM?search_models=chatglm) であり、50〜100 語の長さが適切とされています。

>![NOTE] データセットがすでに前処理済みであることが前提です。前処理が未実施の場合は、`--height`、`--width`、`--fps`、`--max_num_frames`、`--skip_frames_start`、`--skip_frames_end`のパラメータを調整することで、基本的な前処理を行うことができます。なお、トレーニングのバッチサイズが 1 より大きい場合、データセット内のすべての動画は同じフレーム数を含む必要があります。

## トレーニング

必要な要件をインストールして開発環境を設定する必要があります。以下のパッケージが必要です:
- 利用する学習機能に応じて、Torch 2.0 以上（量子化/DeepSpeed 学習には最新バージョンまたは nightly バージョンが必要になる場合があります）
- モデリングやトレーニングに関連するすべての用途には、`pip install diffusers transformers accelerate peft huggingface_hub` を使用してください。
- 動画の学習データを読み込むには、`pip install datasets decord` を実行してください。
- メモリ最適化されたトレーニングで8ビット Adam または AdamW オプティマイザーを使用するには、`pip install bitsandbytes`
- `pip install wandb` を任意でインストールし、トレーニングログの監視を行います
- 必要に応じて[DeepSpeed](https://github.com/microsoft/DeepSpeed)トレーニングのために`pip install deepspeed`
- `pip install prodigyopt` をインストールすると、学習にProdigyオプティマイザーを使用できます。

サンプルスクリプトの最新バージョンを正常に実行できることを確認するために、サンプルスクリプトは頻繁に更新され、サンプル固有の要件がインストールされるため、**ソースからのインストール**と、そのインストールの最新状態の維持を強くお勧めします。これを行うには、新しい仮想環境で以下の手順を実行してください。

スクリプトを実行する前に、ソースからライブラリをインストールしていることを確認してください。
```bash
git clone https://github.com/huggingface/diffusers
cd diffusers
pip install -e .
```

 

次に、トレーニングスクリプトを含むサンプルフォルダに移動し、使用しているスクリプトに必要な依存関係をインストールします。

- PyTorch

```bash
cd examples/cogvideo
pip install -r requirements.txt
```

次のコマンドで[🤗 Accelerate](https://github.com/huggingface/accelerate/)環境を初期化します:

```bash
accelerate config
```

環境に関する質問に答えずに、デフォルトの accelerate 設定を使用する場合

```bash
accelerate config default
```

または、インタラクティブシェルをサポートしていない環境（ノートブックなど）の場合

```python
from accelerate.utils import write_basic_config
write_basic_config()
```

`accelerate config`を実行する際、torch.compileを使用すると、大幅な高速化が得られる場合があります。LoRA学習のバックエンドとしてPEFTライブラリが使用されるため、環境に`peft>=0.6.0`がインストールされていることを確認してください。

トレーニングが完了した後に、整ったモデルカード付きでモデルを Hub にプッシュしたい場合は、ログインしていることを確認してください。

```bash
hf auth login

# Alternatively, you could upload your model manually using:
# hf upload my-cool-account-name/my-cool-lora-name /path/to/awesome/lora
```

[データの準備](#data-preparation)で説明されているように、データが準備されていることを確認してください。準備が整ったら、トレーニングを開始できます!

同様のコンセプトを持つ50本の動画で学習を行う場合、1500〜2000ステップで良好な結果が得られることが確認されています。ただし、公式の推奨値は、合計4000ステップで100本の動画を学習させることです。`--train_batch_size`が`1`の状態で、単一GPUでの学習を行う場合を想定すると:
- 50本の動画で1500ステップは、`30`エポックのトレーニングに相当します
- 100本の動画で4000ステップは、`40`回のトレーニングエポックに相当します

```bash
#!/bin/bash

GPU_IDS="0"

accelerate launch --gpu_ids $GPU_IDS examples/cogvideo/train_cogvideox_lora.py \
  --pretrained_model_name_or_path THUDM/CogVideoX-2b \
  --cache_dir <CACHE_DIR> \
  --instance_data_root <PATH_TO_WHERE_VIDEO_FILES_ARE_STORED> \
  --dataset_name my-awesome-name/my-awesome-dataset \
  --caption_column <CAPTION_COLUMN> \
  --video_column <PATH_TO_VIDEO_COLUMN> \
  --id_token <ID_TOKEN> \
  --validation_prompt "<ID_TOKEN> Spiderman swinging over buildings:::A panda, dressed in a small, red jacket and a tiny hat, sits on a wooden stool in a serene bamboo forest. The panda's fluffy paws strum a miniature acoustic guitar, producing soft, melodic tunes. Nearby, a few other pandas gather, watching curiously and some clapping in rhythm. Sunlight filters through the tall bamboo, casting a gentle glow on the scene. The panda's face is expressive, showing concentration and joy as it plays. The background includes a small, flowing stream and vibrant green foliage, enhancing the peaceful and magical atmosphere of this unique musical performance" \
  --validation_prompt_separator ::: \
  --num_validation_videos 1 \
  --validation_epochs 10 \
  --seed 42 \
  --rank 64 \
  --lora_alpha 64 \
  --mixed_precision fp16 \
  --output_dir /raid/aryan/cogvideox-lora \
  --height 480 --width 720 --fps 8 --max_num_frames 49 --skip_frames_start 0 --skip_frames_end 0 \
  --train_batch_size 1 \
  --num_train_epochs 30 \
  --checkpointing_steps 1000 \
  --gradient_accumulation_steps 1 \
  --learning_rate 1e-3 \
  --lr_scheduler cosine_with_restarts \
  --lr_warmup_steps 200 \
  --lr_num_cycles 1 \
  --enable_slicing \
  --enable_tiling \
  --optimizer Adam \
  --adam_beta1 0.9 \
  --adam_beta2 0.95 \
  --max_grad_norm 1.0 \
  --report_to wandb
```

トレーニング実験をより適切に追跡するために、上記のコマンドでは以下のフラグを使用しています。
* `--report_to wandb` を指定すると、トレーニングの実行が Weights and Biases で追跡されます。使用する際は、`pip install wandb` を実行して `wandb` をインストールしてください。
* `validation_prompt` と `validation_epochs` を指定して、スクリプトが数回の検証推論を実行できるようにします。これにより、トレーニングが想定どおり進んでいるかを定性的に確認できます。

`<ID_TOKEN>`を設定する必要はありません。限られた実験から、`<ID_TOKEN>`を設定した方が、設定しない場合よりも効果的であることがわかりました（[Dreambooth](./dreambooth)の学習に似ているためです）。`<ID_TOKEN>`が指定された場合、各プロンプトの先頭に追加されます。つまり、`<ID_TOKEN>`が`"DISNEY"`で、プロンプトが`"Spiderman swinging over buildings"`の場合、学習で実際に使用されるプロンプトは`"DISNEY Spiderman swinging over buildings"`になります。指定しない場合、追加トークンなしで学習するか、学習を開始する前にデータセットを拡張して、希望する位置にトークンを適用することもできます。

> [!NOTE]
> `--use_8bit_adam` を渡すことで、学習時のメモリ要件を削減できます。

> [!IMPORTANT]
> CogVideoX LoRA 学習のサポートを追加した時点で、以下の設定がテストされています: - テストは主に CogVideoX-2b で行われました。CogVideoX-5b と CogVideoX-5b-I2V については、まもなく対応予定です - 1 つのデータセットは、解像度 `200 x 480 x 720` (F x H x W) の 70 本の学習用動画で構成されていました。これを用いて、データ前処理におけるフレームスキッピングにより、より高速な実験のために、また CogVideoX チームが推奨する最大フレーム数が 49 フレームであるため、49 フレームと 16 フレームの 2 つの小さなデータセットを作成しました。70 本の動画から、10 本、25 本、50 本の 3 つのグループを作成しました。すべての動画は、学習対象のコンセプトの性質が類似していました。 - 新しいコンセプトやスタイルの学習には、25 本以上の動画が最も効果的でした。 - `--id_token` で指定できる識別子トークンを用いて学習する方が望ましいことがわかりました。これは Dreambooth 風の学習に似ていますが、そのようなトークンを用いない通常のファインチューニングでも機能します。 - 学習したコンセプトは、完全に無関係なプロンプトと組み合わせる場合でも、そこそこ良好に機能したようです。CogVideoX-5B をファインチューニングすれば、さらに良い結果が得られると予想しています。 - 元のリポジトリでは `lora_alpha` が `1` に設定されています。多くの実行でこれが適さないことがわかりました。これは、モデリングのバックエンドや学習設定の違いによるものと考えられます。私たちの推奨は、`lora_alpha` を `rank` または `rank // 2` に設定することです。 - 元のモデルでキャプションが不良な結果を生成するデータで学習する場合、`rank` を 64 以上に設定するのが良く、CogVideoX の開発チームの推奨でもあります。学習用キャプションでの生成がすでにそこそこ良好な場合、`rank` を 16/32 に設定すれば機能するはずです。rank を `4` のように低く設定するのは望ましくなく、有望な結果は得られないことがわかりました。 - CogVideoX の著者は、最良の結果を得るために、合計 4000 ステップの学習と 100 本の学習用動画を推奨しています。それが最良の結果をもたらすかもしれませんが、私たちの限られた実験から、2000 ステップと 25 本の動画でも十分であることがわかりました。 - 学習に Prodigy オプティマイザーを使用する場合、[この](https://huggingface.co/blog/sdxl_lora_advanced_script) ブログの推奨事項に従うことができます。Prodigy は急速に過学習する傾向があります。私の非常に限られたテストから、`--prodigy_use_bias_correction`、`prodigy_safeguard_warmup`、`--prodigy_decouple` に加えて、学習率 `0.5` が適していることがわかりました。 - CogVideoX の著者による推奨学習率、および Adam/AdamW での私たちの実験から、25 本以上の動画のデータセットに対しては、`1e-3` から `1e-4` の間が適切です。
>
> 探索に割ける時間が限られているため、当社のテストは網羅的ではありません。データに最適な設定を見つけるために、さまざまなパラメータを調整して試行錯誤することをお勧めします。

## 推論

LoRAモデルの学習が完了したら、`CogVideoXPipeline`にLoRAの重みをロードするだけで推論を実行できます。

```python
import torch
from diffusers import CogVideoXPipeline
from diffusers.utils import export_to_video

pipe = CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-2b", dtype=torch.float16)
# pipe.load_lora_weights("/path/to/lora/weights", adapter_name="cogvideox-lora") # Or,
pipe.load_lora_weights("my-awesome-hf-username/my-awesome-lora-name", adapter_name="cogvideox-lora") # If loading from the HF Hub
pipe.to("cuda")  # or "mps", "xpu", "cpu"

# Assuming lora_alpha=32 and rank=64 for training. If different, set accordingly
pipe.set_adapters(["cogvideox-lora"], [32 / 64])

prompt = "A vast, shimmering ocean flows gracefully under a twilight sky, its waves undulating in a mesmerizing dance of blues and greens. The surface glints with the last rays of the setting sun, casting golden highlights that ripple across the water. Seagulls soar above, their cries blending with the gentle roar of the waves. The horizon stretches infinitely, where the ocean meets the sky in a seamless blend of hues. Close-ups reveal the intricate patterns of the waves, capturing the fluidity and dynamic beauty of the sea in motion."
frames = pipe(prompt, guidance_scale=6, use_dynamic_cfg=True).frames[0]
export_to_video(frames, "output.mp4", fps=8)
```

## メモリ使用量の削減

diffusers ライブラリを用いたテストでは、diffusers ライブラリに含まれるすべての最適化を有効にしました。この方式は、**NVIDIA A100 / H100** アーキテクチャ以外のデバイスでの実際のメモリ使用量についてはテストされていません。一般的に、この方式は**NVIDIA Ampere アーキテクチャ**およびそれ以降のデバイスに適用できます。最適化を無効にすると、メモリ消費量は増加し、ピーク時のメモリ使用量は表の値の約3倍になります。ただし、速度は約3〜4倍向上します。一部の最適化を選択的に無効にできます。対象は以下の通りです。

```
pipe.enable_sequential_cpu_offload()
pipe.vae.enable_slicing()
pipe.vae.enable_tiling()
```

+ マルチGPU推論では、`enable_sequential_cpu_offload()`の最適化を無効にする必要があります。
+ INT8モデルを使用すると推論速度が遅くなります。これは、メモリ容量の少ないGPUに対応しつつ、画質の劣化を最小限に抑えるための措置ですが、推論速度は大幅に低下します。
+ CogVideoX-2B モデルは`FP16`精度で学習されており、すべての CogVideoX-5B モデルは`BF16`精度で学習されています。推論には、モデルが学習された精度の使用を推奨します。
+ [PytorchAO](https://github.com/pytorch/ao) と [Optimum-quanto](https://github.com/huggingface/optimum-quanto/) を使用すると、テキストエンコーダー、transformer、VAE モジュールを量子化して、CogVideoX のメモリ要件を削減できます。これにより、モデルを無料の T4 Colab やメモリ容量の小さい GPU でも実行できるようになります。また、TorchAO の量子化は `torch.compile` と完全に互換性があり、推論速度を大幅に向上させることができます。FP8 精度は NVIDIA H100 以上のデバイスで使用する必要があり、`torch`、`torchao`、`diffusers`、`accelerate` の Python パッケージのソースからのインストールが必要です。CUDA 12.4 が推奨されます。
+ 推論速度のテストでも、上記のメモリ最適化手法を使用しました。メモリ最適化を行わない場合、推論速度は約10%向上します。量子化は、`diffusers`版のモデルのみがサポートしています。
+ モデルは英語のインプットのみをサポートしています。その他の言語は、大規模モデルによる精錬を通じて英語に翻訳して使用できます。
+ モデルのファインチューニングにおけるメモリ使用量は、`8 * H100`環境でテストされており、プログラムは自動的に`Zero 2`最適化を使用します。表に特定のGPU数が記載されている場合、その数以上のGPUを使用してファインチューニングを行う必要があります。

 | **属性**                        | **CogVideoX-2B**                                                       | **CogVideoX-5B**                                                       |
| ------------------------------------ | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| **モデル名**                       | CogVideoX-2B                                                           | CogVideoX-5B                                                           |
| **推論の精度**              | FP16*（推奨）、BF16、FP32、FP8*、INT8、非対応 INT4         | BF16（推奨）、FP16、FP32、FP8*、INT8、非対応 INT4         |
| **シングルGPU推論VRAM**        | FP16: diffusers を使用 12.5GB* INT8: torchao を使用した diffusers 7.8GB* | BF16: diffusers を使用 20.7GB* INT8: torchao を使用した diffusers 11.4GB* |
| **マルチGPU推論VRAM**         | FP16: diffusers を使用した場合 10GB*                                             | BF16: diffusers を使用した場合 15GB*                                             |
| **推論速度**                  | Single A100: 約90秒、Single H100: 約45秒                      | Single A100: 約180秒、Single H100: 約90秒                     |
| **ファインチューニングの精度**            | FP16                                                                   | BF16                                                                   |
| **ファインチューニング時のVRAM消費量**     | 47 GB (bs=1, LORA) 61 GB (bs=2, LORA) 62GB (bs=1, SFT)                 | 63 GB (bs=1, LORA) 80 GB (bs=2, LORA) 75GB (bs=1, SFT)                 |

