- #Autor: Mateusz Bieniek
- euclid <- function(x1,x2)
- {
- return(sqrt(rowSums((x1-x2)^2)))
- }
- rand_points <- function(data, k)
- {
- return(sample(1:dim(data)[1],k))
- }
- max_distance <- function(data, k)
- {
- n <- dim(data)[1]
- compare <- matrix(0,n,n)
- for (i in 1:n) # od 1 do n punktow
- {
- for (j in 2:n) # od 2 do n
- {
- compare[i,j] <- euclid(data[i,],data[j,]) #pierwszy punkt z drugim, pierwszy z trzecim itd
- }
- }
- pair <- which(compare==max(compare), arr.ind = TRUE)[1,]
- #po wyborze najbardziej oddalonej od siebie pary zostaja wybrane (jesli to konieczne) kolejne punkty
- #pierwszenstwo ma punkt najbardziej oddalony od ktoregos z pary
- compare1 <- matrix(0, 2, n)
- compare1[1,] <- compare[pair[1],]
- compare1[1,pair[2]] <- 0
- compare1[2,] <- compare[pair[2],]
- compare1[2,pair[1]] <- 0
- compare1 <- colSums(compare1)
- result <- c(pair)
- if(k==2) return(result)
- result[1:2] <- c(pair)
- for (l in 1 : (k-2))
- {
- result[l+2]<-which(compare1==max(compare1), arr.ind = TRUE)
- compare1[result[l+2]] <- 0
- }
- return(result)
- }
- k_means_test <- function(data, k, max_iter, fn, dim, method)
- #k - liczba klastrow, fn - funkcja celu
- {
- # losowanie punktow poczatkowych
- cat("\ndane wejsciowe:\n")
- print(data)
- if(method == "max_distance")
- {
- cat("\nwybrano metode najbardziej oddalonych punktow poczatkowych\n")
- points <- max_distance(data,k)
- }
- else
- {
- cat("\nwybrano metode losowego wyboru punktow poczatkowych\n")
- points <- rand_points(data,k)
- }
- clusters <- data[points,1:dim]
- data[,dim+1]<-c(0)
- cat("\nklastry poczatkowe \n")
- print(clusters)
- cat("\nklastry zostaly wybrane sposrod punktow: \n")
- print(data)
- #do kazdego klastra zostana przypisane najblizej lezace punkty
- #dla kazdego punktu obliczane sa odleglosci od wszystkich klastrow
- #punkt przypisywany jest do najblizszego klastra jesli spelnia warunki
- clustlist = list() #inicjalizacja listy na macierze klastrow
- w = list()
- s = list()
- for (i in 1:max_iter)
- {
- for (j in 1:k) #petla po wszystkich klastrach
- {
- # macierz klastrow
- clustlist[[j]] <- t(matrix(clusters[j,1:dim],dim,dim(data)[1]))
- w[[j]]<-euclid(data[,1:dim],unlist(clustlist[[j]]))
- }
- y<-matrix(unlist(w),dim(data)[1],k) #macierz odleglosci punktow od klastrow
- cat("\nMacierz odleglosci punktow od klastrow\n")
- print(y)
- for (l in 1:dim(data)[1])
- {
- near <- which.min(y[l,]) # ktoremu klastrowi najblizszy jest dany punkt
- # obliczenie nowego klastra po dodaniu tego punktu
- # algorytm nie bierze pod uwage punktow, ktore sa juz w danym klastrze
- if(i == 1 | (data[l,dim+1] != near))
- {
- ncenter <- ((clusters[near,] + data[l,1:D])/D)
- ncenter <-unlist(ncenter)
- # warunek dodania punktu do klastra
- if (fn(ncenter) <= fn(unlist(clusters[near,])))
- {
- data[l,dim+1]<-which.min(y[l,]) # przypisanie numeru klastra
- }
- else
- {
- data[l,dim+1]<-10 #w.p.p przypisanie nieuzywanego klastra lub nie przypisanie zadnego klastra
- }
- }
- }
- colnames(data)[dim+1] <- "klaster"
- # wybor nowych srodkow klastrow
- old_clusters <- clusters
- for (m in 1:k)
- {
- u = data[data$klaster == m,]
- clusters[m,] <- colSums(u[1:dim])/dim(u)[1]
- }
- #jesli klastry nie zmieniaja sie nastepuje zatrzymanie algorytmu
- if(sum(old_clusters - clusters, na.rm=TRUE) == 0 )
- {
- cat("wykonane iteracje: ", i)
- cat("\nkoncowe klastry\n")
- print(clusters)
- #moze sie zdarzyc, iz powstanie pusty klaster
- if(is.nan(sum(clusters)))
- {
- print("przynajmniej jeden z klastrow jest pusty")
- }
- data2 <- list(data, clusters)
- return(data2)
- }
- print("nowe klastry")
- print(clusters)
- cat("\nPunkty wraz z przypisanymi im klastrami po ", i)
- cat(" iteracjach\n")
- print(data)
- data2 <- list(data, clusters)
- }
- return(data2)
- }