Я изучал кластеризацию k-средних , и одна вещь, которая не совсем ясна, это то, как вы выбираете значение k. Это просто вопрос проб и ошибок, или есть что-то еще?
R
) здесь: stackoverflow.com/a/15376462/1036500
Я изучал кластеризацию k-средних , и одна вещь, которая не совсем ясна, это то, как вы выбираете значение k. Это просто вопрос проб и ошибок, или есть что-то еще?
R
) здесь: stackoverflow.com/a/15376462/1036500
Ответы:
Вы можете максимально увеличить Байесовский информационный критерий (BIC):
BIC(C | X) = L(X | C) - (p / 2) * log n
где L(X | C)
- логарифмическая вероятность набора данных в X
соответствии с моделью C
, p
это число параметров в модели C
и n
количество точек в наборе данных. См. «X-means: расширение K- средних с эффективной оценкой числа кластеров» Дана Пеллега и Эндрю Мура в ICML 2000.
Другой подход заключается в том, чтобы начать с большого значения k
и продолжать удалять центроиды (уменьшая k) до тех пор, пока оно не уменьшит длину описания. См. «Принцип MDL для надежного векторного квантования» Хорста Бишофа, Алеся Леонардиса и Александра Селба в « Анализ образцов и приложения», вып. 2, стр. 59-72, 1999.
Наконец, вы можете начать с одного кластера, а затем продолжать разбивать кластеры, пока точки, назначенные каждому кластеру, не будут иметь гауссово распределение. В «Изучение k в k- средних» (NIPS 2003) Грег Хамерли и Чарльз Элкан показывают некоторые доказательства того, что это работает лучше, чем BIC, и что BIC недостаточно сильно наказывает за сложность модели.
По сути, вы хотите найти баланс между двумя переменными: количеством кластеров ( k ) и средней дисперсией кластеров. Вы хотите минимизировать первое, а также минимизировать второе. Конечно, с увеличением количества кластеров средняя дисперсия уменьшается (вплоть до тривиального случая k = n и дисперсии = 0).
Как всегда в анализе данных, не существует единственного правильного подхода, который работал бы лучше всех остальных во всех случаях. В конце концов, вы должны принять собственное суждение. Для этого полезно построить график зависимости числа кластеров от средней дисперсии (что предполагает, что вы уже запустили алгоритм для нескольких значений k ). Тогда вы можете использовать количество кластеров в колене кривой.
Да, вы можете найти наилучшее количество кластеров, используя метод Elbow, но я обнаружил, что найти значение кластеров по графу колен с помощью скрипта проблематично. Вы можете наблюдать за графиком локтя и найти точку локтя самостоятельно, но было очень сложно найти его по сценарию.
Так что другой вариант - использовать 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")
Надеюсь, поможет!!
Может быть кто-то вроде меня, начинающий, ищет пример кода. информация для 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 в k-средних». Он использует тест Гаусса, чтобы определить правильное количество кластеров. Кроме того, авторы утверждают, что этот метод лучше, чем BIC, который упоминается в принятом ответе.
Есть нечто, называемое «Правило большого пальца». Это говорит о том, что количество кластеров может быть рассчитано
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
Надеюсь, это поможет!
Сначала создайте минимальное связующее дерево ваших данных. Удаление K-1 самых дорогих ребер разделяет дерево на K кластеров,
так что вы можете построить MST один раз, посмотреть на расстояния / метрики кластеров для различных K и взять колено кривой.
Это работает только для Single-linkage_clustering , но для этого это быстро и просто. Кроме того, MST делают хорошие визуальные эффекты.
См., Например, график MST в разделе
stats.stackexchange для визуализации программного обеспечения для кластеризации .
Я удивлен, что никто не упомянул эту прекрасную статью: 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]]
}
Если вы используете MATLAB, любую версию начиная с 2013b, то есть вы можете использовать функцию, evalclusters
чтобы выяснить, какой должна k
быть оптимальность для данного набора данных.
Эта функция позволяет выбрать один из 3 -х алгоритмов кластеризации - kmeans
, linkage
и gmdistribution
.
Она также позволяет выбрать один из 4 кластеризации критериев оценки - CalinskiHarabasz
, DaviesBouldin
, gap
и silhouette
.
Если вы не знаете номера кластеров 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
Я использовал решение, которое нашел здесь: 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()
Моя идея состоит в том, чтобы использовать Силуэт Коэффициент, чтобы найти оптимальный номер кластера (K). Подробности объяснения здесь .
Предполагая, что у вас есть названная матрица данных DATA
, вы можете выполнить разбиение по медоидам с оценкой количества кластеров (с помощью анализа силуэтов) следующим образом:
library(fpc)
maxk <- 20 # arbitrary here, you can set this to whatever you like
estimatedK <- pamk(dist(DATA), krange=1:maxk)$nc
Один из возможных ответов - использовать метаэвристический алгоритм, такой как генетический алгоритм, чтобы найти k. Это просто Вы можете использовать случайный K (в некотором диапазоне) и оценить функцию подбора Генетического алгоритма с помощью некоторого измерения, такого как Silhouette And Find best 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 (самоорганизующаяся карта) - это методология нейронной сети без надзора, для которой требуется только вход, используемый для кластеризации для решения проблем. Этот подход используется в статье о сегментации клиентов.
Ссылка на статью
Абделла Амин и др., Модель сегментации клиентов в электронной торговле с использованием методов кластеризации и модели LRFM: пример интернет-магазинов в Марокко, Всемирная академия наук, инженерии и технологии Международный журнал по вычислительной технике и информатике, том 9, № 8 , 2015, 1999 - 2010
Привет, я сделаю это просто и понятно, мне нравится определять кластеры, используя библиотеку 'NbClust'.
Теперь, как использовать функцию «NbClust» для определения правильного количества кластеров: вы можете проверить фактический проект в Github с фактическими данными и кластерами - расширение этого алгоритма «kmeans» также выполняется с использованием правильного количества «центров».
Ссылка на проект Github: https://github.com/RutvijBhutaiya/Thailand-Customer-Engagement-Facebook
Вы можете выбрать количество кластеров, визуально осмотрев свои точки данных, но вскоре вы поймете, что в этом процессе много неопределенности для всех, кроме самых простых наборов данных. Это не всегда плохо, потому что вы занимаетесь обучением без присмотра, и в процессе маркировки есть некоторая внутренняя субъективность. Здесь, имея предыдущий опыт решения этой конкретной проблемы или чего-то подобного, вы сможете выбрать правильное значение.
Если вы хотите получить некоторую подсказку о количестве кластеров, которые вам следует использовать, вы можете применить метод Elbow:
Прежде всего, вычислите сумму квадратов ошибок (SSE) для некоторых значений k (например, 2, 4, 6, 8 и т. Д.). SSE определяется как сумма квадратов расстояния между каждым членом кластера и его центроидом. Математически:
SSE = ΣKi = 1Σx∈cidist (х, CI) 2
Если вы построите график k по отношению к SSE, вы увидите, что ошибка уменьшается с увеличением k; Это связано с тем, что когда количество кластеров увеличивается, они должны быть меньше, поэтому искажения также меньше. Идея метода локтя состоит в том, чтобы выбрать k, при котором SSE резко уменьшается. Это создает «эффект локтя» на графике, как вы можете видеть на следующем рисунке:
В этом случае k = 6 - это значение, выбранное методом Elbow. Примите во внимание, что метод Elbow является эвристическим и, как таковой, он может или не может хорошо работать в вашем конкретном случае. Иногда бывает больше одного локтя или совсем нет локтя. В этих ситуациях вы обычно заканчиваете тем, что вычисляете наилучшее k, оценивая, насколько хорошо k-means работает в контексте конкретной проблемы кластеризации, которую вы пытаетесь решить.
Я работал над пакетным пакетом Python (алгоритм Kneedle). Он находит номер кластера динамически как точку, где кривая начинает выравниваться. При заданном наборе значений x и 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]
х = диапазон (1, лен (у) +1)
из коленного импорта KneeLocator kn = KneeLocator (x, y, кривая = «выпуклая», направление = «убывающая»)
печать (kn.knee)