お久しぶりです!sodaエンジニアの國田です!
前回、前々回とGANの記事を書き連ねておりましたが、今回もまたGANに関する記事です。タイトル通り、GANの生成器を使って私自身の顔を作る実験を行います!
そもそも、「GANって何?」って方は、こちらの記事を参照いただけますと幸いです。
GANが学習してるのは?
GANの生成物の中で有名なものの1つに、人物の顔画像があります。(この記事のトップに掲載している顔写真も全てGANで作られた画像です。)
ここで、生成される顔画像は、実際に学習した画像そのものとは異なる画像になります。ですが、そもそもどうして学習した画像と異なる画像ができるのか、不思議ではないですか?
その答えは非常に単純です。GANの生成器で学習するのは、与えられた顔画像そのものではなく、あくまでも概念だからです。人間が一般的に「顔」といった時に思い浮かべる特徴(目が2つあって、中心に鼻があり、その下に口がある、輪郭は丸い人もいれば逆三角形の人もいる、髪は男性は短い人が多い・・)を学習してます。
「顔という概念を学んでいる」ということは、ちょっと難しい言い方をすると「顔画像の【潜在空間】を学習している」ということです。以降、この【潜在空間】という言葉を使って説明しますが、難しいな、と感じた方は、潜在空間≒概念と思ってください。
GANが学習した概念(潜在空間)を利用しているというのは、その潜在空間の中にある要素(目や鼻や髪型などを決定するためのパラメータ)を微妙に変化させたり、組み合わせているとも言えます。つまり、顔画像を学習したGANの生成器の潜在空間の中には非常にたくさん、それも様々な顔が存在しているということです。
ということは、そのGANの潜在空間の要素を組み合わせることで、私とよく似た顔を生成できてもおかしくないですよね!?
そこで今回は、顔画像の学習済みモデルを使って、「GANの生成器の中に私の顔はあるのか?」というテーマで実験してみたいと思います。
GANの中から自分の顔をどうやって探すのか?
そうは言っても、GANの生成器の中から、どうやって自分自身の顔を探すべきでしょうか‥。「GANにとりあえず10,000枚画像生成させて、その中から自分で似ている画像を目視で探していく」なんてのも良いですが、日が暮れるどころじゃ済まないですね・・(苦笑。
良い方法が論文(*1,*2)で提案されておりますので、今回はそれを使いましょう。
端的に言ってしまえば、「GANが生成した画像と私の顔画像との差をGAN自身に埋めさせる」ことができれば、要件を満たせます。画像を学習させる時のように、GANの生成器に私の顔画像をお手本として渡し、生成する画像をどんどん近づけていけば良いのです。
具体的には・・
① 学習済みのGANの生成器を使い、画像を適当に⽣成させる。
② ⽣成された画像と私の画像を⽐較することによって、誤差を算出する。
誤差逆伝播を行い、 潜在変数を更新する(≒その誤差が小さくなってくれるようなパラメータを探してくる)。
③ 更新された潜在変数を⽤いて、生成器に新しい画像を⽣成させる。
④ 誤差が⼗分に⼩さくなるまで②、③を繰り返す。
通常の学習では、GANの生成器の重みを更新するのですが、今回は重みは弄らずに、生成器に入力する潜在変数(ノイズ)を更新します。
さぁ、やってみよう
では、解説が終わったところで、実際にやってみたいと思います。
まず用意しましたのは、こちらの画像(私の写真です)。事前に顔の特徴を上手く捉えられるように前処理(*3)を行った上で、StyleGAN2と呼ばれるGANの生成器に渡します。
これに近い画像をGANの生成器に生成してもらいます。先ほどの項目で挙げた生成画像と実写真との比較のプロセスを2000回ほど繰り返してみましょう。
学習スタート直後に生成したものが下の画像の左側になります。(右側には比較のために本物画像を置いておきます。)
まだまだ本物画像にはほど遠いですね。顔の大きさや輪郭からして違います。
50回目
なかなかのイケメンが生成されてます。先ほどの画像と比べると、顔の大きさが本物画像に近づいているのがよく分かると思います。個人的には、こちらのイケメンが私ってことにして実験終了でも良いのですが、非情にも生成プロセスは続きます。
81回目
雰囲気的には大分近いんじゃないですかね??私の高校生の時くらいの顔ですね(大嘘)。
99回目
なんだか目の下にクマができて、ゾンビっぽく・・大丈夫かなぁ・・
202回目
ホラー画像っぽくなってるのに、私本人に似てきてます笑。どうやらクマっぽかったのはメガネを生成している途中だったようです。ヒゲも濃くなってきましたね。
380回目
メガネ完成。髪型などは本物と変わらないくらいになってますが、目が大きい。まるでプリクラで撮影した時のような印象ですね。
1008回目
目が小さくなって、鼻も丸くなってきました。もうほとんど同じと言っても忖度ないような画像に仕上がってます。初期の頃の外国人画像から、変われば変わるものです。
2000回目(最終画像)
はい!目鼻や輪郭がすっきりし、全体的にシャープになった印象です。
と言いますか、本当に私そっくりな画像になりました。もし私が何も知らない状態で上の左側の写真を渡されたら、実写真と誤認してしまいそう。
実験結果
GANは私の顔を作ることができました!
GANの潜在空間に私がいた。つまり、GANが学習した顔という概念の中に、私の顔を構成するパーツが含まれていたということですね!
このタスク、始める前は「もっと難しいのかな」と思っていましたが、学習もGPU1枚で5分ほどで終わりました。意外と簡単に私の顔を見つけられてしまい、少々複雑な気持ちです。
今回実験したこのGANに画像を埋め込んでよく似た画像を生成させる技術は、Image Inversionと呼ばれています。昨今ディープフェイクが話題に上がりましたが、この技術を用いることで、実画像と生成画像を見分けることができるのでは?とも言われています。
日々発展していくAI技術、本当に胸が膨らみます!
おまけ
上記の生成過程をgif画像にしてみました。少しずつ変化していく様子がお判りになるかと思います。
参考
*1 Tero Karras, Samuli Laine, Miika Aittala, Janne Hellsten, Jaakko Lehtinen and Timo Aila, "Analyzing and Improving the Image Quality of StyleGAN" 2019, (https://arxiv.org/pdf/1912.04958.pdf)
*2 Weihao Xia, Yulun Zhang, Yujiu Yang, Jing-Hao Xue, Bolei Zhou and Ming-Hsuan Yang,
"GAN Inversion: A Survey" 2021,
(https://www.researchgate.net/publication/348487325_GAN_Inversion_A_Survey)
*3 dlibにより顔が直立するように回転処理を行っています。
dlib ~Index of /files~
http://dlib.net/files/
StyleGAN2 -- Pytorch Implementation https://github.com/adriansahlman/stylegan2_pytorch