AI を自分好みに調整できる、追加学習まとめ ( その4: Imagic )
こんにちはこんばんは、teftef です。今回も追加学習手法についてです。今回はTextual Inversion , DreamBooth に引き続きファインチューニングの変わり種である Imagic についてです。Imagic はファインチューニングに用いる画像が入力画像の 1 枚の 1 shot の手法で、その入力画像の固有性を維持しながら、画像編集ができるという手法です。
私もまだ初学者であり、説明が間違っていたり勘違いがある可能性が 0 ではないということをご了承ください。ぜひコメントなどをいただけたら幸いです。
それでは行きます。
使用した論文
今回、使用した論文はこちら
問題提起
このところ勢いがある画像生成 AI は自然言語からなる Prompt に沿った高解像度 (高品質) な画像を生成することができます。しかしこの自分の好みの絵を生成してくれるモデルを作成するためには大量の画像データ、時間、電気代や GPU リソースが必要となります。モデルのパラメーター数(サイズ) は年々増加傾向にあり、例えば Stable Diffusion では 10 億近く、自然言語処理で使用される GPT-3 モデルのパラメーター数は 1750 億ほどのパラメーター数となっています。当然これだけのものを学習するためには膨大な量の計算資源が必要となります。
そこで、こういうことは企業に任せて、学習されたモデルを自分好みに調整しようというのが追加学習でした。そして手法には様々なものがあり(この記事をご覧ください)、ベンチャー企業が画像生成モデルを作成し、サービスを提供できる程度の大きさから、個人でも GPU があれば学習できるようなもの、 Google Colab のような Web サービスを借りて学習できるようなものまでさまざまあります。
追加学習の中でも数千、数万枚の画像データを要求されるものから 100 枚ほどでできるものがありますが、それでも画像が足りない場合があります。
また、今までの記事同様
共通認識のある固有名詞が存在しない (個人の所有物など)
言語化することが難しい
ようなものを Text-to-image モデルに出力させることはいまだに困難なのです。
従来手法
そこでこれを克服するために 3~5 枚ほどの画像を用いて追加学習する手法として Textual Inversion や DreamBooth を紹介しました。
本論文の目標
しかし 3~5 枚の画像も用意できない!画像の一部をレタッチするのは面倒で、 Prompt を打つだけでレタッチをやりたい!ということに対応したのが今回の Imagic という手法です。今回改善したい問題点をまとめると
画像の上に絵や図を追加して画像編集をするとき、特定の部分しか変更されない(or 変更されたくない部分も変更されてしまう) こと (下図)
編集の際にただ画像を入力するだけでなく、どの部分をどのように編集するのか、どんなスタイルにするのかを説明するためのサンプル画像が必要になる
そのモデルが入力画像の生成に対応しておらず(学習していないため) 入力画像の固有性が保存されない
となります。
Imagic
今回は入力画像にケーキを使います。このケーキの画像を固有性を保ったままピスタチオ味に変えることが目的です。Prompt : "A photo of a pistachio cake" を使って入力画像と同じようなピスタチオ味のケーキを作ることが目的です。注意として、入力画像と Prompt はセットである必要があります。
ステップ1 : Text Embedding の探索
準備
まずは編集したい画像を用意します。今回はケーキの画像を用意しました。この画像、特に背景をよく覚えておいてください。そして続いて学習済みの Diffusion Model と編集したい Prompt を用意します。今回はピスタチオ味のケーキにしたいので "A photo of a pistachio cake" としました。
使用する Prompt は入力画像と遠すぎてはいけません。Imagic はあくまでも画像編集が目的なので、編集したい入力画像からかけ離れたもので行けません。例えば今回の入力はケーキなのに Prompt : "A beautiful girl " と入力してもうまくいかず、"A strawberry cake" , "A slice of cake" のようなケーキに関するものが好ましいです。Prompt を決めたらこれ以降変えることはできません。
Text Embedding の探索
材料がそろったので、まずは Prompt : "A photo of a pistachio cake" の Embedding を Encoderを通して抽出します。この時の Embedding を e_tgt とします。この e_tgt (Prompt : "A photo of a pistachio cake" の Embedding ) を使って用意した学習済みの Diffusion Model を使って画像生成をするともちろんピスタチオケーキが出てきます。
しかし (もちろん) このように入力画像のホールケーキとはかけ離れています。これを頑張って入力画像に最も近いケーキが生成されるような Embedding を探します。
損失関数
損失関数はこのようになっていて f_θ を固定して e を探索します。 e_tgt (Prompt : "A photo of a pistachio cake" の Embedding ) で生成した画像と入力画像を比べて、なるだけ入力画像に近づくような Embeddin e_opt を探し出します。
途中経過
ちなみにこの e_opt どれだけ近づけるかというと、入力画像と比べてみるとこのようになります。
だいぶ再構成されていることがわかります。ちなみに e_tgt (Prompt : "A photo of a pistachio cake" の Embedding)と e_opt を使って最初に用意した学習済みモデルを使って画像生成した結果を比較すると下図のようになります。(ごめんね画像ガビガビで)
このステップでは、入力画像を生成する Embedding e_opt を探しています 。
ステップ2 : ファインチューニング
ここでは生成された画像が先ほど探した e_opt と入力画像を使って学習済み Diffusion Model (の Unet )をファインチューニング (再学習) します。これをすることで学習済み Diffusion Model は入力画像のある意味過学習状態(というかもうオーバーフィットしてる)になるまでファインチューニングします。
さらに高解像度モデル(super-resolution models) も同様にファインチューニングします。この高解像度モデルは後々使います。
損失関数
ここで使う損失関数はまたもや再構成です。損失関数はこのようになっていて e を固定して f_θ を学習します。これをすることで e_opt を入れても、Diffusion Model が入力画像のケーキを生成してくれるように刷り込ませます。直感的に説明すると、 Prompt を入れても入力画像から離れすぎないような画像を出してくれるように Diffusion Model を調整している感じです。
ステップ3 : e_opt と e_tgt の Interpolation
Interpolation
まず Interpolation についてはこちらの記事で解説しています。簡単に言うと2つの画像を用意してそれらの間をこんな感じで滑らかに変化させたときの中間表現を取り出すことです。
画像生成
最適化された埋め込み e_opt で入力画像xを完全に再現するように学習された Diffusion Model を使って最後に目的のピスタチオケーキを生成します。しかしここで e_tgt (Prompt : "A photo of a pistachio cake" の Embedding ) を使って生成するとこのように入力画像のケーキから少し離れてしまいます。
図を見るとファインチューニング後のモデルは e_opt を用いて入力画像が再構成されるようにファインチューニングしたので、 e_opt を使った出力は一番右の図が出ます。対して、目的の e_tgt (Prompt : "A photo of a pistachio cake" の Embedding ) を使うと右から 2 番目のようにピスタチオケーキが出力されていますが、これは入力画像と少し離れてしまっているので e_opt の要素を少し足して、入力画像に近づける必要があります。
ここで必要なのがこの Interpolation であり具体的には下の式で表されます。
η は強さの指標であり、この式は e_tgt (Prompt : "A photo of a pistachio cake" の Embedding ) と e_opt の混ぜる割合を示しています。
η が大きいと e_tgt (Prompt : "A photo of a pistachio cake" の Embedding ) の割合が多く、ピスタチオケーキ要素が強まります。(右)
η が小さいと e_opt の割合が多く、もとのケーキの画像の要素が強まります
今回は η = 0.75 を使って生成したときが一番元のケーキの画像の固有性を保持しています。
結果
ケーキ以外も見てみましょう
このように入力画像の固有性を保ったまま画像編集ができています。
Prompt を変更してファインチューニングした結果
もちろん Prompt を替えてファインチューニングすると結果が変化します。
シード値を変更
Interpolation の η の大きさによる違い
他の手法との比較
失敗例
失敗することもあります。
Textual Inversion との違い
Textual Inversion は簡単に説明すると入力画像を用意してそれに対応する "擬似単語 S*" を探し、その "擬似単語 S*"を Prompt 内で用いることによって、用意した画像の固有性を保って画像生成するという手法です。この時モデル内の Text Transformer , Unet は再学習しません。
対してImagic は Prompt と入力画像を用意して、その用意した入力画像のもとになったPrompt の代わりとして e_opt を探し、これと入力画像を使って Unet を再学習してから、目的の画像生成をします。
DreamBooth との違い
DreamBooth はPrompt を使わず、入力画像の概念をレアトークン (=[identifier]=[V]) で代用し、続いて入力画像を使用してモデル内の Unetを再学習しています。 (Text Transformer も再学習するときがある)
対して、Imagic は Prompt と入力画像がセットになっている必要があり、入力画像に対応する Embedding を探して、それを使ってファインチューニングを行っています。
Imagic を "試す"
npaka さんの記事で Imagic を試すことができます。
参考文献
次回予告と宣伝
今回は Imagic を論文をもとににまとめました。実装方法、実際に試した記事もそのうち書きたいと思います。次回は LoRA について書くと思います。
公開されている様々なモデルを切り替え一つで変更できる Google Colab ノートブックも配布しています。
追加学習をやってみたい方はこちらの記事より
最後に
最後まで読んでいただきありがとうございました。最後に少し宣伝です。主のteftefが運営を行っているdiscordサーバーを載せます。このサーバーではMidjourneyやStble Diffusionのプロンプトを共有したり、研究したりしています。ぜひ参加して、お絵描きAIを探ってみてはいかがでしょう。(teftef)