web-dev-qa-db-fra.com

K-Means: Lloyd, Forgy, MacQueen, Hartigan-Wong

Je travaille avec l'algorithme K-Means dans R et je veux comprendre les différences entre les 4 algorithmes Lloyd, Forgy, MacQueen et Hartigan-Wong disponibles pour la fonction "kmeans" dans le paquetage stats.

Cependant, j'ai eu la chance d'obtenir une réponse suffisante à cette question.

Je n'ai trouvé que rarement des informations: (Visitez http://fr.wikibooks.org/wiki/Data_Mining_Algorithms_In_R/Clustering/K-Means )

De cette description, Lloyd, Forgy et Hartigan-Wong me semblent identiques. Minimiser la somme des carrés ou Minimiser la distance euclidienne est la même chose.

MacQueen est différent dans le cas où il met à jour les deux clusters impliqués si un objet est déplacé vers un autre cluster si j'ai raison.

Néanmoins, je ne vois toujours pas en quels points ces algorithmes sont différents.

23
user2974776

R fournit l'algorithme de Lloyd en tant qu'option pour kmeans (); l'algorithme par défaut, par Hartigan et Wong (1979) est beaucoup plus intelligent. Comme l'algorithme de MacQueen (MacQueen, 1967), Met à jour les centroïdes chaque fois qu'un point est déplacé; il fait également des choix astucieux (permettant de gagner du temps) lors de la recherche du groupe le plus proche. D'autre part, l'algorithme k-means de Lloyd est le premier et le plus simple de tous ces algorithmes de classification.

L'algorithme de Lloyd (Lloyd, 1957) prend un ensemble d'observations ou de cas (pensez: des lignes de la matrice n_an, ou des points dans les réels) et les regroupe en groupes k. Il essaie de minimiser la somme de carrés À l'intérieur d'une grappe enter image description here

où u_i est la moyenne de tous les points de la grappe S_i. L'algorithme se déroule comme suit (je vous épargne la formalité de la notation exhaustive): enter image description here

Cependant, il y a un problème avec la mise en œuvre de R et le problème se pose lorsque Considère plusieurs points de départ. Il convient de noter qu’il est généralement prudent de considérer plusieurs points de départ différents, car il est garanti que l’algorithme converge, mais ne garantit pas une couverture optimale. Cela est particulièrement vrai pour les grands problèmes De grande dimension. Je commencerai par un exemple simple (grand, pas particulièrement difficile?).

(Ici, je vais coller quelques images car nous ne pouvons pas écrire de formules mathématiques avec du latex)

enter image description hereenter image description hereenter image description hereenter image description here

Notez que la solution est très similaire à celle obtenue précédemment, bien que l'ordre des clusters Soit arbitraire. Plus important encore, le travail n'a pris que 0.199 secondes en parallèle! Cela est sûrement trop beau pour être vrai: l’utilisation de 3 cœurs de processeur devrait, au mieux, prendre le tiers du temps De notre première exécution (séquentielle). Est-ce un problème? Cela ressemble à un repas gratuit. Il n’ya pas de problème avec un déjeuner gratuit de temps en temps, n’est-ce pas?

enter image description here

Cela ne fonctionne pas toujours avec les fonctions R, mais nous avons parfois l'occasion de regarder directement au code. C'est l'une de ces fois. Je vais mettre ce code dans un fichier, mykmeans.R, Et le modifier à la main, en insérant des instructions cat () à différents endroits. Voici un moyen astucieux de le faire, en utilisant sink () (bien que cela ne semble pas fonctionner dans Sweave, cela fonctionnera de manière interactive):

> sink("mykmeans.R")
> kmeans
> sink()

Maintenant, éditez le fichier, changez le nom de la fonction et ajoutez des instructions cat (). Remarque Vous devez également supprimer une dernière ligne:

enter image description here

Nous pouvons ensuite répéter nos explorations, mais en utilisant mykmeans ():

> source("mykmeans.R")
> start.kmeans <- proc.time()[3]
> ans.kmeans <- mykmeans(x, 4, nstart = 3, iter.max = 10, algorithm = "Lloyd")
JJJ statement 1: 0 elapsed time.
JJJ statement 5: 2.424 elapsed time.
JJJ statement 6: 2.425 elapsed time.
JJJ statement 7: 2.52 elapsed time.
JJJ statement 6: 2.52 elapsed time.
JJJ statement 7: 2.563 elapsed time.

enter image description here

Maintenant, nous sommes en affaires: la plupart du temps a été consommé avant la déclaration 5 (je le savais bien sûr. C'est pourquoi la déclaration 5 était 5 plutôt que 2) ........ Vous pouvez continuer à jouer avec.

Voici le code:

#######################################################################
# kmeans()

N <- 100000
x <- matrix(0, N, 2)
x[seq(1,N,by=4),] <- rnorm(N/2)
x[seq(2,N,by=4),] <- rnorm(N/2, 3, 1)
x[seq(3,N,by=4),] <- rnorm(N/2, -3, 1)
x[seq(4,N,by=4),1] <- rnorm(N/4, 2, 1)
x[seq(4,N,by=4),2] <- rnorm(N/4, -2.5, 1)
start.kmeans <- proc.time()[3]
ans.kmeans <- kmeans(x, 4, nstart=3, iter.max=10, algorithm="Lloyd")
ans.kmeans$centers
end.kmeans <- proc.time()[3]
end.kmeans - start.kmeans

these <- sample(1:nrow(x), 10000)
plot(x[these,1], x[these,2], pch=".")
points(ans.kmeans$centers, pch=19, cex=2, col=1:4)

library(foreach)
library(doMC)
registerDoMC(3)
start.kmeans <- proc.time()[3]
ans.kmeans.par <- foreach(i=1:3) %dopar% {
  return(kmeans(x, 4, nstart=1, iter.max=10, algorithm="Lloyd"))
}
TSS <- sapply(ans.kmeans.par, function(a) return(sum(a$withinss)))
ans.kmeans.par <- ans.kmeans.par[[which.min(TSS)]]
ans.kmeans.par$centers
end.kmeans <- proc.time()[3]
end.kmeans - start.kmeans

sink("mykmeans.Rfake")
kmeans
sink()

source("mykmeans.R")
start.kmeans <- proc.time()[3]
ans.kmeans <- mykmeans(x, 4, nstart=3, iter.max=10, algorithm="Lloyd")
ans.kmeans$centers
end.kmeans <- proc.time()[3]
end.kmeans - start.kmeans

#######################################################################
# Diving

x <- read.csv("Diving2000.csv", header=TRUE, as.is=TRUE)
library(YaleToolkit)
whatis(x)

x[1:14,c(3,6:9)]

meancol <- function(scores) {
  temp <- matrix(scores, length(scores)/7, ncol=7)
  means <- apply(temp, 1, mean)
  ans <- rep(means,7)
  return(ans)
}
x$panelmean <- meancol(x$JScore)

x[1:14,c(3,6:9,11)]

meancol <- function(scores) {
  browser()
  temp <- matrix(scores, length(scores)/7, ncol=7)
  means <- apply(temp, 1, mean)
  ans <- rep(means,7)
  return(ans)
}

x$panelmean <- meancol(x$JScore)

Voici la description:

Number of cases: 10,787 scores from 1,541 dives (7 judges score each
dive) performed in four events at the 2000 Olympic Games in Sydney,
Australia.

Number of variables: 10.

Description: A full description and analysis is available in an
article in The American Statistician (publication details to be
announced).

Variables:

Event       Four events, men's and women's 3M and 10m.
Round       Preliminary, semifinal, and final rounds.
Diver       The name of the diver.
Country     The country of the diver.
Rank        The final rank of the diver in the event.
DiveNo      The number of the dive in sequence within round.
Difficulty  The degree of difficulty of the dive.
JScore      The score provided for the judge on this dive.
Judge       The name of the judge.
JCountry    The country of the judge.

Et un jeu de données à expérimenter https://www.dropbox.com/s/urgzagv0a22114n/Diving2000.csv

24
cMinor

Goto page 16-
Ceci a une explication claire de Gorgy/Llyods, MacQueen, Hatigan-Wong algos. 

https://core.ac.uk/download/pdf/27210461.pdf

1
Arpit Sisodia