環境
- Python 3.7.13
- scikit-learn 1.0.2
- nltk 3.7
scikit-learn で KMeans
PythonでKMeansクラスタリングしたいとき、scikit-learn を使うのがポピュラーなのではないかと思います。
import numpy
from sklearn.cluster import KMeans
data = numpy.array([1,2,3,10,11,21,22,23])
KMeans(n_clusters=3).fit_predict(data.reshape(len(data), 1))
出力
array([2, 2, 2, 0, 0, 1, 1, 1], dtype=int32)
scikit-learnのKMeansはユークリッド距離(euclidean distance、2点間の直線距離)に基づいているようです。scikit-learnのソースコードを眺めてみると_euclidean_distances
というメソッドに依存しているのが分かります。
NLTK で KMeans
NLTK でも KMeansクラスタリングができます。
from nltk.cluster import KMeansClusterer, euclidean_distance
data = numpy.array([1,2,3,10,11,21,22,23])
clusterer = KMeansClusterer(3, distance=euclidean_distance, repeats=10)
clusterer.cluster(data.reshape(len(data), 1), assign_clusters=True)
出力
[0, 0, 0, 1, 1, 2, 2, 2]
見ての通り、euclidean_distance
というユークリッド距離算出メソッドを渡しています。ここに別の関数を渡せば、別の距離に基づくクラスタリングができます。
data = numpy.array([(1,1), (0,1), (100,100)])
clusterer = KMeansClusterer(2, distance=euclidean_distance, repeats=10, avoid_empty_clusters=True)
clusterer.cluster(data, assign_clusters=True)
出力
[0, 0, 1]
このように、ユークリッド距離だと例えば(1,1)
と(100,100)
は遠いので別のクラスタになりましたが
from nltk.cluster import cosine_distance
data = numpy.array([(1,1), (0,1), (100,100)])
clusterer = KMeansClusterer(2, distance=cosine_distance, repeats=10, avoid_empty_clusters=True)
clusterer.cluster(data, assign_clusters=True)
出力
[1, 0, 1]
(1,1)
と(100,100)
のコサイン類似度は1.0で一致する(コサイン距離はコサインから1を引いた値なので、ゼロ距離になる)ため、同じクラスタに属するようになります。
もちろん自前で定義した関数を距離として使うこともできます。
# コサイン距離を自前で定義
def cos_dis(i1, i2):
return 1 - (numpy.dot(i1, i2) / (numpy.linalg.norm(i1) * numpy.linalg.norm(i2)))
data = numpy.array([(1,1), (0,1), (100,100)])
clusterer = KMeansClusterer(2, distance=cos_dis, repeats=10, avoid_empty_clusters=True)
clusterer.cluster(data, assign_clusters=True)