私はk平均クラスタリングについて研究してきましたが、はっきりしないのは、kの値をどのように選択するかです。それは試行錯誤の問題なのか、それともそれ以上のものなのか?
R
ここで6ダースの方法(を使用)で同様のQに回答しました:stackoverflow.com/a/15376462/1036500
私はk平均クラスタリングについて研究してきましたが、はっきりしないのは、kの値をどのように選択するかです。それは試行錯誤の問題なのか、それともそれ以上のものなのか?
R
ここで6ダースの方法(を使用)で同様のQに回答しました:stackoverflow.com/a/15376462/1036500
回答:
ベイジアン情報量基準(BIC)を最大化できます。
BIC(C | X) = L(X | C) - (p / 2) * log n
ここで、L(X | C)
データセットの対数尤度であるX
モデルによればC
、p
モデル内のパラメータの数であり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が強く、十分なモデルの複雑さを処罰しないといういくつかの証拠を示します。
基本的に、クラスターの数(k)とクラスターの平均分散の2つの変数間のバランスを求めます。前者を最小限に抑えながら、後者を最小限に抑えたいとします。もちろん、クラスターの数が増えると、平均分散は小さくなります(k = nおよびvariance = 0 の自明なケースまで)。
データ分析ではいつものように、すべてのケースで他のすべての方法よりも優れた真のアプローチはありません。結局、あなたはあなた自身の最高の判断を使わなければなりません。そのためには、平均分散に対するクラスターの数をプロットするのに役立ちます(kのいくつかの値に対して既にアルゴリズムを実行していると想定しています)。次に、カーブの膝でクラスタの数を使用できます。
はい、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")
それが役に立てば幸い!!
コード例を探している私のような初心者かもしれません。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)
経験則と呼ばれるものがあります。クラスターの数は、
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
これが役に立てば幸いです!
最初に、データの最小全域木を構築します。K-1の最も高価なエッジを削除すると、ツリーがK個のクラスターに分割される
ため、MSTを一度構築し、さまざまなKのクラスター間隔/メトリックを確認して、曲線の膝をつかむことができます。
これはSingle-linkage_clusteringでのみ機能しますが、高速で簡単です。さらに、MSTは優れたビジュアルを実現します。
たとえば、クラスタリング用のstats.stackexchange視覚化ソフトウェアの下のMSTプロットを参照してください
。
誰もこの優れた記事に言及していないことに驚いています: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]]
}
クラスターの数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、ソース2、source3
私はここで見つけた解決策を使用しました: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つは、遺伝的アルゴリズムのようなメタヒューリスティックアルゴリズムを使用してkを見つけることです。それは簡単です。ランダムなK(ある範囲内)を使用して、シルエットのような測定で遺伝的アルゴリズムのフィット関数を評価し、フィット関数に基づいて最良のKベースを見つけることができます。
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})
別のアプローチは、自己組織化マップ(SOP)を使用して最適なクラスター数を見つけることです。SOM(自己組織化マップ)は、教師なしのニューラルネットワーク手法であり、問題解決のためのクラスタリングに入力のみを使用する必要があります。このアプローチは、顧客のセグメンテーションに関する論文で使用されています。
論文の参考文献は
Abdellah Amine他、クラスタリング手法とLRFMモデルを使用した電子商取引における顧客セグメンテーションモデル:モロッコのオンラインストアのケース、世界科学技術アカデミージャーナルコンピューターと情報工学Vol.9、No:8 、2015、1999〜2010
こんにちは私はそれを説明するのを簡単でまっすぐにするつもりです、私は「NbClust」ライブラリーを使用してクラスターを決定したいです。
ここで、「NbClust」関数を使用して正しい数のクラスターを決定する方法:Githubで実際のプロジェクトを実際のデータとクラスターで確認できます-この「kmeans」アルゴリズムの拡張は、正しい数の「中心」を使用して実行されました。
Githubプロジェクトリンク:https : //github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook
クラスターの数は、データポイントを視覚的に調べることで選択できますが、最も単純なデータセットを除くすべてのプロセスで、このプロセスには多くのあいまいさが存在することがすぐにわかります。これは常に悪いことではありません。教師なし学習を行っているため、ラベル付けプロセスには固有の主観性があるためです。ここでは、その特定の問題または類似したもので以前に経験を持っていると、正しい値を選択するのに役立ちます。
使用する必要があるクラスターの数に関するヒントが必要な場合は、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を計算することになります。
私はひざまずいた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)