Pythonと機械学習

Pythonも機械学習も初心者ですが、頑張ってこのブログで勉強してこうと思います。

ロジスティック回帰

ロジスティック回帰はADALINEに確率的な解釈を与えたアルゴリズムです。

活性化関数とコスト関数に対し、ロジスティック関数と尤度を用いています。ADALINEとの違いは、この活性化関数とコスト関数だけです。

ここでは、ロジスティック関数と尤度の概念を学んでいきたいと思います。

ロジスティック関数

トレーニングサンプルと重みをかけ合わせた値( {\mathbf{z} = \mathbf{X} \mathbf{w}} )を、ロジスティック関数に入力し活性化関数の値として出力します。

{\displaystyle
\mathbf{\phi} (\mathbf{z}) = \frac{1}{1 + e^{- \mathbf{z}}}    \tag{1}
}

ロジスティック関数{\mathbf{\phi} (\mathbf{z}) }は、-∞~∞までの全実数入力{\mathbf{z}}に対し、0~1までの値を出力します。

トレーニングサンプル{\mathbf{X}}が与えられた場合に、教師データ{\mathbf{y}}を与える条件付き確率として解釈されます。

確かに、ロジスティック関数の出力は0~1までの値になるので確率として解釈できそうですが、その概念は少々難解です。この概念について少し堀り下げてみようと思います。

ロジスティック関数はその形からシグモイド関数とも呼ばれています。-∞~+∞までの実数入力を受けて、0~1までの実数を出力する関数です。

今1組のトレーニングサンプル{\mathbf{x}_i}が与えられた時、クラスラベル{y_i}が1となる条件付き確率を{p}とします。

{\displaystyle
p=p(y_i=1|\mathbf{x}_i)    \tag{2}
}

この時オッズ比{r}を以下のように定義します。オッズ比は[0,1]の定義域をとり、[0,∞)の値域を取ります。

{\displaystyle
r=\frac{p}{1-p}    \tag{3}
}

オッズ比の対数を取ったものはロジット関数と呼ばれています。対数を取ることで、[0,1]の定義域に対し、値域が(-∞,+∞)に拡張されます。

{\displaystyle
z=\log(\frac{p}{1-p})    \tag{4}
}

このロジット関数の逆関数がロジスティック関数となります。ロジスティック関数の定義域は(-∞,+∞)で値域は[0,1]になります。

{\displaystyle
p=\frac{1}{1+e^{-z}}    \tag{5}
}

ロジスティック関数の出力値が確率を表すことが、なんとなくわかりました。

ではなぜオッズ比とロジット関数を考える必要があるかというと、定義域が(-∞,+∞)であるロジスティック関数の入力{z}を、トレーニングサンプルと重みの積の和{\mathbf{x}_i\mathbf{w}}に対応させるためです。

少々強引な気もしますが、{\mathbf{w}}は、トレーニングサンプル{\mathbf{x}_i}に対し、クラスラベル{y_i}が1となる条件付き確率分布関数を決定するパラメータになっていると解釈できるようになるわけです。

ロジスティック関数の微分

コスト関数の勾配を求める際に、ロジスティック関数を微分してやる必要があるので、ここで確認しておきます。

ロジスティック関数{\phi(z)}{z}微分してみます。

{
\displaystyle
\begin{align}
\frac{d \phi(z)}{d z} &= \frac{d }{d z}\frac{1}{1+e^{-z}} \\
 &= \frac{e^{-z}}{(1+e^{-z})^2} \\
 &= \frac{1}{(1+e^{-z})}\left(1-\frac{1}{(1+e^{-z})}\right) \\
 \\
 &=\phi(z)(1-\phi(z))
\end{align}    \tag{6}
}

面白い性質を持っていますね。

ベルヌーイ試行

尤度を考える前にベルヌーイ試行というものを知っておいたほうがいいでしょう。

ベルヌーイ試行とはクラスラベルが1か0の試行で、コイン投げの試行等がそれに当たります。

クラスラベルが{y_i=1}である確率が{\phi_i}であるとき、その条件付き確率の確率分布関数は以下の式で表すことができます。

{\displaystyle
p(y_i|\phi_i)=\phi_i^{y_i}(1-\phi_i)^{1-y_i}    \tag{7}
}

クラスラベルが1の時は、

{\displaystyle
p(y_i=1|\phi_i)=\phi_i    \tag{8}
}

クラスラベルが0の時は、

{\displaystyle
p(y_i=0|\phi_i)=1-\phi_i    \tag{9}
}

となり、一つの式で1と0のクラスラベルの確率分布を同時に表しています。

この式で定義される確率分布関数をベルヌーイ分布といいます。

ここで、{\phi_i}という確率は、クラスラベルが{y_i=1}である確率を表していますが、{\phi_i}は確定した量ではなく、パラメータ{\mathbf{w}}をもつ確率分布関数に従っていることに注意してください。

例えばコイン投げにしても本当に表が出る確率は1/2でしょうか?(ひん曲がったコインを投げた場合、表が出る確率が1/2かどうかを考えるといいと思います。)

つまり、表が出る確率はあるパラメータ{\mathbf{w}}を持つ、確率分布関数に従って変動すると考えます。

言い換えると、ここでは表が出る確率が1/2である確率。つまり確率の確率を考えています。

パラメータを考慮した場合、ベルヌーイ分布を表す式に以下のようにパラメータを考慮しているということを明示的に書いてやります。

{\displaystyle
p(y_i|\phi_i;\mathbf{w})=\phi_i^{y_i}(1-\phi_i)^{1-y_i}    \tag{10}
}

尤度

尤度とはある事象が観測された時、それぞれの事象の確率の確率分布関数のパラメータがどれだけ尤もらしいかを測る量で、事象の同時確率として定義されます。

{
\displaystyle
\begin{align}
l(\mathbf{w})&=p(y_1|\phi_1;\mathbf{w})p(y_2|\phi_2;\mathbf{w})\cdots ~\cdots  p(y_m|\phi_m;\mathbf{w})  \\
\\
&=\prod_{i=1}^{m}p(y_i|\phi_i;\mathbf{w})
\end{align}    \tag{11}
}

ひん曲がったコインを投げた時、表が出る確率が1/2になるかどうか分かりません。

表が出る確率を調べるためには、何回もコインを投げてどれくらいの頻度で表が出るかという事象を調べてやる必要があります。

表が出る確率がベルヌーイ分布に従っていると仮定し、観測された事象からパラメータ{\mathbf{w}}を推定する事で、表が出る確率が分かるわけです。

尤度が最大値を与えるパラメータ{\mathbf{w}}は、事象の確率が一番尤もらしい値となります。

このように尤度を最大化することで、一番尤もらしい事象の確率を求めてやることを最尤推定法と呼びます。

尤度の対数を取ったものは対数尤度と呼ばれており、尤度が最大になる時、対数尤度も最大値を取ります。

対数法則により掛け算が足し算になるので、対数尤度で評価した方が扱いが簡単になるという利点があります。

{
\displaystyle
L(\mathbf{w})=\sum_{i=1}^{m} \log\left[~p(y_i|\phi_i;\mathbf{w})~\right]    \tag{12}
}

まとめ

ベルヌーイ分布を使ってコスト関数を表してやるので、教師データのクラスラベルは1と0とします。

{i}番目のトレーニングサンプルと教師データのセットが得られた時、活性化関数を以下の様に表します。活性化関数の出力は教師データのクラスラベルが1である確率を表しています。

{\displaystyle
\phi_i(z_i)=\frac{1}{1+e^{-z_i}}    \tag{13}
}

{\displaystyle
z_i=\mathbf{x}_i\mathbf{w}    \tag{14}
}

コスト関数は対数尤度にマイナスを付けた値を用います。(コスト関数が最小値の時に、対数尤度は最大値となります。)

{
\displaystyle
J(\mathbf{w})=-\sum_{i=1}^{m} \left[ ~ y_i\log\phi_i + (1-y_i)\log (1-\phi_i) ~ \right ]    \tag{15}
}

コスト関数を{j}番目の重み{w_j}微分して、{j}番目のコスト関数の勾配を求めてみます。

{
\displaystyle
\begin{align}
\frac{\partial J(\mathbf{w})}{\partial w_j} &= \frac{\partial}{\partial w_j} -\sum_{i=1}^{m} \left[ ~ y_i\log\phi_i + (1-y_i)\log (1-\phi_i) ~ \right ] \\

&= -\sum_{i=1}^{m} \left[ ~ y_i \frac{\partial \log \phi_i}{\partial \phi_i}\frac{\partial \phi_i}{\partial z_i}\frac{\partial z_i}{\partial w_i} + (1-y_i)\frac{\partial \log (1-\phi_i)}{\partial \phi_i}\frac{\partial \phi_i}{\partial z_i}\frac{\partial z_i}{\partial w_i} ~ \right ] \\

&= -\sum_{i=1}^{m} \left[ ~ y_i \frac{1}{\phi_i}\phi_i(1-\phi_i)x_{ij} + (1-y_i)\frac{-1}{(1-\phi_i)}\phi_i(1-\phi_i)x_{ij} ~ \right ] \\

&= -\sum_{i=1}^{m} (y_i -\phi_i)x_{ij}


\end{align}    \tag{16}
}

重みの更新は、従来通りコスト関数の勾配に学習率{\eta}をかけ、マイナスをつけて足し込みます。

{
\displaystyle
\Delta w_j = - \eta(-\sum_{i=1}^{m} (y_i -\phi_i)x_{ij}) \\
w_j:=w_j +\Delta w_j    \tag{17}
}

まとめ(行列による表記)

numpyでコーディングしやすいように行列表記しておきます。

トレーニングサンプルと重みの積の和

{\displaystyle
\mathbf{z} = \mathbf{X} \mathbf{w}    \tag{18}
}

活性化関数

{\displaystyle
\mathbf{\phi} (\mathbf{z}) = \frac{1}{1 + e^{- \mathbf{z}}}    \tag{19}
}

コスト関数

{\displaystyle
J(\mathbf{w})=- \mathbf{y}^{T} \log\mathbf{\phi} - (\mathbf{1}-\mathbf{y})^{T} \log(\mathbf{1}-\mathbf{\phi})    \tag{20}
}

コスト関数の勾配

{\displaystyle
\frac{\partial J(\mathbf{w})}{\partial \mathbf{w}} =- \mathbf{X}^{T} (\mathbf{y} - \mathbf{\phi})
    \tag{21}
}

重みの更新

{\displaystyle
\Delta \mathbf{w} =- \eta \left( - \mathbf{X}^{T} (\mathbf{y} - \mathbf{\phi}) \right)
    \tag{22}
}

{\displaystyle
\mathbf{w}:=\mathbf{w}+\Delta \mathbf{w}    \tag{23}
}

コスト関数の最小値を与える重み

コスト関数の勾配を0と置いて式をいじってみたところ、式の上ではコスト関数が最小となる重みが一発で求まりそうだったのでこちらも試してみようかと思います。

{- \mathbf{X}^{T} (\mathbf{y} - \mathbf{\phi}) =0}が常に成り立つためには、{\mathbf{y} = \mathbf{\phi}}です。

{\mathbf{\phi}}を与える{\mathbf{z}}は、ロジット関数より求まるので、

{\displaystyle
\mathbf{z}=\log \frac{\mathbf{\phi}}{\mathbf{1}-\mathbf{\phi}}    \tag{24}
}

(18)式に代入して展開します。

{\displaystyle
\mathbf{X}\mathbf{w}=\log \mathbf{\phi} - \log (\mathbf{1}-\mathbf{\phi})    \tag{25}
}

両辺に{\mathbf{X}^{T}}をかけ、{\mathbf{\phi} = \mathbf{y}}より、{\mathbf{\phi}}を消去します。

{\displaystyle
\mathbf{X}^{T}\mathbf{X}\mathbf{w} = \mathbf{X}^{T}\left(\log \mathbf{y} - \log (\mathbf{1}-\mathbf{y}) \right)    \tag{26}
}

両辺に{(\mathbf{X}^{T}\mathbf{X})^{-1}}をかけてやると、

{\displaystyle
\mathbf{w} =(\mathbf{X}^{T}\mathbf{X})^{-1} \mathbf{X}^{T}\left(\log \mathbf{y} - \log (\mathbf{1}-\mathbf{y}) \right)    \tag{27}
}

ADALINEの最小二乗法の時と似てますね。なんかそれっぽい値になってます。

?。。よく考えると、{y_i=0}{\log (y_i)}が-∞に飛んじゃいますね。

これはコスト関数に極小値が存在しないことを示してるのでは??

どういうことか気になりますが、疲れたので続きはまたの機会に考察することにしましょう。

参考にさせて頂いたサイト