Skip to content

Commit 2f106a7

Browse files
author
Huy Vu2
committed
add examples for openvid1M dataset, update README.md, remove .yaml files
1 parent 6b29410 commit 2f106a7

6 files changed

Lines changed: 170 additions & 94 deletions

File tree

‎examples/diffusion/recipes/wan/README.md‎

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ energon prepare "${DATASET_PATH}"
7474

7575
In the training config, point `dataset.path` to the processed data output directory: `dataset.path=${DATASET_PATH}`.
7676

77+
**Note**: We provide an example instruction to process and train a small portion of OpenVid-1M dataset, at `examples/diffusion/recipes/wan/prepare_dataset/openvid1M_dataset`.
78+
7779
---
7880

7981
## 2. Checkpoint Conversion
@@ -136,41 +138,33 @@ This recipe leverages sequence packing to maximize throughput. When a batch cont
136138

137139
### Training mode
138140

139-
WAN uses different flow-matching hyperparameters for pretraining vs fine-tuning. Select the appropriate step function via `--step_func`:
140-
- `wan_pretrain_step`: logit-normal sampling, higher `logit_std`, lower `flow_shift` — for stability and broad learning
141-
- `wan_finetune_step`: uniform sampling, lower `logit_std`, higher `flow_shift` — to refine details and improve quality
141+
WAN uses different flow-matching hyperparameters for pretraining vs fine-tuning. Always pass `--step_func wan_step`; the mode is automatically inferred from the recipe name:
142+
- **pretrain** (recipe contains `pretrain`): logit-normal sampling, higher `logit_std` (1.5), lower `flow_shift` (2.5) — for stability and broad learning
143+
- **finetune** (recipe contains `finetune`/`sft`/`peft`): uniform sampling, lower `logit_std` (1.0), higher `flow_shift` (3.0) — to refine details and improve quality
142144

143145
### WAN 1.3B — Mock data (no dataset path):
144146

145147
```bash
146148
uv run torchrun --nproc_per_node=8 scripts/training/run_recipe.py \
147149
--recipe wan_1_3B_pretrain_config \
148-
--step_func wan_pretrain_step
150+
--step_func wan_step
149151
```
150152

151153
### WAN 1.3B — Real data (WebDataset path):
152154

153155
```bash
154156
uv run torchrun --nproc_per_node=8 scripts/training/run_recipe.py \
155157
--recipe wan_1_3B_pretrain_config \
156-
--step_func wan_pretrain_step \
158+
--step_func wan_step \
157159
dataset.path=${WORKSPACE}/datasets/wan
158160
```
159161

160-
### WAN 14B — Mock data:
161-
162-
```bash
163-
uv run torchrun --nproc_per_node=8 scripts/training/run_recipe.py \
164-
--recipe wan_14B_pretrain_config \
165-
--step_func wan_pretrain_step
166-
```
167-
168162
### With CLI overrides (iters, LR, batch size, parallelism, etc.):
169163

170164
```bash
171165
uv run torchrun --nproc_per_node=$NUM_GPUS scripts/training/run_recipe.py \
172166
--recipe wan_1_3B_pretrain_config \
173-
--step_func wan_pretrain_step \
167+
--step_func wan_step \
174168
dataset.path=${WORKSPACE}/datasets/wan \
175169
train.global_batch_size=8 \
176170
train.micro_batch_size=1 \

‎examples/diffusion/recipes/wan/conf/wan_14B.yaml‎

Lines changed: 0 additions & 42 deletions
This file was deleted.

‎examples/diffusion/recipes/wan/conf/wan_1_3B.yaml‎

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Preparing OpenVid-1M Dataset for Wan Fine-tuning
2+
3+
This guide walks through downloading a subset of the [OpenVid-1M](https://huggingface.co/datasets/nkp37/OpenVid-1M) dataset, preprocessing it, and converting it into the Energon WebDataset format for Wan training.
4+
5+
## Prerequisites
6+
7+
- `wget`, `unzip` available on your system
8+
- A Hugging Face account with access token (`HF_TOKEN`)
9+
- Python environment with Megatron-Bridge installed
10+
11+
## Step 1: Download a Small Portion of OpenVid-1M
12+
13+
```bash
14+
PROCESSED_DATA_PATH=<path/to/dataset_dir>
15+
cd ${PROCESSED_DATA_PATH}
16+
17+
export HF_TOKEN=<HF_API_KEY>
18+
wget https://huggingface.co/datasets/nkp37/OpenVid-1M/resolve/main/OpenVidHD/OpenVidHD_part_1.zip
19+
wget https://huggingface.co/datasets/nkp37/OpenVid-1M/resolve/main/data/train/OpenVidHD.csv
20+
```
21+
22+
## Step 2: Extract a Subset of Videos
23+
24+
Extract 200 videos as an example (adjust the number as needed):
25+
26+
```bash
27+
unzip -Z1 OpenVidHD_part_1.zip | head -n 200 | xargs -I {} unzip OpenVidHD_part_1.zip "{}" -d OpenVidHD_part_1
28+
```
29+
30+
## Step 3: Create Per-Video Caption JSON Files
31+
32+
The preprocessing script reads the CSV caption file and creates a sidecar `.json` file next to each `.mp4`:
33+
34+
```bash
35+
cd ${MBRIDGE_PATH}
36+
python examples/diffusion/recipes/wan/prepare_dataset/openvid1M_preprocess.py \
37+
--csv_path ${PROCESSED_DATA_PATH}/OpenVidHD.csv \
38+
--video_dir ${PROCESSED_DATA_PATH}/OpenVidHD_part_1
39+
```
40+
41+
Each video will have a corresponding `.json` file with `video` and `caption` fields.
42+
43+
## Step 4: Convert to Energon WebDataset Format
44+
45+
Run the dataset preparation script using `torchrun` with 8 GPUs:
46+
47+
```bash
48+
DATASET_SRC=${PROCESSED_DATA_PATH}/OpenVidHD_part_1
49+
DATASET_PATH=${PROCESSED_DATA_PATH}/prepared_dataset_wds
50+
51+
torchrun --nproc_per_node=8 \
52+
examples/diffusion/recipes/wan/prepare_dataset/prepare_dataset_wan.py \
53+
--video_folder "${DATASET_SRC}" \
54+
--output_dir "${DATASET_PATH}" \
55+
--output_format energon \
56+
--model "Wan-AI/Wan2.1-T2V-1.3B-Diffusers" \
57+
--mode video \
58+
--height 480 \
59+
--width 832 \
60+
--resize_mode bilinear \
61+
--center-crop
62+
```
63+
64+
The output directory `${DATASET_PATH}` can then be passed directly as `dataset.path` when launching Wan training.
65+
66+
## Step 5: Launch Wan Fine-tuning
67+
68+
Set the required environment variables and run the training script:
69+
70+
```bash
71+
DATASET_PATH=${PROCESSED_DATA_PATH}/prepared_dataset_wds
72+
CHECKPOINT_DIR=<path/to/save/checkpoints>
73+
INIT_CHECKPOINT_DIR=<path/to/pretrained/wan/checkpoint>
74+
EXP_NAME=<experiment_name>
75+
76+
NVTE_FUSED_ATTN=1 torchrun --nproc_per_node=8 scripts/training/run_recipe.py \
77+
--recipe wan_1_3B_pretrain_config \
78+
--step_func wan_step \
79+
model.tensor_model_parallel_size=1 \
80+
model.pipeline_model_parallel_size=1 \
81+
model.context_parallel_size=4 \
82+
model.sequence_parallel=false \
83+
model.qkv_format=thd \
84+
model.bias_activation_fusion=false \
85+
dataset.path=${DATASET_PATH} \
86+
dataset.packing_buffer_size=200 \
87+
dataset.num_workers=10 \
88+
checkpoint.save=${CHECKPOINT_DIR} \
89+
checkpoint.load=${INIT_CHECKPOINT_DIR} \
90+
checkpoint.load_optim=false \
91+
checkpoint.save_interval=200 \
92+
optimizer.lr=5e-5 \
93+
optimizer.min_lr=5e-5 \
94+
train.eval_iters=0 \
95+
scheduler.lr_decay_style=constant \
96+
scheduler.lr_warmup_iters=1000 \
97+
model.seq_length=40000 \
98+
dataset.seq_length=40000 \
99+
train.global_batch_size=8 \
100+
train.micro_batch_size=1 \
101+
dataset.global_batch_size=8 \
102+
dataset.micro_batch_size=1 \
103+
logger.log_interval=1 \
104+
logger.wandb_project="wan" \
105+
logger.wandb_exp_name=${EXP_NAME} \
106+
logger.wandb_save_dir=${CHECKPOINT_DIR}
107+
```
108+
109+
> **Note:** With a small dataset (e.g. 200 videos), set `dataset.num_workers=1` to avoid an
110+
> `IndexError` in the Energon sharder caused by too few samples in the val split shard.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import argparse
2+
import pandas as pd
3+
import json
4+
import os
5+
6+
7+
def main():
8+
parser = argparse.ArgumentParser()
9+
parser.add_argument("--csv_path", default="OpenVidHD.csv")
10+
parser.add_argument("--video_dir", default="OpenVidHD_part_1")
11+
args = parser.parse_args()
12+
13+
csv_path = args.csv_path
14+
video_dir = args.video_dir
15+
16+
# 1. Load the CSV into a dictionary for O(1) lookup speed
17+
print(f"Loading {csv_path}...")
18+
df = pd.read_csv(csv_path)
19+
20+
# Create a mapping of filename -> caption
21+
# We strip any whitespace just in case
22+
caption_map = dict(zip(df['video'].str.strip(), df['caption']))
23+
24+
# 2. List all mp4 files in the directory
25+
video_files = [f for f in os.listdir(video_dir) if f.endswith('.mp4')]
26+
print(f"Found {len(video_files)} videos in {video_dir}. Starting conversion...")
27+
28+
count = 0
29+
for video_name in video_files:
30+
if video_name in caption_map:
31+
# Construct the JSON content
32+
content = {
33+
"video": video_name,
34+
"caption": caption_map[video_name]
35+
}
36+
37+
# Create the output filename (replace .mp4 with .json)
38+
json_name = os.path.splitext(video_name)[0] + '.json'
39+
json_path = os.path.join(video_dir, json_name)
40+
41+
# Write the individual JSON file
42+
with open(json_path, 'w', encoding='utf-8') as f:
43+
json.dump(content, f, indent=4, ensure_ascii=False)
44+
45+
count += 1
46+
else:
47+
print(f"Warning: No caption found for {video_name}")
48+
49+
print(f"Finished! Created {count} JSON files in {video_dir}.")
50+
51+
if __name__ == "__main__":
52+
main()

examples/diffusion/recipes/wan/prepare_dataset_wan.py renamed to examples/diffusion/recipes/wan/prepare_dataset/prepare_dataset_wan.py

File renamed without changes.

0 commit comments

Comments
 (0)