# 機械学習 ## 1. 線形回帰モデル ### 要約 基本は連続値を扱う。 直線で予測する=線形回帰 曲線で予測=非線形回帰 - Vapnikの原理 「本来解くべき問題より難しい問題はやるべきでない」 密度ひ推定? - 扱うデータ - 入力 m次元のベクトル - 出力(目的変数) スカラー値 説明変数 $\boldsymbol x=(x_{1},x_{2},・・・,x_{m})^{T} \in \mathbb R^{m}$ $\mathbb R^{m}$=m次元空間の実数, m次元空間中の1点を取る - パラメータ $\boldsymbol w=(w_{1},w_{2},・・・,w_{m})^{T} \in \mathbb R^{m}$ - 線形結合 $\hat y=\boldsymbol w^{T}\boldsymbol x + w_{0}= \displaystyle\sum_{j=1}^{m} w_{j}x_{j} + w_{0}$ (hatは予測値を表すのが慣例) - 説明変数が1個なら単回帰、2個以上なら重回帰 - 参考文献:機械学習のエッセンス おすすめ (特に線形回帰に限らない話↓) - 汎化性能測定 - 学習用データと検証用のデータで分ける - 汎化性能=未知のデータに対してどれくらい精度が高いかを見る - 線形回帰モデル - パラメータは最小二乗法でもとめる。 - 予測と実測値のズレの二乗の和が小さくなるように $\displaystyle MSE_{train}=\frac{1}{n_{train}} \displaystyle\sum_{i=1}^{ntrain}(\hat y_{i}^{(train)}-y_{i}^{(train)})^{2}$ - MSE(Mean Squared Error) - 外れ値は予測が引っ張られるの注意 ```参考文献:イラストで学ぶ機械学習``` $\frac{\partial }{\partial \boldsymbol w} MSE_{train}$ = 0 凸な二乗関数と考えると微分して0になる所が最小値 ### 実装演習結果,考察 **np_regression.ipynb** - 単回帰予測 ![](https://i.imgur.com/zvyEgEf.png) - 多項式回帰 ![](https://i.imgur.com/tHJHkSR.png) - 重回帰分析 ``` w0_true: 1.0 w0_estimated: -0.32 w1_true: 0.5 w1_estimated: 1.2e+01 w2_true: 2.0 w2_estimated: -3.3e+01 w3_true: 1.0 w3_estimated: 2.1e+01 ``` **skl_regression.ipynb** - 線形単回帰分析 ``` # 予測 array([-0.26491325, 8.39106825]) ``` - 重回帰分析(2変数) ``` model2.coef_ array([-0.26491325, 8.39106825]) ``` - モデルの検証 - 決定係数 $R^{2}$ 0から1までの値を取る。 1に近いほど、回帰式が実際のデータに当てはまっている $$ R^{2} = 1 – \displaystyle\frac{\sum_{i=0}^{n-1} (y_i – \hat{y_i})^{2}}{\sum_{i=0}^{n-1} (y_i – \bar{y_i})^{2}} $$ - MSE(平均二乗誤差) 実際の値と予測値の絶対値の2乗を平均したもの。 $$ MSE = \ \displaystyle\frac{1}{n} \sum_{i=0}^{n-1} (y_i – \hat{y_i})^{2} $$ ``` MSE Train : 44.983, Test : 40.412 R^2 Train : 0.500, Test : 0.434 ``` 他の予測 ``` model2.predict([[0.3, 4]]) array([4.24007956]) model2.predict([[0.9, 10]]) array([54.42754109]) ``` --- 元々用意されているsklearnのデータセットを使用、 実際はまずこのデータ構造に持ってくるまでが大変。 - 単回帰 検証として部屋が一つの場合、 部屋の数を1で入れると住宅価格がマイナスのありえない値で出てきてしまう。 直線なのでしょうがないか。以下の**外挿問題**に相当。 - 外挿(extrapolation): 訓練データの範囲外で出力を求める事。一般的には弱い。あまり精度は期待できない - 内挿(interpolation): 学習データの範囲内で出力を求める事 - 重回帰 説明変数として2つ選んでいるが、どちらが結果(価格)に影響を大きく与えているのか分かる方法はないかと思ったが、おそらく係数がそのまま影響、強さになるだろうと思った。 ``` model2.coef_ --- array([-0.26491325, 8.39106825]) # 犯罪率 部屋数 →部屋数の方が影響が大きい ``` ### その他関連事項 他に追加して行列操作に慣れるために 「ゼロから作るディープラーニング1」のP56の多次元配列あたりを 触ってみた。気づきとしては - 改めてPythonでは変数名の大文字、小文字を識別する(別変数になる) - numpyで行列のアダマール積と内積がごっちゃになる。ややこしい。 行列の積(内積) ``` a = np.array([[1,2,3],[4,5,6]]) b = np.array([[1,2],[3,4],[5,6]]) print(np.dot(a, b)) print(a@b) --- [[22 28] [49 64]] [[22 28] [49 64]] ``` 同じ要素数の行列なら```*```で要素同士の掛け算(アダマール積) ``` d = np.array([[1,2,3],[4,5,6]]) e = np.array([[1,2,3],[4,5,6]]) d*e #アダマール積 --- array([[ 1, 4, 9], [16, 25, 36]]) ``` - 外れ値に弱いモデル→例えばざっくり外れ値を見つける方法 max, minを見たり、図として箱ひげ図にするなど。 ``` df.describe() --- CRIM ZN INDUS CHAS NOX RM AGE DIS RAD TAX PTRATIO B LSTAT PRICE count 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 506.000000 mean 3.613524 11.363636 11.136779 0.069170 0.554695 6.284634 68.574901 3.795043 9.549407 408.237154 18.455534 356.674032 12.653063 22.532806 std 8.601545 23.322453 6.860353 0.253994 0.115878 0.702617 28.148861 2.105710 8.707259 168.537116 2.164946 91.294864 7.141062 9.197104 min 0.006320 0.000000 0.460000 0.000000 0.385000 3.561000 2.900000 1.129600 1.000000 187.000000 12.600000 0.320000 1.730000 5.000000 25% 0.082045 0.000000 5.190000 0.000000 0.449000 5.885500 45.025000 2.100175 4.000000 279.000000 17.400000 375.377500 6.950000 17.025000 50% 0.256510 0.000000 9.690000 0.000000 0.538000 6.208500 77.500000 3.207450 5.000000 330.000000 19.050000 391.440000 11.360000 21.200000 75% 3.677083 12.500000 18.100000 0.000000 0.624000 6.623500 94.075000 5.188425 24.000000 666.000000 20.200000 396.225000 16.955000 25.000000 max 88.976200 100.000000 27.740000 1.000000 0.871000 8.780000 100.000000 12.126500 24.000000 711.000000 22.000000 396.900000 37.970000 50.000000 ``` ``` 参考文献:ゼロからつくるDeepLearning ``` ## 2. 非線形回帰モデル ### 要約 データを線形で捉えられない場合 $w$について求めたい。重みについては線形=Liner-in-parameter 線形モデルによる非線形回帰 $y_{i}=w_{0}+\displaystyle \sum_{j=1}^{m} w_{j}\phi_{j}(\boldsymbol x_{i}) + \varepsilon_{i}$ $\phi_{j}(\boldsymbol x_{i})$の部分が線形の時に$x_{i}$だった部分。$x_{i}$を入力として$x_{i}^{2}$や$\log x_{i}$などに変わりえる。 ここを**基底関数**という。 使われる基底関数は - 多項式関数 $\phi_{j}=x^{j}$ - ガウス型基底関数 $\displaystyle \phi_{j}(x)=exp\Big( \frac{(x-\mu_{j})^{2}}{2h_{j}}\Big)$ - スプライン関数/Bスプライン関数 がある #### 未学習、過学習 - 未学習(underfitting) 学習データに対して、十分小さな誤差が得られない - 過学習(overfitting) - 対策1: データ数を増やす - 対策2: 不要な基底関数(変数)を削除して表現力を抑止 - AICによるモデル選択? - 対策3: 正則化法を利用して表現力を抑止(イメージとして9次の項まであっても係数(w)が小さければ無視さされる) - 正則化項 モデルが複雑さに伴ってその値が大きくなる 重みパラメータ(係数)を一定の範囲に押し込める $S_{\gamma}=(y-\Phi^{n\times k} \omega)^{T}(y-\Phi\omega)+\gamma R(w)$ $\gamma>0$ 予測と実際の二乗和誤差 $(y-\Phi^{n\times k} \omega)^{T}(y-\Phi\omega)$ $\gamma$ は重みの調整パラメータ(ハイパーパラメータ) MSEの最小化 - 2種類の正則化 - Ridge推定 - Lasso推定 - 手元のモデルが未学習か過学習かの判定  訓練誤差はやろうと思えば上げられるが未知のデータに対する判定の能力、汎化能力があるかが問題 - 訓練誤差もテスト誤差も下がらない→汎化ができている可能性(OK) - 訓練誤差もテスト誤差も下がらない->未学習(採用している手法の表現力が足りない) - 訓練誤差は小さいが、テスト誤差が大きい→過学習  手元のモデル - ホールドアウト法(評価方法) - 訓練データとテストデータの分け方 - 最初の2割データを評価用、あとは訓練用と決め打ちで変更しない - 手元に大量のデータがある場合は良いが**一般的に問題あり** - 検証データの外れ値があった場合、 - 交差検証法 - 訓練データとテストデータを分け方を変えながらモデル作成  (採用している手法は同じだが、重みが異なるモデルができる) - データの偏りを避けられる - 全ての精度の平均値をCV値と呼ぶ CV値の出し方、二乗誤差が一般的。 - 学習誤差 - $MSE_{train}=\displaystyle\frac{1}{n_{train}} \displaystyle \sum_{i=1}^{n_{train}}(\hat y_{i}^{(train)}-y_{i}^{(train)})^{2}$ - 検証誤差 - $MSE_{test}=\displaystyle\frac{1}{n_{test}} \displaystyle \sum_{i=1}^{n_{test}}(\hat y_{i}^{(test)}-y_{i}^{(test)})^{2}$ - グリッドサーチ - 全てのチューニングパラメータの組み合わせで評価値を算出 - 最も良い評価値を持つチューニングパラメータを持つ組み合わせを  「いいモデルのパラメータ」として採用    ハイパーパラメータの選び方、ニューラルネットで**ベイズ最適化**が出てくる。 ### 実装演習結果,考察 **skl_nonlinear_regression.ipynb** 注意) path名を自分のドライブのフォルダ名に変える必要あり 多項式 次数がある程度上がるとほぼ一緒。多分少ない次数で表現できれば その方がよい。 ![](https://i.imgur.com/FCD0ObJ.png) KerasRegressor ![](https://i.imgur.com/651Pd3x.png) (線形回帰) Kernel Ridgeで当てはまりがよくなっている。パラメータαを大きくすると 制約が強くなり汎化能力が増す方向、小さくすると係数への制約が小さくなる Lasso()はL1正則化。パラメータαの効き方は同様。 「Pythonではじめる機械学習」によると > リッジとLassoの2つではまずリッジを試してみるとよい > しかし特徴量がたくさんあって、そのうち重要なものはわずかしかない場合は > Lassoの方が向いているだろう > とある Lassoとリッジのペナルティと組み合わせたElasticNetというクラスもあるという。 ### その他関連事項 - 俗に言われる訓練データが7,8割、Testデータが2,3割というのは根拠があるのか?疑問を持った。5割で分けると訓練データとしてもっと欲しい気もするし、かといってvalidationが1割だと不安な気もする https://towardsdatascience.com/finally-why-we-use-an-80-20-split-for-training-and-test-data-plus-an-alternative-method-oh-yes-edc77e96295d を見るとパレートの法則(経験則による8割2割の法則)と 以下の論文を紹介している > A scaling law for the validation-set training-set size ratio (Guyon). Here, they reference “ the best training/validation split for a specific problem: preventing overtraining of neural networks. They find that the fraction of patterns reserved for the validation set should be inversely proportional to the square root of the number of free adjustable parameters. Our result generalizes and confirms their result.” (Guyon, 1997). データ数のルート分の1で分けると少し良くなったという報告もある - Kaggleはやった事ないが、コンペ中は順位を決めるテストデータの一部しか公表されていないようだ。この場合のそのテストデータだけで自分のモデルを評価するのは危ない(これがホールドアウト法に該当する)。その為、自らTestデータの一部をValidationデータとして交差検証を行う。 - 少し勘違いしていたが、クロスバリデーションはiterationの中で一番良いモデルを採用するものを決める為のものではなく、今採用している手法(線形回帰、重回帰、非線形回帰など)とパラメータでの汎化性能を知る為のもの、結果他の手法と(CV値を)比べて採用、不採用を決められる。 検証の結果ハイパーパラメータが決まったら、訓練、検証含めて学習できる。 - Leave-one-out 交差検証  データを一つ抜き出して検証データとし、それ以外を訓練データとして学習する。 全てのデータが一回ずつ検証対象になる。 k-分割交差における、kが標本サイズと同じになったもの。 一つ抜き法、ジャックナイフ法とも呼ばれる **精度は高いが、時間がかかる** ```参考文献: 「Pythonではじめる機械学習」``` ## 3. ロジスティック回帰モデル ### 要約 分類タスク あえてDeepではなく、ロジスティック回帰を使う場合もあるので使えるとよい 説明変数は回帰の時と変わらないが目的変数が0か1 > 説明変数 $\boldsymbol x=(x_{1},x_{2},・・・,x_{m})^{T} \in \mathbb R^{m}$ > 目的変数 $\boldsymbol y \in \big\{0, 1 \big\}$ 確率で出力されるので0,1の確度が分かるのでうれしい **分類問題へのアプローチ** - 識別的アプローチ $p(C_{k} |x)$を直接モデル化 - 条件確率。xが決まった上で(割り当てられた上)でクラスC_{k}に割り当てられる確率 -> **ロジスティック回帰** - 生成的アプローチ $p(C_{k})$と$p(x|C_{k})$をmodel化し、その後Bayesの定理を用いて$p(C_{k}|x)$を求める - 識別関数 f(x) > 0 -> C=1, f(x)<0 C=0 $C_{k}$に割り当てられる確率は出せない。 例としてSVM ベイズの定理復習 $p(C_{k}|x)=\displaystyle \frac{p(C_{k}, x)}{p(x)}=\frac{p(x|C_{k})p(C_{k})}{p(x)}$ 線形回帰 $x^{T}w\in \mathbb{R}$ ほしい目的変数は0か1 $\boldsymbol y \in \big\{0, 1 \big\}$ 実数全体に含まれる$x^{T}w$を[0, 1]に押し込める=sigmoid関数の使用 $sigmoid= \displaystyle\frac{1}{1-e^{-z}}=\frac{e^{z}}{1+e^{z}}$ だが $\sigma(x)= \displaystyle \frac{1}{1+exp(-ax)}$ で表すと$a$がパラメータとなって曲線の形を変えられる。 $a$を大きくしていくとステップ関数に近くなる →合成関数の求め方は確認しておく ロジット変換 --- もとめたい値=左辺Xが与えられた時にY=1となる確率を知りたい $\displaystyle P(Y=1|\boldsymbol x)=\sigma(w_{0}+w_{1}x_{1})$ (説明変数を1個として) 求められた確率がある値以上なら1、以下なら0とする。この値は自分で判断、決める。 --- #### 最尤推定 ベルヌーイ分布のパラメータの推定 データから元の分布を推定する $\displaystyle P(y)=p^{y}(1-p)^{1-y}$ $\displaystyle P(y_{1},y_{2},・・・,y_{n};p)=\prod^{n}_{i=1} p^{y_{i}}(1-p)^{1-y_{i}}$ 同時確率: n回の試行でy1~ynが同時に起こる確率(pが固定) 尤度関数: $y_{1}~y_{n}$のデータが得られた際の尤度関数 ここで確率部分はシグモイド関数で置き換えるのだったから $P(y_{1},y_{2},・・・,y_{n}|w_{0},w_{1},・・・,w_{m})=\prod^{n}_{i=1} p^{y_{i}}(1-p)^{1-y_{i}}$ $\displaystyle=\prod^{n}_{i=1} \sigma(\boldsymbol w^{T}\boldsymbol x_{i})^{y_{i}}(1-(\boldsymbol w^{T}\boldsymbol x_{i}))^{1-y_{i}}$ $\displaystyle=L(\boldsymbol w)$ $w$が未知 尤度関数Lを最大とするパラメータを探索 勾配法の最小化問題に持っていきたいのでマイナスをつけて、桁落ちしないようにlogをつける $\displaystyle E(w_{0}, w_{1}, ・・・, w_{m})=-\log L(w_{0}, w_{1},,,w_{m})$ 最小二乗法の最小化に近い形 パラメータは勾配降下法で$w$を更新していく $\displaystyle w(k+1)=w^{k}-\eta\frac{\partial E(w)}{\partial w}$ $\eta$:学習率 誤差関数の微分(傾き)に学習率を掛けたものを引いて次の$w$とする。 $\displaystyle w^{(k+1)}=w^{(k)}-\eta \sum_{i=1}^{n}(y_{i}-p_{i})\boldsymbol x_{i}$ - 確率的勾配降下法(SGD) データの数が多い場合は1回の更新で時間がかかる。 1回の更新ですべてのデータを使うのでは無く、ランダムにデータを一つ選んで更新 --- ### 実装演習結果,考察: **np_logistic_regression.ipynb** ![](https://i.imgur.com/WCqRBbR.png) **skl_logistic_regression.ipynb** (前処理) Titanicデータ, AgeでNan(抜け)あり。DataframeのFilter機能便利。 欠損値補完はfillna()で平均値補完、中央値補完など。 前後関係で保管したい時はinterpolate()使用。 - 幾つか変数、関数についてLogistic regression - **predict_proba()** それぞれのクラスに属する確率を返す - **decision_function()** 確信度を返す。値が大きいほど確信度が高い? (skleanサイトより > Confidence scores per (sample, class) combination. In the binary case, confidence score for self.classes_[1] where >0 means this class would be predicted.) - model.intercept 切片にあたる - model.coef 係数 チケットクラス+性別と年齢より ![](https://i.imgur.com/ZG56fVS.png) 例の中にある```titanic_df['Pclass_Gender'] = titanic_df['Pclass'] + titanic_df['Gender']```の 足し算で混ぜてしまう分け方は意図がよく分からなかった。 チケットクラス2の男性(1)とチケットクラス3の女性(0)を混ぜてもいいのだろうか。 - データを2つに分けてそれぞれで結果の混同行列の出力 ![](https://i.imgur.com/1zlirBy.png) ![](https://i.imgur.com/dFyyzo2.png) - 講義内で出てきた```Using ML to Predict Parking Difficulty[Google AI Blog:2017 Feb.]```より Logistic回帰を選んだ理由 - Logistic回帰は理解しやすい。 - トレーニングデータのNoiseに強い - 確率で出るのは助かる - 各特長量の影響が理解しやすく、モデルの振る舞いがreaosonableか判断しやすい - SGDに関してもう少し。 > 確率的勾配降下法とは、大雑把に言うと、 「勾配法」+「確率を使って勾配の計算を高速に行う」 ような最適化手法です。 通常の勾配法は パラメータは勾配降下法で$w$を更新していく $\displaystyle w(k+1)=w^{k}-\eta\frac{\partial E(w)}{\partial w}$ 最急降下法・・・今いる点の勾配情報を参考にする デメリットとしては曲線の谷が複数ある場合などで局所解に陥る事 確率的勾配降下法=オンライン勾配降下法 「普通の」勾配降下法のことをバッチ勾配降下法=データを全部使う #### モーメンタム:  過去の勾配の変化を使って振動しないようにする。今までの移動平均を使う $\boldsymbol w_{t+1}=\boldsymbol w_{t}-\alpha\nabla_{w}\mathcal{L}(\boldsymbol w)$ $\nabla_{w}$: モーメンタム $\alpha$: 学習率 $\mathcal{L}(\boldsymbol w)$: 損失関数 - Momentum SGD $v_{t+1}\leftarrow\gamma v_{t}-\alpha g_{t}$ $\theta_{t+1}\leftarrow \theta_{t}+v_{t+1}$ $\gamma$: 慣性の減衰率 $t$: 現在のエポック $g_{t}$: そのエポックにおけるコスト関数の勾配 $\alpha$: 学習率 これら勾配降下、モーメンタムなどは後のニューラルネットでも出てくる ### 課題 > 設定 タイタニックの乗客データを利用しロジスティック回帰モデルを作成 特徴量抽出をしてみる > 課題 年齢が30歳で男の乗客は生き残れるか? ### その他関連事項 - オッズ比 ある事象が発生する確率としない確率の比 $\displaystyle \frac{p}{1-p}$ ゼロよりマイナスにならない。大きい方は無限大を取り得る。 - ロジット変換 オッズで対数を取る $\log(\displaystyle \frac{p}{1-p})$ 対数を取ると上記のアンバランスさがなくなる。 - 最尤推定量 > パラメータ$\theta$に従う分布の密度関数$f(x;\theta)$とする。尤度関数を$L(θ;x)=f(x;θ)$とすると、$L(θ;x)$を最大にするような推定量$θ=\hatθ$の最尤推定量という。 - 混同行列 ``` Predict ┌────────┬───────────┬─────────────┐ │ │Positive │ Negative │ ├────────┼───────────┼─────────────┤ │positive│ TP │ FN │ │ │ │ │ Actual├────────┼───────────┼─────────────┤ │ │ │ │ │Negative│ FP │ TN │ │ │ │ │ └────────┴───────────┴─────────────┘ ``` - 真陽性(True Positive) 判別したいものを正しく判別できた数を「真陽性」 - 真陽性率(True Positive Rate) $TP/(TP+FN)$ - 真陰性(True Negative) 判別対象外のものを正しく判別できなかった数を「真陰性」 - 偽陽性(False Positive) 判別対象外のものを誤って判別してしまった数を「偽陽性」 - 偽陽性率(False Positive Rate) $FP/(FP+TN)$ - 偽陰性(False Negative) 判別したいものを誤って判別できなかった数を「偽陰性」 - 正解率(Accuracy) - $(TP+TN)/(TP+FN+FP+TN)$ - 適合率、精度(Precision) - $TP/(TP+FP)$ - 再現率(Recall) - $TP/(TP+FN)$ - F値(F-measure) - $\displaystyle \frac{2}{(1/precision+1/recall)}$ ROC曲線は真陽性率と偽陽性率の関係をグラフにしたもの 考察:最近も会社であったケースだがそもそも異常検出のような 正例データが少ない場合は混同行列による評価は妥当なのだろうか? →異常検知でも使われるようでRecall重視という記述はネット上ではあったが それ以上の事は分からなかった。取りこぼしが許されないケースを想定すればRecall重視というは分かる。 ``` 参考文献: はじめてのパターン認識 ``` ## 4. 主成分分析 ### 要約 PCA(principal component analysis) 次元を圧縮する、特徴量を減らす - 可視化できる - 冗長な特徴量をまとめられる  (一般的には少ない特徴量で多く説明できると好ましい) - 分散が最大になるように軸を探索する。 分散が最大の場合、情報が多く残っている。 →ある軸に射影したデータがばらついている=元のデータの情報を多く含んでいる 分散が少ない=データの区別がつかなくなる 例えばある特徴量a,bの間は a=2bのようなほぼ線形の関係がある場合、実質1次元のデータとして取り扱える。 元の冗長な特徴量を特徴空間に含まれる情報を要約した特徴量に置き換える。 軸を探す=分散の最適化。 --- PCAの実装中身 1. データ行列の中心化 $C=X-1\mu^{T}$ 1は全ての要素が1である列ベクトル $\mu$は$\boldsymbol X$の各行の平均値を要素とする列ベクトル (平均を引いて中心に寄せる) 2. SVDの実行 $C=U\Sigma V^{T}$ 3. 主成分を特定する 最初のk個の主成分はVの最初のk個の列。k個の右特異ベクトル。 4. データの変換 変換されたデータは$U$の最初のk列 - 寄与率 軸一つでデータの何割を説明できているか。 主成分のいくつまで使うかなど参考になる ``` 参考文献:「機械学習のための特徴量エンジニアリング」 参考リンク:統計科学研究所: https://statistics.co.jp/reference/software_R/statR_9_principal.pdf ``` --- ### 実装演習結果,考察: **np_pca.ipynb** 固有値、固有ベクトルの計算 ![](https://i.imgur.com/t1sw6aD.png) 変換 ![](https://i.imgur.com/9zkjrcI.png) 逆変換(元に戻す) ![](https://i.imgur.com/8jdGHXW.png) **skl_pca.ipynb** Cancerデータを元に次元数30でPCAの実行 ![](https://i.imgur.com/sOZjbMO.png) 次元数を2として視覚化している。 ![](https://i.imgur.com/3nKPFSx.png) ```pca.explained_variance_ratio_```=各主成分が持つ分散の比率、寄与率 試しに3次元でPCAを行うと ``` explained variance ratio: [0.43315126 0.19586506 0.09570611] ``` 3番目はあまり説明に寄与していない ## 5. アルゴリズム #### K近傍法(kNN) 分類の手法の一つ。教師あり学習。 最近傍のデータをK個取ってきて、それらがもっとも多く所属するクラスに識別 k=1なら最も近いところ1点で見る。 #### k-means クラスタリング。手元のデータの分類を行う。 1. 各クラスの中心をとりあえず作る 2. 各データ点に対して、各クラスタ中心との距離を計算し、最も距離が近いクラスタを割り当てる 3. 各クラスタで平均ベクトル(中心)を計算する(中心の更新) 4. クラスタの再割り当てと中心の更新を繰り返す 注意:初期値のおかれ方でクラスタの別れ方が違ってくる ### 実装演習結果,考察: **np_kmeans.ipynb** ![](https://i.imgur.com/Z5MmtAM.png) **skl_kmeans.ipynb** ``` species class_0 class_1 class_2 labels 0 0 50 19 1 46 1 0 2 13 20 29 ``` KNeighborsClassifier ![](https://i.imgur.com/AV3SgWc.png) **np_knn.ipynb** sklearnに入っているWineの典型的なデータセット。3つの品種に分かれている。 うまく分かれていないクラスもあった ``` species class_0 class_1 class_2 labels 0 0 50 19 1 46 1 0 2 13 20 29 ``` 初期値によって適切にクラスタリングされない場合があるという事だったので KMeans()の乱数に関連がありそうな所を変えてみたが特に変化は無かった。 実際のケースではあらかじめ分かれているクラス数が分かっている場合、 そうでない場合もあると思うが、結果に関しては自分で解釈する必要がある **np_knn.ipynb** ![](https://i.imgur.com/kbaZEmn.png) ### その他関連事項 **K近傍** 参考文献より行ったコード実行 ```python from sklearn.model_selection import train_test_split from sklearn.datasets import load_breast_cancer from sklearn.neighbors import KNeighborsClassifier import numpy as np import pandas as pd import matplotlib.pyplot as plt c = load_breast_cancer() X_train,X_test,y_train,y_test=train_test_split(c.data, c.target,stratify=c.target, random_state=66) training_accuracy = [] test_accuracy = [] # roll the k neighbors neighbors_settings = range(1, 11) for neighbor in neighbors_settings: clf = KNeighborsClassifier(n_neighbors=neighbor) clf.fit(X_train, y_train) training_accuracy.append(clf.score(X_train, y_train)) test_accuracy.append(clf.score(X_test, y_test)) plt.plot(neighbors_settings, training_accuracy, label="training accuracy") plt.plot(neighbors_settings, test_accuracy, label="test accuracy") plt.ylabel("Accuracy") plt.xlabel("n_neighbors") plt.legend() ``` ![](https://i.imgur.com/fnxQcMW.png) K近傍ではFitは訓練データをセットするのみ。 1つの近傍点のみを用いるとクラスの決定境界は訓練データ配置に近い。 近傍点を増やす、(より多くの点を考慮)すると境界はなだらかで汎化性能が上がる。 過剰適合に相当するのは**考慮する近傍点が少ない方** なぜテストデータの性能が近傍点が少ない所で落ちるかは腑に落ちる ``` 参考文献:Pythonではじめる機械学習 ``` ## 6. サポートベクターマシーン ### 要約 基本的には2クラス分類。線形モデルの正負で2値分類。 (多クラス問題は(K-1)の一対他SVMで実現する事が多い) 線形判別関数と最も近いデータ点(サポートベクター)との距離をマージン。 このマージンが最大となる線形判別関数をもとめる。 線形判別関数(超平面)を $\boldsymbol w^{T}x+b=0$ 全てのデータ点で $|\boldsymbol w^{T}\boldsymbol x + b|$ 目的関数 $\displaystyle \max_{w,b}[\min_{i}\frac{t_{i}(\boldsymbol w^{t}\boldsymbol x_{i}+b)}{\| \boldsymbol w\|}]$ 各点と決定境界との距離は点と直線との距離の公式から $\displaystyle \frac{t_{i}(\boldsymbol w^{t}\boldsymbol x_{i}+b)}{\| \boldsymbol w\|}$ $t_{i}$: 教師データ {-1, 1} $x_{i}$: 学習データ $\displaystyle t_{i}(\boldsymbol w^{t}\boldsymbol x_{i}+b)$ 結果として目的関数は以下になる $\displaystyle \max_{w,b}\frac{1}{\| \boldsymbol w\|}$ $\displaystyle \min_{w,b}\frac{1}{2}\| \boldsymbol w\|$ 線形分離可能でない問題の場合、**スラック変数の導入** このような手法を**ソフトマージン識別器** $\left\{ \begin{array}{ll} \xi_{i}=0 & (マージン内で正しく識別できる場合) \\ 0 < \xi_{i} \leq 1& (マージン境界を越えるが正しく識別できる場合) \\ \xi_{i} > 1 & (識別境界を超えて誤識別される場合) \end{array} \right.$ 訓練データ$D=\{(x_{1},y_{1}),,,(x_{l},y_{l})\}\in \mathfrak R \times\{-1, 1\}$ $\displaystyle \frac{\|w\|}{2}+C\sum_{i=1}^{l}\xi_{i}$ 右が誤差項。$C$はhハイパーパラメータでペナルティの強さを表す。 大きければ大きいほど誤差を優先する解が得られる。(誤差を許容しすぎない) 「モデルの複雑さ」と「誤分類」のトレードオフ 制約条件 $t_{i}(\boldsymbol w^{T}\boldsymbol x_{i}+b) - 1 + \xi_{i} \geq 0$ $\xi_{i} \geq 0$ - マージンの外側のデータは予測に影響を与えない - カーネルトリック - データを別の空間に写像。その空間で線形に分離。 ``` 参考文献: はじめてのパターン認識 http://www-erato.ist.hokudai.ac.jp/lecture2011/material/lecture-1.pdf http://sudillap.hatenablog.com/entry/2013/04/08/235610 ``` ### 実装演習結果,考察: **np_svm.ipynb** 線形分離可能のケース ![](https://i.imgur.com/KgFfuQ2.png) 線形分離不可能のケース ![](https://i.imgur.com/KL2eUPV.png) ![](https://i.imgur.com/koYvMfi.png) - サンプルの個数が大きいとうまく機能しない - 全ての特徴量が同じスケールになるように変換した方がよい - 予測がされた理由の説明が難しい - 特徴量が似た測定器の測定結果(画像)のような同じスケールの場合は試す価値あり ``` 参考文献:Pythonではじめる機械学習 ``` ### その他関連事項 カーネルの種類について 正規化線形カーネルを用いた場合、 $\displaystyle k(x,y)=\frac{x^{T}y}{\|x\|\|y\|}$ は$x$と$y$の相関係数を表している 参考に相関係数は $\displaystyle r_{xy}=\frac{\sum_{i=1}^{n}(x_{i}-\bar x)(y_{i}-\bar y)}{\sqrt{\sum_{i=1}^{n}(x_{i}-\bar x)^{2} \sqrt{\sum_{i=1}^{n}(y_{i}-\bar y)^{2}}}}$ https://zenn.dev/wsuzume/books/66b6fe7bb537b3e2b4bb/viewer/4d8835 - RBF(動径基底関数カーネル) SVMの文脈ではガウスカーネルとも呼ばれる https://mathwords.net/doukeikitei > ある点 c→ からの距離のみに基づいて値が決まる関数のことを動径関数(Radial Function)と言います。 例えば、 ・$\vec{f_{\vec c}}(\vec x)=\|\vec x−\vec c\|^{2}$ ・$\vec f_{\vec c}(\vec x)=exp(−γ\|\vec x−\vec c\|^{2})$ などは動径関数です。 (このページでは、添字の $\vec c$ は動径関数の中心を表します) $\vec x$ が $\vec c$ から遠くなると、この関数の値は急激に 0 に近づいていきます。 $\vec x$ と $\vec c$が近いと1に近づく。 - 多項式カーネル $k(x, y)=(1+x^{T}y)^{d}$ dは正の整数 $k(x, y)=(x^{T}y + c)^{2}$ - カーネルと特徴ベクトルの対応 カーネル関数$k(x,y)$が$k(x,y)=\phi (x)^{T}\phi (y)$ と表現できる時、$k(x,y)$は特徴ベクトル$\phi$に対応する