正則化の意味~制約条件付最適化

疑 問

L2ノルムによるRidge回帰やL1ノルムによるLasso回帰に登場する罰則項。Lpノルムで表現すると次のようになる。

(1)    \begin{equation*} L(\boldsymbol{w}) = E(\boldsymbol{w}) + \alpha \sum_i |w_i|^p \end{equation*}

ここでEは正則化がない場合の下の損失関数、w=(w1, … , wm)は特徴量に対する重みでLは正則化考慮後の損失関数。

このLを最小となるようなwを計算していくことになるのだが、多くの文献やサイトでL1正則化やL2正則化を説明するのに次のような図を使って、制約条件付きの最小化問題としている。

確かに式(1)の形はLagrrangeの未定乗数法に似ているのだが、ここで分からなくなるのが、αがハイパーパラメーターとして設定される点である。未定乗数法の場合、wαを未知数として、Lを偏微分して解いていくが、ここではαは変数としては用いられない。

考え方

まず、以下のように重みwに対する制約を設定する。

(2)    \begin{equation*} \sum_i |w_i|^p \le \frac{1}{\mu} \qquad (\mu > 0) \end{equation*}

これは、重みのノルムが高々1/μであることを意味している。これを0以下の制約条件として以下のように変形する。

(3)    \begin{equation*} g(\boldsymbol{w}) = \mu \sum_i |w_i|^p - 1 \le 0 \end{equation*}

一般化するとa\sum |w_i|^p + bの形になるが、不等式の両辺をaで割ることで、このような表現とすることは差し支えない。

これを制約条件として、元々の損失関数E(w)を最小化するため、λを導入して不等式制約条件付きのLagrangeの未定乗数法の問題を立てる。

(4)    \begin{align*} &\mathrm{minimize} \quad E(\boldsymbol{w}) \\ &\mathrm{subject~to} \quad g(\boldsymbol{w}) = \mu \sum_i |w_i|^p - 1 \le 0 \\ &\rightarrow \quad M(\boldsymbol{w}, \lambda) = E(\boldsymbol{w}) - \lambda \left( \mu \sum_i |w_i|^p - 1 \right) \end{align*}

ここでKKT条件からλ ≤ 0となるので、ξ = −λ ≥ 0を導入して、以下のように表す。

(5)    \begin{align*} M(\boldsymbol{w}, \lambda) = E(\boldsymbol{w}) + \xi \left( \mu \sum_i |w_i|^p - 1 \right) \end{align*}

以降、冒頭の正則化の式と上記の最小化問題の式を並べる。

(6)    \begin{align*} &L(\boldsymbol{w}) = E(\boldsymbol{w}) + \alpha \sum_i |w_i|^p \\ &M(\boldsymbol{w}, \xi) = E(\boldsymbol{w}) + \xi \left( \mu \sum_i |w_i|^p - 1 \right) \end{align*}

これらをwiで偏微分する。

(7)    \begin{align*} &\frac{\partial L}{\partial w_i} = \frac{\partial E}{\partial w_i} + \alpha \frac{d |w_i|^p}{d w_i} \\ &\frac{\partial M}{\partial w_i} = \frac{\partial E}{\partial w_i} + \xi \mu \frac{d |w_i|^p}{d w_i} \end{align*}

上式から、wに関しては2つの問題は等価と言える。しかしながら、Lの最小化についてはwの解が求まるのに対して、Mの最小化で解を確定するためには、ξを未知数としてこれについても偏微分をとり、未知数と方程式を1つ加えなければならない。どうしてLの最小化だけで最適解が定まるのか。

解 釈

ところで、αはハイパーパラメーターとして外部で設定するのであった。Lに関してはwiの個数分の未知数と方程式となり、wの解が確定する。すなわち、元の正則化の式を解くだけで「最適化された」係数のセットがw空間において1つに定まる。

ここからがミソで、wが求められるとこれを満たす制約条件の境界が定まり、同時に|w|pに対する制約も定まるというのがどうもこの計算の仕組みらしい。

そこで、αを設定した後のながれを追ってみる。

  • αを設定してLを最適化する
  • w = (w1, … , wm)が定まる
  • wを通る制約条件の境界g(w) = 0が定まる → Σ|wi|p = μ−1

すなわち、αを設定してLを最適化することで制約条件の境界g = 0が決定され、重みに対する制約の強さμも決まることになる。

なお、α = 0として罰則項の効果をなくす場合のほかは必ず制約条件の境界上で解を求めることになる。一般的なLagrangeの未定乗数法のように、与えられた制約条件と目的関数の関係によって純粋な極値問題となるということはない(後述する∇Eと∇gのgradientの向きの関係からも確認できる)。

ξμはどのように定まるのか

本来なら生真面目に未定乗数法を解いて求めるはずのξはどこへ行ったのか。

  • 式(7)のノルム項の比較よりα = ξμ
  • αは事前に設定した値で、μLの計算結果から導出されることから、ξ = μ/αも計算可能
  • なおMについて、点wにおいては∇E = −ξμgが成り立っており、この点でEgのgradientが平行(−ξμの符号から、両ベクトルは逆向き)

すなわち、ξμと組み合わさって、境界条件における目的関数Eと制約条件gのgradientの比となっている。

μについては、α = ξμの関係から、αを大きくするとμも大きくなる傾向になりそうである。それにつれて式(2)から重みをより小さく制約する方向に効きそうである。ただしこの場合、ξも変動するので単純な比例関係にはならず、αの値を試行錯誤で変化させて学習効果を確認することになる。

参考サイト

本記事をまとめるにあたって、下記サイトが大変参考になったことに感謝したい。

過学習を防ぐ「正則化」とは?○×(まるぺけ)つくろーどっとコム

 

 

 

Ridge回帰の理解

定義

Ridge回帰は多重回帰の損失関数に罰則項としてL2正則化項を加味する。正則化の意味についてはこちらに詳しくまとめている。

L2ノルムは原点からのユークリッド距離。

(1)    \begin{equation*} \| \boldsymbol{w} \| _2 = \sqrt{w_1 ^2 + \cdots + w_m^2} \end{equation*}

ただしリッジ回帰では、根号の中の二乗項で計算する。

(2)    \begin{equation*} \mathrm{minimize} \quad \sum_{i=1}^n (y_i - \hat{y}_i) + \alpha \sum_{j=1}^m w_j^2 \end{equation*}

定式化

最小化すべき関数は、

(3)    \begin{align*} L &= \sum_{i=1}^n ( \hat{y}_i - y_i )^2 + \alpha ({w_1}^2 + \cdots + {w_2}^2) \\ &= \sum ( w_0 + w_1 x_{1i} + \cdots + w_m x_{mi} - y_i )^2 + \alpha ({w_1}^2 + \cdots + {w_m}^2) \end{align*}

重み係数を計算するために、それぞれで偏微分してゼロとする。

(4)    \begin{align*} \frac{\partial L}{\partial w_0} &= 2 \sum (w_0 + w_1 x_{1i} + \cdots + w_m x_{mi} - y_i) = 0 \\ \frac{\partial L}{\partial w_1} &= 2 \sum x_{1i} (w_0 + w_1 x_{1i} + \cdots + w_m x_{mi} - y_i) + 2 \alpha w_1 = 0 \\ \vdots\\ \frac{\partial L}{\partial w_m} &= 2 \sum x_{mi} (w_0 + w_1 x_{1i} + \cdots + w_m x_{mi} - y_i) + 2 \alpha w_m = 0\\ \end{align*}

その結果得られる連立方程式は以下の通り。

(5)    \begin{align*} n w_0 + w_1 \sum x_{1i} + \cdots + w_m \sum x_{mi} &= \sum y_i \\ w_0 \sum x_{1i} + w_1 \left( \sum {x_{1i}}^2 + \alpha \right) + \cdots + w_m \sum x_{1i} x_{mi} &= \sum x_{1i} y_i \\ \vdots \\ w_0 \sum x_{mi} + w_1 \sum x_{1i} x_{mi} + \cdots+ w_m \left( \sum {x_{mi}}^2 + \alpha \right) &= \sum x_{mi} y_i \\ \end{align*}

ここでそれぞれの和を記号Sと添字で表し、さらに行列表示すると以下の通り。

(6)    \begin{equation*} \left[ \begin{array}{cccc} n & S_1 & \cdots & S_m \\ S_1 & S_{11} + \alpha & & S_{1m} \\ \vdots & \vdots & & \vdots \\ S_m & S_{m1} & \cdots & S_{mm} + \alpha \end{array} \right] \left[ \begin{array}{c} w_0 \\ w_1 \\ \vdots \\ w_m \end{array} \right] = \left[ \begin{array}{c} S_y \\S_{1y} \\ \vdots \\ S_{my} \end{array} \right] \end{equation*}

ここでw_0を消去して、以下の連立方程式を得る。

(7)    \begin{align*} &\left[ \begin{array}{ccc} ( S_{11} + \alpha ) - \dfrac{{S_1}^2}{n} & \cdots & S_{1m} - \dfrac{S_1 S_m}{n} \\ \vdots & & \vdots \\ S_{m1} - \dfrac{S_m S_1}{n} & \cdots & ( S_{mm} + \alpha )- \dfrac{{S_2}^2}{n} \end{array} \right] \left[ \begin{array}{c} w_1 \\ \vdots \\ w_m \end{array} \right] \\&= \left[ \begin{array}{c} S_{1y} - \dfrac{S_1 S_y}{n} \\ \vdots \\ S_{my} - \dfrac{S_m S_y}{n} \end{array} \right] \end{align*}

これを分散・共分散で表すと、

(8)    \begin{equation*} \left[ \begin{array}{ccc} V_{11} + \dfrac{\alpha}{n} & \cdots & V_{1m} \\ \vdots & & \vdots \\ V_{m1} & \cdots & V_{mm} + \dfrac{\alpha}{n} \end{array} \right] \left[ \begin{array}{c} w_1 \\ \vdots \\ w_m \end{array} \right] = \left[ \begin{array}{c} V_{1y} \\ \vdots \\ V_{my} \end{array} \right] \end{equation*}

ここで仮に、xjiとxkiが完全な線形関係にある場合を考えてみる。x_j = a x_i + bとすると、分散・共分散の性質より、

(9)    \begin{equation*} V_{jj} = a^2V_{ii}, \; V_{ji} = V_{ij} = aV_{ii}, \; V_{jk} = V_{kj} = aV_{ji} = aV_{ij} \end{equation*}

このような場合、通常の線形回帰は多重共線性により解を持たないが、式(8)に適用すると係数行列は以下のようになる。

(10)    \begin{align*} \left[ \begin{array}{ccccccc} V_{11} + \dfrac{\alpha}{n} & \cdots & V_{1i} & \cdots & aV_{1i} & \cdots & V_{1m}\\ \vdots && \vdots && \vdots && \vdots\\ V_{i1} & \cdots & V_{ii} + \dfrac{\alpha}{n} & \cdots & aV_{ii} & \cdots & V_{im}\\ \vdots && \vdots && \vdots && \vdots\\ aV_{i1} & \cdots & aV_{ii} & \cdots & a^2V_{ii} + \dfrac{\alpha}{n} & \cdots & aV_{im}\\ \vdots && \vdots && \vdots && \vdots\\ V_{m1} & \cdots & V_{mi} & \cdots & aV_{mi} & \cdots & V_{mm} + \dfrac{\alpha}{n} \end{array} \right] \end{align*}

対角要素にαが加わることで、多重共線性が強い場合でも係数行列の行列式は正則となり、方程式は解を持つ。また正則化の効果より、αを大きな値とすることによって係数の値が小さく抑えられる。

行列による表示

式(3)の損失関数を、n個のデータに対する行列で表示すると以下の通り(重回帰の行列表現はこちらを参照)。

(11)    \begin{align*} L &= \left( \boldsymbol{Xw} - \boldsymbol{y} \right)^T \left( \boldsymbol{Xw} - \boldsymbol{y} \right) + \alpha \boldsymbol{w}^T \boldsymbol{w} \\ &= \boldsymbol{w}^T \boldsymbol{X}^T \boldsymbol{Xw} - 2\boldsymbol{y}^T \boldsymbol{Xw} + \boldsymbol{y}^T \boldsymbol{y} + \alpha \boldsymbol{w}^T \boldsymbol{w} \end{align*}

これをwで微分してLを最小とする値を求める。

(12)    \begin{gather*} \frac{dL}{d\boldsymbol{w}} = 2\boldsymbol{X}^T \boldsymbol{Xw} - 2 \boldsymbol{X}^T \boldsymbol{y} + 2 \alpha \boldsymbol{w} = \boldsymbol{0} \\ \boldsymbol{w} = \left( \boldsymbol{X}^T \boldsymbol{X} + \alpha \boldsymbol{I} \right)^{-1} \boldsymbol{X}^T \boldsymbol{y} \end{gather*}

 

waveデータセット – 線形回帰

O’Reillyの”Pythonではじめる機械学習”に載っている、scikit-learnの線形回帰waveデータセットへの適用の再現。

waveデータセットのサンプル数を60、train_test_split()random_satet=42として、書籍と同じグラフを得る。

また、訓練結果の係数、切片とスコアについても同じ結果を得ることができる。

 

Breast cancer データセット – Logistic回帰による学習率曲線

概要

breast-cancerデータセットにscikit-learnのLogisticRegressionクラスでLogistic回帰を適用した結果。

手法全般の適用の流れはLogistic回帰~cancer~Pythonではじめる機械学習よりを参照。

ここではハイパーパラメーターを変化させたときの学習率の違いをみている。

学習率曲線

scikit-learnのLogisticRegressionクラスで、正則化のパラメーターを変化させたときの学習率曲線。同クラスにはsolver引数で収束計算のいくつかの手法が選択できるが、収束手法の違いによって意外に学習率曲線に違いが出た。またtrain_test_split()random_stateを変えても違いがある。569のデータセットで訓練データとテストデータを分けてもいるが、その程度では結構ばらつきが出るということかもしれない。

まず、random_state=0とした場合の、4つの収束手法における学習率曲線を示す。L-BFGSは準ニュートン法の1つらしいので、Newton-CGと同じ傾向であるのは頷ける。SAG(Stochastic Average Gradient)はまた違った計算方法のようで、他の手法と随分挙動が異なる。収束回数はmax_iter=10000で設定していて、これくらいでも計算回数オーバーの警告がいくつか出る。回数をこれより2オーダー多くしても、状況はあまり変わらない。

random_state=11としてみると、liblinearでは大きく違わないが、他の3つの手法では傾向が違っていて、特にsagを用いた場合は訓練データの学習率の方がテストデータの学習率よりも低くなっている。

 

Logistic回帰

概要

適用対象となる問題

ロジスティック回帰(Logistic regression)は「回帰」という名称だが、その機能は2クラス分類である。複数の特徴量に対して、2つのクラス1/0の何れになるかを判定する。

たとえば旅行会社の会員顧客20人の年齢と、温泉(SPA)とレジャーランド(LSR)のどちらを選んだかというデータが以下のように得られているとき、新たな顧客にどちらを勧めればよいか、といったような問題。

上のデータの”is SPA”列は、温泉を選んだ場合に1、レジャーランドを選んだ場合に0としている。これを散布図にすると以下の通り。

年齢が高いほど温泉を選ぶ傾向があるのは分かるが、「年齢が与えられたときに温泉とレジャーランドのどちらを選ぶか」というモデルを導出するのが目的。

(1)    \begin{equation*} (x_1, \ldots, x_m) \rightarrow \left \{ \begin{array}{cc} 1 \\ 0 \end{array} \right. \end{equation*}

モデルを線形モデルとし、特徴量の線形和の値によってクラス1/0の何れになるかが決まるとすると

(2)    \begin{equation*} b + w_1  x_1 + \cdots + w_m x_m \rightarrow \left \{ \begin{array}{cc} 1 \\ 0 \end{array} \right. \end{equation*}

線形回帰による場合

ここでそのままデータに対して線形回帰を適用して、たとえば回帰式の値0.5に対する年齢を境にして温泉とレジャーランドを判定してもよさそうに見える。ただ、この時の回帰式がデータに対してどのような意味を持つのかが定かではない。

確率分布の仮定

単純な線形回帰ではなく、特徴量の線形和に対してクラス1となる確率分布を考える。

(3)    \begin{align*} \Pr (y=1) &= f(z) = f( b + w_1  x_1 + \cdots + w_m x_m ) \\ f(0) &= 0.5 \end{align*}

このときの確率分布の関数形として以下が必要となる。

  • xの(−∞, +∞)の範囲に対して、値が(0, 1)となる
  • xが小さい→確率が0に近くなる→クラス0と判別されやすくなる
  • xが大きい→確率が1に近くなる→クラス1と判別されやすくなる

これをグラフにすると、以下のような形になる。

このような関数の回帰によるクラス分類は、確率分布に用いる関数形からLogistic回帰と呼ばれている。

Logistic回帰の定式化

確率分布関数の仮定

説明変数がx_1, \ldots, x_mであり、それに対してある事象が発生する/発生しないの2通りがあるとする。

いま、i=1, \ldots, nの観察対象についてx_{i1}, \ldots, x_{im}のデータが観測されたとする。このとき、以下のように定式化する。

(4)    \begin{align*} & z_i = b + w_1 x_{i1} + \cdots + w_m x_{im} = b + {\boldsymbol a}{\boldsymbol x} \\ & y_i = \left\{ \begin{array}{cl} 1 & \textrm{(occured)}\\ 0 & \textrm{(not occured)} \end{array} \right. \\ & \Pr (y=1) = p = \frac{1}{1 + e^{- ( b + {\boldsymbol w}{\boldsymbol x} ) }} \end{align*}

x_{ij} \; (j=1, \ldots, m)が得られたとき、その多項式を使った確率によって事象が発生することを意味している。この確率分布の式はLogistic関数と呼ばれる。

ロジスティック関数(logistic function)はシグモイド関数(sigmoid function)とも呼ばれ、その値は(0, 1)の間にあることから確率分布として採用している。

(5)    \begin{equation*} {\rm logistic} (t) = \sigma (t) = \frac{1}{1 + e^{-t}} = p \end{equation*}

 

なお、ロジスティック関数の逆関数はロジット関数(logit function)と呼ばれる。

(6)    \begin{equation*} {\rm logit} (p) =  \ln \frac{p}{1 - p} = t \end{equation*}

ここでLogit関数の対数の中はオッズの形になっている。

最尤推定

x_{ij} (i=1, \ldots , n)のm×n個の説明変数データと、y_i (1 \; \textrm{or} \; 0)のターゲットデータが得られたとする。

このとき、ターゲットデータが得られたパターンとなる確率は、それぞれが独立事象であるとすれば確率の積になるから、

(7)    \begin{equation*} L &= \prod_{i=1}^n \Pr (y_i = 1) ^{y_i} \Pr (y_i = 0) ^{1 - y_i} \end{equation*}

この確率は、パラメーターb , w_1, \ldots, w_mに対する尤度関数であり、その対数尤度関数は以下のようになる。

(8)    \begin{align*} \ln L &= \sum_{i=1}^n \left( y_i \ln \Pr(y_i = 1) + (1 - y_i) \ln \Pr(y_i = 0) \right) \\ &= \sum_{i=1}^n \left( y_i \ln \Pr(y_i = 1) + (1 - y_i) \ln \left(1 - \Pr(y_i = 1) \right) \right) \\ \end{align*}

ここで、

(9)    \begin{align*} \ln \left( 1 - \Pr(y_i = 1) \right) &= \ln \left(1 - \frac{1}{1 - e^{-(b + {\boldsymbol w}{\boldsymbol x})}} \right) \\ &= \ln \frac{e^{-(b + {\boldsymbol w}{\boldsymbol x})}}{1 + e^{-(b + {\boldsymbol a}{\boldsymbol x})}} \\ &= \ln e^{-(b + {\boldsymbol w}{\boldsymbol x})} + \ln \Pr (y_i = 1 ) \\ &= -b - {\boldsymbol w}{\boldsymbol x} + \ln \Pr (y_i = 1 ) \end{align*}

これを使って、対数尤度関数は以下のように変形される。

(10)    \begin{align*} \ln L &= \sum_{i=1}^n \left( y_i \ln \Pr(y_i = 1) + (1 - y_i) \left( -b - {\boldsymbol w}{\boldsymbol x} + \ln \Pr (y_i = 1 ) \right) \right) \\ &= \sum_{i=1}^n \left( \ln \Pr (y_i = 1 ) + (1 - y_i) (-b - {\boldsymbol w}{\boldsymbol x}) \right) \\ &= \sum_{i=1}^n \left( \ln \frac{1}{1 + e^{-(b + {\boldsymbol w}{\boldsymbol x})}} + (1 - y_i) (-b - {\boldsymbol w}{\boldsymbol x}) \right) \\ &= \sum_{i=1}^n \left( -\ln \left( 1 + e^{-(b + {\boldsymbol w}{\boldsymbol x})} \right) + (1 - y_i) (-b - {\boldsymbol w}{\boldsymbol x}) \right) \\ \end{align*}

得られたデータに対してこの対数尤度を最大とするような{\boldsymbol w}を求めるのには、通常数値計算が用いられる。

1変数の場合

定式化

線形表現は以下のようになる。

(11)    \begin{equation*} z = b + w x \end{equation*}

ロジスティック関数による確率表現は

(12)    \begin{equation*} \Pr (y=1) = p = \frac{1}{1 + e^{-(b + w x)}} \end{equation*}

nこのデータセット(x_i, y_i)が与えられたとき、この確率分布に関する尤度関数は

(13)    \begin{equation*} L(b, w) = \prod_{i=1}^n \left( \frac{1}{1 + e^{-(b + wx_i)}} \right)^{y_i} + \left( 1 - \frac{1}{1 + e^{-(b + wx_i)}} \right)^{1 - y_i} \end{equation*}

その対数尤度関数は

(14)    \begin{equation*} \ln L(b, w) &=& \sum_{i=1}^{n} \left( y_i \ln \frac{1}{1 + e^{-b - w x_i}} + (1 - y_i) \ln \left( 1 - \frac{1}{1 + e^{-b - w x_i}} \right) \right) \end{equation*}

ここでデータセット(xi, yi)として、が与えられたとき、対数尤度を最大とするようなb, wを計算する。

LogisticRegressionモデル

温泉のデータセットに対して、scikit-learnのLogisticRegressionモデルを適用した結果が冒頭のグラフで、コードは以下の通り。

LogisticRegressionのコンストラクターの引数としてsolver='lbfgs'を指定しているが、2020年4月時点ではこれを指定しないと警告が出るため。収束アルゴリズムにはいくつかの種類があって、データサイズや複数クラス分類・1対他分類の別などによって使い分けるようだ。

また、同じデータセットについてExcelで解いた例はこちら

正則化

LogisticeRegressionモデルのコンストラクターの引数Cは正則化の強さを正の実数で指定する。大きな値を設定するほど正則化が弱く、小さくするほど正則化が効いてくる。

温泉のデータセットに対してC変化させてみたところ、1000あたりから上はほとんど関数形が変わらず、ほぼ正則化がない状態。デフォルトのC=1(赤い線)は結構強い正則化のように思える。

興味深いのはこれらのグラフがほぼ1点で交わっており、その点での確率が0.6近いことである。温泉かレジャーランドかを選ぶ年齢と確率が正則化の程度に寄らず一定だということになるが、これが何を意味しているか、今のところよくわからない。

一方で、確率0.5に相当する年齢は正則化を強めていくにしたがって低くなっていて、これを判定基準とするとC=0.001ではほぼ全年齢で温泉が選択されることになってしまう。

さらにCが更に小さい値になると、確率曲線はどんどんなだらかになっていき、C=1e-6では全年齢にわたって0.5、すなわち温泉、レジャーランドのいずれを選ぶかは年齢に関わらず1/2の賭けのようになっている。

2変数の場合

2変数の例として、”O’REILLYの”Pythonではじめる機械学習”にあるforgeデータの例をトレースしたものをまとめた。

Logistic回帰~forgeデータ~Pythonではじめる機械学習より

特徴量の係数

式(4)によるとziの値が大きいほどy = 1となる確率が高くなり、小さいほどy = 0となる確率が高くなる。また、特徴量xi ≥ 0とすると、係数wiが正のときにはziを増加させる効果、負の時にはziを減少させる効果がある。y = 0, 1にターゲット0, 1が割り当てられ、それらがクラス0、クラス1を表すとすると、係数が正のときにはその特徴量の増加がクラス1を選択する方向に働き、係数が負の時にはクラス0をを選択する方向に働く。

以下は特徴量数2、クラス数2の簡単な例で、Feature-0は係数が正なのでクラス0を選択する確率を高め、Feature-1の係数は係数が負なのでクラス1を選択する確率を高める。

 

Logistic回帰~1変数・Excelによる解

例題のデータ

ある旅行会社の会員顧客20人の年齢と、温泉(SPA)とレジャーランド(LSR)のどちらを選んだかというデータが以下のように得られているとき、新たな顧客にどちらを勧めればより適切か。

このようなクラス分けの問題にLogistic回帰を使うのにPythonのパッケージなどによる方法もあるが、ここではExcelを使った方法を示す。

その流れは、各観光客の選択結果のカテゴリー変数と年齢から個別の尤度と合計の尤度の計算式を定義し、切片と係数の初期値を設定しておいてから、尤度が最大となるような切片・係数を求めるためにExcelのソルバーを使う。

元となるデータは、各観光客の年齢と、行先に選んだのが温泉(SPA)かレジャーランドか(LSR)の別、それらに対して温泉を選んだ場合は1、レジャーランドを選んだ場合は0となるカテゴリー変数。

計算表の準備

このデータから以下のような表を作る。各セルの意味と内容は以下の通り。

  • coef:線形式の切片Aと係数Bの初期値としてそれぞれ0をセットし、収束計算の結果が入る
  • intercept:切片の計算のために使われるデータで、全て固定値の1
  • prob:coefがA, Bの値の時に各顧客の年齢に対してis_spa=1となる確率で、Logistic関数の計算値
    • セルの内容は計算式で=1/(1+EXP(-$A*Y-$B*Z))
    • $A, $Bは固定座標を表し、全てのデータに対してこれらのセルの内容を使う
  • LH:is_spaの値に対する尤度(likelihood)
    • セルの内容は計算式でX*LN(C)+(1-X)*LN(1-C)
  • MLE:全データのLHの和で、このデータセットのパターンに対する最大尤度の結果が入る

収束計算

データタブの一番右にあるソルバーに入る(ない場合はファイル→オプション→アドイン→設定からソルバーアドインにチェックを入れる)。

ソルバーのパラメーター設定ダイアログで、

  • 目的セルを上記のDで選択
  • 変数セルを上記のA:Bの範囲で選択。
  • 目標値は「最大値」を選択

「解決」ボタンを押して収束計算すると、Dの値を最大化するA:Bの内容がセットされる。

この場合の結果は以下の通り

  • coef:-13.6562, 0.234647
  • MLE:-7.45298

確率0.5(線形式の値が0)を温泉とレジャーランドの閾値とするなら、それに相当する年齢は以下のように計算される。

(1)    \begin{equation*} -13.6562 + 0.234647 \times x = 0 \quad \rightarrow \quad x = \frac{13.6562 }{0.234647 } =58.2 \end{equation*}

Pythonのscikit-learnのLogisticRegressionモデルを同じデータに適用した結果(C=1e5)は以下の通りで、かなり近い値となっている。

  • intercept_ = [-13.38993211]
  • coefficient_ = [0.23015561]

得られた係数の値を使って、以下の関数式のグラフを描いてみたのが以下の図でLogistic曲線が現れている。

Boston house pricesデータセットの俯瞰

概要

Boston house pricesデータセットは、持家の価格とその持家が属する地域に関する指標からなるデータセットで、多変量の特徴量から属性値を予想するモデルに使われる。

各特徴量の分布

データセットからBostonにおける506の地域における13の特徴量と住宅価格の中央値が得られるが、それぞれ単独の分布を見ておく。最後のMEDVは持家価格(1000ドル単位)の中央値(Median Value)。

特徴量CHASはチャールズ川の川沿いに立地しているか否かのダミー変数で、0/1の2通りの値を持つ。いくつかの特徴量は値が集中していたり、離れたところのデータが多かったりしている。

各特徴量と価格の関係

13の特徴量1つ1つと価格の関係を散布図で見てみる。

比較的明らかな関係がみられるのはRM(1戸あたり部屋数)とLATAT(下位層の人口比率)で、この2つは特徴量自体の分布が比較的”整っている”。

NOX(NOx濃度)も特徴量の分布はそこそこなだらかだが、散布図では強い相関とは言い難い。

AGE(古い物件の比率)とDIS(職業紹介所への距離)はそれぞれ分布が単調減少/単調増加で、特徴量の大小と価格の高低の関係はある程度予想通りだがかなりばらついている。いずれの指標についてもMDEVがある値以下で密度が高くなっているように見えるのは興味深い。

2つの特徴量と価格の関係

個々の特徴量ごとの、価格との相関がある程度が明確だったRMとLSTATについて価格との関係を3次元で見てみる。

それぞれの相関がある程度明確なので、3次元でも一つの帯のようになっている。

 

 

Boston house‐pricesデータセット

概要

Boston house-pricesデータセットは、カーネギーメロン大学のStatLibライブラリーから取得したもので、持家の価格とその持家が属する地域に関する指標からなる。

ボストンの各地域にある506の持家の価格の中央値に対して、その地域の犯罪発生率やNOx濃度など13の指標が得られる。

ここではPythonのscikit-learnにあるbostonデータの使い方をまとめる。

データの取得とデータ構造

Pythonで扱う場合、scikit-learndatasetsモジュールにあるload_breast_cancer()でデータを取得できる。データはBunchクラスのオブジェクト。

データセットの構造は辞書型で、506の地域に関する13の特徴量と、当該地域における持家住宅の1000ドル単位の価格などのデータ。

データのキーは以下のようになっている。

データの内容

'data'~特徴量データセット

506の地域における13の指標を特徴量として格納した2次元配列。列のインデックスが特徴量の番号に対応している。

'target'~住宅価格

506の地域における持家住宅の1000ドル単位の価格中央値

'feature_names'~特徴名

13種類の特徴量の名称。

  1. CRIM:町ごとの人口当たり犯罪率
  2. ZN:25,000平方フィート以上の区画の住居用途地区比率
  3. INDUS:町ごとの小売り以外の産業用途地区比率
  4. CHAS:チャールズ川に関するダミー変数(1:川沿い、0:それ以外)
  5. NOX:NOx濃度(10ppm単位)
  6. RM:1戸あたり部屋数
  7. AGE:1940年より前に建てられた持家物件の比率
  8. DIS:ボストンの5つの職業紹介所への重みづけ平均距離
  9. RAD:放射道路へのアクセス性
  10. TAX:10,000ドルあたりの固定資産税総額
  11. PTRATIO:生徒対教師の比率
  12. B:1000(Bk – 0.63)^2(Bkは待ちにおける黒人比率)
  13. LSTAT:下位層の人口比率(%)

'filename'~ファイル名

CSVファイルのフルパス名が示されている。1行目にはデータ数、特徴量数が並んでおり、2行目に13の特徴量とターゲットの住宅価格、その後に506行のレコードに対する13列の特徴量と1列のターゲットデータが格納されている。このファイルにはDESCRに当たるデータは格納されていない。

'DESCR'~データセットの説明

データセットの説明。print(breast_ds_dataset['DESCR'])のようにprint文で整形表示される。

  • レコード数506個
  • 属性は、13の数値/カテゴリー属性と、通常はターゲットに用いられる中央値

データの利用

データの取得方法

bostonデータセットから各データを取り出すのに、以下の2つの方法がある。

  • 辞書のキーを使って呼び出す(例:boston['DESCR']
  • キーの文字列をプロパティーに指定する(例:boston.DESCR

全レコードの特徴量データの取得

'data'から、506のレコードに関する13の特徴量が506行13列の2次元配列で得られる。13の特徴量は’feature_names’の13の特徴名に対応している。

特定の特徴量のデータのみ取得

特定の特徴量に関する全レコードのデータを取り出すときにはX[:, n]の形で指定する。

 

waveデータセット – knn

概要

k-最近傍回帰の例として、scikit-learnのwaveデータKNeighborsRegressorを適用してみた結果。

近傍点数とクラス分類の挙動

訓練データとして10個のwaveデータを訓練データとして与え、2つのテストデータの予測するのに、近傍点数を1, 2, 3と変えた場合の様子を見てみる。

近傍点数=1の場合

2つのテストデータの特徴量の値に最も近い特徴量を持つ訓練データが選ばれ、その属性値がそのままテストデータの属性値となっている。

近傍点数=2の場合

テストデータの特徴量に最も近い方から1番目、2番目の特徴量を持つ訓練データが選ばれ、それらの属性値の平均がテストデータの属性値となっている。

近傍点数=3の場合

同様に、テストデータの特徴量に最も近い3つの訓練データの属性の平均がテストデータの属性値となっている。

実行コード

上記の計算のコードは以下の通り。

knnの精度

O’Reillyの”Pythonではじめる機械学習”中、KNeighborsRegressorのwaveデータに対する精度が計算されている。40サンプルのwaveデータを発生させ訓練データとテストデータに分け、テストデータに対するR2スコアが0.83となることが示されている。実際に計算してみると、確かに同じ値となる。

これを見ると比較的高い精度のように見えるが、train_test_split()の引数random_stateを変化させてみると以下のように精度はばらつく。乱数系列が異なると精度が0.3未満の場合もあるが、全体としてみると0.6~0.7あたりとなりそうである。

ためしにmake_wave(n_samples=1000)としてみると、結果は以下の通りとなり、精度は0.67程度(平均は0.677)と一定してくる。

予測カーブ

訓練データが少ない場合

40個のwaveデータに対して、n_neighborsを変化させたときの予測カーブを見てみる。

  • n_neighbors=1の時は、全ての訓練データを通るような線となる
  • n_neighborsが多くなるほど滑らかになる
  • n_neighborsがかなり大きくなると水平に近くなる
  • n_neighborsが訓練データ数と同じになると、予測線は水平になる(任意の特徴量に対して、全ての点の平均を計算しているため)

訓練データが多い場合

今度はwaveデータでn_samples=200と数を多くしてみる。データ数を多くするとその名の通り、上下に波打ちながら増加している様子が見られる。これに対してn_neighborsを変化させたのが以下の図。

n_neighbors=10~20あたりで滑らかに、かつ波打つ状況が曲線で再現されている。

n_samples=300として訓練データに200を振り分け、n_neighborsを変化させたときのスコアは以下の通り。n_neighbors=20あたりで精度が最もよさそうである。

あるデータが得られたとき、その科学的なメカニズムは置いておいて、とりあえずデータから予測値を再現したいときにはそれなりに使えるかもしれない。

 

forgeデータセット – knn

概要

ここでは、Pythonのscikit-learnパッケージのKNeighborsClassifierクラスにmglearnパッケージのforgeデータを適用してknnの挙動を確認する。

近傍点数を変化させたときのクラス分類の挙動や学習率曲線についてみていく。

近傍点数によるクラス分類の挙動

近傍点数=1の場合

データセットとしてmglearnで提供されているforgeデータを用いて、近傍点数=1とした場合の、3つのテストデータのクラス判定を以下に示す。各テストデータに対して最も距離(この場合はユークリッド距離)が近い点1つが定まり、その点のクラステストデータのクラスとして決定している。

なお、いろいろなところで見かけるforgeデータセットの散布図は当該データセットの特徴量0(横軸)と特徴量1(縦軸)の最小値と最大値に合わせて表示しており、軸目盛の比率が等しくない。ここでは、距離計算に視覚上の齟齬が生じないように、縦軸と横軸の比率を同じとしている。

後の計算のために、このグラフ描画のコードを以下に示す。

概要は以下の通り。

  • 5行目でforgeデータセットを準備
  • 7行目で近傍点数を1で指定してクラス分類器を構築
  • 8行目で訓練データとしてforgeデータを与える
  • 12行目で3つのテストデータを準備
  • 13行目でテストデータに対する近傍点のインデックスとテストデータまでの距離を獲得
  • 14行目でテストデータのクラスを決定
  • 18-19行目で訓練データの散布図を描画
  • 23行目で、テストデータとそのクラス決定結果、クラス決定に用いられた点群のインデックス、テストデータと各点の距離を並行してループ
    • 24行目でテストデータの座標を出力
    • 25行目でテストデータを描画
    • 26行目のループで、テストデータごとの近傍点に関する処理を実行
      • 27行目でテストデータと近傍点の間に直線を描画
      • 28行目で近傍点とテストデータからの距離を出力

出力結果は以下の通りで、各予測点に対して近傍点が1つ決定されている。

近傍点数=3の場合

先の例で、コードの7行目で近傍点=3で指定してクラス分類器を構築する。

一般にknnでは、テストデータに対して複数の近傍点を指定する場合、各近傍点のクラスのうち最も多いものをテストデータのクラスとする(多数決)。

近傍点数=2の場合

テストデータのクラスを近傍点のクラスの多数決で求めるとすると、近傍点数が偶数の時の処理が問題になる。KNeighborsClassifierの場合、偶数でクラス分類が拮抗する場合は、クラス番号が最も小さいものに割り当てられるらしい。実際、n_neighbors=2としたときの3つのテストデータのうち中央の点(10.0, 3.0)については、赤い点(10.24, 2.45)~class-1~距離0.5952の方が青い点(9.5017, 1.9382)~class-0~距離1.1729よりも距離は近いがクラス番号が0である青い点のクラスで判定されている。

偶数の点で多数決で拮抗した場合には、最も近い点のクラスで決定する、平均距離が近い方のクラスで決定するといった方法が考えられるが、この場合は必ず番号が小さなクラスが選ばれるため、若干結果に偏りがでやすいのでは、と考える。

決定境界

近傍点の数を変えた時の決定境界の変化を確認する。k近傍法はscikit-learnのKNeighborsClassifierクラスを利用する。

近傍点の数を1, 2, 3, …と変化させたときの決定境界の変化は以下の通り。

近傍点数が少ないときは訓練データにフィットするよう決定境界が複雑になるが、近傍点数が多いと決定境界は滑らかになる。特に近傍点数が訓練データの点数に等しいとき、全訓練データの多数決でクラス決定され、全領域で判定結果が同じとなる(この場合は近傍点数26が偶数なので、クラス番号の小さいclass-0で決定されている)。

この図を描画したコードを以下に示す。

  • 7行目、引数で与えたAxesに対して決定境界を描く関数を定義
    • 18行目、決定境界をcontourf()を利用して描いている
  • 21行目、引数で与えたAxesに対してクラスごとに色分けした散布図を描く関数を定義
  • 54行目、2次元配列のAxes1次元配列として扱っている