画像生成 AI のしくみ:オートエンコーダー・VAE・GAN から拡散モデルまで
画像生成 AI は、「夕焼けの海辺を歩く猫」のような文章を受け取って、それに合う新しい画像を描くプログラムです。Stable Diffusion・DALL·E・Midjourney などのサービスの多くは、拡散モデルと呼ばれるしくみを使っています。拡散モデルは、純粋なノイズ(砂嵐のような画像)から始めて、ノイズを少しずつ取り除くことをくり返して画像を作ります。
この記事は 画像分類 AI のしくみ、物体検出 AI のしくみ、セグメンテーション AI のしくみ の続きです。これまでの 3 本は画像を「読み取る」モデルでしたが、この記事では画像を「作る」モデルを説明します。畳み込み・損失関数・勾配降下法は画像分類の記事で、U-Net はセグメンテーションの記事で説明したので、ここでは「どうやって新しい画像を作るか」に絞ります。
結論を先に書くと、画像生成のモデルは次のように発展してきました。
- VAE: 画像を少ない数(潜在変数)に圧縮して戻すオートエンコーダーを、「潜在変数を乱数で選べば新しい画像が出てくる」ように学習する
- GAN: 画像を作る生成器と、本物か偽物かを見分ける識別器を競わせて、本物らしい画像を作れるようにする
- 拡散モデル: 画像にノイズを足していく過程を逆にたどれるように、「画像に含まれるノイズを当てる」問題を学習する。今の画像生成 AI の主流
説明の途中に出てくる計算例は、Python と NumPy で実際に動かした結果です。画像のかわりに 1 次元や数次元の数で計算しますが、考え方は画像でも同じです。
環境
計算例を動かした環境です。
| 項目 | バージョン |
|---|---|
| Python | 3.13 |
| NumPy | 2.5 |
生成モデルとは:データの分布をまねる
分類のモデルとの違い
画像分類のモデルは、画像 x を受け取って「猫である確率」を答える関数でした。これに対して、生成モデルは「猫の写真らしい画像 x」そのものを新しく作ります。
| モデル | 入力 | 出力 |
|---|---|---|
| 分類のモデル | 画像 | 種類の確率(「猫 0.9」) |
| 生成モデル | 乱数(と文章などの条件) | 新しい画像 |
「本物らしい画像」は分布で考える
512 × 512 画素のカラー画像は、78 万個あまりの数の並びです。この数をでたらめに決めると、ほぼ確実に砂嵐のような画像になります。写真らしい画像は、ありうる数の並びのごく一部に集まっています。
学習用の画像がどのあたりに集まっているかを データの分布と呼びます。生成モデルの目標は、この分布をまねて、分布から新しい点を取り出せる(サンプリングできる)ようにすることです。学習用の画像をそのまま覚えて返すのではなく、同じ分布にありそうな、まだ誰も見たことのない画像を作ります。
オートエンコーダーと VAE:圧縮して戻す
オートエンコーダー:少ない数に圧縮して元に戻す
オートエンコーダーは、画像を少ない数の並びに圧縮する エンコーダー(符号化器)と、そこから元の画像を復元する デコーダー(復号器)を組み合わせたモデルです。入力と出力が同じになるように学習します。真ん中の少ない数を 潜在変数(latent variable)と呼びます。
圧縮できるのは、画像の画素がばらばらではなく、少ない要因(物の形・向き・明るさなど)でほぼ決まっているからです。4 次元のデータが実は 2 つの数でほぼ決まっている例で、圧縮する数を 1〜3 個にして復元の誤差を比べてみます。エンコーダーとデコーダーを線形(行列を掛けるだけ)にした場合、いちばん誤差の小さい圧縮は主成分分析(PCA)と同じになるので、ここでは特異値分解で求めます。
import numpy as np
# 4 次元のデータ 200 個(実は 2 つの数でほぼ決まる)
rng = np.random.default_rng(0)
z = rng.standard_normal((200, 2))
A = np.array([[1.0, 0.5, -0.3, 0.8], [0.2, -1.0, 0.7, 0.4]])
x = z @ A + 0.05 * rng.standard_normal((200, 4))
mean = x.mean(axis=0)
U, S, Vt = np.linalg.svd(x - mean, full_matrices=False)
for k in [1, 2, 3]:
code = (x - mean) @ Vt[:k].T # 符号化(k 個の数に圧縮)
recon = code @ Vt[:k] + mean # 復号
print(k, round(float(((x - recon) ** 2).mean()), 4))
実行結果:
1 0.4207
2 0.0012
3 0.0005
左が圧縮した数の個数、右が復元の誤差(2 乗誤差の平均)です。1 個では大きく崩れますが、2 個に増やすと誤差は 0.0012 まで下がり、3 個にしてもほとんど変わりません。データを作った 2 つの要因を、2 個の潜在変数でつかめたということです。実際のオートエンコーダーでは、エンコーダーとデコーダーに畳み込みのネットワークを使い、曲がった関係もつかめるようにします。
ふつうのオートエンコーダーでは新しい画像を作りにくい
デコーダーは潜在変数から画像を作れるので、潜在変数を適当に選べば新しい画像が作れそうです。ところが、ふつうのオートエンコーダーは「学習用の画像を復元できる」ことしか求められていないので、学習用の画像の潜在変数は空間のあちこちに散らばり、その間のすき間に何が対応するかは決まっていません。適当に選んだ潜在変数からは、崩れた画像が出てきがちです。
VAE:潜在変数を分布として扱う
2013 年に発表された VAE(変分オートエンコーダー)は、この問題を次のように解きました。
- エンコーダーは、潜在変数を 1 点ではなく、平均 μ と標準偏差 σ の正規分布として出す
- その分布から乱数で潜在変数を 1 つ選び、デコーダーで復元する
- 損失は「復元の誤差」と、「エンコーダーが出した分布が、平均 0・標準偏差 1 の標準正規分布からどれだけ離れているか」の和にする
2 つ目の項は KL ダイバージェンス(2 つの分布の離れ具合)で測ります。正規分布どうしなら、式で計算できます。
import numpy as np
def kl_to_standard_normal(mu, sigma):
return 0.5 * (mu**2 + sigma**2 - 1 - 2 * np.log(sigma))
for mu, sigma in [(0.0, 1.0), (1.0, 1.0), (0.0, 0.1), (3.0, 0.1)]:
print(mu, sigma, round(float(kl_to_standard_normal(mu, sigma)), 3))
# 再パラメーター化:z = μ + σ ε
rng = np.random.default_rng(0)
eps = rng.standard_normal(100000)
z = 1.0 + 0.5 * eps
print(round(float(z.mean()), 3), round(float(z.std()), 3))
実行結果:
0.0 1.0 0.0
1.0 1.0 0.5
0.0 0.1 1.808
3.0 0.1 6.308
1.0 0.5
標準正規分布そのもの(μ = 0、σ = 1)なら KL は 0 で、中心がずれたり(μ = 3)、幅がせまくなったり(σ = 0.1)するほど大きくなります。この項があるので、エンコーダーは画像ごとの潜在変数を原点のまわりに、ある程度の幅を持たせて置くようになります。その結果、潜在変数の空間がすき間なく埋まり、標準正規分布から乱数で選んだ潜在変数をデコーダーに入れれば、それらしい画像が出てくるようになります。
最後の行は、学習のための工夫である 再パラメーター化です。「分布から乱数で選ぶ」操作のままでは勾配が通らないので、標準正規分布の乱数 ε を別に作り、z = μ + σε と計算します。こうすれば、z は平均 μ・標準偏差 σ の分布に従い(ここでは 1.0 と 0.5)、μ と σ についての勾配も計算できます。
VAE は学習が安定していますが、作った画像がぼやけやすいという弱点がありました。
GAN:作る側と見分ける側を競わせる
生成器と識別器のゲーム
2014 年に発表された GAN(敵対的生成ネットワーク)は、2 つのネットワークを競わせて学習します。
| ネットワーク | 入力 | 出力 | 目標 |
|---|---|---|---|
| 生成器(Generator) | 乱数 | 画像 | 識別器をだませる、本物らしい画像を作る |
| 識別器(Discriminator) | 画像 | 本物である確率 | 本物の画像と生成器の画像を見分ける |
偽札を作る人と、偽札を見破る警察のたとえがよく使われます。警察が見破るのがうまくなると、偽札作りはもっと精巧な偽札を作るようになり、それを見破るために警察もさらに腕を上げる、というくり返しで、生成器の画像が本物に近づいていきます。
いちばん良い識別器を計算してみる
生成器を固定したとき、いちばん良い識別器は、本物の分布の密度 p_data と生成器の分布の密度 p_g から、D(x) = p_data(x) / (p_data(x) + p_g(x)) と決まることが分かっています。本物が「2 を中心とする幅 0.5 の正規分布」、生成器がまだ下手で「0 を中心とする幅 1 の正規分布」のときに計算してみます。
import numpy as np
def normal_pdf(x, mu, s):
return np.exp(-((x - mu) ** 2) / (2 * s * s)) / (s * np.sqrt(2 * np.pi))
x = np.array([-2.0, 0.0, 1.0, 2.0])
p_data = normal_pdf(x, 2.0, 0.5) # 本物の分布
p_gen = normal_pdf(x, 0.0, 1.0) # 生成器の分布
d_best = p_data / (p_data + p_gen) # いちばん良い識別器
print(np.round(d_best, 3))
# 生成器が本物と同じ分布になったとき
print(round(float(normal_pdf(1.0, 2.0, 0.5) / (2 * normal_pdf(1.0, 2.0, 0.5))), 3))
実行結果:
[0. 0.001 0.309 0.937]
0.5
x = −2 や 0 は生成器しか作らない値なので、識別器は「本物の確率はほぼ 0」と答えます。x = 2 は本物によくある値なので 0.937 です。生成器は識別器の答えが 1 に近づくように学習するので、作る値を 2 のほうへずらしていきます。
生成器の分布が本物と完全に同じになると、識別器はどの x にも 0.5(どちらとも言えない)としか答えられなくなります。これが GAN の学習のゴールです。
GAN の弱点:学習が不安定でモード崩壊が起きる
GAN は VAE よりくっきりした画像を作れ、2019 年の StyleGAN は実在しない人の顔写真を、本物と見分けがつかないほどの品質で作りました。一方で、次のような難しさがありました。
| 弱点 | 内容 |
|---|---|
| 学習が不安定 | 2 つのネットワークの力の釣り合いが崩れると、学習が進まなくなったり、発散したりする |
| モード崩壊 | 識別器をだませる数種類の画像ばかり作り、データの多様さを再現しなくなる(犬の写真を学習したのに、同じ犬種しか出てこない、など) |
拡散モデル:ノイズを少しずつ取り除く
前向きの過程:画像にノイズを足していく
拡散モデルの出発点は、「画像にノイズを少しずつ足していくと、最後は純粋なノイズになる」という単純な事実です。これを 前向きの過程(拡散過程)と呼びます。
2020 年の DDPM では、1,000 段に分けて少しずつノイズを足します。t 段目の画像 x_t は、元の画像 x_0 とノイズ ε(標準正規分布の乱数)から、1 回の計算で作れます。
x_t = √ᾱ_t · x_0 + √(1 − ᾱ_t) · ε
ᾱ_t は、段が進むほど 1 から 0 に向かって小さくなる数です。つまり、段が進むほど元の画像の割合が減り、ノイズの割合が増えます。DDPM の設定で計算してみます。
import numpy as np
T = 1000
betas = np.linspace(1e-4, 0.02, T) # 1 段ごとに足すノイズの量
alpha_bar = np.cumprod(1 - betas)
for t in [1, 100, 250, 500, 1000]:
a = alpha_bar[t - 1]
print(t, round(float(np.sqrt(a)), 4), round(float(np.sqrt(1 - a)), 4))
# x0 = 2 の点にノイズを足して x_t を作る
rng = np.random.default_rng(0)
x0 = np.full(100000, 2.0)
for t in [100, 500, 1000]:
a = alpha_bar[t - 1]
xt = np.sqrt(a) * x0 + np.sqrt(1 - a) * rng.standard_normal(x0.shape)
print(t, round(float(xt.mean()), 3), round(float(xt.std()), 3))
実行結果:
1 0.9999 0.01
100 0.9471 0.3209
250 0.7239 0.6899
500 0.2803 0.9599
1000 0.0064 1.0
100 1.894 0.321
500 0.562 0.962
1000 0.013 1.001
上の 5 行は、段の番号、元の画像に掛かる係数 √ᾱ_t、ノイズに掛かる係数 √(1 − ᾱ_t) です。250 段目でおよそ半々になり、1,000 段目では元の画像の係数が 0.0064 まで下がります。
下の 3 行は、すべて 2 だった値にノイズを足したときの平均と標準偏差です。1,000 段目では平均 0・標準偏差 1 になり、元の値が何だったかはほとんど分かりません。どんな画像から始めても、最後は同じ標準正規分布のノイズになるということです。
学習:ノイズの量を当てる
逆に、ノイズから 1 段ずつノイズを取り除いていければ、純粋なノイズから画像を作れます。これを 逆向きの過程と呼びます。1 段ぶんのノイズを取り除くには、「今の画像 x_t に含まれているノイズ ε」が分かればよいので、これをニューラルネットワークに当てさせます。
学習は次の手順のくり返しです。
- 学習用の画像 x_0 を 1 枚選ぶ
- 段の番号 t を 1〜1,000 からランダムに選び、ノイズ ε を作る
- 上の式で x_t を作り、ネットワークに x_t と t を入れてノイズを予測させる
- 予測したノイズと本当のノイズ ε の 2 乗誤差を損失にして、勾配降下法で重みを更新する
正解のノイズは自分で足したものなので、いつでも分かっています。GAN のように 2 つのネットワークを競わせる必要がなく、ふつうの回帰の問題として安定して学習できるのが、拡散モデルの大きな長所です。
ノイズを予測するネットワークには、入力と同じ大きさの出力を返す必要があるので、セグメンテーションの記事で説明した U-Net がよく使われます。
1 次元のデータでノイズから生成してみる
本物のデータが「−2 と 2 を中心とする 2 つの山」の 1 次元の分布だとして、純粋なノイズから 1,000 段かけてノイズを取り除き、このデータを作れるか試してみます。ネットワークを学習させる代わりに、この分布なら式で計算できる「正解のノイズの予測」を使います。学習がうまくいったネットワークは、これに近い値を返すはずです。
import numpy as np
T = 1000
betas = np.linspace(1e-4, 0.02, T)
alphas = 1 - betas
alpha_bar = np.cumprod(alphas)
# 本物のデータ:-2 と 2 を中心とする 2 つの山(標準偏差 0.5)
means, std = np.array([-2.0, 2.0]), 0.5
def predict_noise(x, t):
"""x_t に含まれるノイズの予測。ここでは学習の代わりに、正解の式で計算する"""
a = alpha_bar[t]
m = np.sqrt(a) * means # x_t の分布の山の中心
var = a * std**2 + (1 - a) # x_t の分布の山の分散
logw = -((x[:, None] - m) ** 2) / (2 * var)
w = np.exp(logw - logw.max(axis=1, keepdims=True))
w /= w.sum(axis=1, keepdims=True)
score = (w * (m - x[:, None]) / var).sum(axis=1) # log 密度の傾き
return -np.sqrt(1 - a) * score
rng = np.random.default_rng(0)
x = rng.standard_normal(10000) # 純粋なノイズから始める
for t in reversed(range(T)):
eps = predict_noise(x, t)
x = (x - betas[t] / np.sqrt(1 - alpha_bar[t]) * eps) / np.sqrt(alphas[t])
if t > 0:
x += np.sqrt(betas[t]) * rng.standard_normal(x.shape)
left, right = x[x < 0], x[x >= 0]
print(round(len(left) / len(x), 3), round(float(left.mean()), 3), round(float(left.std()), 3))
print(round(len(right) / len(x), 3), round(float(right.mean()), 3), round(float(right.std()), 3))
実行結果:
0.5 -2.018 0.499
0.5 2.002 0.5
1 万個の点を、0 より小さいものと大きいものに分けて、割合・平均・標準偏差を出しました。どちらの山にも半分ずつ、中心 ±2・幅 0.5 で集まっていて、本物のデータの分布をそのまま再現できています。標準正規分布という 1 つの山から始めたのに、ノイズを取り除くうちに 2 つの山に分かれました。GAN で問題になったモード崩壊(片方の山しか作らない)も起きていません。
ループの中の 1 行は、予測したノイズのうち 1 段ぶんを取り除いて少し拡大する計算で、そのあとに小さなノイズを足し直しています。足し直すのは、1 段ごとの答えに適度なばらつきを残し、多様な結果を作るためです。
速く作る工夫:段を飛ばす
DDPM の弱点は、1 枚作るのに 1,000 回ネットワークを計算する必要があり、遅いことです。2020 年の DDIM は、途中でノイズを足し直さない決まった計算に変えることで、学習はそのままに、段を飛ばして 50 回ほどの計算で画像を作れるようにしました。最近は、ノイズから画像までをなるべくまっすぐな道でつなぐように学習する フローマッチングも使われ、さらに少ない回数で作れるようになっています。
文章から画像を作る:条件付けとガイダンス
文章をベクトルにして渡す
ここまでのモデルは、「データの分布にありそうな画像」をランダムに作るだけでした。「猫の絵」のように指示どおりの画像を作るには、ノイズを予測するネットワークに、指示の文章も入力します。文章は Transformer などのモデルでベクトルの列に変え、ネットワークの中のアテンション(アテンションと Transformer のしくみ で説明したクロスアテンション)で画像の各位置から参照させます。
文章のベクトルを作るモデルには、2021 年に OpenAI が発表した CLIP がよく使われます。CLIP は、インターネットから集めた 4 億組の画像と説明文を使って、対応する画像と文章のベクトルが近くなるように学習したモデルです。
classifier-free guidance:条件の効き目を強める
条件を入れるだけでは、文章の指示が弱くしか効かないことがあります。そこで、同じネットワークで「条件ありのノイズの予測」と「条件なし(空の文章)の予測」を両方計算し、その差を強めて使います。これを classifier-free guidance と呼び、強める倍率 w を ガイダンススケールと呼びます。
import numpy as np
eps_uncond = np.array([0.20, -0.10]) # 条件なしのノイズの予測
eps_cond = np.array([0.50, 0.30]) # 「猫の絵」という条件つきの予測
for w in [0.0, 1.0, 7.5]:
print(w, np.round(eps_uncond + w * (eps_cond - eps_uncond), 2))
実行結果:
0.0 [ 0.2 -0.1]
1.0 [0.5 0.3]
7.5 [2.45 2.9 ]
w = 0 なら条件なし、w = 1 ならふつうの条件つきの予測そのものです。w = 7.5 では、「条件なし」から「条件あり」へ向かう差を 7.5 倍に伸ばしていて、「猫らしさ」を強く押し出した方向に画像が変わっていきます。Stable Diffusion では 7.5 前後がよく使われます。大きくするほど指示には忠実になりますが、色が濃すぎる・多様さが減るなどの副作用も出ます。
潜在拡散モデル:小さな潜在空間でノイズを取り除く
画素のままで拡散モデルを動かすと、1,000 段近くの計算を大きな画像のまま行うので、計算がとても重くなります。2022 年の 潜在拡散モデル(Latent Diffusion Model)は、VAE と同じ考え方のオートエンコーダーで画像をまず小さな潜在変数に圧縮し、その中で拡散モデルを動かすことでこれを解決しました。最後にデコーダーで潜在変数を画像に戻します。
このモデルを大規模に学習して公開したのが Stable Diffusion です。512 × 512 画素の画像を、64 × 64 × 4 の潜在変数で扱います。
pixel = 512 * 512 * 3
latent = 64 * 64 * 4
print(f"{pixel:,}", f"{latent:,}", pixel / latent)
実行結果:
786,432 16,384 48.0
扱う数が 78 万個から 1.6 万個と 48 分の 1 になり、家庭用の GPU でも画像を作れるようになりました。細かい模様の再現はオートエンコーダーに任せ、拡散モデルは構図や物の配置といった大きな意味の部分に集中できる、という役割分担にもなっています。
最近は、ノイズを予測するネットワークを U-Net から Transformer に置き換えた DiT(Diffusion Transformer)も使われています。
評価のしかた:FID
画像生成のモデルの良し悪しは、「1 枚 1 枚が本物らしいか」と「全体として本物と同じくらい多様か」の両方で決まります。よく使われる FID(Fréchet Inception Distance)は、本物の画像と生成した画像を、学習済みの画像分類のモデル(Inception-v3)に通して特徴のベクトルを取り出し、2 つの集まりの 平均と分散共分散の違いを測る指標です。小さいほど良いモデルです。
特徴が 1 次元なら、FID は「平均の差の 2 乗 + 標準偏差の差の 2 乗」になります。2 つの山のデータに対して、3 種類の生成モデルの出力を比べてみます。
import numpy as np
def fid_1d(a, b):
"""1 次元の特徴での FID:平均の差の 2 乗 + 標準偏差の差の 2 乗"""
return (a.mean() - b.mean()) ** 2 + (a.std() - b.std()) ** 2
rng = np.random.default_rng(1)
real = rng.choice([-2.0, 2.0], 10000) + 0.5 * rng.standard_normal(10000)
good = rng.choice([-2.0, 2.0], 10000) + 0.5 * rng.standard_normal(10000)
collapsed = 2.0 + 0.5 * rng.standard_normal(10000) # 片方の山しか作らない
blurry = 1.0 * rng.standard_normal(10000) # 山の間を平均した、ぼやけた分布
for name, x in [("good", good), ("collapsed", collapsed), ("blurry", blurry)]:
print(name, round(float(fid_1d(real, x)), 4))
実行結果:
good 0.0001
collapsed 6.4364
blurry 1.1244
本物と同じ分布から作った good はほぼ 0、片方の山しか作らない collapsed(モード崩壊)は平均が大きくずれて 6.44、山の区別がつかないぼやけた blurry は幅が足りずに 1.12 になりました。
ただし、FID が見ているのは平均と分散共分散だけです。たとえば、平均 0・標準偏差 2.06 の 1 つの山(本物の 2 つの山と同じ平均と標準偏差)を作るモデルは、2 つの山をまったく再現していないのに、この 1 次元の例では FID がほぼ 0 になります。実際の FID は 2,048 次元の特徴で計算するので、ここまで極端なことは起きにくいですが、数値だけでなく、生成した画像を目で見て確かめることも欠かせません。
画像生成の手法の流れ
この記事で紹介した手法を年代順に並べます。研究者や企業の動きは AI 開発のキープレイヤー年表 にまとめています。
| 年 | 手法・モデル | 種類 | ポイント |
|---|---|---|---|
| 2013 | VAE | VAE | 潜在変数を正規分布として扱い、乱数から画像を作れるようにする |
| 2014 | GAN | GAN | 生成器と識別器を競わせて学習する |
| 2015 | 拡散確率モデル(Sohl-Dickstein ら) | 拡散 | ノイズを足す過程を逆にたどって生成するという考え方を提案 |
| 2015 | DCGAN | GAN | 畳み込みを使い、GAN の学習を安定させる設計をまとめる |
| 2017 | VQ-VAE | VAE | 潜在変数を決まった候補の中から選ぶ形にする |
| 2017 | FID | 評価 | 特徴の平均と分散共分散で、本物と生成した画像の違いを測る |
| 2019 | StyleGAN | GAN | 実在しない人の顔写真を、本物と見分けがつかない品質で作る |
| 2020 | DDPM | 拡散 | ノイズを当てる問題として学習し、高い品質の画像を作る |
| 2020 | DDIM | 拡散 | 段を飛ばして、少ない計算回数で画像を作る |
| 2021 | 「Diffusion Models Beat GANs」 | 拡散 | 拡散モデルが画像の品質で GAN を上回る |
| 2021 | CLIP | 条件付け | 画像と文章を同じベクトルの空間に置く |
| 2021 | classifier-free guidance | 条件付け | 条件ありとなしの予測の差を強めて、指示を効かせる |
| 2022 | 潜在拡散モデル・Stable Diffusion | 拡散 | 圧縮した潜在変数の中で拡散モデルを動かし、計算を軽くする |
| 2022 | DALL·E 2・Imagen | 拡散 | 文章から高い品質の画像を作る |
| 2023 | DiT | 拡散 | ノイズを予測するネットワークを Transformer にする |
| 2023 | フローマッチング | 拡散の仲間 | ノイズから画像までをまっすぐな道でつなぎ、少ない回数で作る |
まとめ
- 生成モデルは、学習用のデータの分布をまねて、その分布から新しいデータを取り出せるようにするモデル
- オートエンコーダーは、画像を少ない数の潜在変数に圧縮して復元する。VAE は潜在変数を正規分布として扱い、KL ダイバージェンスの項で原点のまわりにすき間なく並べることで、乱数から画像を作れるようにした
- GAN は、生成器と識別器を競わせて本物らしい画像を作る。くっきりした画像を作れるが、学習が不安定で、モード崩壊が起きやすい
- 拡散モデルは、画像にノイズを足していく過程を逆にたどる。学習は「画像に含まれるノイズを当てる」回帰の問題なので安定している
- 1 次元の例でも、ノイズを 1,000 段かけて取り除くと、2 つの山の分布をそのまま再現できた
- 文章から画像を作るには、文章のベクトルをクロスアテンションで渡し、classifier-free guidance で条件の効き目を強める
- Stable Diffusion は、画像を 48 分の 1 の潜在変数に圧縮してから拡散モデルを動かすことで、計算を軽くした
- 評価には FID がよく使われるが、平均と分散共分散しか見ていないので、生成した画像を目で確かめることも必要
参考
- D. P. Kingma and M. Welling, "Auto-Encoding Variational Bayes", ICLR 2014(arXiv:1312.6114)
- I. Goodfellow et al., "Generative Adversarial Nets", NeurIPS 2014(arXiv:1406.2661)
- J. Sohl-Dickstein et al., "Deep Unsupervised Learning using Nonequilibrium Thermodynamics", ICML 2015(arXiv:1503.03585)
- A. Radford et al., "Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks", ICLR 2016(arXiv:1511.06434)
- A. van den Oord et al., "Neural Discrete Representation Learning", NeurIPS 2017(arXiv:1711.00937)
- M. Heusel et al., "GANs Trained by a Two Time-Scale Update Rule Converge to a Local Nash Equilibrium", NeurIPS 2017(arXiv:1706.08500)
- T. Karras et al., "A Style-Based Generator Architecture for Generative Adversarial Networks", CVPR 2019(arXiv:1812.04948)
- J. Ho et al., "Denoising Diffusion Probabilistic Models", NeurIPS 2020(arXiv:2006.11239)
- J. Song et al., "Denoising Diffusion Implicit Models", ICLR 2021(arXiv:2010.02502)
- P. Dhariwal and A. Nichol, "Diffusion Models Beat GANs on Image Synthesis", NeurIPS 2021(arXiv:2105.05233)
- A. Radford et al., "Learning Transferable Visual Models From Natural Language Supervision", ICML 2021(arXiv:2103.00020)
- J. Ho and T. Salimans, "Classifier-Free Diffusion Guidance", 2021(arXiv:2207.12598)
- R. Rombach et al., "High-Resolution Image Synthesis with Latent Diffusion Models", CVPR 2022(arXiv:2112.10752)
- A. Ramesh et al., "Hierarchical Text-Conditional Image Generation with CLIP Latents", 2022(arXiv:2204.06125)
- C. Saharia et al., "Photorealistic Text-to-Image Diffusion Models with Deep Language Understanding", NeurIPS 2022(arXiv:2205.11487)
- W. Peebles and S. Xie, "Scalable Diffusion Models with Transformers", ICCV 2023(arXiv:2212.09748)
- Y. Lipman et al., "Flow Matching for Generative Modeling", ICLR 2023(arXiv:2210.02747)