web-dev-qa-db-ja.com

k-meansクラスタリングを使用する場合、どうすればkを決定できますか?

k-means clustering について研究してきましたが、不明な点の1つは、kの値の選択方法です。それは単なる試行錯誤の問題ですか、それともそれ以上ですか?

135
Jason Baker

Bayesian Information Criterion(BIC)を最大化できます:

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

ここで、L(X | C)はデータセットの対数尤度ですXはモデルCに応じて、pはモデルのパラメーターの数C、およびnは、データセット内のポイントの数です。 "X-means:拡張 K-クラスター数を効率的に推定する手段」 ICML 2000のDan PellegおよびAndrew Mooreによる。

もう1つの方法は、kの大きな値から開始し、記述の長さが短くなるまで重心を削除し続けます(kを減らします)。 「ロバストなベクトル量子化のMDL原理」 Horst Bischof、Ales Leonardis、およびAlexander SelbによるPattern Analysis and Applicationsvol。 2、p。 59-72、1999。

最後に、1つのクラスターから開始し、各クラスターに割り当てられたポイントがガウス分布になるまでクラスターを分割し続けることができます。 In "kink-means" (NIPS 2003)、Greg HamerlyおよびCharlesの学習エルカンは、これがBICよりもうまく機能し、BICがモデルの複雑さを十分に十分にペナルティしないという証拠をいくつか示しています。

139
Vebjorn Ljosa

基本的に、クラスターの数(k)とクラスターの平均分散の2つの変数のバランスを求めます。前者を最小化し、後者も最小化する必要があります。もちろん、クラスターの数が増えると、平均分散は減少します(k= nで分散= 0の自明な場合まで)。

データ分析でいつものように、すべての場合において他のすべてのものよりもうまく機能する真のアプローチはありません。最後に、あなた自身の最高の判断を使用する必要があります。そのため、クラスターの数を平均分散に対してプロットすると役立ちます(これは、kのいくつかの値に対してアルゴリズムを既に実行していることを前提としています)。次に、曲線のひざにあるクラスターの数を使用できます。

36
Jan Krüger

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

したがって、別のオプションは Silhouette Method を使用して検索することです。 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")

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

23
Udeep Shakya

コード例を探している私のような初心者かもしれません。 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)
8
bhargav patel

this 論文、Greg Hamerly、Charles Elkanによる「k-meansでのkの学習」をご覧ください。ガウス検定を使用して、適切なクラスター数を決定します。また、著者は、この方法が受け入れられた答えで言及されているBICよりも優れていると主張しています。

7

経験則と呼ばれるものがあります。クラスターの数はk =(n/2)^ 0,5で計算できると言われています。ここで、nはサンプルの要素の総数です。この情報の信ity性は、次のペーパーで確認できます。

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

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

4

まず、データの 最小スパニングツリー を構築します。 K-1の最も高価なエッジを削除すると、ツリーがKクラスターに分割され、
したがって、MSTを1回作成し、さまざまなKのクラスター間隔/メトリックを確認して、曲線のニーを取得できます。

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

3
denis

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

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

また、4つのクラスタリング評価基準-CalinskiHarabaszDaviesBouldingap、およびsilhouetteから選択できます。

3
Kristada673

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

他のいくつかの提案に従った後、このブログを読んでいるときにようやくこの記事に出会いました: https://datasciencelab.wordpress.com/2014/01/21/selection-of-k-in-k-means-clustering-再読み込み/

その後、私は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]]
}
2
eirirlar

私のアイデアは Silhouette Coefficient を使用して最適なクラスター数(K)を見つけることです。詳細説明は こちら です。

1
qmaruf

K-meansのパラメーターとして提供するクラスターkの数がわからない場合、自動的に見つけるには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ソース

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

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

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

1
nabiltos

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

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

1
Masoud

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

論文の参照は

Abdellah Amine et al。、Customer Segmentation Model in e-commerce Using Clustering Techniques and LRFM Model:The Case of Online Stores in Morocco、World Academy of Science、Engineering and Technology International Journal of Computer and Information Engineering Vol.9 、No:8、2015、1999-201

1
boyaronur
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})
1
sumit

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
Megatron

こんにちは。説明を簡単でわかりやすくします。「NbClust」ライブラリを使用してクラスターを決定します。

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

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

0
Rutvij

私はここで見つけた解決策を使用しました: 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()

enter image description here

0
snoob dogg