k-means法で文書のクラスタリング


前回、ラベルつきのデータを使ってランダムフォレストで分類器を作った。

- http://qiita.com/satzz/items/69beb439ed440d459585

今回は同じデータを使うがラベルは無視してベクトルデータだけを使い、教師なし学習のk-means法でのクラスタリングを行う。コードは以下に置いたので、前回との差分だけ書いていく。

- https://gist.github.com/satzz/009f60f9a304cd81de29



## 環境
- OSX 10.10.5
- Conda 3.19.0
- Python 2.7.11 
- MeCab 0.996




## 準備
k-means法の計算にscikit-learnを使う。
scikit-learnで使える距離はデフォルトではEuclid距離に限られるようなので問題に応じて工夫が必要かも。
あとベクトルの規格化にnumpyを使うことにした。

- http://qiita.com/Kensuke-Mitsuzawa/items/67c17f6bda8a1097740c

```python:
import numpy as np
from sklearn.cluster import KMeans
```

今回はmecab-ipadic-neologdを使うほうが精度が目に見えて上がった気がする。


```python:
m = MeCab.Tagger(' -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
```

## 次元圧縮
文書をベクトルにするところは前回と一緒で、LSIに渡す次元をチューニングできるようにする。トピック数よりも少し多めにするのがよい気がする。

```python:
  print '# LSI Model'
  dimension = num_topics+3
  lsi_model = gensim.models.LsiModel(bow_docs.values(), num_topics=dimension)
  lsi_docs = {}
  for i, docname in enumerate(files):
    vec = bow_docs[docname]
    lsi_docs[i] = lsi_model[vec]

  def vec2dense(vec, num_terms):
    return list(gensim.matutils.corpus2dense([vec], num_terms=num_terms).T[0])
```

## クラスタリング
- 次元による分布の違いの影響が小さくなるようにする
	- ここでは全てのベクトルを規格化して単位10次元球面上のクラスタリングになるようにした。
	- 次元ごとに分散をもとに正規化するほうが一般的か？
- 処理したベクトルとクラスタ数をKMeansに渡してクラスタリングする。

```python:
  print '# Clustering'
  data_all  = [vec2dense(lsi_docs[i],dimension) for i, docname in enumerate(files)]
  normalized = [vec/np.linalg.norm(vec) for vec in data_all]

  result = KMeans(n_clusters=num_topics).fit_predict(normalized)
  for i,docname in enumerate(files):
    print docname,'cluster',result[i]
```


## 実行結果



```
# MORPHOLOGICAL ANALYSIS
number of features 1561
# BAG OF WORDS
# LSI Model
# Clustering
birth-1 cluster 3
birth-2 cluster 3
birth-3 cluster 3
birth-4 cluster 3
birth-5 cluster 3
birth-6 cluster 3
birth-7 cluster 3
birth-8 cluster 3
design-1 cluster 2
design-2 cluster 2
design-3 cluster 2
design-4 cluster 2
design-5 cluster 2
design-6 cluster 2
design-7 cluster 2
design-8 cluster 2
ekiden-1 cluster 6
ekiden-2 cluster 6
ekiden-3 cluster 6
ekiden-4 cluster 6
ekiden-5 cluster 6
ekiden-6 cluster 6
ekiden-7 cluster 6
ekiden-8 cluster 6
fe-1 cluster 5
fe-2 cluster 5
fe-3 cluster 5
fe-4 cluster 5
fe-5 cluster 5
fe-6 cluster 5
fe-7 cluster 5
fe-8 cluster 5
ikukyu-1 cluster 9
ikukyu-2 cluster 9
ikukyu-3 cluster 9
ikukyu-4 cluster 9
ikukyu-5 cluster 9
ikukyu-6 cluster 9
ikukyu-7 cluster 9
ikukyu-8 cluster 9
riken-1 cluster 4
riken-2 cluster 4
riken-3 cluster 4
riken-4 cluster 4
riken-5 cluster 4
riken-6 cluster 4
riken-7 cluster 4
riken-8 cluster 4
starwars-1 cluster 1
starwars-2 cluster 1
starwars-3 cluster 1
starwars-4 cluster 1
starwars-5 cluster 1
starwars-6 cluster 1
starwars-7 cluster 1
starwars-8 cluster 1
takahama-1 cluster 7
takahama-2 cluster 7
takahama-3 cluster 7
takahama-4 cluster 7
takahama-5 cluster 7
takahama-6 cluster 7
takahama-7 cluster 7
takahama-8 cluster 7
thief-1 cluster 8
thief-2 cluster 8
thief-3 cluster 8
thief-4 cluster 8
thief-5 cluster 8
thief-6 cluster 8
thief-7 cluster 8
thief-8 cluster 8
tunnel-1 cluster 0
tunnel-2 cluster 0
tunnel-3 cluster 0
tunnel-4 cluster 0
tunnel-5 cluster 0
tunnel-6 cluster 0
tunnel-7 cluster 0
tunnel-8 cluster 0
```

文書群のとり方にもよるが、この場合は綺麗にクラスタリングできている。