Разве неидентичное недостаточно для того, чтобы считаться «отличным» для центроидов kmeans? - PullRequest
0 голосов
/ 02 мая 2020

У меня проблема с кластеризацией kmeans, предоставляющей центроиды. Я видел ту же проблему, которую уже задавали ( K-означает: начальные центры не различимы ), но решение в этом посте не работает в моем случае.

Я выбрал центроиды, используя ClusterR::Kmeans_arma. Я подтвердил, что мои центроиды не идентичны при использовании mgcv::uniquecombs, но все равно получил ошибку initial centers are not distinct.

> dim(t(dat))
[1] 13540 11553
> centroids = ClusterR::KMeans_arma(data = t(dat), centers = 561, 
                                    n_iter = 50, seed_mode = "random_subset",
                                    verbose = FALSE, CENTROIDS = NULL)
> dim(centroids)
[1]   561 11553
> x = mgcv::uniquecombs(centroids)
> dim(x)
[1]   561 11553
> res = kmeans(t(dat), centers = centroids, iter.max = 200)
Error in kmeans(t(dat), centers = centroids, iter.max = 200) : 
  initial centers are not distinct

Есть какие-либо предложения по решению этой проблемы? Спасибо!

1 Ответ

0 голосов
/ 03 мая 2020

Я повторил проблему, о которой вы упомянули, со следующими данными:

    cols = 13540
    rows = 11553

    set.seed(1)
    vec_dat = runif(rows * cols)

    dat = matrix(vec_dat, nrow = rows, ncol = cols)
    dim(dat)

    dat = t(dat)
    dim(dat)

В функции ClusterR :: KMeans_arma () 'нет параметра' центров ', поэтому я предположил, что вы фактически означают «кластеры»,

centroids = ClusterR::KMeans_arma(data = dat, 
                                  clusters = 561,                
                                  n_iter = 50,
                                  seed_mode = "random_subset",
                                  verbose = TRUE, 
                                  CENTROIDS = NULL)

str(centroids)
dim(centroids)

«Центроиды» представляют собой матрицу класса «кластеризация k-средних». Если вы намереваетесь прийти в кластеры, вы можете использовать

clust = ClusterR::predict_KMeans(data = dat, 
                                 CENTROIDS = centroids, 
                                 threads = 6)
length(unique(clust))    # 561

class(centroids)   # "k-means clustering"

Если вы хотите передать центроиды функции base R 'kmeans', вам нужно установить класс класса объект 'centroids' равен NULL, и это потому, что базовая функция R 'kmeans' внутренне использует функцию base 'duplicated ()' (вы можете просмотреть это с помощью print (kmeans) в консоли R), которая не распознает центроиды 'объект как матрица или data.frame (это объект класса "кластеризация k-средних") и выполняет проверку по столбцам, а не по строкам. Таким образом, для вашего случая должно работать следующее:

class(centroids) = NULL

dups = duplicated(centroids)
sum(dups)                        # this should actually give 0

res = kmeans(dat, centers = centroids, iter.max = 200)

Я внес несколько корректировок в ClusterR :: Foregnetic_KMeans () и, в частности, добавил параметр «threads» и проверку поэтому для дубликатов, если вы хотите прийти в кластеры с несколькими ядрами, вам необходимо установить пакет из Github, используя

remotes::install_github('mlampros/ClusterR', 
                        upgrade = 'always', 
                        dependencies = TRUE, 
                        repos = 'https://cloud.r-project.org/')

Изменения вступят в силу в следующей версии пакета CRAN, которая будет «1.2.2»


ОБНОВЛЕНИЕ относительно производительности и производительности (на основе вашего комментария):

data(dietary_survey_IBS, package = 'ClusterR')

kmeans_arma = function(data) {

  km_cl = ClusterR::KMeans_arma(data, 
                                clusters = 2, 
                                n_iter = 10, 
                                seed_mode = "random_subset",
                                seed = 1)

  pred_cl = ClusterR::predict_KMeans(data = data,
                                     CENTROIDS = km_cl,
                                     threads = 1)

  return(pred_cl)
}

km_arma = kmeans_arma(data = dietary_survey_IBS)



km_algos = c("Hartigan-Wong", "Lloyd", "Forgy", "MacQueen")

for (algo in km_algos) {

  cat('base-kmeans-algo:', algo, '\n')

  km_base = kmeans(dietary_survey_IBS, 
                   centers = 2,
                   iter.max = 10,
                   nstart = 1,                     # can be set to 5 or 10 etc.
                   algorithm = algo)

  km_cl = as.vector(km_base$cluster)

  print(table(km_arma, km_cl))
  cat('--------------------------\n')
}


microbenchmark::microbenchmark(kmeans(dietary_survey_IBS, 
                                      centers = 2,
                                      iter.max = 10,
                                      nstart = 1,                     # can be set to 5 or 10 etc.
                                      algorithm = algo), kmeans_arma(data = dietary_survey_IBS), times = 100)

Не знаю Мы не видим существенной разницы в выходных кластерах между функцией 'base R kmeans' и функцией 'kmeans_arma' для всех доступных алгоритмов 'base R kmeans' (вы можете проверить это также для ваших собственных наборов данных). Я не уверен, какой алгоритм внутренне использует библиотека 'armadillo', кроме того, 'base R kmeans' включает параметр 'nstart' (вы можете обратиться к документации для получения дополнительной информации). Что касается производительности, вы не увидите каких-либо существенных различий для небольших и средних наборов данных, но из-за того, что библиотека armadillo использует OpenMP внутри, если ваш компьютер имеет более 1 ядра, чем для больших наборов данных, я думаю, что 'ClusterR :: Функция KMeans_arma 'вернет' центроиды 'быстрее.

...