0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

アルゴリズム(kNN、k-means)のまとめ

Last updated at Posted at 2020-11-03

この記事は個人的なお勉強用のメモです。

講義

k近傍法(kNN)

  • 教師あり学習
  • 分類を予測
  • 予測対象のデータに最も近い k個のデータを取ってきて、それらのデータが最も多く所属するクラスを予測値とする、という単純なアルゴリズム。(要するに、多数決でクラスを決めるだけ)

kについて

  • kの値によって分類の結果が変わる場合がある。
  • kは事前に決めておく。(ハイパーパラメータ)
  • kを大きくすると決定境界は滑らかになる。

k-平均法(k-means)

  • 教師なし学習
  • クラスタリングする(クラス分けする)

処理順序

  1. 分類する個数を決める。
  2. クラスタの中心の初期値をランダムに決める。
  3. 各データに対して、どれが最も近いクラスタの中心か求める。
  4. 各クラスタの平均ベクトル(中心)を計算する。
  5. 3と4を繰り返す。

クラスタの中心を変化させていって、変化が落ち着いたところが
クラスタリング終了といったところか。

特徴

  • 中心の初期値が近いと、うまくクラスタリングできない。
    k-means++という手法を使うと、初期値がうまくばらける。
  • kの値を変えるとクラスタリング結果も変わる。
    人間の目で見てkの値を判断する必要性がある。

修了テスト~練習問題~(kNN)

kNNの問題が無い。

修了テスト~練習問題~(k-means)

問題22(k-means)

内側の1つ目のforループ
データごとに最も近いクラスタの中心を求める処理。

for centroid in centroids:
  for i, x in enumerate(data):
    indexes[i] = np.argmin(np.sum((x - centroid) ** 2, axis=1))

説明
x:既存の1つのデータ
centroid:クラスタの中心の1つのデータ
x - centroid:成分ごとの差を求める。
(...) **2:成分の差ごとに二乗する。
np.sum(..., axis=1):異なる成分の差を足す。足すのは右方向。
np.argmin:最小値を持つインデックスを返す。

問題23(k-means)

内側の2つ目のforループ
クラスタの中心を再計算する。
再計算とは、データの平均値を求める。

for i in range(k):
  centroisd[i] = data[indexes==i].mean(axis=0)

説明
k:クラスタの個数(4個)
i:クラスタの番号(みたいなもの、0~3)
centroids:クラスタの中心が複数
data[indexes==i]:クラスタの番号iと一致するdataを抽出する。
data[...].mean:該当するデータの平均値を計算する。

問題25(k-means)

k-meansの欠点は、初期値が近いとうまくクラスタリングできないこと。
k-means++によって、この欠点が改良された。

問題26(k-means++)

k-means++で初期のクラスタの中心(セントロイド)を決めるアルゴリズム

probabilities = np.repeat(1/n, n)
centroids = np.zeros((k, 2))
distances = np.zeros((n, k))

for in in range(k):
  centroids[i] = data[np.random.choice(np.arange(n), p=probabirities, size=(1))]
  distances[:, i] = np.sum((data - centroids[i]) ** 2, axis=1)
  probabilities = np.sum(distance, axis=1) / np.sum(distance)

probabilities:確率をセットする。確率なので全部足すと1になる。
全体の距離のうち、データごとの距離の割合を求める。
その割合を probabilities変数にセットする。

距離が遠い
=probabilities変数にセットされる値が大きい
=次にセントロイドとして選ばれる確率が高い
という仕組み。
逆に言うと、近い距離のデータはセントロイドとして選ばれづらくなる。

こうやって、距離が遠いものをセントロイドとして選んでいく。

用語
クラスタの中心:セントロイド

実装演習(kNN)

image.png

上の結果はkの値が3の場合。
100×100のメッシュグリッドを作って、そのメッシュグリッドに対して
クラス分類をしている。
NumPyを使った実装による結果だが、十分にクラス分類できている。

kの値を10にしたところ、滑らかな線が描かれた。
どの程度のkが適切かは機械的に求めるのは難しい側面があるので
人間の目で結果を見て、パラメータ(kNNの場合はk)の値が適切か
判断する必要がありそう。

scikit-learnのKNeighborsClassifierクラスを使った方も実行してみた。
NumPyのときと同じグラフが描かれた。
当然だろうが、NumPyで自前で書いたものと同じアルゴリズムで
KNeighborsClassifierクラスが動作しているのであろう。

実装演習(k-means)

image.png

これは iter_max=100 の場合。
きれいにクラスタリングできている。

試しに、iter_max=2にして実行してみたところ、
それでもきれいにクラスタリングできた。
(100の場合と分類境界がほぼ同じ)

今回のデータは明確に3種類に分けられるため、
クラスタの中心を再計算する回数も少なくて済むのだろう。
逆いうと、データが明確に分けづらい場合は
クラスタの中心を再計算する回数が多く必要になるのだろう。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?