Как определить k при использовании кластеризации k-mean?

Я изучал k-mean clustering, и одна вещь, которая неясно, - это то, как вы выбираете значение k. Это просто вопрос проб и ошибок, или это еще не так?

Ответ 1

Вы можете максимизировать байесовский информационный критерий (BIC):

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

где L(X | C) - лог-правдоподобие набора данных X по модели C, p - количество параметров в модели C, а n - количество точек в набор данных. См. "X-означает: расширение K - средство с эффективной оценкой количества кластеров" Дэн Пеллег и Эндрю Мур в ICML 2000.

Другой подход - начать с большого значения для k и продолжать удалять центроиды (уменьшение k), пока оно больше не уменьшит длину описания. См. "Принцип MDL для надежного векторного квантования" Хорста Бишофа, Алеса Леонардиса и Александра Селба в анализе и применении шаблонов vol. 2, p. 59-72, 1999.

Наконец, вы можете начать с одного кластера, а затем продолжать разбивать кластеры, пока точки, назначенные для каждого кластера, не будут распределены по Гаусу. В "Изучение k в k-значении" (NIPS 2003) Грег Хамерли и Чарльз Элькан показывают некоторые доказательства того, что это работает лучше, чем BIC, и что BIC не слишком сильно оценивает сложность модели.

Ответ 2

В принципе, вы хотите найти баланс между двумя переменными: количеством кластеров (k) и средней дисперсией кластеров. Вы хотите свести к минимуму первое, а также минимизировать последнее. Конечно, по мере увеличения количества кластеров средняя дисперсия уменьшается (вплоть до тривиального случая k = n и дисперсии = 0).

Как всегда в анализе данных, нет ни одного истинного подхода, который бы работал лучше всех остальных во всех случаях. В конце концов, вы должны использовать свое собственное суждение. Для этого он помогает построить число кластеров против средней дисперсии (которая предполагает, что вы уже выполнили алгоритм для нескольких значений k). Затем вы можете использовать количество кластеров в колене кривой.

Ответ 3

Да, вы можете найти лучшее количество кластеров, используя метод Elbow, но мне было трудно найти значение кластеров из локтевого графа с помощью script. Вы можете наблюдать график локтя и находить локтевую точку самостоятельно, но это было много работы, чтобы найти его от script.

Так что еще один вариант - использовать Silhouette Method, чтобы найти его. Результат от Silhouette полностью соответствует результату метода Elbow в R.

Вот что я сделал.

#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")

Надеюсь, что это поможет!

Ответ 4

Может быть кто-то вроде меня, начинающий, ищет пример кода. информация для 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)

Ответ 5

Посмотрите на эту статью "Изучение k в k-средних" Грега Хамерли, Чарльза Элкана. Он использует тест Гаусса, чтобы определить правильное количество кластеров. Кроме того, авторы утверждают, что этот метод лучше, чем BIC, который упоминается в принятом ответе.

Ответ 6

Есть нечто, называемое "Правило большого пальца". Это говорит о том, что количество кластеров можно рассчитать с помощью

k = (n/2)^0.5

где n - общее количество элементов в вашем образце. Вы можете проверить достоверность этой информации на следующей бумаге:

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

Есть также еще один метод, называемый G-means, где ваше распределение следует гауссову распределению или нормальному распределению. Он состоит из увеличения k до тех пор, пока все ваши k группы не будут следовать распределению Гаусса. Это требует много статистики, но может быть сделано. Вот источник:

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

Надеюсь, это поможет!

Ответ 7

Сначала создайте минимальное остовное дерево ваших данных. Удаление самых дорогих кромок K-1 разбивает дерево на кластеры K,
поэтому вы можете построить MST один раз, посмотрите на кластерные расстояния/метрики для разных K, и возьмите колено кривой.

Это работает только для Single-linkage_clustering, но для этого это быстро и просто. Кроме того, MST создают хорошие визуальные эффекты.
См., Например, график MST в разделе программное обеспечение визуализации stats.stackexchange для кластеризации.

Ответ 8

Если вы используете MATLAB, любую версию с 2013 года, то вы можете использовать функцию evalclusters, чтобы узнать, какой должен быть оптимальный k для данного набора данных.

Эта функция позволяет выбрать один из 3 алгоритмов кластеризации - kmeans, linkage и gmdistribution.

Он также позволяет выбрать один из 4 критериев оценки кластеризации - CalinskiHarabasz, DaviesBouldin, gap и silhouette.

Ответ 9

Я удивлен, что никто не упомянул эту замечательную статью: 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]]
}

Ответ 10

Моя идея - использовать Силуэт-коэффициент, чтобы найти оптимальное количество кластеров (K). Подробное объяснение здесь.

Ответ 11

Предполагая, что у вас есть матрица данных с именем DATA, вы можете выполнить разбиение на медоиды с оценкой количества кластеров (по анализу силуэта) следующим образом:

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

Ответ 12

Один из возможных ответов - использовать метаэвристический алгоритм, такой как генетический алгоритм, чтобы найти k. Так просто. вы можете использовать случайный K (в некотором диапазоне) и оценивать функцию соответствия генетического алгоритма с некоторыми измерениями, такими как Silhouette И найдите лучшую K-базу по подходящей функции.

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

Ответ 13

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})

Ответ 14

Другой подход заключается в использовании самоорганизующихся карт (SOP) для поиска оптимального количества кластеров. SOM (самоорганизующаяся карта) - это методология нейронной сети без надзора, для которой требуется только вход, используемый для кластеризации для решения проблем. Этот подход используется в статье о сегментации клиентов.

Ссылка на статью

Абделла Амин и др., Модель сегментации клиентов в электронной коммерции с использованием методов кластеризации и модели LRFM: пример интернет-магазинов в Марокко, Всемирная академия наук, инженерии и технологий Международный журнал по вычислительной технике и информатике, том 9, № 8, 2015, 1999 - 2010

Ответ 15

Если вы не знаете номера кластеров k, чтобы предоставить их в качестве параметра для k-средних, есть четыре способа найти их автоматически:

  • Алгоритм G-средних: он определяет количество кластеров автоматически, используя статистический тест, чтобы решить, следует ли разбивать центр k-средних на два. Этот алгоритм использует иерархический подход для определения количества кластеров, основанный на статистической проверке гипотезы о том, что подмножество данных следует гауссову распределению (непрерывная функция, которая приближается к точному биномиальному распределению событий), и если нет, то оно разделяет кластер, Он начинается с небольшого числа центров, скажем, только один кластер (k = 1), затем алгоритм разбивает его на два центра (k = 2) и снова разбивает каждый из этих двух центров (k = 4), имея четыре центра в Всего. Если G-среднее не принимает эти четыре центра, то ответом является предыдущий шаг: два центра в этом случае (k = 2). Это количество кластеров, на которые будет разделен ваш набор данных. G-means очень полезен, когда у вас нет оценки количества кластеров, которые вы получите после группировки ваших экземпляров. Обратите внимание, что неудобный выбор параметра "k" может привести к неверным результатам. Параллельная версия g-средних называется р-средними. Источники G-средних: источник 1, источник 2, источник 3

  • x-означает: новый алгоритм, который эффективно ищет пространство местоположений кластеров и количество кластеров для оптимизации байесовского критерия информации (BIC) или показателя информационного критерия Акаике (AIC). Эта версия k-средних находит число k, а также ускоряет k-средние.

  • K-средства онлайн или потоковые k-средства: он позволяет выполнить k-средства путем сканирования всех данных один раз и автоматически находит оптимальное число k. Spark реализует это.

  • Алгоритм MeanShift: это непараметрическая методика кластеризации, которая не требует предварительного знания количества кластеров и не ограничивает форму кластеров. Кластеризация со средним сдвигом направлена на обнаружение "пятен" в гладкой плотности образцов. Это алгоритм, основанный на центроидах, который работает, обновляя кандидатов на центроиды, чтобы они были средними точками в данном регионе. Эти кандидаты затем фильтруются на этапе последующей обработки, чтобы исключить почти дубликаты, чтобы сформировать окончательный набор центроидов. Источники: источник1, источник2, источник3

Ответ 16

Я использовал решение, которое нашел здесь: 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

Ответ 17

Большое спасибо. Пытаясь соединить все решения и найти лучший способ найти к.

Ответ 18

Привет, я сделаю это просто и понятно, мне нравится определять кластеры, используя библиотеку NbClust.

Теперь, как использовать функцию "NbClust" для определения правильного количества кластеров: вы можете проверить фактический проект в Github с фактическими данными и кластерами - расширение этого алгоритма "kmeans" также выполняется с использованием правильного количества "центров".

Ссылка на проект Github: https://github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook