1. HOME
  2. ブログ
  3. IT技術
  4. 教師なし機械学習「VAE」による連続的な手書き文字の生成

教師なし機械学習「VAE」による連続的な手書き文字の生成

認識モデルから生成モデルへ

以前まで、手書き文字の認識は、難しいタスクであると考えられてきました。

しかし、ニューラルネットワークの開発が進んだ2020年現在では、比較的、簡単な課題へと変化しました。

手書き文字の認識モデル

このような「認識モデル」では、手書き文字などのデータの分布を考慮せず、与えられたデータそのものから、直接識別境界を引いていきます

手書き文字の生成モデル

それに対し「生成モデル」は与えられたデータ群の分布そのものを求めていきます。

生成モデルのメリット

生成モデルでは、分布が分かっているため、任意のデータを生成できます。

これは、機械学習タスクの弱点の一つ、データ不足を補えます

また、データを連続的に変化させることが可能となり、モーフィングを行うことができるようになります。

Variational AutoEncoder(VAE)を用いて顔画像の表情・向きを変化させる

例えば、映画やアニメなどで、キャラクターが「普通の顔」から「笑顔」に変化していくアニメーションを作成するとしましょう。

このとき、様々な表情を学習した生成モデルを用いれば、イラストレーターなしに、アニメーションの連続的な変化を作成することができます。

VAE で同一人物の顔画像を学習させ変化させた図

以下は、VAE により、同一人物の顔画像を学習させ、連続的な表情・顔の向きを変化させた図です。

AutoEncoder と Variational AutoEncoder(VAE)

前回、AutoEncoder を用いた次元削減について話しましたが、AutoEncoder では、データと潜在変数の関係を \(1:1\) として次元埋め込みをしていました。

「Variational AutoEncoder(VAE)」では、潜在変数に確率的なブレを与えることで、与えられたデータ群の分布を推定し、連続的な画像生成を可能にします。

つまり、VAE は、生成モデルの一つとなります。

AutoEncoder による次元削減の記事

なお、AutoEncoder を用いた次元削減については、以下の記事で解説しています。

Variational AutoEncoder(VAE) の理論

ネットワーク構造

さて、「生成モデルは、データの分布を求めること」と述べました。

今後は、データを

$$X = { x_{1} , x_{2} , \ldots , x_{n} | x_{i} は i 番目のピクセルの画素値 }$$

として、その確率分布を \(P(X)\) とします。

そして、AutoEncoder の時にもお話したように、画像のような高次元データは、ほとんどの画素値が冗長であり、周りの画素値で補完できます

そのため、実際には、データはより低次元に分布するはずです。

「0~9」の手書き文字画像を3次元の潜在変数に次元削減する

以下は、AutoEncoder により、「0~9」の手書き文字画像を3次元の潜在変数に次元削減したときの例です。

このような低次元の潜在変数を \(z\) とし、その確率分布を \(P(z)\) とします。

潜在変数 z をニューラルネットワークで求める

AutoEncoder 同様、潜在変数 \(z\) をニューラルネットワークによって求めていきます

しかし、AutoEncoder のように、直接 \(z\) を求めるわけではありません

分布 \(P(z|X)\) が正規分布に従うとし、ニューラルネットワークは、\(z\) をサンプリングするため、正規分布の平均 \(μ(X)\) と、分散 \(σ(X)\) を出力します。

(詳しくは後で解説します)

ニューラルネットワークの出力から平均と分散を求め、\(N(μ(X),σ(X))\) から \(z\) をサンプリングし、その \(z\) から入力データ \(X\) の復元を行います

そもそもの目的

ネットワーク構造は、比較的簡単にお話しできましたが、損失関数の理解は難しいです。

VAE を実装するにあたって、私たちが考えるべき損失関数とは何でしょうか。

生成モデルの目的は、データの分布、すなわち \(P(X)\) を求めることでした。

尤度(ゆうど)の最大化をすることで確率分布を推定する

確率分布を求める方法として、尤度の最大化があげられます。

確率分布 \(P(X)\) が、何らかのパラメータ \(θ\)(普通は平均とか分散をあらわす)で表されているとします。

最尤推定で確率分布を求める際の尤度関数は、同時確率分布に等しく、以下のようになります。

$$P_{\theta}(X) = \prod_{i = 1}^n P_{\theta} (x_{i})$$

また、尤度関数は、普通対数を取ります。

尤度が確率の掛け算であるため、対数を取ることで、微分の計算が和で済むからです。

$$\log (P_{\theta} (X)) = \sum_{i = 1}^n \log (P_{\theta} (x_{i})) \dots ①$$

この尤度関数を最大化するようなパラメータ\(θ\)を求めることで、最もデータ\(X\)の生成分布に近い分布が得られます。

$$ar g \max_{\theta} \sum_{i =1}^n \log (P_{\theta}(x_{i}))$$

損失関数

対数尤度関数の最大化が目的となったので、さらに式を変形します。

観測データは、潜在変数により生成されたと考えることもできるため、\(z\) により \(P(X)\) を周辺化し、式変形すると以下のようになります。

$$\begin{eqnarray}
\log(P_{\theta}(X)) &=& \sum_{i = 1}^n \log(P_{\theta}(x_{i})) \dots ① \\
&=& \sum_{i = 1}^n \log \begin{pmatrix} \displaystyle \int P_{\theta} (x_{i} , z) dz \end{pmatrix} \\
&=& \sum_{i = 1}^n \log \begin{pmatrix} \displaystyle \int \frac{P_{\theta} (z|x_{i})P_{\theta}(x_{i} , z)}{P_{\theta}(z|x_{i})} dz \end{pmatrix} \\
\end{eqnarray}$$

ここで \(P(X|z)\) は、潜在変数 \(z\) が与えられたときの復元データの分布です。

そのため、ニューラルネットワークでいう Decoder 部は、この分布に基づいてサンプリングされたものが出力されます。


また逆に、\(P(z|X)\) はデータが与えられたときの潜在変数の分布であり、Decoder 同様、ネットワークの Encoder 部分は、この分布に基づいて \(z\) が観測されます。

AutoEncoder では、データ \(X\) と潜在変数 \(z\) の関係を点で求めていました。

しかし、VAE では、 \(P(z|X)\) を求めることでデータの低次元な分布を得ることができます

そして、この\(P(z|X)\)を近似することで、対数尤度の最大化を解いていきます

近似分布の平均と分散を推定する

近似した分布 \(q(z|X)\) は、正規分布に従うとし、先ほど述べたように、その平均と分散パラメータを Encoder により推定していきます。


\(q(z|X)\) で分布を仮定したら、イェンセンの不等式から対数尤度の下限を求めます

$$\begin{eqnarray}
\displaystyle \sum_{i = 1}^n \log \begin{pmatrix} \displaystyle \int \frac{P_{\theta}(z|x_{i})P_{\theta}(x_{i},z)}{P_{\theta}(z|x_{i})}dz\end{pmatrix} &\approx& \displaystyle \sum_{i = 1}^n \log \begin{pmatrix} \displaystyle \int \frac{q_{\varphi}(z|x_{i})P_{\theta}(x_{i},z)}{q_{\varphi}(z|x_{i})}dz \end{pmatrix}\\
&≧& \displaystyle \sum_{i = 1}^n \displaystyle \int q_{\varphi}(z|x_{i}) \log \begin{pmatrix} \frac{P_{\theta}(x_{i} , z)}{q_{\varphi}(z|x_{i})}\end{pmatrix}dz\\
&=& \displaystyle \sum_{i = 1}^n L(x_{i},\theta,\varphi) \dots ②
\end{eqnarray}$$

②の下限は、変分下限(Variational Lower Bound)と言われており、VAE がそう呼ばれることの根拠となっています

対数尤度の最大化をするには、この下限を押し上げればよいということになります。

対数尤度①と変分下限②の差を計算

ここで、対数尤度①と、右辺に出てきた変分下限②の差を計算してみましょう。

$$\begin{eqnarray}
&\sum_{i = 1}^n& \log (P_{\theta}(x_{i})) – L(x_{i},\theta,\varphi)\\
&=& \sum_{i = 1}^n \log (P_{\theta}(x_{i}))\displaystyle \int q_{\varphi}(z|x_{i})dz – \displaystyle \int q_{\varphi}(z|x_{i}) \log \begin{pmatrix} \frac{P_{\theta}(x_{i} , z)}{q_{\varphi}(z|x_{i})} \end{pmatrix}dz\\
&=& \sum_{i = 1}^n \displaystyle \int q_{\varphi}(z|x_{i})\begin{pmatrix} \log (P_{\theta}(x_{i})) – \log (P_{\theta}(x_{i},z)) + \log (q_{\varphi}(z|x_{i}))\end{pmatrix}dz\\
&=& \sum_{i = 1}^n \displaystyle \int q_{\varphi}(z|x_{i})\begin{pmatrix} \log (P_{\theta}(x_{i})) – \log (P_{\theta}(z|x_{i})) – \log (P_{\theta}(x_{i})) + \log(q_{\varphi}(z|x_{i}))\end{pmatrix}dz\\
&=& \sum_{i = 1}^n \displaystyle \int q_{\varphi}(z|x_{i})\begin{pmatrix} \log (q_{\varphi}(z|x_{i})) – \log (P_{\theta}(z|x_{i}))\end{pmatrix}dz\\
&=& \sum_{i = 1}^n KL[q_{\varphi}(z|x_{i})||P_{\theta}(z|x_{i})]
\end{eqnarray}$$

最後の式は、KL ダイバージェンスと呼ばれるもので、分布間の距離を表す指標です。

KL ダイバージェンスは、2つの分布が全く同じであるならば「0」を示します。

つまり、対数尤度は、以下の2つの項で表されることが分かりました。

$$\sum_{i = 1}^n \log (P_{\theta}(x_{i})) = \sum_{i = 1}^n L(x_{i},\theta,\varphi) + \sum_{i = 1}^n KL[q_{\varphi}(z|x_{i})||P_{\theta}(z|x_{i})]$$

第2項目は、近似精度がよくなれば、おのずと「0」に近づく非負値です。

そのため、対数尤度の最大化を行うには、変分下限の最大化を行えばよいことになります。

$$ar g \max_{\theta} \sum_{i =1}^n \log (P_{\theta}(x_{i})) = ar g \max_{\theta,\varphi} \sum_{i =1}^n L(x_{i},\theta,\varphi)$$

変分下限を式変形していくと、ようやくお目当ての損失関数が得られます。

$$\small \begin{eqnarray}
&\sum_{i = 1}^n& \log (P_{\theta}(x_{i}))-\displaystyle \int q_{\varphi}(z|x_{i})\begin{pmatrix} \log(q_{\varphi}(z|x_{i}))-\log(P_{\theta}(z))-\log(P_{\theta}(x_{i}|z))+\log(P_{\theta}(x_{i})) \end{pmatrix}dz\\
&=& \sum_{i = 1}^n – \displaystyle \int q_{\varphi}(z|x_{i})\begin{pmatrix} \log(q_{\varphi}(z|x_{i})) – \log(P_{\theta}(z)) -\log(P_{\theta}(x_{i}|z)) \end{pmatrix}dz\\
&=& \sum_{i = 1}^n \displaystyle \int q_{\varphi}(z|x_{i})\log(P_{\theta}(x_{i}|z))dz – KL[q_{\varphi}(z|x_{i})||P_{\theta}(z)]
\end{eqnarray}$$

この式を最大化することで、VAE は学習を進めていきます。

実装上の損失関数

損失関数は、このままでは積分計算が入っているため、積分が入らない形に変形します。

1項目の KL ダイバージェンスについて

まずは、1項目の KL ダイバージェンスについて説明します。

正規分布同士の KL ダイバージェンスは、以下のように計算されます。

$$\frac{1}{2}\sum_{j = 1}^J(1 + \log(\sigma_{j}(X))-\mu_{j}(X)^2 – \sigma_{j}(X)^2$$

\(J\) は、潜在変数の次元数です。

積分計算をゴリゴリやれば出るので、式は割愛します。

2項目の積分はサンプリング近似を実行

2項目に関して、積分計算を解くのが難しいので、サンプリング近似を行います。

$$\displaystyle \int q_{\varphi}(z|x_{i})\log(P_{\theta}(x_{i}|z))dz \approx \frac {1}{L} \sum_{i = 1}^L \log (P_{\theta}(x_{i}|z_{i}))$$

これは、確率分布 \(q(z|X)\) に対する期待値計算であるため、有限個のサンプルの平均で近似してしまおうというものです。

また、mnist データは、普通「0, 1」 のデータで表されているため、分布には、ベルヌーイ分布を仮定します。

さらに、学習時のバッチサイズが大きければ、\(L=1\) で十分です。

以上を元に、近似した値を求めていくと、以下のようになります。

$$\begin{eqnarray}
\log(P_{\theta}(x_{i}|z_{i})) &=& \log(f(z_{i})^{x_{i}}(1-f(z_{i})^{1-x_{i}}))\\
&=& x_{i}\log(f(z_{i}))+(1-x_{i})\log(1-f(z_{i}))
\end{eqnarray}$$

ただし、\(f\)は、潜在変数を入力とする Decoder の関数、つまりは、再構成後の画素値を出力します。

以上から、第2項の損失関数は、以下のように表されます。

$$\sum_{i = 1}^n x_{i} \log (f(z_{i}))+(1-x_{i}) \log(1-f(z_{i}))$$

実験結果

画像の再構成

AutoEncoder と同様に、再構成をしてみました。

元画像

再構成結果

潜在変数が二次元なので、間違えている部分もありますね。

VAE だからと言って、AutoEncoder よりも表現力が上がるわけではなさそうです

それに画像がぼやけています。

VAE に限らず、ピクセル単位で誤差を計算するモデルは、すべて画像がぼけやすいです。

潜在変数の分布の可視化

潜在変数の散らばりも見てみましょう!

AutoEncoder のように無秩序ではなく、分布が正規分布に引き寄せられるようになりました。

この分布であれば、本来は、非線形であるそれぞれの数字の分布を線形分離することもできそうですね。

連続的な数字画像の生成

では今度は、この二次元に落とし込んだ潜在変数上で、画像を滑らかに変化させてみましょう!

潜在変数の値を徐々に変化させ、その値を Decoder に通して画像を生成しました。

「2」⇒「4」⇒「9」⇒「3」⇒「5」⇒「3」⇒「8」と、左上から右下にジグザグに見ていくことで、数字が徐々に変化していく様子が分かります。

まとめ

確率モデルを扱う VAE を用いることで、画像を連続的に変化をさせることが可能になりました

今回は、数字のみで実験しましたが、VAE を用いれば、顔画像であろうと衣類であろうと様々なものを連続的に変化させ、モーフィングさせることができます

面白いので、ぜひ、ご自身の手でも確かめてみてくださいね!

ソースコード全体

 

ライトコードよりお知らせ

にゃんこ師匠にゃんこ師匠
システム開発のご相談やご依頼はこちら
ミツオカミツオカ
ライトコードの採用募集はこちら
にゃんこ師匠にゃんこ師匠
社長と一杯飲みながらお話してみたい方はこちら
ミツオカミツオカ
フリーランスエンジニア様の募集はこちら
にゃんこ師匠にゃんこ師匠
その他、お問い合わせはこちら
ミツオカミツオカ
   
お気軽にお問い合わせください!せっかくなので、別の記事もぜひ読んでいって下さいね!

一緒に働いてくれる仲間を募集しております!

ライトコードでは、仲間を募集しております!

当社のモットーは「好きなことを仕事にするエンジニア集団」「エンジニアによるエンジニアのための会社」。エンジニアであるあなたの「やってみたいこと」を全力で応援する会社です。

また、ライトコードは現在、急成長中!だからこそ、あなたにお任せしたいやりがいのあるお仕事は沢山あります。「コアメンバー」として活躍してくれる、あなたからのご応募をお待ちしております!

なお、ご応募の前に、「話しだけ聞いてみたい」「社内の雰囲気を知りたい」という方はこちらをご覧ください。

ライトコードでは一緒に働いていただける方を募集しております!

採用情報はこちら

関連記事