# CogVideoX

CogVideoX는 프롬프트와 더 잘 정렬된 일관성 있는 비디오를 생성하는 데 초점을 맞춘 텍스트-비디오 생성 모델입니다. 이를 위해 여러 방법을 사용합니다.

- 영역적 및 시간적으로 비디오를 압축하여 압축률과 비디오 정확도를 향상시키는 3D 변분 오토인코더

- 텍스트와 비디오를 정렬하는 데 도움을 주는 전문가 transformer 블록과 공간적 및 시간적으로 정확한 비디오를 포착하고 생성하기 위한 3D full attention 모듈

비디오 지시 차원에 대한 실제 테스트 결과, CogVideoX는 일관된 주제, 동적 정보, 일관된 배경, 객체 정보, 부드러운 움직임, 색상, 장면, 외형 스타일, 시간적 스타일에서 좋은 효과를 보였지만, 인간 동작, 공간 관계, 다중 객체에서는 좋은 결과를 얻지 못했습니다.

Diffusers를 사용한 Fine-tuning은 이러한 저조한 결과를 보완하는 데 도움이 될 수 있습니다.

## 데이터 준비

training scripts는 두 가지 형식의 데이터를 지원합니다.

첫 번째 형식은 소규모 학습에 적합하며, 두 번째 형식은 CSV 형식을 사용하여 대규모 학습을 위한 스트리밍 데이터에 더 적합합니다. 향후 Diffusers는 `<Video>` 태그를 지원할 예정입니다.

### 소형 형식

`--instance_data_root`을 지정할 때 전달하는 경로 기준으로 상대 경로여야 하는 비디오 파일 경로를 줄바꿈으로 구분하여 포함하는 파일과, 줄바꿈으로 구분된 프롬프트를 포함하는 파일 두 개입니다. 더 잘 이해하기 위해 예시를 살펴보겠습니다!

`--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` 파일에는 비디오 파일의 경로를 줄바꿈으로 구분하여 포함해야 합니다. 경로는 `--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) 호환 데이터셋이어야 합니다. `https://huggingface.co/datasets/my-awesome-username/minecraft-videos`에 Minecraft 게임 플레이 비디오가 있다고 가정하면, `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-bit Adam 또는 AdamW 옵티마이저를 사용하려면 `pip install bitsandbytes`
- `pip install wandb`를 선택적으로 설치하여 학습 로그를 모니터링할 수 있습니다
- `pip install deepspeed`를 선택적으로 설치하여 [DeepSpeed](https://github.com/microsoft/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 설정에 대한 환경 관련 질문 없이 기본 accelerate 구성을 사용하려면

```bash
accelerate config default
```

또는 환경이 인터랙티브 셸을 지원하지 않는 경우(예: 노트북)

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

`accelerate config`를 실행할 때, torch.compile을 사용하면 상당한 속도 향상을 기대할 수 있습니다. PEFT 라이브러리가 LoRA 학습의 백엔드로 사용되므로, 환경에 `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 스텝이 효과적임을 확인했습니다. 그러나 공식 권장 사항은 100개 비디오와 총 4000 스텝입니다. 단일 GPU에서 `--train_batch_size`가 `1`인 상태로 학습한다고 가정하면:
- 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>`을 설정하는 것은 필수 사항이 아닙니다. 제한적인 실험을 통해, [Dreambooth](https://huggingface.co/docs/diffusers/en/training/dreambooth) 학습과 유사한 구조를 가지므로 `<ID_TOKEN>`를 제공하지 않는 경우보다 제공했을 때 성능이 더 좋음을 확인했습니다. `<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에 대한 작업도 진행할 예정입니다. - 데이터셋은 해상도 `200 x 480 x 720`(F x H x W)인 70개의 학습 비디오로 구성되었습니다. 데이터 전처리 단계에서 프레임 스킵을 사용하여 더 빠른 실험을 위해 49프레임과 16프레임의 두 개의 더 작은 데이터셋을 만들었습니다. 이는 CogVideoX 팀이 권장하는 최대 프레임 수가 49프레임이기 때문입니다. 70개 비디오 중 10개, 25개, 50개로 구성된 세 그룹을 만들었습니다. 모든 비디오는 학습되는 개념의 성격이 유사했습니다. - 새로운 개념과 스타일 학습에는 25개 이상의 비디오가 가장 효과적이었습니다. - `--id_token`으로 지정할 수 있는 식별자 토큰을 사용하여 학습하는 것이 더 좋다는 것을 발견했습니다. 이는 Dreambooth와 유사한 학습 방식과 비슷하지만, 이러한 토큰 없이 일반적인 파인튜닝도 작동합니다. - 학습된 개념은 완전히 무관한 프롬프트와 결합했을 때 상당히 잘 작동하는 것으로 보였습니다. CogVideoX-5B를 파인튜닝하면 더 나은 결과를 얻을 것으로 기대합니다. - 원래 저장소는 `lora_alpha`를 `1`로 사용합니다. 모델링 백엔드와 학습 설정의 차이로 인해 많은 실행에서 이 값이 적합하지 않다는 것을 발견했습니다. `lora_alpha`를 `rank` 또는 `rank // 2`로 설정하는 것을 권장합니다. - 캡션이 원래 모델에서 나쁜 결과를 생성하는 데이터로 학습하는 경우, 64 이상의 `rank`가 좋으며 CogVideoX 개발팀의 권장 사항이기도 합니다. 학습 캡션에서 이미 중간 정도의 좋은 생성 결과가 나오는 경우, 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)
```

## 메모리 사용량 줄이기

While testing using the diffusers library, all optimizations included in the diffusers library were enabled. This scheme has not been tested for actual memory usage on devices outside of **NVIDIA A100 / H100** architectures. Generally, this scheme can be adapted to all **NVIDIA Ampere architecture** and above devices. If optimizations are disabled, memory consumption will multiply, with peak memory usage being about 3 times the value in the table. However, speed will increase by about 3-4 times. You can selectively disable some optimizations, including:

```
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/)를 사용하면 CogVideoX의 텍스트 인코더, 트랜스포머, VAE 모듈을 양자화하여 메모리 요구량을 줄일 수 있습니다. 이를 통해 무료 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*                                             |
| **추론 속도**                  | A100 1개: 약 90초, H100 1개: 약 45초                      | A100 1개: 약 180초, H100 1개: 약 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)                 |

