こんにちは。

本日は待ちに待ったソフトマックス回帰の実装です。ロジスティックの兄さんのような存在のロジスティック。出力が確率の多値分類になっただけです。この記事では数式をゴリゴリ計算していこうと思います。

Softmax function

    \[\phi: \mathbb{R}^n \rightarrow \mathbb{R}^K     \textbf{    s.t.     } \sum_{i=1}^{K} \phi_i = 1   }\]


    \[\phi_j(z) = \dfrac{\exp(z_j)}{\sum_{k=1}^{K}\exp(z_k)}     \textbf{for}j=1,…,K\]

n次元の入力に対してK種類に分類する写像です。ロジスティックの場合はK=2です、なので特に問題はなさそうですね。ではとりあえずこのソフトマックスを微分してみます。まずj \neq kの時

    \[\frac{\partial \phi_{j}}{\partial z_{k}} &=\frac{0-\exp \left(z_{j}\right) \exp \left(z_{k}\right)}{\left(\sum_{k} \exp \left(z_{k}\right)\right)^{2}} \ &=-\phi_{j} \phi_{k}\]

同様にj = kの時、

    \[\frac{\partial \phi_{j}}{\partial z_{k}} =\frac{\exp \left(z_{j}\right) \sum_{k} \exp \left(z_{k}\right)-\exp \left(z_{j}\right) \exp \left(z_{k}\right)}{\left(\sum_{k} \exp \left(z_{k}\right)\right)^{2}}\]


    \[=\phi_{j}\left{\frac{\sum_{k} \exp \left(z_{k}\right)-\exp \left(z_{k}\right)}{\sum_{k} \exp \left(z_{k}\right)}\right}\]


    \[=\phi_{j}\left(1-\phi_{k}\right)\]

これで微分ができました。次にソフトマックス関数の実装時、大切になる次の性質を紹介します。

    \[\dfrac{\exp({\theta^{(k)}}^T x^{(i)})}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} = \dfrac{C\exp({\theta^{(k)}}^T x^{(i)})}{C\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} = \dfrac{\exp({\theta^{(k)}}^T x^{(i)} + \log C)}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)} + \log C)}\]

ソフトマックスを実装の際、何がやばいかというとオーバーフローなんです。それは指数関数を使ってるので当たり前なんですが僕のように情報上がりでない方はなぜエラーが起きるのか・オーバーフローとはなんなのかわからない方もいると思います。しかし、上の性質よりオーバーフロー対策ができます。つまり、定数を加えてもOKだよ、ということです。なので\log C = - \max_j {\theta^{(j)}}^T x^{(i)}とすることでその対策ができます。これは便利。 ではコスト関数に参ります。今回使うデータを次のようにします。

    \[{ (x^{(0)} , y^{(0)}), \cdots, (x^{(N)} , y^{(N)})   }\]

また、便宜上、1 { True } = 1, 1 {False } = 0となる関数を定義しておきます。するとコスト関数は次のようになります。

    \[J(\theta) = - \left[ \sum_{i=1}^{N}\sum_{k=1}^{K} 1{y^{(i)} = k} \log \dfrac{\exp({\theta^{(k)}}^T x^{(i)})}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} \right]\]

今からこれを微分するんですが式がちょっと複雑なので

    \[P(y=1|x;\theta) = \phi(x;\theta) = \dfrac{\exp({\theta^{(1)}}^T x)}{\sum_{k=1}^{K}\exp({\theta^{(k)}}^T x)}\]

とおきます。では微分行きましょう。

    \[\nabla_{\theta^{(k)}} J(\theta) = - \nabla_{\theta^{(k)}} \left[ \sum_{i=1}^{N}\sum_{k=1}^{K} 1{y^{(i)} = k} \log \dfrac{\exp({\theta^{(k)}}^T x^{(i)})}{\sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)})} \right]\]


    \[= - \nabla_{\theta^{(k)}} \sum_{i=1}^{N}\sum_{k=1}^{K} \left[ 1{y^{(i)} = k}  \left{  {\theta^{(k)}}^T x^{(i)} - \left { \log \sum_{j=1}^{K}\exp({\theta^{(j)}}^T x^{(i)}) \right}\right} \right]\]


    \[= - \sum_{i=1}^{N} \left{  1{y^{(i)} = k} [x^{(i)} - P(y^{(i)}=k|x^{(i)};\theta) x^{(i)}]\]


    \[= - \sum_{i=1}^{N} x^{(i)} \left[ 1{y^{(i)} = k} - P(y^{(i)}=k|x^{(i)};\theta)  \right]\]

となりました。最後はちょっとだけシンプルですね!ではコーディングに移ります。用いるデータはsklearnのdigitsです。
でわ。

参考