k-meansクラスタリングを使用する場合、どのようにkを決定しますか?


142

私はk平均クラスタリングについて研究してきましたが、はっきりしないのは、kの値をどのように選択するかです。それは試行錯誤の問題なのか、それともそれ以上のものなのか?


34
ああああ...それは本当にです(K-平均について)質問。
mjv 2009年

関数L(対数尤度)のコードを共有できますか?X、Yに中心があり、(x(i = 1,2,3,4、...、n)、y(i = 1,2,3,4、..、n))にポイントがある場合、どのようにLはもらえるの?

7
テーマに関するWikipediaの記事へのリンク:en.wikipedia.org/wiki/...
アムロ

11
私はRここで6ダースの方法(を使用)で同様のQに回答しました:stackoverflow.com/a/15376462/1036500
Ben

回答:


142

ベイジアン情報量基準(BIC)を最大化できます。

BIC(C | X) = L(X | C) - (p / 2) * log n

ここで、L(X | C)データセットの対数尤度であるXモデルによればCpモデル内のパラメータの数でありC、そしてnデータセット内のポイントの数です。ICML 2000のDan PellegとAndrew Mooreによる「X-means:K -meansの拡張によるクラスター数の効率的な推定」を参照してください。

もう1つのアプローチは、の大きな値から開始し、k重心を削除し続け(kを減らし)、説明の長さが短くならないようにすることです。パターン分析とアプリケーション vol。2のHorst Bischof、Ales Leonardis、およびAlexander Selbによる「堅牢なベクトル量子化のMDL原理」を参照してください。2、p。59-72、1999。

最後に、1つのクラスターから開始して、各クラスターに割り当てられた点がガウス分布になるまでクラスターを分割し続けることができます。では、「学習のkをk個の -means」(NIPS 2003)、グレッグHamerlyとチャールズElkanが、これは、より良いBICよりも動作し、BICが強く、十分なモデルの複雑さを処罰しないといういくつかの証拠を示します。


正解です。X-Meansの場合、全体的なBICスコアn:= k * 2(kクラスター、各クラスターは平均/分散パラメーターを使用してガウスによってモデル化されている)かどうかを知っていますか また、「親」のBIC>「2つの子」のBICを決定した場合、次の反復でそのクラスターを再び分割することはありますか?
Budric

2
@Budric、これらはおそらく個別の質問であり、おそらくstats.stackexchange.comにあるはずです。
Vebjorn Ljosa、2011

37

基本的に、クラスターの数(k)とクラスターの平均分散の2つの変数間のバランスを求めます。前者を最小限に抑えながら、後者を最小限に抑えたいとします。もちろん、クラスターの数が増えると、平均分散は小さくなります(k = nおよびvariance = 0 の自明なケースまで)。

データ分析ではいつものように、すべてのケースで他のすべての方法よりも優れた真のアプローチはありません。結局、あなたはあなた自身の最高の判断を使わなければなりません。そのためには、平均分散に対するクラスターの数をプロットするのに役立ちます(kのいくつかの値に対して既にアルゴリズムを実行していると想定しています)。次に、カーブの膝でクラスタの数を使用できます。


24

はい、Elbowメソッドを使用して最適な数のクラスターを見つけることができますが、スクリプトを使用してエルボグラフからクラスターの値を見つけるのは面倒でした。エルボグラフを観察してエルボポイントを自分で見つけることができますが、スクリプトからそれを見つけるのは大変な作業でした。

したがって、別のオプションは、シルエットメソッドを使用してそれを見つけることです。Silhouetteの結果は、RのElbowメソッドの結果に完全に準拠しています。

これが私がしたことです。

#Dataset for Clustering
n = 150
g = 6 
set.seed(g)
d <- data.frame(x = unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2))), 
                y = unlist(lapply(1:g, function(i) rnorm(n/g, runif(1)*i^2))))
mydata<-d
#Plot 3X2 plots
attach(mtcars)
par(mfrow=c(3,2))

#Plot the original dataset
plot(mydata$x,mydata$y,main="Original Dataset")

#Scree plot to deterine the number of clusters
wss <- (nrow(mydata)-1)*sum(apply(mydata,2,var))
  for (i in 2:15) {
    wss[i] <- sum(kmeans(mydata,centers=i)$withinss)
}   
plot(1:15, wss, type="b", xlab="Number of Clusters",ylab="Within groups sum of squares")

# Ward Hierarchical Clustering
d <- dist(mydata, method = "euclidean") # distance matrix
fit <- hclust(d, method="ward") 
plot(fit) # display dendogram
groups <- cutree(fit, k=5) # cut tree into 5 clusters
# draw dendogram with red borders around the 5 clusters 
rect.hclust(fit, k=5, border="red")

#Silhouette analysis for determining the number of clusters
library(fpc)
asw <- numeric(20)
for (k in 2:20)
  asw[[k]] <- pam(mydata, k) $ silinfo $ avg.width
k.best <- which.max(asw)

cat("silhouette-optimal number of clusters:", k.best, "\n")
plot(pam(d, k.best))

# K-Means Cluster Analysis
fit <- kmeans(mydata,k.best)
mydata 
# get cluster means 
aggregate(mydata,by=list(fit$cluster),FUN=mean)
# append cluster assignment
mydata <- data.frame(mydata, clusterid=fit$cluster)
plot(mydata$x,mydata$y, col = fit$cluster, main="K-means Clustering results")

それが役に立てば幸い!!


2
ただ、Pythonのユーザーのためのシルエット解析のチュートリアルへのリンクを追加しscikit-learn.org/stable/auto_examples/cluster/...
Chaitanya Shivade

10

コード例を探している私のような初心者かもしれません。silhouette_scoreの情報 はここにあります。

from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score

range_n_clusters = [2, 3, 4]            # clusters range you want to select
dataToFit = [[12,23],[112,46],[45,23]]  # sample data
best_clusters = 0                       # best cluster number which you will get
previous_silh_avg = 0.0

for n_clusters in range_n_clusters:
    clusterer = KMeans(n_clusters=n_clusters)
    cluster_labels = clusterer.fit_predict(dataToFit)
    silhouette_avg = silhouette_score(dataToFit, cluster_labels)
    if silhouette_avg > previous_silh_avg:
        previous_silh_avg = silhouette_avg
        best_clusters = n_clusters

# Final Kmeans for best_clusters
kmeans = KMeans(n_clusters=best_clusters, random_state=0).fit(dataToFit)

9

チャールズ・エルカンのグレッグ・ハマリーによる「k-meansでkを学ぶ」というこの論文を見てください。ガウステストを使用して、クラスターの適切な数を決定します。また、著者らは、この方法は、受け入れられた回答で言及されているBICよりも優れていると主張しています。


7

経験則と呼ばれるものがあります。クラスターの数は、

k = (n/2)^0.5

ここで、nはサンプルの要素の総数です。この情報の信憑性は、次のペーパーで確認できます。

http://www.ijarcsms.com/docs/paper/volume1/issue6/V1I6-0015.pdf

また、分布がガウス分布または正規分布に従うG平均法と呼ばれる別の方法もあります。これは、すべてのkグループがガウス分布に従うまでkを増やすことで構成されます。多くの統計が必要ですが、実行できます。ここにソースがあります:

http://papers.nips.cc/paper/2526-learning-the-k-in-k-means.pdf

これが役に立てば幸いです!


3

最初に、データの最小全域木を構築します。K-1の最も高価なエッジを削除すると、ツリーがK個のクラスターに分割される
ため、MSTを一度構築し、さまざまなKのクラスター間隔/メトリックを確認して、曲線の膝をつかむことができます。

これはSingle-linkage_clusteringでのみ機能しますが、高速で簡単です。さらに、MSTは優れたビジュアルを実現します。
たとえば、クラスタリング用のstats.stackexchange視覚化ソフトウェアの下のMSTプロットを参照してください 。


3

誰もこの優れた記事に言及していないことに驚いています:http : //www.ee.columbia.edu/~dpwe/papers/PhamDN05-kmeans.pdf

他のいくつかの提案に従った後、私はこのブログを読んでいる間にこの記事に出会いました:https : //datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/

その後、私はそれをScalaに実装しました。この実装は、私のユースケースでは本当に良い結果をもたらします。ここにコードがあります:

import breeze.linalg.DenseVector
import Kmeans.{Features, _}
import nak.cluster.{Kmeans => NakKmeans}

import scala.collection.immutable.IndexedSeq
import scala.collection.mutable.ListBuffer

/*
https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-reloaded/
 */
class Kmeans(features: Features) {
  def fkAlphaDispersionCentroids(k: Int, dispersionOfKMinus1: Double = 0d, alphaOfKMinus1: Double = 1d): (Double, Double, Double, Features) = {
    if (1 == k || 0d == dispersionOfKMinus1) (1d, 1d, 1d, Vector.empty)
    else {
      val featureDimensions = features.headOption.map(_.size).getOrElse(1)
      val (dispersion, centroids: Features) = new NakKmeans[DenseVector[Double]](features).run(k)
      val alpha =
        if (2 == k) 1d - 3d / (4d * featureDimensions)
        else alphaOfKMinus1 + (1d - alphaOfKMinus1) / 6d
      val fk = dispersion / (alpha * dispersionOfKMinus1)
      (fk, alpha, dispersion, centroids)
    }
  }

  def fks(maxK: Int = maxK): List[(Double, Double, Double, Features)] = {
    val fadcs = ListBuffer[(Double, Double, Double, Features)](fkAlphaDispersionCentroids(1))
    var k = 2
    while (k <= maxK) {
      val (fk, alpha, dispersion, features) = fadcs(k - 2)
      fadcs += fkAlphaDispersionCentroids(k, dispersion, alpha)
      k += 1
    }
    fadcs.toList
  }

  def detK: (Double, Features) = {
    val vals = fks().minBy(_._1)
    (vals._3, vals._4)
  }
}

object Kmeans {
  val maxK = 10
  type Features = IndexedSeq[DenseVector[Double]]
}

scala 2.11.7にbreeze 0.12とnak 1.3で
実装

こんにちは@eirirlar Pythonで同じコードを実装しようとしていますが、Webサイトでコードを追跡できませんでした。私の投稿を見てください:stackoverflow.com/questions/36729826/python-k-means-clustering
piccolo

@ImranRashid申し訳ありませんが、2次元でのみテストしました。私はPythonのエキスパートではありません。
eirirlar

3

MATLABを使用する場合、2013b以降のすべてのバージョン、つまり、関数evalclustersを利用kして、特定のデータセットに最適なものを見つけることができます。

この機能を使用すると、3つのクラスタリングアルゴリズム- kmeanslinkageおよびから選択できますgmdistribution

-それはまた、あなたが4クラスタリング評価基準の中から選択することができますCalinskiHarabaszDaviesBouldingapsilhouette


3

クラスターの数kがわからない場合、パラメーターとしてk-meansに提供するため、それを自動的に見つけるには4つの方法があります。

  • G平均アルゴリズム:統計的検定を使用してクラスターの数を自動的に検出し、K平均の中心を2つに分割するかどうかを決定します。このアルゴリズムは、データのサブセットがガウス分布(イベントの正確な二項分布を近似する連続関数)に従うという仮説の統計的検定に基づいて、クラスターの数を検出するために階層的アプローチを採用し、そうでない場合はクラスターを分割します。それは少数の中心、たとえば1つのクラスターのみ(k = 1)から始まり、アルゴリズムはそれを2つの中心(k = 2)に分割し、これらの2つの中心のそれぞれを(k = 4)に分割します。合計。G-meansがこれらの4つの中心を受け入れない場合、答えは前のステップです。この場合は2つの中心(k = 2)です。これは、データセットが分割されるクラスターの数です。G-meansは、インスタンスをグループ化した後に取得されるクラスターの数を推定できない場合に非常に役立ちます。「k」パラメーターの不便な選択は、誤った結果をもたらす可能性があることに注意してください。g-meansの並列バージョンは、p-means。G-meansソース: ソース1 ソース2 ソース3

  • x-means:効率的に、クラスターの場所のスペースとクラスターの数を検索して、ベイジアン情報基準(BIC)または赤池情報基準(AIC)メジャーを最適化する新しいアルゴリズム。このバージョンのk-meansは、数kを検出し、k-meansを高速化します。

  • オンラインk-meansまたはストリーミングk-means:データ全体を1回スキャンすることでk-meansを実行でき、最適なkの数が自動的に検出されます。Sparkはそれを実装します。

  • MeanShiftアルゴリズム:ノンパラメトリッククラスタリング手法であり、クラスター数の事前の知識を必要とせず、クラスターの形状を制約しません。平均シフトクラスタリングは、滑らかな密度のサンプルで「ブロブ」を発見することを目的としています。これはセントロイドベースのアルゴリズムであり、セントロイドの候補を特定の領域内のポイントの平均になるように更新することで機能します。次に、これらの候補は、後処理段階でフィルター処理されて、ほぼ重複するものを排除して、重心の最終セットを形成します。ソース:ソース1ソース2source3


2

私はここで見つけた解決策を使用しました:http : //efavdb.com/mean-shift/そしてそれは私にとって非常にうまくいきました:

import numpy as np
from sklearn.cluster import MeanShift, estimate_bandwidth
from sklearn.datasets.samples_generator import make_blobs
import matplotlib.pyplot as plt
from itertools import cycle
from PIL import Image

#%% Generate sample data
centers = [[1, 1], [-.75, -1], [1, -1], [-3, 2]]
X, _ = make_blobs(n_samples=10000, centers=centers, cluster_std=0.6)

#%% Compute clustering with MeanShift

# The bandwidth can be automatically estimated
bandwidth = estimate_bandwidth(X, quantile=.1,
                               n_samples=500)
ms = MeanShift(bandwidth=bandwidth, bin_seeding=True)
ms.fit(X)
labels = ms.labels_
cluster_centers = ms.cluster_centers_

n_clusters_ = labels.max()+1

#%% Plot result
plt.figure(1)
plt.clf()

colors = cycle('bgrcmykbgrcmykbgrcmykbgrcmyk')
for k, col in zip(range(n_clusters_), colors):
    my_members = labels == k
    cluster_center = cluster_centers[k]
    plt.plot(X[my_members, 0], X[my_members, 1], col + '.')
    plt.plot(cluster_center[0], cluster_center[1],
             'o', markerfacecolor=col,
             markeredgecolor='k', markersize=14)
plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

ここに画像の説明を入力してください



1

と呼ばれるデータのマトリックスがあると仮定するとDATA、次のように(シルエット分析による)クラスター数の推定を使用してmedoidの周囲でパーティション化を実行できます。

library(fpc)
maxk <- 20  # arbitrary here, you can set this to whatever you like
estimatedK <- pamk(dist(DATA), krange=1:maxk)$nc

1

考えられる答えの1つは、遺伝的アルゴリズムのようなメタヒューリスティックアルゴリズムを使用してkを見つけることです。それは簡単です。ランダムなK(ある範囲内)を使用して、シルエットのような測定で遺伝的アルゴリズムのフィット関数を評価し、フィット関数に基づいて最良のKベースを見つけることができます。

https://en.wikipedia.org/wiki/Silhouette_(clustering)


1
km=[]
for i in range(num_data.shape[1]):
    kmeans = KMeans(n_clusters=ncluster[i])#we take number of cluster bandwidth theory
    ndata=num_data[[i]].dropna()
    ndata['labels']=kmeans.fit_predict(ndata.values)
    cluster=ndata
    co=cluster.groupby(['labels'])[cluster.columns[0]].count()#count for frequency
    me=cluster.groupby(['labels'])[cluster.columns[0]].median()#median
    ma=cluster.groupby(['labels'])[cluster.columns[0]].max()#Maximum
    mi=cluster.groupby(['labels'])[cluster.columns[0]].min()#Minimum
    stat=pd.concat([mi,ma,me,co],axis=1)#Add all column
    stat['variable']=stat.columns[1]#Column name change
    stat.columns=['Minimum','Maximum','Median','count','variable']
    l=[]
    for j in range(ncluster[i]):
        n=[mi.loc[j],ma.loc[j]] 
        l.append(n)

    stat['Class']=l
    stat=stat.sort(['Minimum'])
    stat=stat[['variable','Class','Minimum','Maximum','Median','count']]
    if missing_num.iloc[i]>0:
        stat.loc[ncluster[i]]=0
        if stat.iloc[ncluster[i],5]==0:
            stat.iloc[ncluster[i],5]=missing_num.iloc[i]
            stat.iloc[ncluster[i],0]=stat.iloc[0,0]
    stat['Percentage']=(stat[[5]])*100/count_row#Freq PERCENTAGE
    stat['Cumulative Percentage']=stat['Percentage'].cumsum()
    km.append(stat)
cluster=pd.concat(km,axis=0)## see documentation for more info
cluster=cluster.round({'Minimum': 2, 'Maximum': 2,'Median':2,'Percentage':2,'Cumulative Percentage':2})

データとライブラリの追加を選択し、km = []をパーセンテージにコピーします ':2})最後にpythonを実行して確認します
sumit

Stack Overflowへようこそ!このコードは問題の解決に役立つ可能性がありますが、なぜまたはどのように質問に回答するかについては説明していません。この追加のコンテキストを提供すると、その長期的な教育的価値が大幅に向上します。回答を編集して、適用される制限や前提条件などの説明を追加してください。
Toby Speight 2016

1

別のアプローチは、自己組織化マップ(SOP)を使用して最適なクラスター数を見つけることです。SOM(自己組織化マップ)は、教師なしのニューラルネットワーク手法であり、問​​題解決のためのクラスタリングに入力のみを使用する必要があります。このアプローチは、顧客のセグメンテーションに関する論文で使用されています。

論文の参考文献は

Abdellah Amine他、クラスタリング手法とLRFMモデルを使用した電子商取引における顧客セグメンテーションモデル:モロッコのオンラインストアのケース、世界科学技術アカデミージャーナルコンピューターと情報工学Vol.9、No:8 、2015、1999〜2010


0

こんにちは私はそれを説明するのを簡単でまっすぐにするつもりです、私は「NbClust」ライブラリーを使用してクラスターを決定したいです。

ここで、「NbClust」関数を使用して正しい数のクラスターを決定する方法:Githubで実際のプロジェクトを実際のデータとクラスターで確認できます-この「kmeans」アルゴリズムの拡張は、正しい数の「中心」を使用して実行されました。

Githubプロジェクトリンク:https : //github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook


githubリンクを追加する代わりに、コードに到達できない場合でも他の人を助けることができるいくつかの主要なコード行を追加できますか?
Giulio Caccin

0

クラスターの数は、データポイントを視覚的に調べることで選択できますが、最も単純なデータセットを除くすべてのプロセスで、このプロセスには多くのあいまいさが存在することがすぐにわかります。これは常に悪いことではありません。教師なし学習を行っているため、ラベル付けプロセスには固有の主観性があるためです。ここでは、その特定の問題または類似したもので以前に経験を持っていると、正しい値を選択するのに役立ちます。

使用する必要があるクラスターの数に関するヒントが必要な場合は、Elbowメソッドを適用できます。

まず、kのいくつかの値(たとえば、2、4、6、8など)の二乗誤差(SSE)の合計を計算します。SSEは、クラスターの各メンバーとその重心間の距離の2乗の合計として定義されます。数学的に:

SSE = ∑Ki = 1∑x∈cidist(x、ci)2

SSEに対してkをプロットすると、kが大きくなるにつれてエラーが減少することがわかります。これは、クラスターの数が増えると、クラスターが小さくなるため、歪みも小さくなるためです。エルボー法の考え方は、SSEが急激に減少するkを選択することです。これにより、次の図に示すように、グラフに「エルボ効果」が生じます。

ここに画像の説明を入力してください

この場合、k = 6はElbowメソッドが選択した値です。エルボー方式はヒューリスティックであるため、特定のケースではうまく機能しない場合があることを考慮してください。エルボーが2つ以上ある場合や、まったくない場合もあります。これらの状況では、通常、解決しようとしている特定のクラスタリング問題のコンテキストでk-meansがどの程度うまく機能するかを評価することにより、最良のkを計算することになります。


0

私はひざまずいたPythonパッケージ(Kneedleアルゴリズム)で作業しました。カーブが平坦化し始めるポイントとして動的にクラスター番号を見つけます。xとyの値のセットを指定すると、kneedは関数のニーポイントを返します。ニーポイントは最大曲率のポイントです。サンプルコードは次のとおりです。

y = [7342.1301373073857、6881.7109460930769、6531.1657905495022、
6356.2255554679778、6209.8382535595829、6094.9052166741121、5980.0191582610196、5880.1869867848218、5779.8957906367368、5691.1879324562778、5617.5153566271356、5532.2613232619951、5467.352265375117、5395.4493783888756、5345.3459908298091、5290.6769823693812、5243.5271656371888、5207.2501206569532、5164.9617535255456]

x = range(1、len(y)+1)

ニードインポートからKneeLocator kn = KneeLocator(x、y、curve = 'convex'、direction = 'decreasing')

プリント(kn.knee)


他の人がそれを学ぶことができるように、あなたの答えにいくつかの説明を追加してください
ニコ・ハーセ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.