バックエンドエンジニアがscikit-learn入門しました【教師なし学習編】

# はじめに
機械学習ライブラリのデファクトスタンダード的存在であるscikit-learnの"教師なし学習"とその定量的評価手法をまとめる。
数学レベルでの理解は途中で挫折したため、まずはライブラリから概要を理解しようと思いまとめました。

教師あり学習編は[こちら](https://qiita.com/gold-kou/items/96f7b6da1fba5d96c12d)
前処理編は[こちら](https://qiita.com/gold-kou/items/5e25ab42bd92b4bb4686)

# 教師なし学習とは
教師なし学習とは、入力データのみが与えられ正解ラベルがない状態で学習を行う手法である。
教師なし学習を使う場面は以下。

- 正解ラベルを用意できないケース
- 教師あり学習や他の教師なし学習の前処理をするケース
- データを可視化するケース
- データをなんとなく理解したいケース

教師なし学習は、`次元削減`と`クラスタリング`の2つの大きなタスクに活用される。

# 次元削減
次元削減とは、データを表現する特徴量の数（次元数）が多すぎる場合に、その特徴量の数を減らすことである。
本記事では、アルゴリズムとして以下をまとめる。

- PCA
- NMF
- t-SNE

アルゴリズムの種類により異なるが、次元削減により以下の効果のいずれかが期待できる。

- 前処理として他機械学習の精度をあげる。
- 前処理として他機械学習の高速化。
- 人間が理解できる2,3次元に削減することでデータを可視化する。

## PCA(主成分分析)
### アルゴリズム概要
PCAは、データから"第一成分"（分散が大きく最も情報量の多い方向）、"第二成分"（第一成分に直行する方向の中から最も情報量の多い方向）、・・・と任意の数の主成分を抽出し、それらを回転(例えば2次元に削減する場合には、第一成分をx軸に、第二成分をy軸に沿うように回転)させて次元削減する手法である。
上述の通り、元の特徴量からいくつかの特徴量を単に抽出するだけではなく、回転させた後の成分を残す。したがって、次元削減後の特徴量は基の特徴量とは異なるため、可視化してもそれ自体の解釈は難しい。
次元削減で最もポピュラーな手法である。
前処理としての効果が期待できる。

### 実行例
```py
# インスタンス生成
pca=PCA(n_components=2)

# 主成分の発見。fitは学習データに対してのみ実行。
pca.fit(X_train)

# 回転と次元削減
pca.transform(X_train)
pca.transform(X_test)
```

### 主なパラメータ
- n_components : 抽出する主成分の数。
- whiten : StandardScalerによるスケール変換を実行するかどうか。Trueならば実行する。

## NMF(非負値行列因子分解)
### アルゴリズム概要
NMFは、非負の特徴量を持つデータの次元削減を行う手法である。
データを表現するのに十分な数の成分がある場合には、データの極端な部分の方向を主成分として残す。少ない場合には、データの中間を表現するような方向を主成分として新たに作成してそれを残す。
複数の独立したデータが合成されたデータに対して有効とされている。
前処理としての効果が期待できる。

### 実行例
```py
# インスタンス生成
nmf=NMF(n_components=2)

# 主成分の発見。fitは学習データに対してのみ実行。
nmf.fit(X_train)

# 次元削減
nmf.transform(X_train)
nmf.transform(X_test)
```

### 主なパラメータ
- n_components : 抽出する主成分の数。

## t-SNE
### アルゴリズム概要
t-SNEは、高次元のデータを2次元に削減する多様体学習アルゴリズムである。
高次元特徴量空間で近かったものは2次元でも近くに、遠かったものはより遠くにマッピングする。距離はユークリッド距離を使うのが一般的である。
可視化の効果が期待できる。
学習データに利用することはできるがテストデータには利用できないため、教師あり学習のための前処理としての次元削減には向かない。

### 実行例
```py
# インスタンス生成
tsne=TSNE()

# 次元削減。TSNEにtransform関数は無い。
tsne.fit_transform(X_train)
```

### 主なパラメータ
あるにはあるが、デフォルトでけっこううまくいく。

# クラスタリング
クラスタリングとは、データをクラスタ(かたまり)に分割する手法である。
クラスタリングと教師あり学習の"分類"との違いは、意味のあるラベルが集合に付いているかどうかである。クラスタは単に似た者同士が集まっているだけで、その集合にナンバリングはされても、意味のあるラベルは付いていない。あるいは人間が後付けで付ける。一方、分類はその集合がどのようなものかを説明できるラベルが付いている。
ラベルが無いため定量的評価はできない。したがって、学習データとテストデータという分割の考え方が存在しない。
正解ラベル付きデータを用意できるならクラスタリングでなく分類にしたいところ。

本記事では、以下のアルゴリズムをまとめる。

- k-meansクラスタリング
- 凝集型クラスタリング
- DBSCAN

## k-meansクラスタリング
### アルゴリズム概要
k-meansクラスタリングは、最初に、ランダムにk個のデータ（クラスタの重心）を選択し、全てのデータに対して最も近い重心のクラスタに属すると判定する。次に各クラスタのベクトルの平均値を新たな重心として更新し、再び各学習データを最も近い重心のクラスタに属すると判定する。これを重心が移動しなくなるまで繰り返すことで、データは特徴量空間上で似た者同士があつまったk個のクラスタに分割される。距離は一般的にユークリッド距離が用いられる。
アルゴリズムの特性上、実行結果が初期化時の乱数シードに依存するため、scikit-learnでは自動で異なる乱数を用いて10回実行をしたうち、各クラスタの分散の和が最小のクラスタモデルが自動で選択するように実装されている。
最適なクラスタ数を自分で探して指定する必要がある。
単純に距離しか考慮しないため、特徴量毎の重要度の違いを考慮することができない。また、最適なクラスタが距離だけでは発見できないような複雑な形の場合には向かない。
クラスタリングで最もポピュラーな手法である。

### 実行例
```py
# インスタンス生成
km=KMeans(n_clusters=5)

# クラスタモデルを生成
km.fit(data)

# クラスタラベルを作成
km.predict(data)
```

### 主なパラメータ
n_clusters : クラスタの数

## 凝集型クラスタリング
### アルゴリズム概要
凝集型クラスタリングは、まず各データを全て個別のクラスタとし、次に全クラスタ中で最も距離が近い2つのクラスタを併合する。この併合をクラスタ数がk個になるまで繰り返すことで、データは特徴量空間上で似た者同士があつまったk個のクラスタに分割する手法である。
最適なクラスタ数を自分で探して指定する必要があるが、デンドログラム（Scipyの機能）により可視化することで最適なクラスタ数を発見しやすい。デンドログラムの枝の長さは2つのクラスタ間の距離を示すため、枝が長いところを選択すればよい。
距離しか考慮しないため、k-means同様の課題を抱える。

### 実行例
```py
# インスタンス生成
ac=AgglomerativeClustering(n_clusters=5)

# クラスタリング実行
ac.fit_predict(data)
```

### 主なパラメータ
- n_clusters : クラスタの数

## DBSCAN
### アルゴリズム概要
DBSCANは、データが密集している部分がクラスタであり、クラスタは密集していない部分によって切り取られるものだという考えに基づくアルゴリズムである。(まぁ当たり前といえば当たり前だが)
あるデータから一定距離以内に一定数以上のデータが存在する場合に、そのデータを"コアサンプル"と判定し、クラスタを割り当て、一定距離以内にあるコアサンプル同士を同じクラスタとする。一定数より小さい数のデータしか存在しなかった場合は、そのデータを"ノイズ"と判定する。クラスタが割り当てられていないデータがなくなるまでこれを繰り返す。

距離だけでなく密集度を考慮するため、k-meansや凝集型では発見できなかった複雑な形のクラスタでも発見可能である。

k-meansや凝集クラスタリングのように最適なクラスタ数を自分で指定する必要はないが、結局別のパラメータで似たような調整が必要になる。
k-meansや凝集クラスタリングよりも遅い。
事前にスケール変換が必要である。

### 実行例
```py
# インスタンス生成
dbscan=DBSCAN(min_samples=5, eps=1)

# クラスタリング実行
dbscan.fit_predict(X)
```

### 主なパラメータ
- min_samples : データがコアサンプルかノイズかを判定するために使用されるデータの個数に関する閾値。あるデータから距離eps以内にmin_samples個以上のデータがある場合はそのデータをコアサンプルとする。
- eps : データがコアサンプルかノイズかを判定するために使用されるデータ間の距離。デフォルトは0.5。

# 教師なし学習(クラスタリング)の定量的評価
## 正解データありの場合
正解データクラスタリングと比較して評価する調整ランド指数(ARI:Adjusted Rand Index)や正規化相互情報量(NMI:Normalized Mutual Information)という手法が存在する。
しかし、そもそも正解データがないから教師なし学習をやるという背景が多いはずなので、これらの手法を使う場面は少ないだろう。もし、正解データを用意できるならば、教師あり学習の分類器を作るべきである。

## 正解データなしの場合
正解データが存在しない場合でもクラスタリングを定量的に評価する指標としてシルエット係数が存在する。
しかしながら、一般的にこの指標はそれほどうまくいかないことで知られている。

# 教師なし学習に関する俺的（初心者的）結論
- 教師なし学習はメインで使うよりも補助ツール（教師あり学習のための前処理や可視化）として使う。
- 定量的評価は無理ゲー。定性的評価(人間の主観)にならざる得ない。それゆえに、できればクラスタリングでなく、ラベルデータを用意して分類にする。
- 定量的評価できないのでテストデータはいらない。全て学習データに使う。