ベイズ分類器とニューラルネット

先の記事で、ピクセル相互の共分散を考慮したベイズ分類器にすると、MNISTで94%の正解率を実現できることを示した。この分類器は、ピクセル相互の独立分布を前提にしたNaive Bayes Classifier (単純ベイズ分類器)とは違う。MNISTの場合、28X28=784次元(ピクセル数)のベクトルが考慮されている。共分散マトリクスが使われるので、それらの相互関係が考慮されているところがすごいのである。

もちろん、全く共分散がないピクセル関係もある。また、特に、画像の端のピクセルなどは、そもそも1以上の値を持つことがないので、どの他のピクセルとも相関がゼロだったりする。pythonのscipy.statsライブラリの多変量正規分布の共分散マトリクスは、フルランクではなくてもいいので、こうしたゼロ相関に寛容である。

共分散マトリクスで全てのベクトル要素同士が関連しているというのは、ニューラルネットと構造はよく似ている。この全要素をつなげている共分散マトリクスは、分類されるべきパターン(概念)それぞれ一つずつあるので、例えばMNISTの識字の場合は10層のネットワークがあることになる。

学習によってこれらの共分散マトリクスが形成されるということは、ディープラーニングでウェイトの学習が行われるのと類似の機能である。

この共分散マトリクスを分析にすのは興味深い。やってみたい。

共分散を考慮したベイズ分類器 MNIST 94%

Naive Bayes Classifierでは、MNISTの正解率が84%にとどまったと言うことで、多変量ベルヌーイ分布の共分散を考慮したモデルで試みようとしたが、プログラミングの制約が大きくうまくいっていない。

そこで、こちらのサイトで紹介されている、ピクセル間の相関を多変量正規分布の相関で表現したモデルに注目した。プログラムも提示されているので、自分でもやってみたところ、MNISTの手書き文字認識で、なんと94%の正解率に到達した。ディープラーニングのパフォーマンスに肉薄している。計算では、このプログラム用のMNISTデータが見当たらなかったので、プログラムに合うようにフォーマットを整えたことくらいで、あとは普通に動いた。

理論的には、ある文字ラベルcのもとで、ピクセルベクトルxが生じる確率が、次のような多変量正規分布で表されるという前提になっている。

 P(x | c) = \frac{1}{\sqrt{ (2\pi)^k |\Sigma| }} exp\left({ -\frac{1}{2}(x-\mu)^T \Sigma^{-1} (x-\mu) }\right)

ベイズ定理から、

P(c|x)=\frac{P(x|c)P(c)}{P(x)}

となる。P(x)は、ラベルに依存せず共通なので、結局右辺の分母の値を標本(事前学習データ)から求めて、左辺、すなわち、ピクセルベクトルxが与えられた元での、出現確率が最大となる数字ラベルを求めれば良いわけである。実際の計算では、順序は変わらないので、右辺の対数をとったもので比較している。

ぱっと見、上の多変量正規分布の計算は、共分散行列\Sigmaの逆数を求めるというのが深刻な壁のように感じるが、プログラムでは、pythonの科学計算ライブラリで簡単に処理してしまっている。驚いた。何しろこのサイトの、pythonで書かれたプログラムは、ライブラリを巧妙に使っていて、超短く、効率的で、何しろ早い。

MNISTデータは、訓練用60000個あるが、プログラムでは、教育用に5000個、テスト用に5000個使っているだけである。それで、94%の正解率なのだが、これを例えば30000個を教育用に使っても、成果率は94%から上昇しない。つまり、5000個で、文字の特徴を捉えてしまっているのだ。悪く言えば、そこまでの分類器でしかないと言うこともできるが、それにしても94%という正解率、および、その使いやすさは、とてつもなく優れているというべきだ。

このサイトのプログラマーさんのすごさもある。あまりにプログラムが短い、すなわち、全く無駄がない。それによって、改めて、pythonというプログラミングの優秀さを感じた。私は大体、JavaとC++をメインにしているのだが、これからはpythonを本格的に使っていきたい。

ツールとしては、これ以上のものは望めない。自然言語の方に戻ろう。

共分散のある多変量ベルヌーイ分布の考察

先の記事で導出した3次元の多変量ベルヌーイ分布の同時確率の形を再掲すると、次のようなものである(記号の説明は、前の記事を参照のこと)。

v_{1}=q_{1}q_{2}q_{3}+q_{3}\sigma_{12}+q_{2}\sigma_{13}+q_{1}\sigma_{23}-\sigma_{123}
v_{2}=q_{1}q_{2}p_{3}+p_{3}\sigma_{12}-q_{2}\sigma_{13}-q_{1}\sigma_{23}+\sigma_{123}
v_{3}=q_{1}p_{2}q_{3}-q_{3}\sigma_{12}+p_{2}\sigma_{13}-q_{1}\sigma_{23}+\sigma_{123}
v_{4}=q_{1}p_{2}p_{3}-p_{3}\sigma_{12}-p_{2}\sigma_{13}+q_{1}\sigma_{23}-\sigma_{123}
v_{5}=p_{1}q_{2}q_{3}-q_{3}\sigma_{12}-q_{2}\sigma_{13}+p_{1}\sigma_{23}+\sigma_{123}
v_{6}=p_{1}q_{2}p_{3}-p_{3}\sigma_{12}+q_{2}\sigma_{13}-p_{1}\sigma_{23}-\sigma_{123}
v_{7}=p_{1}p_{2}q_{3}+q_{3}\sigma_{12}-p_{2}\sigma_{13}-p_{1}\sigma_{23}-\sigma_{123}
v_{8}=p_{1}p_{2}p_{3}+p_{3}\sigma_{12}+p_{2}\sigma_{13}+p_{1}\sigma_{23}+\sigma_{123}

これを一般ベイズ分類器(Naiveではない)の事前確率として利用し、MNISTデータの読み取りをテストすることが次の課題だ。ただ、昨夜布団に入って、ここでの\sigma_{ij}\sigma_{123}は、事前学習で標本値を作ることができるが、各係数の前についている符号はどのように決定するのかが気になった。そのまま寝てしまったが、今朝、考えたので、それをメモしておく。(図の\thetaは、\sigma_{123}のことである)


基本は、正の相関のあるピクセル同士が同じ値を持つ確率は高まる、負の相関の場合は低くなるということである。

そうなると\sigma_{ij}の係数にかかる符号は、次のようにして決まる。まず、それぞれの式の第1の項目は、三つのピクセルの状態と、それらが独立の場合の同時確率を示している。例えば最初の式の場合はq_{1}q_{2}q_{3}で、全てがqということは、すべのピクセルの値が負である状態と言うことである。次に、第二の項は、q_{3}\sigma_{12}で、その符号は正である。この符号が正である理由は、相関の問題になっている第1ピクセルと第2ピクセルが、ともに0で、同じ方向に動いている、連動しているから、正なのである。その第1式は、全てが連動しているので、すべて正なのである。

第2式を見てみよう。その第1項は、q_{1}q_{2}p_{3}である。ピクセルの状態は、第1,2ピクセルガ0で、第3ピクセルが1となっていることがわかる。第2項は、+p_{3}\sigma_{12}であるが、この場合も、第1,2ピクセルは連動しているので正である。第3項は-q_{2}\sigma_{13}で、符号は負だが、これは、第1ピクセルが0で、第3ピクセルは1で、方向が逆になっているので、負なのである。

ちなみに、\sigma_{ij}の前についているのが、p_{i}であるかq_{j}であるかは、第1項の組み合わせの中に入っているものがそのまま踏襲されているだけである。

また\sigma_{123}は、三つのピクセル値の符号によって決まる。すなわち、その式の第1項のqが含まれていれば(-1)をかけ、pが含まれているならば(1)をかけ、その三つの値の掛け算の符号で決まるのである。つまり、第2式のような場合は、(-1)(-1)(1) だから、正である。

すなわち、第1項が決まると、式の形は全て決まってしまうと言うことになる。そうすると、3次多変量ベルヌーイ分布の同時確率の一般形もすぐにかけそうだ。それができると、n次多変量ベルヌーイ分布の一般形もかけることになる。ただ、頭の痛くなるほど複雑になるので、今は、書くのをやめておく。

 

多変量ベルヌー分布の変数間の相関を考慮した同時確率分布を考える

タイトルがやたら難しい!おそらく、3、4日前の自分がこのタイトルを見たら、記事の中身を決して読まなかっただろうと思う(笑)

はじめに:それはベルヌーイ分布だった

最近、何か色々考えたりプログラムしていて、自分のやろうとしていることを、後で、その理論的枠組みを知ることが多くなった。もともと、中野馨氏のアソシアトロン をやっていて、そこでベイズ定理を用いて概念分類をしているのが面白くて、やってみたら、後で、それが「単純ベイズ分類器 Naive Bayes Classifier」というものであることを知って、色々な知識が増えた。それをやったら、今度は、「単純」ではダメだ。ピクセルの変数間の相互関係を考慮しないとMNISTの正解率を84%以上には上げれないと思って、どうしたらいいんだと色々調べたら、そのために必要なことが、実は多変量ベルヌーイ分布の相関を考慮したモデルの問題なのだということを知った。

そもそも、MNISTデータのテスト正解率をあげるのに、なぜ相関を考慮する必要があるかをまず書いておこう。単純ベイズ分類器の場合、一つのピクセルの事前分布を調べるが、その変数の分布は独立であると想定する。MNSITデータは、一つの手書き数字に、28X28=748ピクセルを用いている。Naiveの場合、その第iピクセルが0であるか1であるか(MNISTは、0から255までの数値になっているが、経験的に、これを0,1に変換しても結果はそれほど変わらない)になっているが、その0か1かの値をとる変数x_{i}は他のピクセルの変数とは独立に与えられる確率変数であると想定するのである。しかし、実際は、数字が形をなすということは、ピクセルのどこかの値が1になることと、別のピクセルの値が1になることが、連動していることを意味している。連動しているからこそ、数字として人間が認識できるのである。だから、相関を考慮することはどうしても必要なのである。

また、ピクセルが独立しているなどという想定は、脳の機構とは全く違ったものになる。ニューロンが他のニューロンとは独立に発火するというのは、脳的ではないし、面白くない。相関を考慮するということは、ニューロン同士の関係性をある程度シミュレートすることにもつながる。

というわけで、ここにたどり着いたのである。この「多変量ベルヌー分布の変数間の相関を考慮した同時確率分布の導出」という問題は、一つのピクセルの値をベルヌーイの二値の分布ではなく、正規分布と仮定すること、さらには、多くのピクセルの変数を相関のある多変量正規分布と仮定することよりも、問題が複雑なのではないかと思う。

そもそも、1,0の二値の分布が独立でない場合の同時分布とはなんだろうか、そこが全く掴めなかった。ネットでも、わかりやすく解説しているところがなかなか見つからなかった。しかし、自分の理解した範囲で、以下で解説してみよう。

2変数のベルヌーイ分布:共分散がある場合

MNISTは784ピクセルで1文字を表す。が、ここで目一杯単純化して、あるパターン(MNISTの場合は文字)が2ピクセルで表されたとしよう。一つのピクセルが0か1の値を持つとする。このパターンのもとで、二つのピクセルがどのような値を持つかを考えるのである。最大可能状態なパターンは4つしかなく、それをs_{i}, i=1,2,3,4とし、それらが二つのピクセルの値をそれぞれs_{1}= (0,0), s_{2}=(1,0), s_{3}=(0,1), s_{4}=(1,1)である。一般的に、第1ピクセルの値を確率変数(ベルヌーイ確率変数)としてx_{1}, x_{2}と表すと考えておいても良い。

\begin{array}{c|cc|c}State&x_{1}&x_{2}& \\ \hline s_{1}&0&0&v_{1}\\ s_{2}&1&0&v_{2}\\s_{3}&0&1&v_{3}\\s_{4}&1&1&v_{4} \\ \hline & p_{1} & p_{2} &prob. \end{array}

今、このパターンのもとで、状態s_{i}が現れる確率は、x_{1}, x_{2}の二変数の同時確率であり、それをv_{i}で表すことにしよう。この同時確率は、一般ベイズ分類器の事前確率になるものであり、私たちが求めたいところのものである。つまり、あるパターンのもとで、状態iが現れる確率がわかれば、状態iが現れた元でその原因となるパターンの確率がベイズ定理によって推計することができる、元のパターンを推定することができるわけである。

今、このパターンのもとで、第1ピクセルが1の値を持つ確率をp_{1}としよう。確率演算子Pを用いて、次のように書くこともできる。すなわち、普通の期待値演算子Eを使うとp_{1}=E(x_{1})である。同じく、第2ピクセルが1になる確率をp_{2}としよう。

今もし、二つのピクセルの値の確率変数が、相互に独立だとしたら、先の同時確率は簡単に求めることができる。すなわち、状態s_{1}の場合、二つのピクセルはともにゼロであるから、同時確率v_{1}は、

v_{1}=(1-p_{1})(1-p_{2})

となる。同様に、状態2の場合は、第1ピクセルが1で第2ピクセルは0であるから

v_{2}=p_{1}(1-p_{2})

となる。一般に、

v_{i} = p_{1}^{x_{1}}(1-p_{1})^{(1-x_{1})}p_{2}^{x_{2}}(1-p_{2})^{(1-x_{2})}

と書けば、すべての状態を表していることになる。独立の場合は、これを使えばベイズ分類が可能になり、それは、先の記事で私がやったNaive Bayes Classifierに他ならない。

では、独立性がなく、二つのピクセルの値の間に相関がある場合はどうなるだろうか。それを以下で考えてみよう。

今、第1ピクセルが1を持つ状態は、s_{2}s_{4}であるから、それらの状態の同時確率と、この状態の確率(周辺確率と呼んでもいい)との関係は次のようになる。(括弧つきの数字は、式の番号)

v_{2}+v_{4}=p_{1} \cdots (1)

p_{2}は、二番目のピクセル(確率変数)が1になる確率であり、それは次のようになる。

v_{3}+v_{4}=p_{2} \cdots (2)

さらに、二つの確率変数の間の共分散が存在し、それを\sigma_{12}であらわそう。この時、状態の同時確率と共分散の間には次のような関係が成立する。

p_{1}p_{2}v_{1}-(1-p_{1})p_{2}v_{2}-p_{1}(1-p_{2})v_{2}+(1-p_{1})(1-p_{2})v_{4}=\sigma_{12} \cdots (3)

私と同じくらいの理解力の人間では、上の式を見てすぐには理解できないと思うので、少し説明しよう。

共分散の普通の定義は、確率変数x_{i}x_{j}の共分散\sigma_{ij}は、その期待値をそれぞれp_{i}, p_{j}として、期待値演算子E を用いて、\sigma_{ij}=E(x_{i}-p_{i})(x_{j}-p_{j})と表される。言葉で表せば、\sigma_{ij}は、状態の値 (x_{i}-p_{i})(x_{j}-p_{j})に、この状態が現れる確率をかけたものである。

今、(3)式をvの項が4つあると見て、一番最初の項をみてください。これは状態s_{1}は変数が0,0の値を持っているので、分散の定義では、(0-p_{1})(0-p_{2})$???v_{1}$をかけたもの、すなわち、p_{1}p_{2}v_{1}となったものなのである。他の三つの項も、分散の定義に沿っていることは、お分かりになるだろう。それらの合計が、我々の求める\sigma_{12}に他ならない。

さて、もう一つ式がある。これが一番簡単だ。すなわち、同時確率も確率だから、それらを合計したものは1でなければならないということである。

v_{1}+v_{2}+v_{3}+v_{4}=1 \cdots (4)

我々の目的は、 各状態の同時確率の4つの値v_{1}, v_{2}, v_{3},v_{4}を求めることだが、それに対応する4つの式を得たことになる。当然、 p_{1},p_{2},p_{3},p_{4}および\sigma_{12}は与えられているものとする。実際それは、MNISTの場合、教育用データで標本値を求めることができるので、心配はいらない。

解くための学力は、中学あるいは高校の数学力があればいいだろう。が、4元連立方程式を解くというのはとても面倒くさい。十代の頃は、いつもケアレスミスで、間違ってしまった。でも、やらなければ前に進めないので、やりました。結果は次のようなものとなる。

v_{1}=(1-p_{1})(1-p_{2})+\sigma_{12}
v_{2}=p_{1}(1-p_{2})-\sigma_{12}
v_{3}=(1-p_{1})p_{2}-\sigma_{12}
v_{4}=p_{1}p_{2}+\sigma_{12}

結果を見て、そのわかりやすさに感激した。つまり、共分散のある場合の同時確率は、共分散がない場合、すなわち、相互に独立の場合の同時確率に、分散を足すか引くかしたもの。両方が1ないしは0の時は、共分散を足し、違う場合は引くということだ。つまり、共分散がある状態は同時に現れたり、消えたりする確率が高くなる。

結果を見て、なるほどと思った。

ただ、これだけでは、一般にどうなるかが予想できない。これは2ピクセルの場合である。しかし、MNISTは、784ピクセルもあるのだ。

もちろん、すぐに一般的な場合を考えても良いのかもしれない。計算手順はだいたいわかったので。しかし、やはりそれは無謀だ。まず、3ピクセルの場合をやってみようと思った。

3変数のベルヌーイ分布:共分散がある場合

3変数の場合も、基本同じだろう。と、思った。まず、テーブルを書いておく。

\begin{array}{c|ccc|c}State&x_{1}&x_{2}&x_{3}& \\ \hline s_{1}&0&0&0&v_{1}\\ s_{2}&0&0&1&v_{2}\\ s_{3}&0&1&0&v_{3}\\ s_{4}&0&1&1&v_{4}\\ s_{5}&1&0&0&v_{5}\\ s_{6}&1&0&1&v_{6}\\ s_{7}&1&1&0&v_{7}\\ s_{8}&1&1&1&v_{8}\\ \hline & p_{1} & p_{2} &p_{3} &prob. \end{array}

まず、式を作っていく。一番わかりやすいのは同時確率の合計が1という \sum_{i=1}^{8}v_{i}=1である。さらに、周辺確率p_{1},p_{2},p_{3}と同時確率との関係から、3本の式ができる。また、相関係数\sigma_{12},\sigma_{13},\sigma_{23}と確率の関係から式が3本できる(相関係数は、対象であることに注意)。あれ、7つしかできない。未知数である同時確率は8個あるのに、式が一つ足りないのだ。これには、かなり悩んだ。訳がわからなかったが、いろいろ調べてわかった。

x_{1},x_{2},x_{3}の三つの確率変数の間の同時共分散を考慮しなければならないのである。今この分散を\sigma_{123}としよう。すなわち、\sigma_{123}=E(x_{1}-p_{1})(x_{2}-p_{2})(x_{3}-p_{3})である。

この8本の式を全部書くと、ノート1ページを埋めるくらいになった(笑)。さらに、このサイトに書く元気は湧いてこない。かといって、何も書かないわけにもいかないので、行列表現で、この8元連立方程式を書いておこう。ただし、要素の中の式が長くならないように1-p_{i}=q_{i}, i=1,2,\cdots,8としておく。

\left(\begin{array}{cccccccc}1&1&1&1&1&1&1&1 \\0&0&0&0&1&1&1&1\\0&0&1&1&0&0&1&1\\0&1&0&1&0&1&0&1\\p_{1}p_{2}&p_{1}p_{2}&-p_{1}q_{2}&-p_{1}q_{2}&-q_{1}p_{2}&-q_{1}p_{2}&q_{1}q_{2}&q_{1}q_{2}\\p_{1}p_{3}&-p_{1}p_{3}&p_{1}q_{3}&-p_{1}q_{3}&-q_{1}p_{3}&q_{1}q_{3}&-q_{1}p_{3}&q_{1}q_{3}\\p_{2}p_{3}&-p_{2}q_{3}&-q_{2}p_{3}&q_{2}q_{3}&p_{2}p_{3}&-p_{2}q_{3}&-q_{2}p_{3}&q_{2}q_{3}\\-p_{1}p_{2}p_{3}&p_{1}p_{2}q_{3}&p_{1}q_{2}p_{3}&-p_{1}q_{2}q_{3}&q_{1}p_{2}p_{3}&-q_{1}p_{2}q_{3}&-q_{1}q_{2}p_{3}&q_{1}q_{2}q_{3}\end{array}\right)\left(\begin{array}{c}v_{1}\\v_{2}\\v_{3}\\v_{4}\\v_{5}\\v_{6}\\v_{7}\\v_{8}\end{array}\right)=\left(\begin{array}{c}1\\p_{1}\\p_{2}\\p_{3}\\\sigma_{12}\\\sigma_{13}\\\sigma_{23}\\\sigma_{123}\end{array}\right)

式はできた。解くための必要条件、式の数=未知数の数、も満たしている。が、さすがにこれを記号的に解く気にはなれない。コンピュータに頼るしかない。記号が入っていない、変数以外は実際の数値ならば、EXCElで簡単に解くことができるが、ここでは係数などが記号のままとかなければならないのである。数式を記号のまま処理して、連立方程式を解けるシステム、まず、頭に浮かんだのはMathematicaで、かつてライセンスを取っていた。ほとんど使わなかったが、今更、アップグレードやら何やらの手続きも面倒だ。トライアル期間を利用して解くという手もあるかと思ったが、そもそも使い方がよくわからない。

そこで、Maximaというのが無料で、よく使われているということを知って、これをMacにインストールした(サイト)。すぐに解くことができた。ただし、式が少し間違っていると、答えを出さなかったり、とんでもなく長い答えを出してくるので、正確に式を入れなければならない。

solve([v1+v2+v3+v4+v5+v6+v7+v8=1,
            v5+v6+v7+v8=p1,
            v3+v4+v7+v8=p2,
            v2+v4+v6+v8=p3,
            p1*p2*(v1+v2)-p1*(1-p2)*(v3+v4)-(1-p1)*p2*(v5+v6)+(1-p1)*(1-p2)*(v7+v8)=s12,
            p1*p3*(v1+v3)-p1*(1-p3)*(v2+v4)-(1-p1)*p3*(v5+v7)+(1-p1)*(1-p3)*(v6+v8)=s13,
            p2*p3*(v1+v5)-p2*(1-p3)*(v2+v6)-(1-p2)*p3*(v3+v7)+(1-p2)*(1-p3)*(v4+v8)=s23,
            -p1*p2*p3*v1+p1*p2*(1-p3)*v2+p1*(1-p2)*p3*v3-p1*(1-p2)*(1-p3)*v4
            +(1-p1)*p2*p3*v5-(1-p1)*p2*(1-p3)*v6
            -(1-p1)*(1-p2)*p3*v7+(1-p1)*(1-p2)*(1-p3)*v8=theta]
,[v1,v2,v3,v4,v5,v6,v7,v8]);

(%o19) [[v1 = (- theta) + s23 + p1 ((- s23) + p3 + p2 (1 - p3) - 1) + s13
 + p2 ((- s13) + p3 - 1) + s12 + p3 ((- s12) - 1) + 1, 
v2 = theta + p1 (s23 + p2 p3 - p3) - s23 + p2 (s13 - p3) - s13 + p3 (s12 + 1), 
v3 = theta + p1 (s23 + p2 (p3 - 1)) - s23 + p2 (s13 - p3 + 1) + p3 s12 - s12, 
v4 = (- theta) + s23 + p1 ((- s23) - p2 p3) + p2 (p3 - s13) - p3 s12, 
v5 = theta + p1 (s23 - p3 + p2 (p3 - 1) + 1) + p2 s13 - s13 + p3 s12 - s12, 
v6 = (- theta) + p1 ((- s23) - p2 p3 + p3) - p2 s13 + s13 - p3 s12, 
v7 = (- theta) + p1 (p2 (1 - p3) - s23) - p2 s13 - p3 s12 + s12, 
v8 = theta + p1 (s23 + p2 p3) + p2 s13 + p3 s12]]

上半分に、solveというコマンドで解くための式を定式化している。下半分の、Maximaのコマンドプロンプト(%o19)の後に、 '[[' と ']]'に挟まれてv_{1}からv_{8}までの答えが書き出されている。素晴らしい!!なお、thetaは\sigma_{123}のことである。

簡略化が、不完全なので、ぱっと見よくわからないが、整理すると次のようになる。ただし、q_{i}=1-p_{i}であることに注意する。2次元の場合の自然な拡張になっていることも直ちに読み取ることができる。

v_{1}=q_{1}q_{2}q_{3}+q_{3}\sigma_{12}+q_{2}\sigma_{13}+q_{1}\sigma_{23}-\sigma_{123}
v_{2}=q_{1}q_{2}p_{3}+p_{3}\sigma_{12}-q_{2}\sigma_{13}-q_{1}\sigma_{23}+\sigma_{123}
v_{3}=q_{1}p_{2}q_{3}-q_{3}\sigma_{12}+p_{2}\sigma_{13}-q_{1}\sigma_{23}+\sigma_{123}
v_{4}=q_{1}p_{2}p_{3}-p_{3}\sigma_{12}-p_{2}\sigma_{13}+q_{1}\sigma_{23}-\sigma_{123}
v_{5}=p_{1}q_{2}q_{3}-q_{3}\sigma_{12}-q_{2}\sigma_{13}+p_{1}\sigma_{23}+\sigma_{123}
v_{6}=p_{1}q_{2}p_{3}-p_{3}\sigma_{12}+q_{2}\sigma_{13}-p_{1}\sigma_{23}-\sigma_{123}
v_{7}=p_{1}p_{2}q_{3}+q_{3}\sigma_{12}-p_{2}\sigma_{13}-p_{1}\sigma_{23}-\sigma_{123}
v_{8}=p_{1}p_{2}p_{3}+p_{3}\sigma_{12}+p_{2}\sigma_{13}+p_{1}\sigma_{23}+\sigma_{123}

この同時確率の正しさを検証するものとしては、Jozef L. Teugels氏が1990年にJournal of Multivariate Analysis, Vol.32,誌に発表した論文"Some Representations of the Multivariate Bernoulli and Binominal Distributions" (pp.256-268)がある(サイト)。そこに、私のものと同じように、2次の場合と3次の場合の式が書かれている。ただし、3次の場合の式の並びと、ここでの式の並びは対応していない。それを適切に対応させれば、両者が一致していることを確認できるだろう。実は、先の\sigma_{123}が必要になることは、この論文に教えてもらった。

ここまでくると、一般的な多数のベルヌーイ変数がある場合の同時確率が予想できる。ただし、その一般形を書いた式は、私は見つけていない。いや、書き方が大変なことは予測できる。だからこそ、上記のTeugels氏は、クロネッカー積というものを使わざるを得なかったのだろうと思う。もし、どなたか、多変量ベルヌーイ分布の同時確率の一般系の書き方がわかる方がおられたら是非教えていただきたい(ツイッター @wassiisg まで)。

ただし、共分散を考慮したベルヌーイ分布を使って、一般的な(Naiveではない)ベイズ分類器を作る場合、必ずしも一般式は必要ではないというか、一般的な式のまま計算はできないと思う。どのように使うかは、次以降の記事で書きたい。

 

MNISTの手書き数字データをベイズ推計してみた:Naive Bayes Classifier

この間、アソシアトロンの本を読んだりプログラムを書いたりするうちに、概念形成の場合は、アソシアトロンよりもベイズ推計のほうがパフォーマンスが良くなる可能性に思い当たった。そこで、このさい、この概念形成のベイズ推計モデルを使って、ディープラーニングなどの人工知能の性能評価に使われているMNISTの手書き数字データをベイズモデルで推計してみた。

MNISTデータは、中身を変えずに少し形式を変形して用いた。訓練用の60000個のデータで、事前確率を計算し、それをもとにテストデータ10000個で、テストした。どうせパフォーマンスはぼろぼろだろうと思ったが、84.1%の正解率だった。ディープラーニングだと90%の後半の数字が出るので(私が作ったDeep Learningのプログラムで、MNISTのテストした時には、96%にとどまったが:笑)、それから比べると相当低いが、私は正直、こんなに高い数字が出たことで、ちょう驚いた。どこか、正解を計算に使ったような、とんでもない間違いをしているのではないかと思ったくらいだ。

まず、プログラムが、ディープラーニングよりも無茶苦茶簡単なものになる。プログラムは、以下に置いてある。

https://github.com/toyowa/NaiveBayesClassifier

MNISTのデータは大きすぎて載せていないが、読み込み関数を見れば、どのようなフォーマットか理解できると思う。MNISTデータをテキストファイルとして、わかりやすいフォーマットに変えている。

プログラムの簡単さよりも遥かに大きな驚きは、60000個の学習から10000個のテストを終えるまでに、私の8コアのubuntu18.04で9秒33で終わってしまうのだ。プログラムはg++用のc++で書いている。テストは、4秒弱で終わる。データの読み込み時間がかかっているので、実際の計算はもっと短い。

これは、単純ベイズ分類器(Naive Bayes Classifier)というものだ。単純というのは、変数間の相関を考慮せず、独立であると想定していることである。独立でない場合については、のちに書く予定だ。

理論的な枠組みを示す。単純ベイズ分類器といっても、理論はそんな単純ではない。手書き数字データは、0から9までの10個の数字のラベルがつけられている。このラベルに結びついた事象をA_{s}, s=0,1,\cdots,9であらわす。MNISTでは1ピクセルを0から255の数値でその濃さを表しているが、ここでは正ならば1、負ならば0と変換しておく(多変量ベルヌーイ試行あるいはベルヌーイ分布にしている。これを多変量正規分布でも、試みたが色々不都合があった。機会があれば説明する)。このピクセルのベクトル(あるいは事象)をx^{n} = (x_{i}^{n},i=0,1,\cdots, 783)としよう。nはデータ番号(必要がないときは省略する)、iはピクセル番号である。

このとき、ベイズ定理は次のように表される。

P(x|A_{s})P(A_{s})=P(A_{s}|x)P(x)

今、P(x|A_{s})は、数字ラベルsのときに、ピクセルベクトルxが得られる確率であり、P(A_{s}|x)は、逆に、ベクトルxが得られた時に、それが数字ラベルsに属する確率、P(A_{s})およびP(x)は、それぞれの条件に依存しない全体に対する確率である。

これは次のように変形できる。

式(1)
\begin{array}{lll}P(A_{s}|x) & = & \displaystyle\frac{P(x|A_{s})P(A_{s})}{P(x)} \\ & = & \displaystyle\frac{P(x|A_{s})P(A_{s})}{P(x|A_{0})P(A_{0})+P(x|A_{1})P(A_{1})+,\cdots,+P(x|A_{9})P(A_{9})} \\ & = & \displaystyle\frac{P(x|A_{s})P(A_{s})}{\sum_{s=0}^{9}P(x|A_{s})P(A_{s})}\end{array}

また、ここでは、変数(ピクセル値)の相関がないと想定しているので、P(x|A_{s})は、極めて単純(Naive)な形になり、次のように求められる。

式(2)
\begin{array}{lll}P(x|A_{s}) & = & p_{s0}^{x_{0}}(1-p_{s0})^{1-{x_{0}}}\cdot p_{s1}^{x_{1}}(1-p_{s1})^{1-{x_{1}}}\cdot,\cdots,\cdot p_{s783}^{x_{783}}(1-p_{s783})^{1-{x_{783}}} \\ & = & \prod_{i=0}^{783}p_{si}^{x_{i}}(1-p_{si})^{1-{x_{i}}}\end{array}

ここで、p_{si}は、ラベルがsのときに、ピクセルベクトルxの第i番目の要素x_{i}が1になる確率である。P(x|A_{s})が、各ピクセルが1であったり0で会ったりする同時確率になっていることを示しているのである。すなわち、x_{i}が1であるときはp_{si}そのものになり、0であるときはp_{si}のべき乗x_{i}が0で、値が1になってしまうかわりに1-p_{si}の冪乗1-x_{i}が1になるという算段である。

これを用いて、(1)式の左辺の確率が最大のラベルを求めれた、それがピクセルデータから推計された数字ラベルとなる。

ただ、(2)式が784回もかけるかたちになっていて、途方も無い計算と思われるかもしれない。

計算について、もし、このような784回も積を取る形が望ましく無い場合は、自然対数をとって和のかたちにすることもあり得る。すなわち、われわれの目的は、(1)式において、P(A_{s}|x)を最大にするsを求めることであり、各ラベルで共通する(1)式の分母は本質的役割を果たさない。そこで、(1)式の両辺を自然対数で変換変換して、(1)の右辺の分母だけを比較しても、最もあり得る数字ラベルを求めることは、理論的には全く問題ない。

ただ、実際の計算をすると、どちらも全く同じ答えを出し、自然対数を取る時間が余計にかかるだけであり、実際の計算では元々のかたちを用いている。

元々のかたちでの計算では、教育用データから事前確率を計算し、全てのテストデータを処理するのにMacPro上のUbuntu18.04 g++で8秒弱で計算を終えるのに対して、対数計算を加えると11秒かかった。計算結果は同じである。

なお、学習データは、基本60000個用いたが、1000個くらいから増やしていって、30000個くらいまでは、テストの正解率が上昇し、正解率は84.1%に達し、その後全く増加しなくなる。計算の確実性は高まっているようだが、パフォーマンスは良くならない。