Optimizing K-means clustering using Genetic Algori

2019-06-11 11:08发布

问题:

I have the following dataset (obtained here):

----------item survivalpoints weight
1  pocketknife             10      1
2        beans             20      5
3     potatoes             15     10
4       unions              2      1
5 sleeping bag             30      7
6         rope             10      5
7      compass             30      1

I can cluster this dataset into three clusters with kmeans() using a binary string as my initial choice of centers. For eg:

## 1 represents the initial centers
chromosome = c(1,1,1,0,0,0,0)
## exclude first column (kmeans only support continous data)
cl <- kmeans(dataset[, -1], dataset[chromosome == 1, -1])
## check the memberships
cl$clusters
# [1] 1 3 3 1 2 1 2

Using this fundamental concept, I tried it out with GA package to conduct the search where I am trying to optimize(minimize) Davies-Bouldin (DB) Index.

library(GA)           ## for ga() function
library(clusterSim)   ## for index.DB() function

## defining my fitness function (Davies-Bouldin)
DBI <- function(x) {
        ## converting matrix to vector to access each row
        binary_rep <- split(x, row(x))
        ## evaluate the fitness of each chromsome
        for(each in 1:nrow(x){
            cl <- kmeans(dataset, dataset[binary_rep[[each]] == 1, -1])
            dbi <- index.DB(dataset, cl$cluster, centrotypes = "centroids")
            ## minimizing db
            return(-dbi)
    }
}

g<- ga(type = "binary", fitness = DBI, popSize = 100, nBits = nrow(dataset))

Of course (I have no idea what's happening), I received error message of Warning messages: Error in row(x) : a matrix-like object is required as argument to 'row'

Here are my questions:

  1. How can correctly use the GA package to solve my problem?
  2. How can I make sure the randomly generated chromosomes contains the same number of 1s which corresponds to k number of clusters (eg. if k=3 then the chromosome must contain exactly three 1s)?

回答1:

I can't comment on the sense of combining k-means with ga, but I can point out that you had issue in your fitness function. Also, errors are produced when all genes are on or off, so fitness is only calculated when that is not the case:

DBI <- function(x) {
  if(sum(x)==nrow(dataset) | sum(x)==0){
    score <- 0
  } else {
    cl <- kmeans(dataset[, -1], dataset[x==1, -1])
    dbi <- index.DB(dataset[,-1], cl=cl$cluster, centrotypes = "centroids")
    score <- dbi$DB
  }

  return(score)
}

g <- ga(type = "binary", fitness = DBI, popSize = 100, nBits = nrow(dataset))
plot(g)

g@solution
g@fitnessValue

Looks like several gene combinations produced the same "best" fitness value