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

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

誰でもわかるStable Diffusion テキストエンコーダー:CLIPのしくみ

以前の記事でStable Diffusionがどのように絵を描いているか順番に解説しました。

その中で特に重要な働きをするモジュール「テキストエンコーダー」については少し紹介しただけであまり詳しく解説しなかったので、今回はテキストエンコーダーについて少し詳しく見てみます。

 

 

テキストエンコーダーとは

テキストエンコーダーとは、その名の通り「テキスト」を「エンコード」(つまり変換)するモジュールです。

テキストとは、「picture of black cat」のような、人間が理解できる文章のことです*1。テキストエンコーダーはこれを「ベクトル」の集まりに変換します。

ベクトルとは数字の集まりです。通常は[0.5 0.2 0.3]のように数字をカッコでくくって、これを1つのベクトルと呼びます。カッコの中の数字の数は「次元」と呼ばれます。数字を3つ持つベクトルは「3次元ベクトル」です。次元が増えれば持てる情報量も増えます。

テキストをベクトルに変換
テキストエンコーダーがやってるのはこれだけ

なぜテキストをベクトルに変換するのかといえば、数字の方が機械にとって扱いやすいからです。数字であれば計算できます。また、絵とテキストをどちらもベクトルに変換すれば、それらが似ているか、違うならどれくらい違うか、などを数字で直接比較できるようになります。

 

Stable Diffusionでのテキストエンコーダーの役割

テキストエンコーダーはStable Diffusion内ではどういう風に使われるのでしょう?

Stable Diffusionは「プロンプト」と呼ばれるテキストをユーザーから受け取り、それをもとに絵を描きます。Stable Diffusionが絵を描くには、まずプロンプトに何が書かれているかをStable Diffusionが理解しなければいけません。Stable Diffusionが唯一理解できる言葉、それはベクトルです。つまりプロンプトをベクトルに「翻訳」する必要がありますが、Stable Diffusion本体にはその機能はありません。そこで、テキストエンコーダーにプロンプトを翻訳させるのです。

つまり、テキストエンコーダーはStable Diffusion自体の機能ではありません!そのため、テキストエンコーダーをどこか他から持ってくる必要があります。Stable Diffusionはそれを「CLIP」という別の仕組みから借りてきています。

テキストエンコーダーはCLIPから借りてきてます

 

CLIPは実際はテキストエンコーダーのほかに「イメージエンコーダー」(後述)を持っていますが、Stable Diffusionはテキストエンコーダーのみを利用しています。

ちなみにバージョン1系とバージョン2系のStable Diffusionは使っているテキストエンコーダーが違います。バージョン2系のテキストエンコーダーは「OpenCLIP」という、もともとのCLIPをさらにグレードアップさせたものを使っています。

 

CLIPとは

「CLIP」とは、「与えられた画像にテキストラベルをつけてクラス分けする」ために作られたモデルです。ChatGPTで有名なOpenAI社が2021年に発表しました。

例えば学習済み(つまり完成版の)CLIPにネコの絵を入れると、「cat」というラベルをつけてくれます。どんなネコの絵を入れても、だいたい「cat」というラベルをつけてくれるようになっています(もちろん完璧というわけではありませんが)。そのほか、学習したいろいろな画像をもとに、複雑な画像を的確にラベル付けしてくれる優秀なモデルです。

CLIPはワカモレの写真もちゃんと「ワカモレ」とラベル付けしてくれます
私はワカモレなんて知らなかった…

 

上でも説明した通り、CLIPは「テキストエンコーダー」と「イメージエンコーダー」からできています。テキストエンコーダーの機能は上で説明した通り、テキストをベクトルに変換することです。一方、イメージエンコーダーは画像をベクトルに変換する機能を持ちます。つまり、CLIPはテキストと画像の両方を読み込むことができるのです。

 

CLIPが賢くなるしくみ

さて、CLIPは他の人工知能と同じく、最初は何もできません。テキストも画像も何も知らないからです。そこで、賢くするために学習を行う必要があります。

学習には「テキストラベル付き画像」を使います。これを大量に読み込ませて、少しずつ賢くします。

学習は以下のような手順で行われます。

  1. 大量のラベル付き画像から決まった数だけランダムに取り出し、それらを1つにまとめる(ラベル集、画像集)。
  2. ラベル集をテキストエンコーダーに、画像集をイメージエンコーダーに入れる。
  3. テキストエンコーダーから、それぞれのラベルに応じたベクトル(テキストベクトル集)が出てくる。
  4. 同時に、イメージエンコーダーから、それぞれの画像に応じたベクトル(画像ベクトル集)が出てくる。
  5. テキストベクトル集と画像ベクトル集を比べる。ペアになっているラベルと画像のベクトルが似たベクトルとなるように、テキストエンコーダーとイメージエンコーダーを調整する。
  6. 大量の画像を使って学習を膨大な数繰り返す

CLIPの学習方法

しつこいようですが、CLIPはStable Diffusionではありません。CLIPの学習はStable Diffusionとは全く別に行われたもので、Stable Diffusionは学習済みのCLIPテキストエンコーダーを使っているだけです。そのため、Stable Diffusionモデルの学習ではテキストエンコーダーは全く変化しません*2

 

CLIPの利用法

学習後のCLIPは、テキストエンコーダーとイメージエンコーダーがよく協調して、ペアになるラベルと画像を入れるとどちらのエンコーダーも似たようなベクトルを出力するようになります。つまり画像「だけ」を入れたときにイメージエンコーダーから出てくるベクトルと、ラベル「たけ」を入れたときにテキストエンコーダーから出てくるベクトルを比べることで、それが何の画像か判断できるわけです。例えば、ある画像を入れて出てきたベクトルが「dog」というラベルのベクトルとよく似ていれば、その画像は「犬の画像」といえるわけです。

こんな感じでCLIPは画像のラベル付けができるわけですが、そのほかにもStable Diffusionにとって重要な特徴があります。それが「分類化」です。

「分類化」とは、「似たような画像は似たようなベクトルに、似てない画像は全然似てないベクトルに」画像を変換する性質です。ラベルについても同様に、「似たような概念は似たようなベクトルに、似ていない概念は全然似てないベクトルに」変換されます。

先ほどの「dog」画像のベクトルですが、もしかしたら「cat」画像のベクトルともちょっとは似ているかもしれません。一方「house」というラベルのベクトルとは全然似ていないでしょう。dogとcatの画像ベクトルが少し似ているのは、どちらも4つの脚を持つ毛の生えた哺乳類動物だからです。houseは生き物でなく形も特徴も犬と全然違うので、全然違うベクトルになるでしょう。

Stable Diffusionはこのような性質を応用して「学習したことがない画像」を描き出すことができます。「cat」と「dog」の中間ぐらいのベクトルであれば、どちらの特徴も取り入れて「ネコっぽくもあり犬っぽくもある」絵を描きます。

 

テキストエンコーダーのしくみ

テキストエンコーダーとイメージエンコーダは「Transformer」というメカニズムによってベクトル変換を行っています。Transformerの概要については以前の記事で中身を説明したので読んでみてください。

 

hoshikat.hatenablog.com

 

イメージエンコーダーはStable Diffusionでは使わないので、テキストエンコーダーのみ仕組みの概要を説明します。

テキストエンコーダーは「Tokenizer」と「Transformerのデコーダーブロック」からなっています。

※Transformerは本来「エンコーダー」と「デコーダー」の2つのブロックからできていますが、ここでは「デコーダーブロック」のみ使っています。

 

テキストエンコーダーは実質Transformer

入力されたテキスト(プロンプト)はまずTokenizer(トークナイザー)に送られます。トークナイザーは与えられたテキストを「トークン」に切り分けます。トークンとはテキストエンコーダーが処理できる単語の最小単位です。なぜ単語のままでなくてトークンに切り分けるかは、その方が機械にとって都合がいいから、というだけです。

CLIPのテキストエンコーダーで一度に処理できるトークンは77個が最大です。もしトークン数が77を超える場合、超えた分は次回の処理に回されます。

※この77個ルールで別々になってしまったトークンはまったく別のテキストとして扱われるため、つながりが無くなってしまいます。Stable Diffusionのプロンプトで長い文章を入力するときは注意しましょう。

 

トークナイザーは49408個のトークンを含むトークン辞書を持っています。単語や記号(スペースは除く)はこの辞書に従ってトークンごとに「トークンID」に変換されます*3。このIDはひとつの数字で、ベクトルではありません。例えば「cat」というトークンのIDは「1481」です。

トークンIDは次に、ベクトルに変換されます。まず0を49408個含んだベクトル(49408次元ベクトル)を用意します。このベクトルに並ぶ0のうち、ID+1番目だけを1にします。catでいうと1482番目の0を1に変えます。このように、IDに対応する数字だけを1にすると49408通りのベクトルが作れるので、これらのベクトルによってトークンを表現することができます。

このトークンベクトルをトークンの数だけ作ります。もしトークンが3つあれば49408次元ベクトルが3つ作られます。

 

トークナイザーで作られたこれらのベクトルは、いっぺんにTransformerに送られます。トークンの順番は非常に重要なので、順番を保ったまま送られます。

Transformerはこのトークンの順番ごとに番号を割り振ります。Stable Diffusionでは前のほうに書かれた単語が重要視されますが、その重要度はここで振られた番号によって決められます。

Transformerのこれ以上の詳しい説明はしませんが、入力されたベクトルはいろいろな処理を経て変換され、768次元ベクトルに変換されます(Stable Diffusionバージョン1系の場合)。これがStable DiffusionのU-Netに送られて画像生成に使われます。

 

まとめ

Stable Diffusionに入力されたプロンプトは、処理しやすくするためにベクトルに変換されますが、それを行うのがCLIPのテキストエンコーダーです。

CLIPはStable Diffusionとは全く別の仕組みで、画像をテキストラベルによってクラス分けするために提案されたものです。CLIPはテキストエンコーダーとイメージエンコーダーからなり、ペアになる画像とラベルで似たようなベクトルを出力するように学習されます。Stable Diffusionはこのテキストエンコーダーだけを使って画像生成を行っています。

テキストエンコーダーの中身は実質Transformerです。Transformerについて少し詳しく知りたい方は以前の記事をご覧ください。

*1:ちなみに2023年6月時点ではStable Diffusionは英語しか使えません。

*2:ただしTextual inversionやLoRAなど追加学習で賢くすることは可能です

*3:ちなみに、もしこの辞書にない単語が入力されたら、極端な場合その単語は1文字ずつ切り分けられ、それぞれ別トークンとして処理されます。