人工知能と親しくなるブログ

人工知能に関するトピックを取り上げるブログです

誰でもわかるStable Diffusion その1:しくみ

誰でもというか、自分のために書いてます。

 

 

Stable Diffusionとは

Stable Diffusion(ステーブル ディフュージョン)とは、指示した通りに絵を描いてくれる、いわゆる「人工知能絵描き」です。

これ以前もそれっぽいものはいくつかありましたが、Stable Diffusionの登場で世界が一変しました。

Stable Diffusionの特徴は以下の2つです。

  • とにかく絵のクオリティが高い、人間の描く絵や写真と区別がつかないこともある

  • オープンソース(しくみが完全に公開されている)。完全無料で誰でも使える

こんなすごい技術ですが、突然現れたテクノロジーというわけではなく、2015年ごろから徐々に発表されてきた様々な技術をいくつも組み合わせて作られています。

ここでは、Stable Diffusionにどんな技術が使われているのかを見てみましょう。

 

Stable Diffusionの構造を図で表したものですが
これだけで見て理解できる人はいないでしょう

 

Diffusionモデル: Stable Diffusionの心臓部

あなたが絵を描くとき、まず真っ白な紙(画像)を用意するでしょう。そこに線を描いたり色を描いたりして絵を仕上げていくのが普通です。

Stable Diffusionはそのように絵を描きません。例えばネコの絵を描くとき、まずノイズだらけの画像を用意します。「ノイズだらけの画像」というのは、テレビで何も放送されていないときの砂嵐画像を思い浮かべてもらえればいいと思います。あれは白黒ですが、Stable Diffusionではカラーの砂嵐を用意します。

ランダムに作ったノイズの画像。
ここからノイズを取り除いていって最終的に絵を浮かび上がらせます

次に、そのノイズ画像から少しだけノイズを取り除きます。ノイズを取り除くどうなるかといえば、少しだけ、ぼんやりと何かが見えてきます。

ぼんやり

もういちどそこから少しだけノイズを取り除きます。そうすると、ぼんやり見えていたものがほんの少しはっきりしてきます。

何度も何度も少しだけノイズを引くと、ぼんやりしていたものが最終的にはっきりとしたネコの形になり、完全なネコの画像になります。

Stable Diffusionでは最大1000回ノイズを取り除きます(ただし1000回も取り除かなくても十分きれいな画像になります)。

このように、ノイズを少しずつ取り除いていって最終的に絵だけを浮かび上がらせる手法をDiffusionモデルと言います。これがStable Diffusionの核となる技術です。

技術的な話

ノイズ除去にはU-Net(ユーネット)という方法が使われています

 

black cat」と指定して最終的に出てきた絵

 

Text Encoder: 指定された言葉を理解し、絵のデザインを決める

Stable Diffusionの最大の特徴は「指定された通りに絵を描く」ことですが、そのためには、ユーザーから指定された言葉を理解して、どういう絵を描くか考える必要があります。

Text Encoderがその役割を担います。これには2つの機能があります。1つ目は言葉を理解する機能、2つ目はその言葉とマッチする絵の情報を取り出す機能です。

技術的な話

Text EncoderにはCLIP(クリップ)という手法が使われています。この手法を使うと、与えられた言葉とそれに対応する画像を結びつけることができます。

 

言葉を理解する

Stable Diffusionは機械で動くので、人間の言葉そのままでは理解できません。機械が理解できるのは数字です。なのでText Encoderは言葉を数字の列(別名「ベクトル」)に直します

人間がStable Diffusionに指定するテキストの事を「プロンプト」と言います。例えば「black cat」と指定してみます。これはまず「トーク」という単位に分割されます。トークンとは、基本的に単語と考えて差し支えありませんが、1単語が2トークンだったりする場合もあります(その方が機械にとって扱いやすいというだけです)。「black cat」の例では「black」と「cat」の2トークンです。

この2つのトークンがText Encoderに送られ、そこでいろんな処理(ここでは詳しく説明しません)が行われ、複数の数字の列(ベクトル)が作成されます。1つのトークンを入れると、それが1つのベクトルとなって出てきます。複数のトークンを入れると、複数のベクトルが出てきます。つまり「black」というトークンに対応するベクトル、「cat」というトークンに対応するベクトルが同時に出てくるわけです*1

このベクトルには、いろいろな情報が含まれています。トークンが指定されたプロンプトの何番目の位置にあるか、プロンプトの他のトークンとどういう関係を持っているかなど、Stable Diffusionがプロンプトを正しく理解するための情報です。

例で挙げた「black cat」の中の「black」は「黒い色」という意味で使われていますが、もし「black Friday」というプロンプトだった場合、「black」は「黒字の」という意味になります(あるいはblack Fridayひとまとめで「セール」の意味になるでしょう)。両者の「black」は意味が違うので、たとえ同じ単語であっても出てくる数字の列は違います。

ベクトルをまとめると「行列」になりますが、この記事では「複数のベクトル」という扱いにしておきます

 

言葉から絵のデザインを決める

上で出てきた「ベクトル化した言葉」は、対応する画像の情報に変換することができます。変換された後の画像の情報として、768個の数字からなるベクトルが複数(77個)出てきます。

画像情報を含むためにはもちろん「black cat」に対応する画像情報をあらかじめ知っていなければなりません。この「知っている」という意味は「blackに関する画像とcatに関する画像を学習済み」という意味です。

学習についてはこの記事の下の方を見てください。

 

こうして出てきたベクトルたちは生成途中の画像の今の状態に影響を与えます。上の例の場合では、最終的に「黒いネコ」の画像が出てくるように(ノイズ入りの)今の画像を描き替えます。

大ざっぱに説明すると、出てきた「プロンプト由来の画像情報」と、いま生成している途中の「画像の今の状態」を比べて、今ふさわしい状態のそれっぽい絵を新たに作り出します*2。「画像の今の状態」(これもベクトルに変換されていますが、この記事ではこの変換については説明しません)には、現在どの生成段階にいるかなどの情報が入っているので、それも考慮してノイズ量なども調節されます。

 

Latent Space:データを圧縮して処理

Diffusionモデルのパートで「ノイズ画像からノイズを少しずつ取り除く」という説明をしましたが、これはとても処理の重い作業で、とんでもないマシンパワーと時間が必要になります。

そこでStable Diffusionでは、まず画像を圧縮して小さくしてから、それを処理し、処理が終わった後でまた画像に戻して出力するという方法をとっています。この画像圧縮が「Latent Space」です。Latentとは「潜在の」というような意味ですが、意味はあまり気にしないで構いません。要するに圧縮です。

例えば512X512ピクセルの画像を描きたいとします。この画像の総ピクセル数は26万2144です。しかも、ピクセルごとにRGBの3つの色データを持っています。つまり512X512X3=78万6432個の情報をそれぞれ処理する必要があります。決してサイズの大きくない画像ですが、すでに膨大な処理です。

そこで、この画像情報をLatent Spaceのデータに変換します。詳しい説明は省きますが、変換後は画像の幅、高さがそれぞれ8分の1になります。総データ数で比べると1/8X1/8=1/64、つまりサイズだけを比べればデータ量が64分の1になり(512X512の実際の画像データ量は1万6384)、これは相当な処理の軽減になります。

ノイズ除去作業はこのLatent Spaceで行われます。圧縮したデータなので、これはもはや画像ではありません。すべての処理が終わった後、圧縮を展開します。そうすると画像に戻ります。

ノイズ除去処理は何度も繰り返し行われるのに対し、Latent Spaceへの変換はノイズ除去処理を始める前に1度だけ行われます。同じように、画像生成処理の終了後にLatent Spaceから画像への変換が1度だけ行われます。

技術的な話

Latent Spaceへの変換、逆変換にはVariational Auto Encoder (VAE)が使われます。

 

事前学習: Stable Diffusionを鍛えるしくみ

Stable Diffusionは「しくみ」であって、それだけ用意していきなり「黒いネコの絵を描け」と言われても描けません。それはまるで生れたての赤ちゃんのようで、今は何もできませんが鍛えればどんどんできることが増えていきます。この鍛える作業の事を「学習」と言います。

これこそStable Diffusionが「人工知能」と呼ばれるゆえんで、ちゃんとした絵を描いてもらうには事前にたくさんの絵と言葉(絵につけられたキャプション)を使って賢くしておかなければなりません。

Stable Diffusionは2つの学習を行います。1つ目は絵に乗っているノイズを予測するための学習、2つ目は与えられた言葉からふさわしい絵を予測するための学習です。

 

絵に乗っているノイズを予測するための学習

ノイズだらけの画像から適当にノイズを少しずつ取り除いても、きれいな画像ができるわけがありません。白身と黄身がかき混ぜられた状態から少しずつ白身と黄身が混ざる前の状態に戻すようなものです。だから、ノイズを取り除くにしても「賢く」取り除いていく必要があります。

Stable Diffusionを賢くするには以下のように学習させます。

  • ノイズのない、きれいな画像を用意する。

  • この画像に、ノイズを乗せる。ノイズの量は、少しだったり、たくさんだったり、毎回変える

  • Diffusionモデルにノイズ入りの画像を入力し、「その画像に乗っているノイズ」を予測してもらう

  • 答えが間違っていたら、モデルを修正して、ちょっと賢くする

  • これを膨大な数繰り返しているうちに、モデルがだんだんと「画像に乗っているノイズ」を予測できるようになる

さて、画像に乗っているノイズを予測できるようになると、何がうれしいのでしょう?

 

ノイズの乗っている画像=きれいな画像+ノイズ

 

です。ノイズの乗っている画像から予測されたノイズを引くと

 

ノイズの乗っている画像ー予測ノイズ=きれいな画像+ノイズー予測ノイズ

 

右の部分に注目してください。もし、予測ノイズが本当のノイズに限りなく近い場合、

 

きれいな画像+(ノイズー予測ノイズ) → きれいな画像

 

となって、きれいな画像を得られます。

ここで、Diffusionモデルについて思い出してください。まず「ノイズ画像」を用意すると言いましたが、この「ノイズ画像」は

 

ノイズ画像=きれいな画像+ものすごくたくさんのノイズ

 

と考えることができます。ならば、もしモデルが十分に賢い場合、そこに乗っているノイズを予測することもできるはずです。

というわけで、Diffusionモデルはノイズを予測し、ノイズ画像からノイズを取り除いていきます。ただし、ものすごくたくさんのノイズを一気に予測することは難しいので、少しずつノイズを取り除きます。

ここまで賢くなるのに、何枚の画像を使って学習しなければいけないのでしょう?Stable Diffusionが公式に公開したモデルでは、なんと23億枚の画像を使って学習しているそうです。

 

言葉と画像を結びつけるための学習

Stable Diffusionは与えられたプロンプトによって絵を描くわけですから、当然どのテキストがどの絵に対応するかを知っていなければなりません。これも事前に学習しておきます*3

学習には上でちらっと書いたCLIPが使われます。学習で使われる画像には、キャプションがそれぞれついています。画像とキャプションを入力し、この二つが強く結びつくように学習します。

こうして言葉と画像の結びつきを賢くして、のちにStable Diffusionが入力プロンプトに対応する画像を思い出してその画像を取り出すことができるようにします。

2つの学習によって賢くなった「人工知能の脳みそ」は「チェックポイント」または単に「モデル」と呼ばれ、.ckptまたは.safetenrosという拡張子が付いたファイルとして多く公開されています。これらの公開モデルをダウンロードすれば自分で1から学習させる必要はありません。「脳みそ」が変われば描かれる絵もガラッと変わるので、モデルを取り換えながら絵を描かせてみるのも面白いかもしれません。

 

まとめ

Stable Diffusionとは1つの技術というわけではなく、いくつかの手法が組み合わさって動いています。ノイズから画像を浮かび上がらせていくDiffusionモデル、テキストを処理するText Encoder、データの圧縮展開を担うLatent Spaceが代表的なものです。

さらに、これらが賢く動くために膨大な画像とテキストを使って事前に学習をする必要があります。この学習によって、Stable Diffusionは絵を描けるようになるのです。

*1:実際はベクトルの数は77で固定です。トークンが77より少ない場合は空のトークンで埋めて、つねに77トークンになるようにします

*2:実際は絵でなく「絵に乗っているであろうノイズ」を作り出します。例えばネコの絵を描いているときは、「ネコではない」要素がノイズです。これをもとのノイズ入りの絵から引けばネコっぽい要素だけが残っていくというしくみです。学習の項目にもう少し詳しく書いてあります。

*3:テキストに関してはStable Diffusion専用に学習させたわけではなく、既存の学習済みデータを利用しているようです