[PYTHON] Sélection des caractéristiques par algorithme génétique

introduction

Existe-t-il un algorithme génétique? 011101010 ... Cela peut-il être utilisé pour la sélection de quantité de fonctions? Quand j'y ai pensé, il y avait une personne qui le faisait naturellement. Je l'ai réorganisé à ma manière en référence au code du pionnier. C'est la nième décoction.

référence

--Sélection de fonctionnalités à l'aide d'un algorithme génétique (https://horomary.hatenablog.com/entry/2019/03/10/190919)

procédure

Implémentation d'algorithme génétique

Pour plus de détails sur l'algorithme génétique, consultez ici. Cet article utilise le problème OneMax comme exemple. Le problème OneMax est un problème qui définit tous les éléments de la séquence [0,1,0,1,1,1,0, ...] donnés comme valeurs initiales à 1, et essaie de le résoudre avec un algorithme génétique. Je vais.

Pour le code, je me suis référé à ce github. Les noms des termes et variables qui apparaissent dans l'algorithme génétique sont [ici](https://www.slideshare.net/kzokm/genetic-algorithm-41617242?ref=https://tech.mof-mof.co.jp /blog/ga-one-max-problem.html) a été mentionné. Pour résumer brièvement, la valeur scalaire qui prend 0 ou 1 est le gène, et la séquence [0,0,1,1,0,1, ...] qui est obtenue en collectant les gènes est le chromosome (chromosome). Corps avec? A été défini comme un individu. De par sa conception, l'individu a un chromosome comme attribut. L'ensemble des individus s'appelle une population. L'algorithme est une sélection d'élite, pas une sélection de roulette.

Les éléments requis pour un algorithme génétique sont:

"""
Écrit par Azunyan https://github.com/Azunyan1111/OneMax
"""
"""
Modifié Copyright 2020 ground0state Tous droits réservés.
"""
import random
import time


class Individual():
    """individuel.
    
    Parameters
    ----------
    chromosome : list of {0 or 1}
Chrome.
        
    evaluation : float
Évaluation.
    """
    chromosome = None
    evaluation = None

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


def create_individual(length):
    """Renvoie l'individu qui a généré et stocké le chromosome aléatoire du chiffre spécifié par l'argument.
    
    Parameters
    ----------
    length : int
Chrome longueur.

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


def evaluate_individual(individual):
    """Fonction d'évaluation.
    
    Parameters
    ----------
    individual : Individual
individuel.
        
    Returns
    -------
    eval : float
Valeur d'évaluation.
    """
    eval = sum(individual.chromosome)/len(individual.chromosome)
    return eval


def extract_elites(population, num):
    """Fonction de sélection.
    
    Parameters
    ----------
    population : list of Individual
Groupe.
    num : int
Nombre de sélections individuelles.
        
    Returns
    -------
    elites : list of Individual
Groupe ayant fait l'objet d'un processus de sélection.
    """        
    #Trier les évaluations de la population de la génération actuelle par ordre décroissant
    sort_result = sorted(population, reverse=True, key=lambda individual: individual.evaluation)
    
    #Extraire certains sommets
    elites = sort_result[:num]
    return elites


def crossover(individual1, individual2, chromosome_length):
    """Fonction de croisement.
Faire un croisement en deux points.
    
    Parameters
    ----------
    individual1 : Individual
Traverser des individus 1.
    individual2 : Individual
Croiser des individus 2.
    chromosome_length : int
Chrome longueur.
        
    Returns
    -------
    offsprings : list of Individual
Deux petits-enfants.
    """
    
    #Définissez deux points à remplacer
    cross_one = random.randint(0, chromosome_length)
    cross_second = random.randint(cross_one, chromosome_length)
    
    #Sortez le gène
    one = individual1.chromosome
    second = individual2.chromosome
    
    #Traverser
    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:]
    
    #descendance
    offsprings = [Individual(progeny_one, 0), Individual(progeny_second, 0)]
    return offsprings


def create_next_generation(population, elites, offsprings):
    """Effectuer le traitement des changements de génération.
    
    Parameters
    ----------
    population : list of Individual
Population de la génération actuelle.
    elites : list of Individual
Groupe élite de la génération actuelle.
    offsprings : list of Individual
Groupe descendant de la génération actuelle.
        
    Returns
    -------
    next_generation_population : list of Individual
Population de la prochaine génération.
    """
    #Trier les évaluations de la population de la génération actuelle par ordre croissant
    next_generation_population = sorted(population, reverse=False, key=lambda individual: individual.evaluation)
    
    #Supprimer le total du groupe élite et du groupe descendant à ajouter
    next_generation_population = next_generation_population[len(elites)+len(offsprings):]
        
    #Ajouter des groupes d'élite et de descendants à la prochaine génération
    next_generation_population.extend(elites)
    next_generation_population.extend(offsprings)
    return next_generation_population


def mutation(population, induvidual_mutation_probability, gene_mutation_probability):
    """Fonction de mutation.
    
    Parameters
    ----------
    population : list of Individual
Groupe.
    induvidual_mutation_probability : float in [0, 1]
Probabilité de mutation individuelle.
    gene_mutation_probability : float in [0, 1]
Probabilité de mutation génique.
        
    Returns
    -------
    new_population : list of Individual
Population mutée.
    """
    new_population = []
    for individual in population:
        #La mutation se produit avec une certaine probabilité pour un individu
        if induvidual_mutation_probability > random.random():
            new_chromosome = []
            for gene in individual.chromosome:
                #Des mutations se produisent pour chaque information génétique individuelle
                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

Utilisez ces classes et fonctions pour exécuter dans le code suivant.

#Chrome longueur
CHROMOSOME_LENGTH = 13

#Taille de groupe
POPULATION_SIZE = 30

#Numéro de sélection du chromosome Elite
PICK_OUT_SIZE = 5

#Probabilité de mutation individuelle
INDIVIDUAL_MUTATION_PROBABILITY = 0.3

#Probabilité de mutation génique
GENE_MUTATION_PROBABILITY = 0.1

#Nombre de générations à répéter
ITERATION = 10


#Initialiser la population de la génération actuelle
current_generation_population = [create_individual(CHROMOSOME_LENGTH) for i in range(POPULATION_SIZE)]

for count in range(ITERATION):
    #Heure de début de chaque boucle
    start = time.time()
    
    #Évaluer les individus de la population de la génération actuelle
    for individual in current_generation_population:
        individual.evaluation = evaluate_individual(individual)

    #Sélectionnez un individu élite
    elites = extract_elites(current_generation_population, PICK_OUT_SIZE)
    
    #Croisez les gènes d'élite et stockez dans la liste
    offsprings = []
    for i in range(0, PICK_OUT_SIZE-1):
        offsprings.extend(crossover(elites[i], elites[i+1], CHROMOSOME_LENGTH))
        
    #Créer la population de la prochaine génération à partir de la génération actuelle, de la population d'élite et de la population descendante
    next_generation_population = create_next_generation(current_generation_population, elites, offsprings)
    
    #Mettre en sourdine tous les individus de la population de prochaine génération
    next_generation_population = mutation(next_generation_population,
                                          INDIVIDUAL_MUTATION_PROBABILITY,
                                          GENE_MUTATION_PROBABILITY)

    #Le calcul évolutif d'une génération est terminé. Passer à l'évaluation

    #Organisez les valeurs d'évaluation de chaque individu.
    fits = [individual.evaluation for individual in current_generation_population]

    #Évaluer les résultats évolutifs
    min_val = min(fits)
    max_val = max(fits)
    avg_val = sum(fits) / len(fits)

    #Sort les résultats d'évolution de la génération actuelle
    print("-----Non.{}Résultats générationnels-----".format(count+1))
    print("  Min:{}".format(min_val))
    print("  Max:{}".format(max_val))
    print("  Avg:{}".format(avg_val))

    #Échangez la génération actuelle avec la prochaine génération
    current_generation_population = next_generation_population
    
    #mesure du temps
    elapsed_time = time.time() - start
    print ("  {}/{} elapsed_time:{:.2f}".format(count+1, ITERATION, elapsed_time) + "[sec]")

#Sortie du résultat final
print("")  #nouvelle ligne
print("Le meilleur individu est{}".format(elites[0].chromosome))

La sortie ressemble à ceci:

-----Résultats de 1ère génération-----
  Min:0.23076923076923078
  Max:0.8461538461538461
  Avg:0.5384615384615384
  1/10 elapsed_time:0.00[sec]
-----Résultats de 2e génération-----
  Min:0.46153846153846156
  Max:0.8461538461538461
  Avg:0.6692307692307694
  2/10 elapsed_time:0.00[sec]
-----Résultats de 3e génération-----
  Min:0.6923076923076923
  Max:0.9230769230769231
  Avg:0.761538461538462
  3/10 elapsed_time:0.00[sec]
-----Résultats de 4e génération-----
  Min:0.6923076923076923
  Max:0.9230769230769231
  Avg:0.8102564102564106
  4/10 elapsed_time:0.00[sec]
-----Résultats de 5e génération-----
  Min:0.6923076923076923
  Max:0.9230769230769231
  Avg:0.8512820512820515
  5/10 elapsed_time:0.00[sec]
-----Résultats de 6e génération-----
  Min:0.7692307692307693
  Max:0.9230769230769231
  Avg:0.848717948717949
  6/10 elapsed_time:0.00[sec]
-----Résultats de 7e génération-----
  Min:0.7692307692307693
  Max:0.9230769230769231
  Avg:0.8948717948717951
  7/10 elapsed_time:0.00[sec]
-----Résultats de 8e génération-----
  Min:0.6153846153846154
  Max:0.9230769230769231
  Avg:0.8974358974358977
  8/10 elapsed_time:0.00[sec]
-----Résultats de la 9e génération-----
  Min:0.7692307692307693
  Max:0.9230769230769231
  Avg:0.9000000000000002
  9/10 elapsed_time:0.00[sec]
-----Résultats de 10e génération-----
  Min:0.8461538461538461
  Max:1.0
  Avg:0.9102564102564105
  10/10 elapsed_time:0.00[sec]

Le meilleur individu est[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

J'ai pu obtenir une personne avec les 1 éléments.

Sélection des caractéristiques par algorithme génétique

J'ai préparé les données et le modèle en me référant à ici.

La préparation des données est le code suivant.

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


#Chargement de l'ensemble de données
X = pd.DataFrame(load_boston().data, columns=load_boston().feature_names)
y = load_boston().target

#Ajout de fonctionnalités polymorphes
poly = PolynomialFeatures(2)
poly.fit(X)
X_poly = pd.DataFrame(poly.transform(X), columns=poly.get_feature_names(input_features=X.columns))

#Standardisation
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 est celui qui utilise PolynomialFeatures pour augmenter la quantité de caractéristiques afin de vérifier le modèle avec une grande quantité de caractéristiques.

Modèle avec l'ensemble de données brutes.

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

#Ensemble de données tel quel
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

Un modèle avec des fonctionnalités polymorphes ajouté.

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


#Lorsqu'un élément polymorphe est ajouté
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

Maintenant, sélectionnons des fonctionnalités avec un algorithme génétique pour ce modèle. C'est la méthode ʻevaluate_individual` qui se modifie. Convertit le chromosome de l'individu en une valeur booléenne en tant qu'entrée et spécifie la colonne à utiliser. Après cela, l'apprentissage et le score sont calculés à l'aide du modèle. Le score est renvoyé comme valeur d'évaluation de l'individu.

def evaluate_individual(individual):
    """Fonction d'évaluation.
    
    Parameters
    ----------
    individual : Individual
individuel.
        
    Returns
    -------
    eval : float
Valeur d'évaluation.
    """
    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

J'ai changé les paramètres comme suit et j'ai essayé d'exécuter.

#Chrome longueur
CHROMOSOME_LENGTH = 13

#Taille de groupe
POPULATION_SIZE = 100

#Numéro de sélection du chromosome Elite
PICK_OUT_SIZE = 20

#Probabilité de mutation individuelle
INDIVIDUAL_MUTATION_PROBABILITY = 0.3

#Probabilité de mutation génique
GENE_MUTATION_PROBABILITY = 0.1

#Nombre de générations à répéter
ITERATION = 10

Le résultat est le suivant.

-----Résultats de 1ère génération-----
  Min:0.245482696210891
  Max:0.7062246093438559
  Avg:0.5643638813331334
  1/10 elapsed_time:13.21[sec]
-----Résultats de 2e génération-----
  Min:0.28765890628509017
  Max:0.7175019664075553
  Avg:0.6611343782899052
  2/10 elapsed_time:14.07[sec]
-----Résultats de 3e génération-----
  Min:0.5958052127889627
  Max:0.7343341487237112
  Avg:0.6840346805288029
  3/10 elapsed_time:14.39[sec]
-----Résultats de 4e génération-----
  Min:0.6011227398695212
  Max:0.7265364514547696
  Avg:0.694531099756538
  4/10 elapsed_time:11.29[sec]
-----Résultats de 5e génération-----
  Min:0.6314510371602322
  Max:0.7249977461594102
  Avg:0.6938166370760438
  5/10 elapsed_time:11.72[sec]
-----Résultats de 6e génération-----
  Min:0.6539907671434392
  Max:0.7256998515926862
  Avg:0.7042345770684423
  6/10 elapsed_time:11.44[sec]
-----Résultats de 7e génération-----
  Min:0.6557998988298114
  Max:0.7273580445493621
  Avg:0.7009249865262361
  7/10 elapsed_time:9.64[sec]
-----Résultats de 8e génération-----
  Min:0.6530159418050802
  Max:0.7250968150681534
  Avg:0.7044189020700958
  8/10 elapsed_time:9.90[sec]
-----Résultats de la 9e génération-----
  Min:0.6087336519329122
  Max:0.7316442169584539
  Avg:0.7008118423172378
  9/10 elapsed_time:9.64[sec]
-----Résultats de 10e génération-----
  Min:0.6328245771251623
  Max:0.7244970729879131
  Avg:0.7034862249363725
  10/10 elapsed_time:13.06[sec]

Le meilleur individu est[1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]

Puisque le score est de «0,72», une meilleure sélection des fonctionnalités est possible.

Classification

Classé pour pouvoir être réutilisé. Créez-le en tant que classe abstraite et héritez-en pour implémenter ʻevaluate_individual`.

"""
Écrit par Azunyan https://github.com/Azunyan1111/OneMax
"""
"""
Modifié Copyright 2020 ground0state Tous droits réservés.
"""
import random
import time
from abc import ABCMeta, abstractmethod


class Individual():
    """individuel.
    
    Parameters
    ----------
    chromosome : list of {0 or 1}
Chrome.
        
    evaluation : float
Évaluation.
    """
    chromosome = None
    evaluation = None

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

        
class GaSolver(metaclass=ABCMeta):
    """Classe abstraite d'algorithme génétique.
Méthode "évaluer" qui génère la valeur d'évaluation pour le chromosome_"individuel" nécessite une mise en œuvre.

    Parameters
    ----------
    chromosome_length : int
Chrome longueur.

    population_size : int
Taille de groupe.
        
    pick_out_size : int
Numéro de sélection du chromosome Elite.

    individual_mutation_probability : float
Probabilité de mutation individuelle.
        
    gene_mutation_probability : float
Probabilité de mutation génique.

    iteration : int
Nombre de générations à répéter.
    """
    
    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):
        """Renvoie l'individu qui a généré et stocké le chromosome aléatoire du chiffre spécifié par l'argument.

        Parameters
        ----------
        length : int
Chrome longueur.

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

    @abstractmethod
    def evaluate_individual(self, individual, X, y):
        """Fonction d'évaluation.

        Parameters
        ----------
        individual : Individual
individuel.
        X : pandas.DataFrame
Variable explicative.
        y : pandas.DataFrame
Variable objectif.

        Returns
        -------
        eval : float
Valeur d'évaluation.
        """
        raise NotImplementedError()

    def _extract_elites(self, population, num):
        """Fonction de sélection.

        Parameters
        ----------
        population : list of Individual
Groupe.
        num : int
Nombre de sélections individuelles.

        Returns
        -------
        elites : list of Individual
Groupe ayant fait l'objet d'un processus de sélection.
        """        
        #Trier les évaluations de la population de la génération actuelle par ordre décroissant
        sort_result = sorted(population, reverse=True, key=lambda individual: individual.evaluation)

        #Extraire certains sommets
        elites = sort_result[:num]
        return elites

    def _crossover(self, individual1, individual2, chromosome_length):
        """Fonction de croisement.
Faire un croisement en deux points.

        Parameters
        ----------
        individual1 : Individual
Traverser des individus 1.
        individual2 : Individual
Croiser des individus 2.
        chromosome_length : int
Chrome longueur.

        Returns
        -------
        offsprings : list of Individual
Deux petits-enfants.
        """

        #Définissez deux points à remplacer
        cross_one = random.randint(0, chromosome_length)
        cross_second = random.randint(cross_one, chromosome_length)

        #Sortez le gène
        one = individual1.chromosome
        second = individual2.chromosome

        #Traverser
        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:]

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

    def _create_next_generation(self, population, elites, offsprings):
        """Effectuer le traitement des changements de génération.

        Parameters
        ----------
        population : list of Individual
Population de la génération actuelle.
        elites : list of Individual
Groupe élite de la génération actuelle.
        offsprings : list of Individual
Groupe descendant de la génération actuelle.

        Returns
        -------
        next_generation_population : list of Individual
Population de la prochaine génération.
        """
        #Trier les évaluations de la population de la génération actuelle par ordre croissant
        next_generation_population = sorted(population, reverse=False, key=lambda individual: individual.evaluation)

        #Supprimer le total du groupe élite et du groupe descendant à ajouter
        next_generation_population = next_generation_population[len(elites)+len(offsprings):]

        #Ajouter des groupes d'élite et de descendants à la prochaine génération
        next_generation_population.extend(elites)
        next_generation_population.extend(offsprings)
        return next_generation_population

    def _mutation(self, population, induvidual__mutation_probability, gene__mutation_probability):
        """Fonction de mutation.

        Parameters
        ----------
        population : list of Individual
Groupe.
        induvidual__mutation_probability : float in [0, 1]
Probabilité de mutation individuelle.
        gene__mutation_probability : float in [0, 1]
Probabilité de mutation génique.

        Returns
        -------
        new_population : list of Individual
Population mutée.
        """
        new_population = []
        for individual in population:
            #La mutation se produit avec une certaine probabilité pour un individu
            if induvidual__mutation_probability > random.random():
                new_chromosome = []
                for gene in individual.chromosome:
                    #Des mutations se produisent pour chaque information génétique individuelle
                    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):
        """Classe principale d'algorithmes génétiques.

        Returns
        -------
        list of {0 or 1}
Le meilleur chromosome individuel.
        """
        self.history = {"Min":[], "Max":[], "Avg":[], "BestChromosome":[]}
        
        #Initialiser la population de la génération actuelle
        current_generation_population = [self._create_individual(self.chromosome_length) for i in range(self.population_size)]
        
        #Évaluer les individus de la population de la génération actuelle
        for individual in current_generation_population:
            individual.evaluation = self.evaluate_individual(individual, X, y)

        for count in range(self.iteration):
            #Heure de début de chaque boucle
            start = time.time()

            #Sélectionnez un individu élite
            elites = self._extract_elites(current_generation_population, self.pick_out_size)

            #Croisez les gènes d'élite et stockez dans la liste
            offsprings = []
            for i in range(0, self.pick_out_size-1):
                offsprings.extend(self._crossover(elites[i], elites[i+1], self.chromosome_length))

            #Créer la population de la prochaine génération à partir de la génération actuelle, de la population d'élite et de la population descendante
            next_generation_population = self._create_next_generation(current_generation_population, elites, offsprings)

            #Mettre en sourdine tous les individus de la population de prochaine génération
            next_generation_population = self._mutation(next_generation_population,
                                                  self.individual_mutation_probability,
                                                  self.gene_mutation_probability)
            
            #Évaluer les individus de la population de la génération actuelle
            for individual in current_generation_population:
                individual.evaluation = self.evaluate_individual(individual, X, y)

            #Le calcul évolutif d'une génération est terminé. Passer à l'évaluation

            #Organisez les valeurs d'évaluation de chaque individu.
            fits = [individual.evaluation for individual in current_generation_population]
            
            #Éliminez l'individu avec la meilleure valeur d'évaluation
            best_individual = self._extract_elites(current_generation_population, 1)
            best_chromosome = best_individual[0].chromosome

            #Évaluer les résultats évolutifs
            min_val = min(fits)
            max_val = max(fits)
            avg_val = sum(fits) / len(fits)

            #Sort les résultats d'évolution de la génération actuelle
            if self.verbose:
                print("-----Non.{}Résultats générationnels-----".format(count+1))
                print("  Min:{}".format(min_val))
                print("  Max:{}".format(max_val))
                print("  Avg:{}".format(avg_val))
                
            #création d'histoire
            self.history["Min"].append(min_val)
            self.history["Max"].append(max_val)
            self.history["Avg"].append(avg_val)
            self.history["BestChromosome"].append(best_chromosome)

            #Échangez la génération actuelle avec la prochaine génération
            current_generation_population = next_generation_population
            
            #mesure du temps
            elapsed_time = time.time() - start
            print ("  {}/{} elapsed_time:{:.2f}".format(count+1, self.iteration, elapsed_time) + "[sec]")

        #Sortie du résultat final
        if self.verbose:
            print("")  #nouvelle ligne
            print("Le meilleur individu est{}".format(elites[0].chromosome))
            
        return self.history

Implémentez le modèle d'apprentissage automatique que vous souhaitez évaluer dans ʻevaluate_individual`.

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

Créez une instance de la classe d'implémentation, transmettez les données et exécutez-la. La méthode résoudre renvoie l'historique historique.

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)

Le résultat de l'exécution est le suivant.

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

Le meilleur individu est[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]

L'histoire ressemble à ceci:

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

La colonne à utiliser à la fin doit être triée par colonne Max, essayez-en par le haut et adoptez-la en tenant compte de la recherche d'hyper paramètres.

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

en conclusion

J'ai essayé de sélectionner le montant de la fonctionnalité par l'algorithme génétique. Il semble y avoir une variété d'algorithmes génétiques, et le [DEAP](https: //) utilisé sur le site ici Vous pouvez également essayer d'utiliser une bibliothèque telle que github.com/DEAP/deap).

Recommended Posts

Sélection des caractéristiques par algorithme génétique
Sélection des fonctionnalités par sklearn.feature_selection
Sélection de fonctionnalités par importances nulles
Ensembles de données de sélection de fonctionnalités
Algorithme génétique en python
Méthode de programmation linéaire par méthode de marqueur de voiture
Automatisation de la génération d'algorithmes à l'aide d'algorithmes génétiques
[Français] scikit-learn 0.18 Guide de l'utilisateur 1.13 Sélection des fonctionnalités
Score de puissance prédictif pour la sélection des fonctionnalités
Prise en charge de la régression vectorielle et de la sélection des fonctionnalités
Génération de fonctionnalités avec pandas group par