2017-02-23 4 views
2

Ich verwende GA Package, um eine Funktion zu minimieren. Im Folgenden sind einige Phasen, die ich implementiert habe.Genetischer Algorithmus - Crossover und Mutation funktionieren nicht

0. Bibliotheken und Dataset

library(clusterSim)  ## for index.DB() 
library(GA)    ## for ga() 
data("data_ratio") 
dataset2 <- data_ratio 
set.seed(555) 

1. Binäre Codierung und Anfangspopulation erzeugen.

initial_population <- function(object) { 
    ## generate a population where for each individual, there will be number of 1's fixed between three to six 
    population <- t(replicate([email protected], {i <- sample(3:6, 1); sample(c(rep(1, i), rep(0, [email protected] - i)))})) 
    return(population) 
} 

2. Fitness-Funktion Minimiert Davies-Bouldin (DB) Index.

DBI2 <- function(x) { 
    ## number of 1's will represent the initial selected centroids and hence the number of clusters 
    cl <- kmeans(dataset2, dataset2[x == 1, ]) 
    dbi <- index.DB(dataset2, cl=cl$cluster, centrotypes = "centroids") 
    score <- -dbi$DB 

    return(score) 
} 

3. Benutzerdefinierte Crossover-Operator. Diese Crossover-Methode vermeidet Situationen, in denen keine Cluster eingeschaltet sind. Der Pseudocode kann here gefunden werden.

pairwise_crossover <- function(object, parents){ 
    fitness <- [email protected][parents] 
    parents <- [email protected][parents, , drop = FALSE] 
    n <- ncol(parents) 
    children <- matrix(as.double(NA), nrow = 2, ncol = n) 
    fitnessChildren <- rep(NA, 2) 

    ## finding the min no. of 1's between 2 parents 
    m <- min(sum(parents[1, ] == 1), sum(parents[2, ] == 1)) 
    ## generate a random int from range(1,m) 
    random_int <- sample(1:m, 1) 
    ## randomly select 'random_int' gene positions with 1's in parent[1, ] 
    random_a <- sample(1:length(parents[1, ]), random_int) 
    ## randomly select 'random_int' gene positions with 1's in parent[1, ] 
    random_b <- sample(1:length(parents[2, ]), random_int) 
    ## union them 
    all <- sort(union(random_a, random_b)) 
    ## determine the union positions 
    temp_a <- parents[1, ][all] 
    temp_b <- parents[2, ][all] 

    ## crossover 
    parents[1, ][all] <- temp_b 
    children[1, ] <- parents[1, ] 
    parents[2, ][all] <- temp_a 
    children[2, ] <- parents[2, ] 

    out <- list(children = children, fitness = fitnessChildren) 
    return(out) 
} 

4. Mutation.

k_min <- 2 
k_max <- ceiling(sqrt(75)) 

my_mutation <- function(object, parent){ 
    pop <- parent <- as.vector([email protected][parent, ]) 
    for(i in 1:length(pop)){ 
      if((sum(pop == 1) < k_max) && pop[i] == 0 | (sum(pop == 1) > k_min && pop[i] == 1)) { 
        pop[i] <- abs(pop[i] - 1) 
        return(pop) 
      } 

    } 

} 

5. zusammen die Stücke Putting. Mit Roulette-Rad Auswahl, Crossover Prob. = 0,8, Mutationsprob. = 0,1

g2<- ga(type = "binary", 
    population = initial_population, 
    fitness = DBI2, 
    selection = ga_rwSelection, 
    crossover = pairwise_crossover, 
    mutation = my_mutation, 
    pcrossover = 0.8, 
    pmutation = 0.1, 
    popSize = 100, 
    nBits = nrow(dataset2)) 

ich meine erste Bevölkerung in einer Art und Weise geschaffen haben, dass in der Bevölkerung für jeden einzelnen, gibt es Zahl der 1's insgesamt drei bis sechs fixiert sein. Der Crossover- und Mutationsoperator soll sicherstellen, dass die Lösung nicht zu viele Cluster (1's) aufweist, die "eingeschaltet" sind. Ich habe meine Crossover- und Mutationsfunktionen separat ausprobiert, bevor ich sie integrieren konnte, und sie scheinen gut zu funktionieren.

Idealerweise die Endlösung Anzahl von 1's + haben wird - = 1 von der Anfangspopulation, d.h, wenn ein Individuum drei 1's in seinem Chromosom hat, wird es am Ende mit dem Zufallsprinzip entweder zwei, drei oder vier 1's. Aber ich habe stattdessen diese Lösung, die zeigt, dass 12 Cluster (1's) "angeschaltet" sind, was bedeutet, dass die Crossover- und Mutationsoperatoren gut ausgegangen sind.

> sum([email protected]==1) 
[1] 12 

Das Problem hier ist reproduzierbar durch Kopieren des gesamten Codes. Wer mit dem GA-Paket vertraut ist, kann mir hier helfen?

[EDITED]

mit einem anderen Daten-Set Der Versuch iris, hat mich in den folgenden Fehler.(Geändert nur die Daten, blieb der Rest der Einstellungen)

0. Bibliotheken und Dataset

library(clusterSim)  ## for index.DB() 
library(GA)    ## for ga() 
## removed last column since it is a categorical data 
dataset2 <- iris[-5] 
set.seed(555) 

> Error in kmeans(dataset2, centers = dataset2[x == 1, ]) : 
    initial centers are not distinct 

Ich habe versucht, in die code suchen, und fand heraus, dieser Fehler verursacht wurde durch if(any(duplicated(centers))). Was würde es möglicherweise bedeuten?

+0

können Sie Ihre Probe Anfangspopulation Daten gemeinsam nutzen? –

+1

Es ist in der 'initial_population' Funktion, in der es eine 100 x 75 binäre Matrix zurückgibt. Ich bin nicht sicher, wie man mit dem ga-Paket darauf zugreifen kann, aber man kann es mit 'population <- t (replicate (100, {i <- Probe (3: 6, 1); Probe (c (rep (1, i), rep (0, 75 - i)))})) ' –

+0

' k_max' und 'k_min'? –

Antwort

2

Ein paar Punkte erwähnenswert:

  1. In crossover, um 'random_int' Genpositionen mit 1 der nach dem Zufallsprinzip auszuwählen, in parent[1, ] Sie die folgende Codezeile ändern von

    random_a <- sample(1:length(parents[1, ]), random_int)

    bis

    random_a <- sample(which(parents[1, ]==1), random_int)

    und ähnlich für die anderen parernt.

    Aber diese Crossover-Strategie garantiert, dass jeder Nachwuchs kann die Gesamtzahl der Cluster-Bits maximal aktiviert als die maximale Anzahl von 1 Bits seiner Eltern (die 6 in diesem Fall von der Grundgesamtheit sein können, sollte nicht 4 sein, wenn du nur 1 bit Unterschied im Lösungsgen willst?).

    Die folgende Abbildung zeigt 3 zufällig ausgewählte Positionen, bei denen mindestens eines der Elterngene 1 Bit hat, während Crossover und die Nachkommen erzeugt wurden.

enter image description here

  1. In der mutation Funktion, glaube ich, noch deutlicher zu sein, sollten wir diese Codezeile ändern

    if((sum(pop == 1) < k_max) && pop[i] == 0 | (sum(pop == 1) > k_min && pop[i] == 1))

    von

    if((sum(pop == 1) < k_max && pop[i] == 0) | (sum(pop == 1) > k_min && pop[i] == 1))

    mit richtigen Klammern.

  2. Auch scheint es, dass Ihre fitness Funktion (Davies-Bouldin's index Messung Cluster-Trennung) begünstigt mehr Cluster aktiviert werden.

Schließlich halte ich es für die mutation ist, dass der Täter ist, wenn Sie k_max auf einen niedrigen Wert (zB 3) ändern und pmutation auf einen niedrigen Wert (zB pmutation = 0.01), werden Sie in den endgültigen Lösungen zu finden, Die Gene haben 4 Bits eingeschaltet.

[EDITED]

set.seed(1234) 
k_min = 2 
k_max = 3 #ceiling(sqrt(75)) 
#5. Putting the pieces together. Using roulette-wheel selection, crossover prob. = 0.8, mutation prob. = 0.1 
g2<- ga(type = "binary", 
     population = initial_population, 
     fitness = DBI2, 
     selection = ga_rwSelection, 
     crossover = pairwise_crossover, 
     mutation = my_mutation, 
     pcrossover = 0.8, 
     pmutation = 0.01, 
     popSize = 100, 
     nBits = nrow(dataset2))  

[email protected] # there are 6 solution genes 
    x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 
[1,] 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[2,] 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[3,] 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[4,] 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[5,] 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[6,] 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    x38 x39 x40 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 x61 x62 x63 x64 x65 x66 x67 x68 x69 x70 x71 x72 
[1,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[2,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[3,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[4,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[5,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
[6,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
    x73 x74 x75 
[1,] 0 0 0 
[2,] 0 0 0 
[3,] 0 0 0 
[4,] 0 0 0 
[5,] 0 0 0 
[6,] 0 0 0 

rowSums([email protected]) # all of them have 4 bits on 
#[1] 4 4 4 4 4 4 

[EDIT 2]

  1. Eigentlich ist die crossover Strategie gewährleistet, dass es keine Extra gedreht, um die auf der Kombination Eltern, dh Gesamtanzahl von 1 Bits in den Kindern = Gesamtzahl von 1 Bits in den Eltern, aber jedes einzelne Kind kann mehr Bits eingeschaltet haben. Beispiel, in dem ein einzelner Nachkommen können mehr Bits eingeschaltet haben als jede der Eltern ist unten dargestellt:

enter image description here

+1

danke sir für den Hinweis auf meinen Fehler! Ja, ich stimme Ihrem Punkt auf dem "Crossover" -Operator zu, meine Absicht ist es, verschiedene Anfangsschwerpunkte für den Clustering-Algorithmus zu testen. Und bezüglich 'Mutation' habe ich versucht mit' k_max = 3' und 'pmutation = 0.01', während ich die beste Lösung' g2 @ solution' überprüfe, habe ich herausgefunden, dass 12 Bits (Cluster) angeschaltet sind. Wieso ist es so? Würde es irgendwie mit Punkt 3 zu tun haben, auf den Sie hingewiesen haben? –

+1

@jacky_learns_to_code Ja, es könnte sein, dass ein paar reproduzierbarer Code hinzugefügt wurde, wo die endgültigen Lösungen nur 4 Bits enthalten. –

+0

Sie sind herzlich willkommen @jacky_learns_to_code –

Verwandte Themen