diffusersにSGHMC(Stochastic Gradient Hamiltonian Monte Carlo)を入れる話
画像生成AI Advent Calendar 2022 - Adventar12/17日分の記事です。
いろいろな拡散モデルの手法が実装されているdiffusers huggingface.co にSGHMC(Stochastic Gradient Hamiltonian Monte Carlo)という手法を実装し評価しようとしています。 実装は github.com にあります(feature_SGHMC branch)。 追加モジュールはscheduling_sghmc.pyで pipeline_stable_diffusion.pyにも変更点があります。
SGHMCのアルゴリズム
通常の変数θに対する確率的勾配降下法
(Uはポテンシャルで拡散モデルでは はscore functionに相当する。Nは正規分布ノイズ,Bは分散)に対して 運動量rを慣性として入れることで広い範囲のサンプリングを可能としているのが特徴です(相空間を等エネルギー面に沿ってぐるぐる回るハミルトン系の要素があると効率的にサンプリングできるという直感的理解になるかと思います。 Tokyo.stanの感想 - xiangze's sparse blog) 摩擦項を入れることで定常分布となることが保証されています(Linkの論文とpdf参照)。 統計モデリングの計算で用いられるHMCとの違いは方程式に沿って進めたステップを選択する処理(Metropolis-Hastings)が存在しないところにあります。*1 (ハミモン、ゲットだぜ! - xiangze's sparse blog)。
diffusers ソースの構造
diffusers 以下に
├── docker ├── docs ├── examples ├── scripts ├── setup.cfg ├── setup.py ├── src ├── tests └── utils
ソースコード本体src/diffusersの他にテストコード、ドキュメント、ライブラリ生成用のコードなどがあります。 src/diffusers以下の主なディレクトリは
├── __init__.py ├── commands ├── experimental ├── models ├── pipelines ├── schedulers └── utils
となっており
piplines以下のpipline_*.pyというファイルには拡散モデルとその周辺にあるEncoder,Decoder、Unetなど組み合わせが記述されています。 https://huggingface.co/docs/diffusers/index#diffusers-pipelines
例えばpipeline_stable_diffusion.pyにはlatent variableを用いたstable diffusionの手法が実装されています。
models以下にはVAEなど拡散モデル以外の部分のコードがあります。これらの組み合わせをpipelineでは記述しています。
schedulers以下にはscheduling_*.pyという名前で拡散モデルの本体が実装されておりstep,step_predなどの関数が1時間ステップの動作なのでその外側で変数を保持しています。 scheduling_ddpm_flax.pyなどpytorchだけでなくJAX/Flaxの実装もあります。
今回はimportのしやすさからsrcに下記のようなテストスクリプト、ipynbなどを作って作業しています。
追加点
schedulerに運動量に当たる変数pを追加し、方程式
を既存のschedulerを改造して実装します。Mは質量に相当しますがここでは1に固定しました。
のときに追加前の式
(overdamped)の場合と同じようになるように係数γを決定します。すると外力がない場合は となり解は指数的に減衰するのでγは摩擦係数と解釈できます。ここで問題になるのがノイズの分散との関係です。 定常分布が
[tex: exp(-H(x,p))=exp(-1/2 pT M^{-1}p+U(x))]
がランジュバン方程式の解になるようにすると分散はとなります。
ただし拡散モデルではノイズの分散はステップによって変化していく(温度Tが変化して分散はとなる)ので摩擦係数との関係は一定にはならない(はず)です*2。
コードはscheduling_sghmc.pyのようになり、 pipeline_stable_diffusion.pyにも変更点があります。 本来はschedulerに対応したpipelineを用意すべきですがpipeline_stable_diffusionを改造する形になってしまっています。
pipeの呼び出し、画像生成コードは以下のようになります。 pipline定義以降もschedulerを動的に差し替えることができます。
import torch from torch import autocast import diffusers import datetime import diffusers.schedulers from diffusers import StableDiffusionPipeline from diffusers.schedulers import SGHMCScheduler YOUR_TOKEN ="ここにhuggingfaceで取得したtokenを書く" def gen_images(pipe,name:str,num_images=10,init_seed=0,num_inference_steps=50): for i in range(num_images): #seed固定 SEED=i+init_seed generator = torch.Generator(device=DEVICE).manual_seed(SEED) #print(pipe.scheduler) with autocast(DEVICE): image = pipe(prompt, guidance_scale=7.5, num_inference_steps=num_inference_steps,generator=generator)["images"][0] # 現在時間 dt_now = datetime.datetime.now() now = dt_now.strftime("%Y%m%d%H%M%S") # ファイル名 file_path = name+str(SEED) + "_" + str(now)+"_"+str(num_inference_steps) + ".png" # ファイル保存 image.save(file_path) MODEL_ID = "CompVis/stable-diffusion-v1-4" DEVICE = "cuda" pipe = StableDiffusionPipeline.from_pretrained(MODEL_ID, revision="fp16", torch_dtype=torch.float16, use_auth_token=YOUR_TOKEN) pipe.to(DEVICE) prompt = "a dog painted by Katsuhika Hokusai" ## schedulerの変更 pipe.scheduler = SGHMCScheduler.from_config(pipe.scheduler.config,sampler_type="DDPM") gen_images(pipe,"DDPM",1,num_inference_steps=500)
途中結果
プロンプト"a dog painted by Katsuhika Hokusai"に対して
Euler discrete ベースで摩擦係数dump_coef=1(定数)の場合 犬がどんどん薄くなっていってしまう!
noise variance=varに対して dump_coef=varvar の場合 var ,100 step
DDPMベースで摩擦係数dump_coef=1(定数)の場合
3000 step
運動量の可視化
そしてstepを続けるとUnetの出力がNaNになってしまう現象が見られる。 なにか仮定が不適切なのか デバッグ中です。‥ DDPM、DDIMなど各サンプリング手法では分散のとり方を工夫しているがそれと調和するようなunderdamping手法があるのか、あるいはないのか‥
評価方法
既存のscheduler(sampler)の違いが画質に及ぼす影響はこちらが参考になります。 zenn.dev bookyakuno.com
Eulerでは淡白な印象になります。DPM++2Mは数ステップで収束するらしいのですが、濃いめの出力になるようです。
定量評価はFID(Frechet Inception Distance ,2つの確率分布μ、ν間の距離を表す量で分布 と定義される量)を使いますがまだ実行できてはいません。。。
追記(2/19) Score-Based Generative Modeling through Stochastic Differential Equations の4.2 PREDICTOR-CORRECTOR SAMPLERSで既にHMCの存在は考慮されておりもしかしたらうまく行かなかったのかもしれない。 Predictor-Corrector methodsとは最初に計算した差分に対して補正を行うようなサンプリングステップのことでLeapFlogに近い(Appendix G参照)
追記(3/19)
この論文、前にxiangzeさんが試してたやつと似てる!https://t.co/RCIvfmAB3u https://t.co/QwtkOajf2v
— なんか (@_determina_) February 24, 2023
あと岡野原先生の本の最後の方で紹介されていた
— xiangze (@xiangze750) February 24, 2023
Critically-Damped Langevin Diffusionというのも変数を追加する手法で面白そうですhttps://t.co/LpUfh62dvB
Link
SGHMCについて
- [1402.4102] Stochastic Gradient Hamiltonian Monte Carlo
- Stochastic Gradient MCMC
[2208.07698] Score-Based Diffusion meets Annealed Importance Sampling 逆にscore matchingをAnnealed Importance Samplingに組み込む方法について
pythonについて
めちゃめちゃ助けられました。型ヒント、VScode, jupyterが三種の神器
Langevin方程式、Fokker plank方程式について
- stochastic processes - Underdamped vs overdamped Langevin dynamics - Physics Stack Exchange overdamped,underdampedのLangevin方程式の関係
- http://www2.yukawa.kyoto-u.ac.jp/~kiyoshi.kanazawa/yuragi_kiso.pdf Fokker plank方程式について
- 非平衡科学: 授業ノート
- stochastic processes - Underdamped vs overdamped Langevin dynamics - Physics Stack Exchange
やりたかったこと
経路に沿って生成した静止画像をアニメーションとして再生したかったです。 色々な方の作品をお楽しみ下さい
www.youtube.comAI画像がどんどん出力される動画作りました。#AIart #8528d pic.twitter.com/QniHUxBHOt
— 852話 (@8co28) 2022年12月7日
🚨I may have had a little too much to cyberdrink 🚨 pic.twitter.com/o6ct9CyBsn
— Jeremy Torman (minting now) (@TormanJeremy) 2022年12月9日
Warpfusion by @devdef (thank you very much)#Stablediffusion #wrpfusion #AIart
— aiplague (@aiplague) 2022年9月23日
Full 4K Version YouTube Link 👇 pic.twitter.com/g4N7Lw2QTs
A #stablediffusion 3D animation from u/Healthy_Ad9884 on Reddit using the @deforum_art notebook. (Posted with permission)
— TomLikesRobots (@TomLikesRobots) 2022年9月17日
The smooth rotation around the Y-Axis works so well here to create a coherent scene. #AIart pic.twitter.com/n0rQTml8aJ
Here kitty kitty... 🐈⬛🐈⬛ pic.twitter.com/SEb84FHW4K
— makeitrad (@makeitrad1) 2022年9月14日
#StableDiffusion の出力をLatent Diffusion Models
— Akira Saito (@a_saito) 2022年9月4日
で超解像しBoosting Monocular Depth Estimation Models to High-Resolution via Content-Adaptive Multi-Resolution Mergingでデプスを求め #Houdini で立体化。 pic.twitter.com/trlAe5RhZI
#midjourney pic.twitter.com/zL5ujH1d6x
— bias and variance(過学習) (@biasandvariance) 2022年11月24日