Developer Blog AIフレームワーク 開発ブログ

2026年07月09日

平均、期待値、その連続する空間

平均、期待値...

前回、前々回のブログで、MNISTの手書き数字とCelebAの顔画像について、属性から画像を生成するニューラルネットワークを学習させたこと、そして、その画像を生成するニューラルネットワークによって、生成された画像が「平均画像」とよく一致することを紹介しました。
たとえばMNISTでは、例えば数字の「0」に対応する訓練画像をすべて集め、各画素の値を平均して作った画像と、学習済みネットワークが「0」という属性から生成した画像がほぼ一致しました。「1」から「9」についても同様の結果が得られました。
いっぽうCelebAには40個の属性(男性/女性、眼鏡あり/なし など)があり、それらの組み合わせによって顔画像が特徴づけられています。そのため、画像を生成するニューラルネットワークにより得られる画像は、属性の組み合わせごとに異なるものとなり、全体としては多様な顔画像が生成されました。
「平均画像」と表現してきましたが、数学的には「属性が与えられたときの条件付き期待値」と呼ぶ方がより正確です。つまり、ネットワークは各属性に対応する画像集合の中心的な特徴を表す画像を生成している、と解釈できます。つまり、ニューラルネットワークは「属性」を入力すると、「その属性による条件付き期待値」を出力するように学習したという事になります。

無いものが有る!?

そしてその「その属性による条件付き期待値」を出力するニューラルネットワークですが、この学習をさせる際には、属性、あるいは、属性の組み合わせを入力とし、それに対応する画像を正解画像として、これに近づくようにしました。つまり、属性ないしは属性の組み合わせと、それに対応する画像は、学習データに含まれるものであって、「有る」(存在する)ものです。
さて、ここまで書いたところで、前回のブログの内容から、なにか気付くことはないでしょうか?

そうなんです。
前回のブログではcelebAで顔画像を生成するように学習したニューラルネットワークで、学習完了後に「乱数」を入力して画像生成することを紹介しましたが、「乱数」であるから、元の属性の組み合わせに有るとは限らないものであるし、その上、学習データでは属性が0/1の値であるのに対し、0~1の範囲の浮動小数点数、すなわち、0でも1でもない値の組み合わせになっていて、これは明らかに「無い」ものなのです。たとえば0.4男性で0.7眼鏡あり...といった具合です。
そしてその有るかどうかわからない、ないしは、明らかに無い属性に対してもニューラルネットワークは、少なくとも間違いなく「顔」の画像を生成するのです。

顔画像空間

画像は2次元で空間は3次元、などと突っ込まないでください。
私が言いたいのは、先ほど書いたように、「顔」画像が生成される、その生成画像は、ある一つの独立した点ではなく、空間のように連続的につながっているという事です。そして、その空間内でいずれかの属性の値が変化すれば、その変化に応じて、顔画像が連続的に変化する、さらには、それでもこの空間内であれば、「顔」、少なくとも人には「顔」と認識されうる画像になっている、という事です。つまり「顔画像空間」を形成していると言えるのではないでしょうか?
むろん、ここで述べたのはどちらかというならば、理想的な状態を言っており、きれいに連続しなかったり、顔に見えない画像になったりという事はありうる話です。
しかしともかくも理想がそうであるならば、それを乱数による生成だけでなく、もう少し役に立つ、そして分かりやすく、見ておくのが良いでしょう。

属性に応じた変化

まずは次の画像をご覧ください。

これは、40項目の属性の全データの平均をベースとして、その属性のうち、'Eyeglasses','Gray_Hair','Pale_Skin','Smiling','Wearing_Necktie'の5つの項目の値を0~1で連続変化させた値を作って、それを学習済みニューラルネットワークに入力して得られた生成画像です。

ベースとした値(属性の平均)は具体的には以下のようなものです。

array([[0.124, 0.275, 0.52 , 0.217, 0.022, 0.149, 0.247, 0.248, 0.254,
        0.148, 0.05 , 0.199, 0.148, 0.065, 0.045, 0.065, 0.06 , 0.054,
        0.382, 0.463, 0.432, 0.503, 0.034, 0.125, 0.827, 0.259, 0.043,
        0.281, 0.076, 0.07 , 0.057, 0.51 , 0.218, 0.287, 0.207, 0.044,
        0.461, 0.128, 0.079, 0.754]], dtype=float32)

そもそもこのベースが没個性の平均顔なのですが、それはさておき、例えば1段目の'Eyeglasses'=0.00~1.00では左端の眼鏡無しの顔から右に行くほどサングラスをかけた顔に、連続して変化していくのが分かります。2段目の'Gray_Hair'では、右に行くほど髪の毛が背景のグレーに溶けて無くなっていくように見えています。そのほかも同様に、いずれも連続して変化させた属性に応じた画像が生成されています。

だれか特定の人物なら...

先ほどは全データの平均の属性をベースとしましたが、だれか特定の人物の属性をベースにしたらどうなるでしょうか?
早速やってみたのが次の画像です。

'Gray_Hair'が上手く髪の色が抜けなかったり、'Smiling'が何だかひきつっていたりしますが、まあまあ属性に応じた連続変化と言えるのではないでしょうか?

次のステップは?

画像を生成するニューラルネットワークが「属性が与えられたときの条件付き期待値」を出力しているという話から始めて、属性を振りながら画像生成する実例を紹介しました。
生成画像を見ることでたしかにそうなっている、と思ってもらえればと思います。
しかし、今回紹介した範囲では、やはり画像がボケている、はっきりしない、というのも正直なところです。
さあ、どうする?となりますが、それは次回に譲ることにさせて頂きます。
今回の社内研修会の内容は、実に盛りだくさんだったなあと思います。

ブログのご感想やAIフレームワーク「ufiesia」「pyaino」に関するお問い合わせは、
問い合わせフォームからお送りください。

お問い合わせ
  • お問い合わせ内容によりましては、ご期待に添えない場合やご回答が出来ない事が有ります。