読書：Pythonで始める機械学習


[Pythonで始める機械学習](https://www.amazon.co.jp/Python%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E2%80%95scikit-learn%E3%81%A7%E5%AD%A6%E3%81%B6%E7%89%B9%E5%BE%B4%E9%87%8F%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%A8%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%81%AE%E5%9F%BA%E7%A4%8E-Andreas-C-Muller/dp/4873117984)を読んだのでざっくりとまとめます。
著者：Sarah Guido
翻訳：中田 秀基
出版社：オライリージャパン
発売日：2017/5/25

# 所間
[courseraのMachine Learning](https://ja.coursera.org/learn/machine-learning) を受講後に<b>「pythonで機械学習がやりたい！」</b>と思い本書を購入しました。

最後までなんとかやり切ったというのが率直な感想。技術書あるあるで基礎って書いてあるのに普通に難しい。
2章の教師あり学習でいきなり挫折しかけましたが毎日少しずつやって1ヶ月近くかけて終えることができました。

サンプルコードを写経して動かすことで一通りの機械学習の流れを身につけることができたかと思います。
ただ理論の説明はなく、淡々と機械学習プログラムを書いていくのでいきなり本書をやると何をやっているのかが掴めず挫折しそう。
一冊簡単な本を挟むかcourseraを受講した方が良いと思います。

*近年盛り上がっているディープラーニングは一瞬紹介があるだけで特に触れられていません。
教師あり学習アルゴリズムとその精度を高める方法がメインです。


# 目次
[1.はじめに](#1-はじめに)
[2.教師あり学習](#2-教師あり学習)
[3.教師なし学習と前処理](#3-教師なし学習と前処理)
[4.データの表現と特徴量エンジニアリング](#4-データの表現と特徴量エンジニアリング)
[5.モデルの評価と改良](#5-モデルの評価と改良)
[6.アルゴリズムチェーンとパイプライン](#6-アルゴリズムチェーンとパイプライン)
[7.テキストデータの処理](#7-テキストデータの処理)


#1-はじめに
レコメンドや画像認識など普段の生活と切り離すことができなくなってきた機械学習。
機械学習は統計学の上に成り立っているので数学的な知識が必要です。
つまりすごく難しいですが、その難しさを隠蔽してくれる機械学習ライブラリにscikit-learnというものがあります。
本書ではこのscikit-learnをつかって機械学習を進めます。また、より視覚的に理解しやすい様にmatplotlibというグラフ描画ライブラリも使います。
開発環境にはもろもろのライブラリをパッケージとして提供してくれる[anaconda](https://www.anaconda.com/products/individual)を使用しました。

*mglearnという著者が作ったライブラリが頻出するのですがちょくちょくエラーが出ます？が、今後使わないので特に深掘りしませんでした。

#2-教師あり学習
正解を教えて訓練させる一番使われていている学習法ですね。
クラス分類と回帰に大別することができます。
以下アルゴリズムをざざっとまとめます
## k-最近傍法(k-nn)
訓練セットから一番近い点つまり「最近傍点」を見つける。
近傍点を複数持つ時は属するクラスの数が一番多いものを採用。
多クラスでも可！
処理速度が遅く、多数の特徴量が使えないのであまり用いられない

- メリット
    - 理解しやすい
    - モデルの構築が高速*近傍点は3 ~ 5個で十分な場合が多い
- デメリット
    - 訓練セットが大きくなると予測が遅くなる
    - 多数の特徴量（数100程度）ではうまく動かない

## 線形モデル
特徴量が一つの場合
y = w[0] ＊ x[0] + b
特徴量が多くの場合、wにはそれぞれの特徴量の軸に対する傾きが入る。
予測は入力特徴量の重み付き和ともいう。
モデルを作る手法にはyとの平均二乗誤差が最小となるような最小二乗法を用いる。
一般にデータ数が多いと、過剰適合する可能性がある。
そこで重みの影響を小さくして過剰適合を防ぐ（正則化）
ペナルティーの計算方法によって以下の二つがある。
### Ridge回帰
特に L2正則化と呼ばれる。(ユークリッド距離に対してペナルティーを与える)
正則化の大きさはαで調整できる。＝＞αを大きくするとwを小さくする。
### Lasso回帰
リッジ回帰と同様に重みを調整する。
L1正則化と呼ばる(係数の絶対値の和にペナルティを与える)
*0となって無視される特徴が現れる。

特徴量が多すぎる時はLassoを使う。
LassoとRidgeを組み合わせたElasticNetも存在する。

## 線形モデルでクラス分類を行う
決定境界が入力の線形関数を求める。

- ロジスティック回帰(LogisticRegression)
- サポートベクタマシン(LinearSVC)
正則化はcを用いる
回帰とは逆で正則化パラメーターcが小さいとwが大きくなる。

## ナイーブベイズクラス分類器
確率で学んだベイズの定理が基礎になっているアルゴリズム。
クラスに対する統計値を特徴がそれぞれ独立として計算する。
線形モデルに比べてより高速だが、性能が劣る。

- GaussianNB
    - 特徴量の平均値と標準偏差を考慮
    - 大規模データに使う
- BernoulliNB
    - 0,1からなる2値データに使う
- MultinomialNB
    - 特徴量の平均値を考慮

## 決定木
クラス分類(DecisionTreeClassifier)と回帰タスク(DecisionTreeRegressor)に使える
Yes,Noで答えを絞っていく「質問ゲーム」のような木構造がモデルになる。
例）食べ物か？、甘いか？などで答えを絞っていくイメージ

過剰適合しやすい

- 事前枝刈り(木の生成を早めに止める)
    - 深さを決めておく
    - 葉の最大値を制限する
- 事後枝刈り
    - 木を構築してから情報を削る

### メリット
可視化が容易にできる
### デメリット
訓練データにない領域は答えを返せない
過剰適合しやすい=>アサンブル法に使われる
*アサンブル法：機械学習アルゴリズムを組み合わせる

### アサンブル法

- ランダムフォレスト
    - 少しずつ異なる決定木をたくさん集める
    - 決定木の過剰適合の平均を取ればうまくいきそうだから
- 勾配ブースティング決定木
    - 一つ前の決定技の誤りを次の決定木が修正するように、決定木を順番に作っていく
    - 強力な事前枝刈りを使用。
    - より正確になるがモデルの構築に時間がかかる

## カーネル法を用いたサポートベクタマシン
より複雑なモデルを可能にするために、線形サポートベクタマシンを拡張したもの。
サポートベクタ：境界を作成する時に、重要となるデータポイントのこと

カーネル法：高次元の特徴を持つ時、計算量を落とす時に使う。
C(正則化項)とgamma（ガウシアンカーネルの幅）でチューニングする
ガウシアンカーネル:exp(-r || x1  - x2 ||^2)
gammaが大きいと、多くの点を判断するようになる。=>より複雑なモデル。
gammaが小さいと、滑らかなモデル。
Cが大きいと、データポイントの影響が大きくなる

#### svmではデータの特徴量の大きさが違いすぎると、うまくいかない
スケーリングしてあげる => 0〜１に調整する
x - min(x) / 特徴量の幅(max(x)-min(x))

svmはサンプル数が多くなると機能しなくなる。
1000000ほどに止める

メリット：データ数が少なくても複雑なモデルを作れる
デメリット：パラメータとデータの前処理が重要。予測の理由が難しい

## 決定関数
分類器の予測がどれぐらい確かなのかを示す。
decision_functionやpredict_probaで表現できる。
decision_function: 確信度が+-の数値で出てくる
predict_proba: 確率が出てくる（総和は1）

#3-教師なし学習と前処理
アルゴリズムには入力データだけ与えられ、データから知識を抽出する。
1. 教師なし変換
元のデータ表現を変換して、人間や他の機械学習アルゴリズムにとってわかりやすいデータ表現にする。
　1-1. 次元抽出
　本質的な特徴を抽出する
　1-2. 成分を見つける
　似ているデータにトピックをつけるなど
2. クラスタリング
グループ分けするアルゴリズム
例)SNSにあげた写真を人物ごとにグループ分けする

## 前処理とスケール変換

### スケール変換
ニューラルネットワークやSVMなどのアルゴリズムはデータのスケール変換に敏感
例)cmとmが混在しているなど単位が違うと正しく学習できない
前処理をしてデータのスケールを揃える

- StandardScaler
    - 標準正規分布に従うよう変換
- RobustScaler
    - 四分位数を用いて外れ値を無視する
- MinMaxScaler
    - データが0~1に入るように変換(Xi-min(X))/(max(X)-min(X))
- Normalizer
    - ユークリッド長1に入るように変換（半径1の円）

### 主成分分析（PCA）
データセットの特徴量を相互に統計的に関連しないように回転する。
回転させた後、重要な特徴量を抜き出す。軸を削るイメージ

### 非負値行列因子分解（NMF）
有用な特徴量を抽出する教師なし学習。
名前の通りデータの特徴を因数分解して主要成分を抜き出すイメージ。
成分の数が変わると、全く別の成分集合が構成される
*非負の成分を持つデータにしか使えない

## クラスタリング
### k-meansクラスタリング
1. データポイントを最寄のクラスタ重心に割り当てる。
2. 個々のクラスタ重心をその点に割り当てられたデータポイントの平均に設定する

### 凝集型クラスタリング
ある原則に基づく一連のクラスタリングアルゴリズム
個々のデータポイントをそれぞれ個別のクラスタとして開始し、最も類似した2つのクラスタを指定したクラスタの数まで併合していく。

クラスタを併合する連結度の調整。
ward:併合したクラスタ内の分散の増分が最小
average:ポイント間の距離の平均値が最小のクラスタを併合
complete:クラスタ間の距離の最大値が最小となるように併合

凝集型クラスタリングは階層的にクラスタが割り当てられる
２次元だと図示できるが、特徴が多くなると難しい=>デンドログラム（樹形図）を使って確認できる。

### DBSCAN
Density Based Spatial Clustering of Applications with Noise
密度に基づくノイズあり空間クラスタリング
多くの点が混んでいる領域に属する(高密度)点を見つける。

1. クラスタ数を先に与える必要がない
2. どのクラスタにも属さない点を見つけることができる
3. 遅いが大きなデータセットにも適用できる

パラメーター

- コアサンプル
    - 高密度領域の中にあるデータポイント
- eps
    - 距離
- min_samples
    - クラスタを構成する（eps以内にある）最小のデータ数

1. 適当に一つのデータポイントを選ぶ。そのデータポイントからeps以内にある全てのデータポイントを見つける。
2. その数がmin_samples以下であればnoiseとなる
3. min_samples以上のデータポイントがあれば、その点はコアサンプルとなり、クラスラベルが割り当てられる。eps以内にある全ての近傍点をテストする。既に近傍点がコアサンプルであれば、その近傍点をさらにテストする。
4. クラスタは、クラスタからeps以内にコアサンプルが存在しなくなるまで成長する。

#4-データの表現と特徴量エンジニアリング
特徴量エンジニアリング：最良のデータ表現を模索すること
特徴量は2つに大別できる
連続値特徴量:データポイント。ピクセルの明るさや花の大きさなど
カテゴリ特徴量:離散値特徴量ともいう。製品やブランドの色、販売されている部門など連続的に変化しないもの。

カテゴリ特徴量は数値に直さないと意味を出せない
## one hot encoding（ダミー変数）
カテゴリ変数を0と1の値を持つ新しい特徴量に置き換える。
```pandas.get_dummies()```

*訓練データとテストデータのダミー変数が一致するよう注意が必要。
訓練とテストの双方が入ったdataFrameにget_dummiesを実行。
*数値は連続値として扱われるのでカテゴリ変数に離散値が入っている場合は別途処理が必要。

## 自動特徴量選択
特徴量を増やしすぎると、複雑になる。
汎用性を上げるために有効な特徴量を採用する。

機械なし学習で出てきたPCAとは何が違うのか混乱したが、PCAは新たな特徴を作り出している特徴抽出。
一方で特徴選択は不要な特徴を削る次元削除。

#### 単変量統計
個々の特徴量とターゲットとの間に統計的に顕著な関係があるかどうかを計算する。
最も高い確信度で関連している特徴量が選択される。
#### モデルベース選択
教師あり学習モデルを用いて、重要な特徴を残す
最終的に使うモデル特徴量選択用のモデルは違って良い。
#### 反復選択
全く特徴量を使わないところから、ある基準が満たされるところまで1つずつ特徴量を加えていく方法と、全ての特徴量を使う状態から1つずつ特徴量を取り除いていく方法。
#### 再起的特徴量削減
全ての特徴量から開始してモデルを作り、もっとも重要度が低い特徴量を削除する。
モデルを作り、削除を繰り返す。
時間がかかる。

#5-モデルの評価と改良
教師あり学習においてテストセットでの適合度が高いモデルが未知のデータに対する適合度が高いとは言えない。より頑健な評価法として交差検証を用いる。

交差検証：
データを何分割もして繰り返し評価する手法
モデルを作るわけではなく、与えられたアルゴリズムがどの程度凡化できるかを評価する。

### k分割交差検証
1. データをk分割。
2. 最初の分割をテストセットに残りを訓練セットにする
3. 次の分割をテストセット、残りを訓練セットをk回やる

### 層化k分割交差検証
クラスの分布に偏りがある時、単純なk分割では精度が低くなる
クラスの比率が全体の比率と同じになるように分割するk分割交差検証

### 一つ抜き交差検証
k分割交差検証の個々の分割が1サンプルしかないものだと考える。
毎回、テストセット中の1サンプルだけをテストセットとして検証する
時間がかかるが、より良い推定が可能。

### シャッフル分割交差検証
毎回訓練セットとテストセットを作る。

### グループ付き交差検証
訓練とテストのデータが被らないようにする。

## 偏ったデータセット
2クラス分類で一方のクラスが他方のクラスよりずっと多い時、CTRの例で100の広告を流して99をスルー、1つの広告がクリックされる時などに最適なモデルはなんだろう。
全ての広告を「クリックされない」と判定するモデルが99%の精度のモデルになる。
これは正しくないが、これまでの検証では検出できない。

### 混同行列
正確にクラス分類されたサンプルの個数と、誤った分類の個数を示す。
TP:真陽性
TN:真陰性
FP:偽陽性
FN:偽陰性
精度をTP + TN / nとして求める。

#### 適合率、再現率、f値
混合行列を以下の値で整理することができる。
適合率 = TP / TP + FP
再現率 = TP / TP + FN
f値 = 2 x (適合率 x 再現率) / (適合率 + 再現率)

### 多クラスの評価
2クラス分類の基準から導出されたf値で平均化する。
個々のクラスに対して、そのクラスを陽性、他のクラスを陰性とする2クラスのf値を求める。
平均化の手法は複数ある。

- macro平均
    - 重みをつけずにクラスごとのf値を平均する。クラスのサイズを考慮せずに、全てのクラスに同じ重みをつける
- weighted平均
    - 各クラスの支持度に応じて重みをつけて、クラスごとのf値を平均する。クラス分類レポートで表示されるのはこの値。
- micro平均
    - 全てのクラスの偽陽性、偽陰性、真陽性の総数尾を計算し、その値を用いて計算する。

#6-アルゴリズムチェーンとパイプライン
機械学習では一つのアルゴリズムを実行するだけではなく、様々な処理と複数の機械学習アルゴリズムを連鎖的に実行する。
毎回処理を書くのではなく、Pipelineを用いる。

*注意
スケール変換を用いた交差検証では交差検証用のデータを除いてscalerを作る。

#7-テキストデータの処理
テキストデータは文字列と構成され、長さはまちまちである。
このデータを機械学習アルゴリズムに適応する前に処理する必要がある。
テキストデータは大きく以下4つに分けることができる。

- カテゴリデータ
- 意味的にはカテゴリに分類できる自由に書かれた文字列
- 構造化された文字列
- テキストデータ

## BoW(bag-of-words)
よく使われるテキストデータ表現。
入力テキストの持つ構造のほとんどを無視して、単語がテキストに現れる回数をカウントする。
#### 手順
1. トークン分割:個々の文書を単語に分割する
2. ボキャブラリ構築:全ての文書に現れる単語をボキャブラリとして集め、番号をつける
3. エンコード:個々の文書に対してボキャブラリの単語が現れる回数をカウント。

*意味のない単語を拾わない様に最低2回以上登場（min_df）するなどが必要。

## ストップワード
頻出単語から得られる情報は少ないので除外する。
除外用のリストをあらかじめ作っておく。
1. 言語固有のストップワードリストを作っておく
2. 頻度の高い単語を捨てる

## tf-idf
特徴量がどの程度情報を持っていそうかに応じて、特徴量のスケールを変換する手法。
特定の文書に頻出し、他の文書にあまり現れない単語は、その文書の内容をよく示していると考える。
=> 特定の文書にだけ頻出する単語の重みを大きくする！

#### n-グラム
区切る単語の列の長さを変えることで2語、3語の特徴を学習できるようにする
例）not good, not badなど
単語数1: ユニグラム
単語数2: バイグラム
単語数3: トリグラム