[PYTHON] Merkmalsauswahl durch genetischen Algorithmus

Einführung

Gibt es einen genetischen Algorithmus? 011101010 ... Kann dies zur Auswahl der Merkmalsmenge verwendet werden? Als ich darüber nachdachte, gab es eine Person, die das selbstverständlich tat. Ich habe es auf meine eigene Weise unter Bezugnahme auf den Code des Pioniers neu organisiert. Es ist die n-te Abkochung.

Referenz

Verfahren

Implementierung eines genetischen Algorithmus

Einzelheiten zum genetischen Algorithmus finden Sie unter hier. In diesem Artikel wird das OneMax-Problem als Beispiel verwendet. Das OneMax-Problem ist ein Problem, bei dem alle Elemente der Sequenz [0,1,0,1,1,1,0, ...], die als Anfangswerte angegeben sind, auf 1 gesetzt werden und versucht wird, dies mit einem genetischen Algorithmus zu lösen. Ich werde.

Für den Code habe ich auf [diesen Github] verwiesen (https://github.com/Azunyan1111/OneMax). Die Namen der Begriffe und Variablen, die im genetischen Algorithmus erscheinen, sind [hier](https://www.slideshare.net/kzokm/genetic-algorithm-41617242?ref=https://tech.mof-mof.co.jp /blog/ga-one-max-problem.html) wurde verwiesen. Kurz zusammengefasst ist der Skalarwert, der 0 oder 1 annimmt, das Gen, und die Sequenz [0,0,1,1,0,1, ...], die durch Sammeln der Gene erhalten wird, ist das Chromosom (Chromosom). Körper mit? Wurde als Einzelperson eingestellt. Das Individuum hat von Natur aus ein Chromosom als Attribut. Die Gruppe von Individuen wird als Bevölkerung bezeichnet. Der Algorithmus ist Elite-Auswahl, nicht Roulette-Auswahl.

Die für einen genetischen Algorithmus erforderlichen Elemente sind:

"""
Geschrieben von Azunyan https://github.com/Azunyan1111/OneMax
"""
"""
Geändertes Copyright 2020 ground0state Alle Rechte vorbehalten.
"""
import random
import time


class Individual():
    """Individuell.
    
    Parameters
    ----------
    chromosome : list of {0 or 1}
Chrom.
        
    evaluation : float
Auswertung.
    """
    chromosome = None
    evaluation = None

    def __init__(self, chromosome, evaluation):
        self.chromosome = chromosome
        self.evaluation = evaluation


def create_individual(length):
    """Gibt die Person zurück, die das zufällige Chromosom der durch das Argument angegebenen Ziffer generiert und gespeichert hat.
    
    Parameters
    ----------
    length : int
Chromlänge.

    Returns
    -------
    individual : Individual
Individuell.
    """
    individual = Individual([random.randint(0, 1) for i in range(length)], 0)
    return individual


def evaluate_individual(individual):
    """Bewertungsfunktion.
    
    Parameters
    ----------
    individual : Individual
Individuell.
        
    Returns
    -------
    eval : float
Bewertungswert.
    """
    eval = sum(individual.chromosome)/len(individual.chromosome)
    return eval


def extract_elites(population, num):
    """Auswahlfunktion.
    
    Parameters
    ----------
    population : list of Individual
Gruppe.
    num : int
Anzahl der Einzelauswahlen.
        
    Returns
    -------
    elites : list of Individual
Gruppe, die einer Auswahlverarbeitung unterzogen wurde.
    """        
    #Sortieren Sie die Bewertungen der Bevölkerung der aktuellen Generation in absteigender Reihenfolge
    sort_result = sorted(population, reverse=True, key=lambda individual: individual.evaluation)
    
    #Bestimmte Spitzen extrahieren
    elites = sort_result[:num]
    return elites


def crossover(individual1, individual2, chromosome_length):
    """Kreuzungsfunktion.
Überqueren Sie zwei Punkte.
    
    Parameters
    ----------
    individual1 : Individual
Überqueren von Personen 1.
    individual2 : Individual
Überqueren von Personen 2.
    chromosome_length : int
Chromlänge.
        
    Returns
    -------
    offsprings : list of Individual
Zwei Enkelkinder.
    """
    
    #Stellen Sie zwei zu ersetzende Punkte ein
    cross_one = random.randint(0, chromosome_length)
    cross_second = random.randint(cross_one, chromosome_length)
    
    #Nehmen Sie das Gen heraus
    one = individual1.chromosome
    second = individual2.chromosome
    
    #Kreuz
    progeny_one = one[:cross_one] + second[cross_one:cross_second] + one[cross_second:]
    progeny_second = second[:cross_one] + one[cross_one:cross_second] + second[cross_second:]
    
    #Nachkommenschaft
    offsprings = [Individual(progeny_one, 0), Individual(progeny_second, 0)]
    return offsprings


def create_next_generation(population, elites, offsprings):
    """Führen Sie die Generierungswechselverarbeitung durch.
    
    Parameters
    ----------
    population : list of Individual
Bevölkerung der aktuellen Generation.
    elites : list of Individual
Elitegruppe der aktuellen Generation.
    offsprings : list of Individual
Nachkommengruppe der aktuellen Generation.
        
    Returns
    -------
    next_generation_population : list of Individual
Bevölkerung der nächsten Generation.
    """
    #Sortieren Sie die Bewertungen der Bevölkerung der aktuellen Generation in aufsteigender Reihenfolge
    next_generation_population = sorted(population, reverse=False, key=lambda individual: individual.evaluation)
    
    #Entfernen Sie die Summe der hinzuzufügenden Elite- und Nachkommengruppe
    next_generation_population = next_generation_population[len(elites)+len(offsprings):]
        
    #Fügen Sie der nächsten Generation Elite- und Nachkommengruppen hinzu
    next_generation_population.extend(elites)
    next_generation_population.extend(offsprings)
    return next_generation_population


def mutation(population, induvidual_mutation_probability, gene_mutation_probability):
    """Mutationsfunktion.
    
    Parameters
    ----------
    population : list of Individual
Gruppe.
    induvidual_mutation_probability : float in [0, 1]
Individuelle Mutationswahrscheinlichkeit.
    gene_mutation_probability : float in [0, 1]
Wahrscheinlichkeit einer Genmutation.
        
    Returns
    -------
    new_population : list of Individual
Mutierte Bevölkerung.
    """
    new_population = []
    for individual in population:
        #Eine Mutation tritt mit einer bestimmten Wahrscheinlichkeit für ein Individuum auf
        if induvidual_mutation_probability > random.random():
            new_chromosome = []
            for gene in individual.chromosome:
                #Mutationen treten für jede einzelne genetische Information auf
                if gene_mutation_probability > random.random():
                    new_chromosome.append(random.randint(0, 1))
                else:
                    new_chromosome.append(gene)
                    
            individual.chromosome = new_chromosome
            new_population.append(individual)
        else:
            new_population.append(individual)
            
    return new_population

Verwenden Sie diese Klassen und Funktionen, um den folgenden Code auszuführen.

#Chromlänge
CHROMOSOME_LENGTH = 13

#Gruppengröße
POPULATION_SIZE = 30

#Elite-Chromosomenauswahlnummer
PICK_OUT_SIZE = 5

#Individuelle Mutationswahrscheinlichkeit
INDIVIDUAL_MUTATION_PROBABILITY = 0.3

#Wahrscheinlichkeit einer Genmutation
GENE_MUTATION_PROBABILITY = 0.1

#Anzahl der zu wiederholenden Generationen
ITERATION = 10


#Initialisieren Sie die Bevölkerung der aktuellen Generation
current_generation_population = [create_individual(CHROMOSOME_LENGTH) for i in range(POPULATION_SIZE)]

for count in range(ITERATION):
    #Startzeit jeder Schleife
    start = time.time()
    
    #Bewerten Sie Personen in der Bevölkerung der aktuellen Generation
    for individual in current_generation_population:
        individual.evaluation = evaluate_individual(individual)

    #Wählen Sie eine Elite-Person
    elites = extract_elites(current_generation_population, PICK_OUT_SIZE)
    
    #Überqueren Sie Elite-Gene und speichern Sie sie in der Liste
    offsprings = []
    for i in range(0, PICK_OUT_SIZE-1):
        offsprings.extend(crossover(elites[i], elites[i+1], CHROMOSOME_LENGTH))
        
    #Erstellen Sie die Bevölkerung der nächsten Generation aus der aktuellen Generation, der Elite und der Nachkommenbevölkerung
    next_generation_population = create_next_generation(current_generation_population, elites, offsprings)
    
    #Mutation aller Individuen in der Bevölkerung der nächsten Generation.
    next_generation_population = mutation(next_generation_population,
                                          INDIVIDUAL_MUTATION_PROBABILITY,
                                          GENE_MUTATION_PROBABILITY)

    #Die evolutionäre Berechnung einer Generation ist abgeschlossen. Fahren Sie mit der Bewertung fort

    #Ordnen Sie die Bewertungswerte jedes Einzelnen an.
    fits = [individual.evaluation for individual in current_generation_population]

    #Evolutionsergebnisse bewerten
    min_val = min(fits)
    max_val = max(fits)
    avg_val = sum(fits) / len(fits)

    #Gibt die Evolutionsergebnisse der aktuellen Generation aus
    print("-----Nein.{}Generationsergebnisse-----".format(count+1))
    print("  Min:{}".format(min_val))
    print("  Max:{}".format(max_val))
    print("  Avg:{}".format(avg_val))

    #Tauschen Sie die aktuelle Generation gegen die nächste Generation aus
    current_generation_population = next_generation_population
    
    #Zeitmessung
    elapsed_time = time.time() - start
    print ("  {}/{} elapsed_time:{:.2f}".format(count+1, ITERATION, elapsed_time) + "[sec]")

#Endergebnis Ausgabe
print("")  #Neue Zeile
print("Das beste Individuum ist{}".format(elites[0].chromosome))

Die Ausgabe sieht folgendermaßen aus:

-----Ergebnisse der 1. Generation-----
  Min:0.23076923076923078
  Max:0.8461538461538461
  Avg:0.5384615384615384
  1/10 elapsed_time:0.00[sec]
-----Ergebnisse der 2. Generation-----
  Min:0.46153846153846156
  Max:0.8461538461538461
  Avg:0.6692307692307694
  2/10 elapsed_time:0.00[sec]
-----Ergebnisse der 3. Generation-----
  Min:0.6923076923076923
  Max:0.9230769230769231
  Avg:0.761538461538462
  3/10 elapsed_time:0.00[sec]
-----Ergebnisse der 4. Generation-----
  Min:0.6923076923076923
  Max:0.9230769230769231
  Avg:0.8102564102564106
  4/10 elapsed_time:0.00[sec]
-----Ergebnisse der 5. Generation-----
  Min:0.6923076923076923
  Max:0.9230769230769231
  Avg:0.8512820512820515
  5/10 elapsed_time:0.00[sec]
-----Ergebnisse der 6. Generation-----
  Min:0.7692307692307693
  Max:0.9230769230769231
  Avg:0.848717948717949
  6/10 elapsed_time:0.00[sec]
-----Ergebnisse der 7. Generation-----
  Min:0.7692307692307693
  Max:0.9230769230769231
  Avg:0.8948717948717951
  7/10 elapsed_time:0.00[sec]
-----Ergebnisse der 8. Generation-----
  Min:0.6153846153846154
  Max:0.9230769230769231
  Avg:0.8974358974358977
  8/10 elapsed_time:0.00[sec]
-----Ergebnisse der 9. Generation-----
  Min:0.7692307692307693
  Max:0.9230769230769231
  Avg:0.9000000000000002
  9/10 elapsed_time:0.00[sec]
-----Ergebnisse der 10. Generation-----
  Min:0.8461538461538461
  Max:1.0
  Avg:0.9102564102564105
  10/10 elapsed_time:0.00[sec]

Das beste Individuum ist[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Ich konnte eine Person mit allen 1 Elementen bekommen.

Merkmalsauswahl durch genetischen Algorithmus

Ich habe die Daten und das Modell unter Bezugnahme auf hier vorbereitet.

Die Datenaufbereitung ist der folgende Code.

import pandas as pd
import numpy as np
from sklearn.datasets import load_boston
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler


#Laden des Datensatzes
X = pd.DataFrame(load_boston().data, columns=load_boston().feature_names)
y = load_boston().target

#Polymorphe Merkmale hinzugefügt
poly = PolynomialFeatures(2)
poly.fit(X)
X_poly = pd.DataFrame(poly.transform(X), columns=poly.get_feature_names(input_features=X.columns))

#Standardisierung
sc = StandardScaler()
X_sc = pd.DataFrame(sc.fit_transform(X), columns=X.columns)
X_poly_sc = pd.DataFrame(sc.fit_transform(X_poly), columns=X_poly.columns)

X_poly_sc ist derjenige, der PolynomialFeatures verwendet, um die Feature-Menge zu erhöhen und das Muster mit einer großen Menge an Feature-Menge zu überprüfen.

Modell mit dem Rohdatensatz.

from sklearn.linear_model import RidgeCV
from sklearn.model_selection import train_test_split

#Ist-Datensatz
scores = []
for _ in range(30):
    X_train, X_test, y_train, y_test = train_test_split(X_sc, y, test_size=0.4)
    model = RidgeCV()
    model.fit(X_train, y_train)
    scores.append(model.score(X_test, y_test))

print(np.array(scores).mean())  # 0.70

Ein Modell mit hinzugefügten polymorphen Merkmalen.

from sklearn.linear_model import RidgeCV
from sklearn.model_selection import train_test_split


#Wenn ein polymorphes Merkmal hinzugefügt wird
scores = []
for _ in range(30):
    X_train, X_test, y_train, y_test = train_test_split(X_poly_sc, y, test_size=0.4)
    model = RidgeCV()
    model.fit(X_train, y_train)
    scores.append(model.score(X_test, y_test))

print(np.array(scores).mean())    # 0.82

Lassen Sie uns nun Merkmale mit einem genetischen Algorithmus für dieses Modell auswählen. Es ist die Methode "evaluiere_individuell", die geändert wird. Konvertiert das Chromosom des Individuums als Eingabe in einen Booleschen Wert und gibt die zu verwendende Spalte an. Danach werden Lernen und Punktzahl anhand des Modells berechnet. Die Punktzahl wird als Bewertungswert der Person zurückgegeben.

def evaluate_individual(individual):
    """Bewertungsfunktion.
    
    Parameters
    ----------
    individual : Individual
Individuell.
        
    Returns
    -------
    eval : float
Bewertungswert.
    """
    use_cols = [bool(gene) for gene in individual.chromosome]
    X_temp = X_sc.iloc[:, use_cols]
    
    scores = []
    for _ in range(30):
        X_train, X_test, y_train, y_test = train_test_split(X_temp, y, test_size=0.4)
        model = RidgeCV()
        model.fit(X_train, y_train)
        scores.append(model.score(X_test, y_test))
    
    eval = float(np.array(scores).mean())
    return eval

Ich habe die Parameter wie folgt geändert und versucht, sie auszuführen.

#Chromlänge
CHROMOSOME_LENGTH = 13

#Gruppengröße
POPULATION_SIZE = 100

#Elite-Chromosomenauswahlnummer
PICK_OUT_SIZE = 20

#Individuelle Mutationswahrscheinlichkeit
INDIVIDUAL_MUTATION_PROBABILITY = 0.3

#Wahrscheinlichkeit einer Genmutation
GENE_MUTATION_PROBABILITY = 0.1

#Anzahl der zu wiederholenden Generationen
ITERATION = 10

Das Ergebnis ist wie folgt.

-----Ergebnisse der 1. Generation-----
  Min:0.245482696210891
  Max:0.7062246093438559
  Avg:0.5643638813331334
  1/10 elapsed_time:13.21[sec]
-----Ergebnisse der 2. Generation-----
  Min:0.28765890628509017
  Max:0.7175019664075553
  Avg:0.6611343782899052
  2/10 elapsed_time:14.07[sec]
-----Ergebnisse der 3. Generation-----
  Min:0.5958052127889627
  Max:0.7343341487237112
  Avg:0.6840346805288029
  3/10 elapsed_time:14.39[sec]
-----Ergebnisse der 4. Generation-----
  Min:0.6011227398695212
  Max:0.7265364514547696
  Avg:0.694531099756538
  4/10 elapsed_time:11.29[sec]
-----Ergebnisse der 5. Generation-----
  Min:0.6314510371602322
  Max:0.7249977461594102
  Avg:0.6938166370760438
  5/10 elapsed_time:11.72[sec]
-----Ergebnisse der 6. Generation-----
  Min:0.6539907671434392
  Max:0.7256998515926862
  Avg:0.7042345770684423
  6/10 elapsed_time:11.44[sec]
-----Ergebnisse der 7. Generation-----
  Min:0.6557998988298114
  Max:0.7273580445493621
  Avg:0.7009249865262361
  7/10 elapsed_time:9.64[sec]
-----Ergebnisse der 8. Generation-----
  Min:0.6530159418050802
  Max:0.7250968150681534
  Avg:0.7044189020700958
  8/10 elapsed_time:9.90[sec]
-----Ergebnisse der 9. Generation-----
  Min:0.6087336519329122
  Max:0.7316442169584539
  Avg:0.7008118423172378
  9/10 elapsed_time:9.64[sec]
-----Ergebnisse der 10. Generation-----
  Min:0.6328245771251623
  Max:0.7244970729879131
  Avg:0.7034862249363725
  10/10 elapsed_time:13.06[sec]

Das beste Individuum ist[1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]

Da die Punktzahl "0,72" beträgt, ist eine bessere Auswahl der Merkmale möglich.

Einstufung

Klassifiziert, damit es wiederverwendet werden kann. Erstellen Sie es als abstrakte Klasse und erben Sie es, um "evalu_individual" zu implementieren.

"""
Geschrieben von Azunyan https://github.com/Azunyan1111/OneMax
"""
"""
Geändertes Copyright 2020 ground0state Alle Rechte vorbehalten.
"""
import random
import time
from abc import ABCMeta, abstractmethod


class Individual():
    """Individuell.
    
    Parameters
    ----------
    chromosome : list of {0 or 1}
Chrom.
        
    evaluation : float
Auswertung.
    """
    chromosome = None
    evaluation = None

    def __init__(self, chromosome, evaluation):
        self.chromosome = chromosome
        self.evaluation = evaluation

        
class GaSolver(metaclass=ABCMeta):
    """Abstrakte Klasse des genetischen Algorithmus.
Methode "evaluieren", die den Evaluierungswert für das Chromosom ausgibt_"Individuum" erfordert Implementierung.

    Parameters
    ----------
    chromosome_length : int
Chromlänge.

    population_size : int
Gruppengröße.
        
    pick_out_size : int
Elite-Chromosomenauswahlnummer.

    individual_mutation_probability : float
Individuelle Mutationswahrscheinlichkeit.
        
    gene_mutation_probability : float
Wahrscheinlichkeit einer Genmutation.

    iteration : int
Anzahl der zu wiederholenden Generationen.
    """
    
    def __init__(self, chromosome_length, population_size, pick_out_size,
                 individual_mutation_probability=0.3, gene_mutation_probability=0.1, iteration=1, verbose=True):        
        self.chromosome_length = chromosome_length
        self.population_size = population_size
        self.pick_out_size = pick_out_size
        self.individual_mutation_probability = individual_mutation_probability
        self.gene_mutation_probability = gene_mutation_probability
        self.iteration = iteration
        self.verbose = verbose
        self.history = None
    
    def _create_individual(self, length):
        """Gibt die Person zurück, die das zufällige Chromosom der durch das Argument angegebenen Ziffer generiert und gespeichert hat.

        Parameters
        ----------
        length : int
Chromlänge.

        Returns
        -------
        individual : Individual
Individuell.
        """
        individual = Individual([random.randint(0, 1) for i in range(length)], 0)
        return individual

    @abstractmethod
    def evaluate_individual(self, individual, X, y):
        """Bewertungsfunktion.

        Parameters
        ----------
        individual : Individual
Individuell.
        X : pandas.DataFrame
Erklärende Variable.
        y : pandas.DataFrame
Objektive Variable.

        Returns
        -------
        eval : float
Bewertungswert.
        """
        raise NotImplementedError()

    def _extract_elites(self, population, num):
        """Auswahlfunktion.

        Parameters
        ----------
        population : list of Individual
Gruppe.
        num : int
Anzahl der Einzelauswahlen.

        Returns
        -------
        elites : list of Individual
Gruppe, die einer Auswahlverarbeitung unterzogen wurde.
        """        
        #Sortieren Sie die Bewertungen der Bevölkerung der aktuellen Generation in absteigender Reihenfolge
        sort_result = sorted(population, reverse=True, key=lambda individual: individual.evaluation)

        #Bestimmte Spitzen extrahieren
        elites = sort_result[:num]
        return elites

    def _crossover(self, individual1, individual2, chromosome_length):
        """Kreuzungsfunktion.
Überqueren Sie zwei Punkte.

        Parameters
        ----------
        individual1 : Individual
Überqueren von Personen 1.
        individual2 : Individual
Überqueren von Personen 2.
        chromosome_length : int
Chromlänge.

        Returns
        -------
        offsprings : list of Individual
Zwei Enkelkinder.
        """

        #Stellen Sie zwei zu ersetzende Punkte ein
        cross_one = random.randint(0, chromosome_length)
        cross_second = random.randint(cross_one, chromosome_length)

        #Nehmen Sie das Gen heraus
        one = individual1.chromosome
        second = individual2.chromosome

        #Kreuz
        progeny_one = one[:cross_one] + second[cross_one:cross_second] + one[cross_second:]
        progeny_second = second[:cross_one] + one[cross_one:cross_second] + second[cross_second:]

        #Nachkommenschaft
        offsprings = [Individual(progeny_one, 0), Individual(progeny_second, 0)]
        return offsprings

    def _create_next_generation(self, population, elites, offsprings):
        """Führen Sie die Generierungswechselverarbeitung durch.

        Parameters
        ----------
        population : list of Individual
Bevölkerung der aktuellen Generation.
        elites : list of Individual
Elitegruppe der aktuellen Generation.
        offsprings : list of Individual
Nachkommengruppe der aktuellen Generation.

        Returns
        -------
        next_generation_population : list of Individual
Bevölkerung der nächsten Generation.
        """
        #Sortieren Sie die Bewertungen der Bevölkerung der aktuellen Generation in aufsteigender Reihenfolge
        next_generation_population = sorted(population, reverse=False, key=lambda individual: individual.evaluation)

        #Entfernen Sie die Summe der hinzuzufügenden Elite- und Nachkommengruppe
        next_generation_population = next_generation_population[len(elites)+len(offsprings):]

        #Fügen Sie der nächsten Generation Elite- und Nachkommengruppen hinzu
        next_generation_population.extend(elites)
        next_generation_population.extend(offsprings)
        return next_generation_population

    def _mutation(self, population, induvidual__mutation_probability, gene__mutation_probability):
        """Mutationsfunktion.

        Parameters
        ----------
        population : list of Individual
Gruppe.
        induvidual__mutation_probability : float in [0, 1]
Individuelle Mutationswahrscheinlichkeit.
        gene__mutation_probability : float in [0, 1]
Wahrscheinlichkeit einer Genmutation.

        Returns
        -------
        new_population : list of Individual
Mutierte Bevölkerung.
        """
        new_population = []
        for individual in population:
            #Eine Mutation tritt mit einer bestimmten Wahrscheinlichkeit für ein Individuum auf
            if induvidual__mutation_probability > random.random():
                new_chromosome = []
                for gene in individual.chromosome:
                    #Mutationen treten für jede einzelne genetische Information auf
                    if gene__mutation_probability > random.random():
                        new_chromosome.append(random.randint(0, 1))
                    else:
                        new_chromosome.append(gene)

                individual.chromosome = new_chromosome
                new_population.append(individual)
            else:
                new_population.append(individual)

        return new_population
    
    def solve(self, X, y):
        """Hauptklasse genetischer Algorithmen.

        Returns
        -------
        list of {0 or 1}
Das beste individuelle Chromosom.
        """
        self.history = {"Min":[], "Max":[], "Avg":[], "BestChromosome":[]}
        
        #Initialisieren Sie die Bevölkerung der aktuellen Generation
        current_generation_population = [self._create_individual(self.chromosome_length) for i in range(self.population_size)]
        
        #Bewerten Sie Personen in der Bevölkerung der aktuellen Generation
        for individual in current_generation_population:
            individual.evaluation = self.evaluate_individual(individual, X, y)

        for count in range(self.iteration):
            #Startzeit jeder Schleife
            start = time.time()

            #Wählen Sie eine Elite-Person
            elites = self._extract_elites(current_generation_population, self.pick_out_size)

            #Überqueren Sie Elite-Gene und speichern Sie sie in der Liste
            offsprings = []
            for i in range(0, self.pick_out_size-1):
                offsprings.extend(self._crossover(elites[i], elites[i+1], self.chromosome_length))

            #Erstellen Sie die Bevölkerung der nächsten Generation aus der aktuellen Generation, der Elite und der Nachkommenbevölkerung
            next_generation_population = self._create_next_generation(current_generation_population, elites, offsprings)

            #Mutation aller Individuen in der Bevölkerung der nächsten Generation.
            next_generation_population = self._mutation(next_generation_population,
                                                  self.individual_mutation_probability,
                                                  self.gene_mutation_probability)
            
            #Bewerten Sie Personen in der Bevölkerung der aktuellen Generation
            for individual in current_generation_population:
                individual.evaluation = self.evaluate_individual(individual, X, y)

            #Die evolutionäre Berechnung einer Generation ist abgeschlossen. Fahren Sie mit der Bewertung fort

            #Ordnen Sie die Bewertungswerte jedes Einzelnen an.
            fits = [individual.evaluation for individual in current_generation_population]
            
            #Nehmen Sie die Person mit dem besten Bewertungswert heraus
            best_individual = self._extract_elites(current_generation_population, 1)
            best_chromosome = best_individual[0].chromosome

            #Evolutionsergebnisse bewerten
            min_val = min(fits)
            max_val = max(fits)
            avg_val = sum(fits) / len(fits)

            #Gibt die Evolutionsergebnisse der aktuellen Generation aus
            if self.verbose:
                print("-----Nein.{}Generationsergebnisse-----".format(count+1))
                print("  Min:{}".format(min_val))
                print("  Max:{}".format(max_val))
                print("  Avg:{}".format(avg_val))
                
            #Geschichtserstellung
            self.history["Min"].append(min_val)
            self.history["Max"].append(max_val)
            self.history["Avg"].append(avg_val)
            self.history["BestChromosome"].append(best_chromosome)

            #Tauschen Sie die aktuelle Generation gegen die nächste Generation aus
            current_generation_population = next_generation_population
            
            #Zeitmessung
            elapsed_time = time.time() - start
            print ("  {}/{} elapsed_time:{:.2f}".format(count+1, self.iteration, elapsed_time) + "[sec]")

        #Endergebnis Ausgabe
        if self.verbose:
            print("")  #Neue Zeile
            print("Das beste Individuum ist{}".format(elites[0].chromosome))
            
        return self.history

Implementieren Sie das maschinelle Lernmodell, das Sie auswerten möchten, in "evaluieren_individuell".

from sklearn.linear_model import RidgeCV
from sklearn.model_selection import train_test_split


class GaSolverImpl(GaSolver):
    
    # override
    def evaluate_individual(self, individual, X, y):
        use_cols = [bool(gene) for gene in individual.chromosome]
        X_temp = X.iloc[:, use_cols]

        scores = []
        for _ in range(30):
            X_train, X_test, y_train, y_test = train_test_split(X_temp, y, test_size=0.4)
            model = RidgeCV()
            model.fit(X_train, y_train)
            scores.append(model.score(X_test, y_test))

        eval = float(np.array(scores).mean())
        return eval

Erstellen Sie eine Instanz der Implementierungsklasse, übergeben Sie die Daten und führen Sie sie aus. Die Methode "lösen" gibt den Verlauf "Verlauf" zurück.

solver = GaSolverImpl(
    chromosome_length = X_poly_sc.shape[1], 
    population_size = 50, 
    pick_out_size = 10,
    individual_mutation_probability = 0.3,
    gene_mutation_probability = 0.1,
    iteration = 50,
    verbose = True
)

history = solver.solve(X_poly_sc, y)

Das Ausführungsergebnis ist wie folgt.

-----Ergebnisse der 1. Generation-----
  Min:0.7248417700796147
  Max:0.8360838319205105
  Avg:0.7927103625892467
  1/50 elapsed_time:6.13[sec]
-----Ergebnisse der 2. Generation-----
  Min:0.7350424889460248
  Max:0.8264758137896353
  Avg:0.8114411035733131
  2/50 elapsed_time:10.81[sec]
-----Ergebnisse der 3. Generation-----
  Min:0.7902116792529935
  Max:0.8286229243915363
  Avg:0.8125974889978004
  3/50 elapsed_time:8.20[sec]
-----Ergebnisse der 4. Generation-----
  Min:0.773199874021567
  Max:0.8312887517624212
  Avg:0.810950812639705
  4/50 elapsed_time:7.56[sec]
-----Ergebnisse der 5. Generation-----
  Min:0.768479730905661
  Max:0.8386114466226944
  Avg:0.8076230726252596
  5/50 elapsed_time:8.13[sec]
-----Ergebnisse der 6. Generation-----
  Min:0.7797249579245809
  Max:0.8319768049107215
  Avg:0.8138790949911054
  6/50 elapsed_time:9.00[sec]
-----Ergebnisse der 7. Generation-----
  Min:0.7971344524880782
  Max:0.8333411281001641
  Avg:0.8168863897838727
  7/50 elapsed_time:7.56[sec]
-----Ergebnisse der 8. Generation-----
  Min:0.7709812458007903
  Max:0.8316092177782253
  Avg:0.8082876757394714
  8/50 elapsed_time:7.96[sec]
-----Ergebnisse der 9. Generation-----
  Min:0.7459891729563418
  Max:0.8322393628831635
  Avg:0.8159389943969992
  9/50 elapsed_time:8.77[sec]
-----Ergebnisse der 10. Generation-----
  Min:0.7538656919599587
  Max:0.8254541549046537
  Avg:0.8034195187548075
  10/50 elapsed_time:8.99[sec]
-----Ergebnisse der 11. Generation-----
  Min:0.8046900766607942
  Max:0.8379618406470278
  Avg:0.8217659811828382
  11/50 elapsed_time:8.60[sec]
-----Ergebnisse der 12. Generation-----
  Min:0.8020625272756005
  Max:0.8356958927515973
  Avg:0.8132506462797608
  12/50 elapsed_time:8.31[sec]
-----Ergebnisse der 13. Generation-----
  Min:0.7442093041785434
  Max:0.826166208838109
  Avg:0.7693376466706999
  13/50 elapsed_time:9.22[sec]
-----Ergebnisse der 14. Generation-----
  Min:0.80133807286147
  Max:0.8264198880246336
  Avg:0.8085481113173225
  14/50 elapsed_time:8.08[sec]
-----Ergebnisse der 15. Generation-----
  Min:0.7316094852550766
  Max:0.8139831643344952
  Avg:0.7929373870389733
  15/50 elapsed_time:8.92[sec]
-----Ergebnisse der 16. Generation-----
  Min:0.7955982071682629
  Max:0.8210496822695305
  Avg:0.8134173712784526
  16/50 elapsed_time:9.72[sec]
-----Ergebnisse der 17. Generation-----
  Min:0.758489267352653
  Max:0.826441026953439
  Avg:0.7773437348210647
  17/50 elapsed_time:8.58[sec]
-----Ergebnisse der 18. Generation-----
  Min:0.7687388062022248
  Max:0.8211801466346264
  Avg:0.7826663042340634
  18/50 elapsed_time:6.94[sec]
-----Ergebnisse der 19. Generation-----
  Min:0.7429453738843712
  Max:0.794799782442768
  Avg:0.7525262014670999
  19/50 elapsed_time:8.35[sec]
-----Ergebnisse der 20. Generation-----
  Min:0.7059056866516289
  Max:0.8115968792777923
  Avg:0.7941420197838582
  20/50 elapsed_time:7.01[sec]
-----Ergebnisse der 21. Generation-----
  Min:0.7035195424104084
  Max:0.8339769569079513
  Avg:0.785429874209423
  21/50 elapsed_time:8.84[sec]
-----Ergebnisse der 22. Generation-----
  Min:0.7605334574905934
  Max:0.8178769887665864
  Avg:0.7764313614722025
  22/50 elapsed_time:8.89[sec]
-----Ergebnisse der 23. Generation-----
  Min:0.7622888571603964
  Max:0.8125955330567856
  Avg:0.7761008854264979
  23/50 elapsed_time:8.47[sec]
-----Ergebnisse der 24. Generation-----
  Min:0.7325862134323571
  Max:0.7781021993458462
  Avg:0.76629374412332
  24/50 elapsed_time:6.80[sec]
-----Ergebnisse der 25. Generation-----
  Min:0.7155008056263605
  Max:0.7770200781667415
  Avg:0.7679494414264083
  25/50 elapsed_time:6.34[sec]
-----Ergebnisse der 26. Generation-----
  Min:0.7435193687961383
  Max:0.8178098302473983
  Avg:0.8025839605868198
  26/50 elapsed_time:7.55[sec]
-----Ergebnisse der 27. Generation-----
  Min:0.757023831644299
  Max:0.8134233524435134
  Avg:0.7987707913780304
  27/50 elapsed_time:8.24[sec]
-----Ergebnisse der 28. Generation-----
  Min:0.7731968991993663
  Max:0.8307874217208041
  Avg:0.7886999734804412
  28/50 elapsed_time:6.93[sec]
-----Ergebnisse der 29. Generation-----
  Min:0.7918044164374493
  Max:0.8258234982562584
  Avg:0.8092356291245499
  29/50 elapsed_time:6.45[sec]
-----Ergebnisse der 30. Generation-----
  Min:0.7742914329017841
  Max:0.8170916314535998
  Avg:0.8057764064558626
  30/50 elapsed_time:6.46[sec]
-----Ergebnisse der 31. Generation-----
  Min:0.7900272740547029
  Max:0.8252185280503214
  Avg:0.8121724282164997
  31/50 elapsed_time:6.87[sec]
-----Ergebnisse der 32. Generation-----
  Min:0.7668694386968217
  Max:0.8231354707898234
  Avg:0.8170271080711664
  32/50 elapsed_time:7.61[sec]
-----Ergebnisse der 33. Generation-----
  Min:0.7721459013264073
  Max:0.8365223852672053
  Avg:0.82567433930934
  33/50 elapsed_time:8.28[sec]
-----Ergebnisse der 34. Generation-----
  Min:0.802896605790934
  Max:0.8367820565860135
  Avg:0.8256706142219095
  34/50 elapsed_time:7.94[sec]
-----Ergebnisse der 35. Generation-----
  Min:0.8188038196577934
  Max:0.8388260026966802
  Avg:0.8358101024561487
  35/50 elapsed_time:7.64[sec]
-----Ergebnisse der 36. Generation-----
  Min:0.7887209549961678
  Max:0.8386551764887261
  Avg:0.8301462683188676
  36/50 elapsed_time:8.13[sec]
-----Ergebnisse der 37. Generation-----
  Min:0.7862123272076996
  Max:0.8405895787926129
  Avg:0.8165090312639174
  37/50 elapsed_time:7.54[sec]
-----Ergebnisse der 38. Generation-----
  Min:0.79041640507099
  Max:0.8389789987982965
  Avg:0.8075935438809548
  38/50 elapsed_time:8.58[sec]
-----Ergebnisse der 39. Generation-----
  Min:0.7632897869020304
  Max:0.8249959874282974
  Avg:0.7783194384843993
  39/50 elapsed_time:8.18[sec]
-----Ergebnisse der 40. Generation-----
  Min:0.7391820233337305
  Max:0.8140492870179213
  Avg:0.7954486450055553
  40/50 elapsed_time:6.36[sec]
-----Ergebnisse der 41. Generation-----
  Min:0.7085099265464342
  Max:0.7981244256568432
  Avg:0.7831723305042879
  41/50 elapsed_time:7.90[sec]
-----Ergebnisse der 42. Generation-----
  Min:0.7826056505944214
  Max:0.8327777219420097
  Avg:0.8064707164336307
  42/50 elapsed_time:7.53[sec]
-----Ergebnisse der 43. Generation-----
  Min:0.7799209160785368
  Max:0.8183673115100479
  Avg:0.7992172395182555
  43/50 elapsed_time:6.74[sec]
-----Ergebnisse der 44. Generation-----
  Min:0.756001056689909
  Max:0.8338583079593664
  Avg:0.8051445406627477
  44/50 elapsed_time:6.31[sec]
-----Ergebnisse der 45. Generation-----
  Min:0.7755735607344747
  Max:0.8283597660188781
  Avg:0.7882919431369523
  45/50 elapsed_time:6.52[sec]
-----Ergebnisse der 46. Generation-----
  Min:0.7766070559704219
  Max:0.8165316562327392
  Avg:0.8106111873738964
  46/50 elapsed_time:7.22[sec]
-----Ergebnisse der 47. Generation-----
  Min:0.7780606007516856
  Max:0.8084622225234689
  Avg:0.7942400594914705
  47/50 elapsed_time:9.72[sec]
-----Ergebnisse der 48. Generation-----
  Min:0.7745173603676726
  Max:0.8363078519583506
  Avg:0.8206202750563127
  48/50 elapsed_time:10.67[sec]
-----Ergebnisse der 49. Generation-----
  Min:0.7800301936781145
  Max:0.8368475790583294
  Avg:0.8222375502197947
  49/50 elapsed_time:7.54[sec]
-----Ergebnisse der 50. Generation-----
  Min:0.8077617917763787
  Max:0.841354566380394
  Avg:0.8147771424682558
  50/50 elapsed_time:6.78[sec]

Das beste Individuum ist[1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1]

Die Geschichte sieht so aus:

df = pd.DataFrame(history)
スクリーンショット 2020-01-24 21.40.11.png

Die am Ende zu verwendende Spalte sollte nach Max-Spalte sortiert sein, einige von oben ausprobieren und unter Berücksichtigung der Suche nach Hyperparametern übernehmen.

df.sort_values(["Max"], ascending=False)
スクリーンショット 2020-01-24 21.45.42.png

abschließend

Ich habe versucht, die Merkmalsmenge durch den genetischen Algorithmus auszuwählen. Es scheint eine Vielzahl genetischer Algorithmen zu geben, und die [DEAP](https: //), die auf der hier Website verwendet wird Sie können auch versuchen, eine Bibliothek wie github.com/DEAP/deap zu verwenden.

Recommended Posts

Merkmalsauswahl durch genetischen Algorithmus
Funktionsauswahl durch sklearn.feature_selection
Funktionsauswahl durch Null-Wichtigkeiten
Feature-Auswahldatensätze
Genetischer Algorithmus in Python
Lineare Programmiermethode nach Automarkierungsmethode
Automatisierung der Algorithmusgenerierung mit genetischen Algorithmen
[Übersetzung] scikit-learn 0.18 Benutzerhandbuch 1.13 Funktionsauswahl
Predictive Power Score für die Funktionsauswahl
Unterstützung der Vektorregression und Merkmalsauswahl
Feature-Generierung mit Pandas gruppieren nach