【text2video】ModelScopeモデルの微調整方法

概要

先日、text2videoを実現するModelScopeの動画生成モデルが一般公開となりました。さらに、別の方によってそのモデルを微調整するためのツールも公開されました。まだまだ発展途上な感じではありますが面白いです。
ここでは、modelscopeモデルを微調整する方法を簡単に記載します。技術の詳細等については詳しくないので書きません。要点だけ。

※2023/4/2現在の方法です。4/8にがリリースされ大幅にアップデートされました。近いうちそっちの方法も記載する予定です。


動作環境

  • GPU
    まずGPUですが、VRAM16GBは必須のようです。推奨はRTX3090です。私もRTX3090で学習中のVRAM消費量を確認しましたが256x256のトレーニングで20GB近く消費していました。

  • git
    ツール取得のためgitと、また大規模モデルをダウンロードするためgit lfsを導入します。

  • Python
    Python仮想環境構築のため、Anacondaをインストールしておきます。
    (私は横着してcondaを使用せずpythonも3.9.13で試しましたが問題はありませんでした。。)

環境構築

学習ツールとモデルのダウンロード

windowsであればpowershell等を開き、ツールを導入したいフォルダ下で以下のコマンドを順に実行します。モデル取得が結構時間かかります。

git clone -b 4bdc2b20f2c83ffb7f077e9c29a8d6648734db55 https://github.com/ExponentialML/Text-To-Video-Finetuning.git
cd Text-To-Video-Finetuning
git lfs install
git clone -b 2ba8250cba6b21ee3d82d1947768c9edc171ded5 https://huggingface.co/damo-vilab/text-to-video-ms-1.7b ./models/model_scope_diffusers/

Python仮想環境の構築

グローバルPython環境と切り離すため仮想環境を作り、その環境を有効化します。正常に仮想環境に入れればコマンドラインが「(text2video-finetune) PS C:\path\to\your\dir>」というような形になってるはずです。

conda create -n text2video-finetune python=3.10
conda activate text2video-finetune

必要なPythonモジュールのインストール

gitでダウンロードしたText-To-Video-Finetuningフォルダ下に入り、以下を実行します。また追加でxformersを導入するとVRAM使用量が抑えられるようです。

pip install -r requirements.txt

トレーニング (複数動画を対象に微調整)

まず、この微調整ツールには2種類のトレーニング方法があります。複数の動画を学習データにする方法と、単一の動画を学習する方法です。まず前者の方法について記載します。

学習動画の用意

学習となる動画を用意します。mp4形式。まだあまり長いデータは学習できず16フレーム程度が限度のようですので、それを念頭にデータを探しましょう。

学習データ前処理(内容抽出)用ツールの用意

複数動画を学習させる場合は、対象動画の動画内容をテキストとして抽出して学習に使用するため以下のようにツールを取得し、仮想環境作成、その仮想環境に入ります。text2video-finetune仮想環境にいる場合はconda deactivateで退出しておきます。

git clone -b 93932dd0106283b1bd59c5ffd6cd40476afd32e6 https://github.com/ExponentialML/Video-BLIP2-Preprocessor.git
cd Video-BLIP2-Preprocessor
conda create -n Video-BLIP2-Preprocessor python=3.9
conda activate Video-BLIP2-Preprocessor
pip install -r requirements.txt

#私の環境では別途以下も必要でした
pip install git+https://github.com/huggingface/transformers 
pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116

#accelerateを使うとベターなようです
pip install accelerate

内容抽出の実行

Video-BLIP2-Preprocessor下で以下のようにコマンド実行してjsonファイルを作成します。---video_directoryに対象動画のあるフォルダを指定します。--config_nameは文字通り設定の名前ですが、たぶん重要じゃないので適当でいいと思います。--config_save_nameで出力jsonファイル名を指定します。--prompt_amountはランダムなフレームから内容を抽出する回数です。デフォルト値が25ですが短くてシーンに変化の少ない動画が多いならもっと小さい値(5とか?)でもいいかもです。他にも隠し引数がありますが私もよくわかってません。

python preprocess.py --video_directory <your path of videos (vid1.mp4, vd2.mp4, etc.)> --config_name "My Videos" --config_save_name "my_videos" --prompt_amount 25
#または
accelerate launch preprocess.py --video_directory <your path of videos (vid1.mp4, vd2.mp4, etc.)> --config_name "My Videos" --config_save_name "my_videos" --prompt_amount 25

抽出データの確認

上記も場合によって結構時間がかかります。私の場合、200個程度の動画でprompt_amount=25の指定だと1時間半くらいかかりました。prompt_amount=1だと数分でした。
出力されたjsonを確認します。問題がなければ以下のような形になっているはずです。

{
    "name": "My Videos",
    "data": [
        {
            "video_path": "./videos/video.mp4",
            "num_frames": 1000,
            "data": [
                {
                    "frame_index": 134,
                    "prompt": "a person is riding a bike on a busy street."
                },
                {
                    "frame_index": 745,
                    "prompt": "a person is wearing a blue shirt and riding a bike on grass."
                },
                ...
            ]
        },
        ...
    ]
}

学習設定の変更

まず設定を調整するため、Text-To-Video-Finetuningフォルダ下に戻り、configs/my_config.yamlをテキストエディタで開き、編集します。色々と項目がありますが、重要と思われるものにコメントを加えておきます。

pretrained_model_path: "./models/model_scope_diffusers/"  # ModelScopeモデルデータの場所。上記ですでに用意されてるはず。
output_dir: "./outputs"  # 学習結果のモデルやサンプル動画等が出力されるフォルダ
train_text_encoder: False #テキストエンコーダの学習有無。現在バグで動作しない模様。ver2に期待。

train_data:
  json_path: "./json/train.json"  # 上記で出力されたjsonファイルのパス
  preprocessed: True  # 前処理を行っているか
  n_sample_frames: 8  # 動画からサンプリングするフレーム数。この数値が大きいほど、より多くのVRAMが必要(使い方はバッチサイズと同様
  width: 256    # 学習用データの縦と横。
  height: 256   #
  sample_start_idx: 0
  sample_frame_rate: 15
  use_random_start_idx: False
  vid_data_key: "video_path"

  single_video_path: ""  # 単一動画の学習の場合に設定
  single_video_prompt: ""  # 同上

validation_data:
  prompt: ""  # 単一動画の学習の場合に設定
  sample_preview: True  # サンプル動画を出力するか否か
  num_frames: 16 
  width: 256  # サンプル動画の縦と横
  height: 256
  num_inference_steps: 50 
  guidance_scale: 9

learning_rate: 5e-6 
adam_weight_decay: 1e-2
train_batch_size: 1
max_train_steps: 50000  # トレーニングステップ数。大きい値ほどたくさん学習する(良い結果となるかは別)。
checkpointing_steps: 5000  # 中途結果モデルを出力するステップのスパン
validation_steps: 100  # 中途結果サンプル動画の出力等を行うステップのスパン
trainable_modules:
  - "attn1.to_out"
  - "attn2.to_out"
seed: 64
mixed_precision: "fp16"
use_8bit_adam: False # This seems to be incompatible at the moment. 
enable_xformers_memory_efficient_attention: False

# Use scaled dot product attention (Only available with >= Torch 2.0)
enable_torch_2_attn: True

max_train_stepsは学習動画数が数個程度であれば3000前後などでおそらく十分です。VRAMが24GBあれば学習width/heightなどをもう少し上げられると思います。私は上記設定で学習を始めた結果、20GB弱程度の消費となりました。

学習の実行

設定完了後、仮想環境を変更して学習を実行します。

conda deactivate  # text2video-finetune環境にいたなら実行
conda activate text2video-finetune #仮想環境を変更
python train.py --config ./configs/my_config.yaml

これもまた長くなる可能性があります。max_train_stepsの値に寄りますが上記設定だと9時間くらいかかりました。

結果の確認

学習が正常に完了していれば、output_dirで設定したフォルダに結果も出るが出力されているはずです。以下のスクリプトを実装したpythonファイルを実行すれば微調整モデルから動画を生成できます。

import torch
from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler
from diffusers.utils import export_to_video
import sys
import time
import math

args = sys.argv

my_trained_model_path = "./path/to/your/output/dir/"    # 微調整モデルの場所(model_index.jsonを含むフォルダ)
output_path = "./outputs/t2v/"  # 動画の出力先
prompt = "your prompt"  # プロンプト
ng_prompt = "your negative prompt"  # ネガティブプロンプト
num = 1  # 出力動画数
num_frame = 16  # 動画フレーム数
num_inference_step = 25  # 動画の精度

pipe = DiffusionPipeline.from_pretrained(my_trained_model_path, torch_dtype=torch.float16, variant="fp16")
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
pipe.enable_model_cpu_offload()

for i in range(num):
    video_frames = pipe(prompt, num_inference_steps=num_inference_step, negative_prompt=ng_prompt, width=320, height=256, num_frames=num_frame).frames
    out_file = output_path + str(math.floor(time.time())) + "_" + prompt[0:64] + ".mp4"
    video_path = export_to_video(video_frames, out_file)

diffusersパイプラインによる動画生成の詳細については以下。https://huggingface.co/docs/diffusers/main/en/api/pipelines/text_to_video
学習精度以上のサイズを指定しても出力は崩れるようです。

おわりに

webuiを使った画像生成などと比べるとまだ結構手間も時間もかかります。
今後ModelScopeがtext2videoのある種の主流になるかはわかりませんが、興味のある方は試してみてください。


この記事が気に入ったらサポートをしてみませんか?