以前の投稿で、ロジスティック回帰に通常の線形関数ではなくシグモイド関数を使用する理由を掘り下げて説明しました。 この投稿では、引き続きコスト関数について説明します。
コスト関数は、予測値の誤差を与え、その後、学習アルゴリズムに必要であるため、重要です。 具体的には、予測値の誤差を最小化したい、つまり、コスト関数を最小化したいのです。 理想を言えば、誤差がゼロであれば、ダーツゲームのように、すべてのダーツが的中になるようなものである。 一方、誤差が非常に大きい場合、これは予測値がすべての真の観測値を逃している、つまり、ダーツが一般的に正鵠を逸していることを意味します。
仮説値でコスト関数を実行するときに誤差ゼロにしたい(すべての値に対して完全な予測)のですが、これは「高分散」と呼ばれる現象を引き起こすかもしれないので良いシナリオではないかもしれません。 これについては後ほど詳しく説明します。
損失関数の定式化に戻ると、典型的な損失関数は二乗誤差の和を最小化すること、つまり、次のようなものです。
しかしこの関数は、最適化の過程で複数の局所最適を生じさせることができ、最適化したソリューションが最適でない(より良いソリューションがある)可能性を意味します。 理想的には、最適化されたソリューションは、ローカル ミニマムではなく、グローバル ミニマムでありたいものです。 https://www.cs.ubc.ca/labs/lci/mlrg/slides/non_convex_optimization.pdf
上の図に見られるように、不注意にパラメータを初期化し、「真の」グローバルミニマムに到達せずにローカルミニマムに最適化する可能性があります。 したがって、前述の損失関数は私たちが使用するには理想的ではありません。
では、どのような損失関数が考えられるでしょうか。
ロジスティック回帰によく使われる損失関数の 1 つは次のとおりです:
なお、私はコストと損失を同じ意味で使用していますが、Andrew Ng の講義に慣れた人は「損失関数」が 1 つの学習例に対してで、「コスト関数」はすべての学習例の平均を取っています。
この損失関数がなぜ意味を持つかを見てみましょう。 y = 1 とし、一番上の式 -log(h⊖(x)) に注目すると、これは損失関数であるため、非常に負になるようにします (目的としては、損失関数を最小化したいことを思い出してください)。 その結果、h⊖(x)は大きくなります。 つまり、シグモイド関数が仮説の推定値を0から1の間で制約するため、h⊖(x)は最大値の1に制限されることを思い出してください:
h⊖(x) = ŷ = σ(z)
したがって、y=1のとき、損失関数はŷ=1で極限まで最小化されることになります。
逆に、y = 0 の場合、式の下の部分に注目すると、-log(1- h⊖(x)) です。 損失最小化の目的から、これは非常に負であることが望ましい。 その結果、1- h⊖(x)は非常に大きくなり、その結果としてh⊖(x)は非常に小さくなります。 しかし、シグモイド関数が推定仮説値を0から1の間にするため、h⊖(x)は最小値0に制限されることを思い出してください。
したがって、y=0のとき、損失関数はŷ=0と極限まで最小になることがわかります。
Their corresponding graphs will illustrate the above points:
左のグラフ(y = -log(h⊖(x)) からわかるように、y = 1のとき、仮説の値が1であればコストは0になり、仮説の値が0に近くなると無限大になる。
同様に、右のグラフ(y = -log(1 – h⊖(x)), y = 0のとき、仮説値が0のときコストは0になり、仮説値が1に近いとき無限大になります。
両者をきちんと式にまとめると、m個の学習例によるロジスティック回帰のコスト関数が得られる:
で、iは1〜mまで、m個の学習例で推移している。
AI や機械学習では、多くの表記が飛び交いますが、それらの意味を理解するのに役立つでしょう。
物流回帰モデルの学習では、全体のコスト関数を最小化するパラメータ「w」と「b」を見つけることを目指します。 次回は、次の重要なセグメントである勾配降下について触れます。
numpy では、コスト関数は次のようにコーディングできます。
import numpy as npcost = (-1/m) * np.sum(Y*np.log(A) + (1-Y)*(np.log(1-A)))
説明すると、
- np.sum は配列要素 (Y*np.log(A) + (1-Y)*(np.log(1-A)) を合計しますが、この場合すべての学習例に対する合計となるでしょう。 詳しくはこちら
- np.logは配列の要素ごとに自然対数をとります。 詳しくはこちら。
- “*”は、ある配列の要素を受け取り、別の配列の要素に、要素ごとに掛け合わせます。 これは、両方の配列から形状を要求される行列の乗算ではありません。 最初の配列の列の数は、2番目の配列の行と同じでなければなりません。