Deep Python appris de DEAP

introduction

Connaissez-vous le cadre de calcul évolutif appelé DEAP? e? Calcul d'évolution avant DEAP Quel est cet état? Eh bien, la connaissance préalable des calculs évolutifs n'est pas très pertinente dans cet article. L'objectif principal de cet article est d'expliquer dans quelle mesure DEAP utilise Python pour implémenter des calculs évolutifs et pour aider à améliorer la puissance de Python.

Calculs évolutifs, en particulier sur les algorithmes génétiques

Même si vous dites OK sans aucune connaissance préalable, vous devez comprendre les mots qui apparaîtront après cela, donc je vais expliquer brièvement les calculs évolutifs, en particulier l'algorithme génétique (GA) utilisé pour l'explication.

GA est un algorithme inspiré de l'évolution des organismes vivants, comme on dit qu'il est «génétique». Pourquoi les créatures vivantes survivent-elles? Il y a plusieurs raisons, mais les trois suivants sont les principaux facteurs de GA.

sélection
Les créatures faibles meurent et les créatures fortes survivent. J'expliquerai ce que signifie être fort et faible plus tard.
croisement
Les organismes survivants sont accouplés pour laisser leur progéniture. L'enfant hérite des gènes de ses parents.
mutation
Bien sûr, les créatures que nous avons maintenant ne sont pas du moment où la terre a été créée. Cela a évolué progressivement, mais cela nécessite un enfant avec une partie légèrement différente en plus d'hériter de la nature du parent. Quand il s'accumule, il devient une créature complètement différente.

Au fait, j'ai écrit que les créatures fortes survivent par choix, mais «forte» signifie «haute forme». Vient ensuite "Quel est le degré de conformité?", Mais en GA c'est la "valeur de la fonction objectif que vous voulez résoudre". C'est $ f (\ vec {x}) $. Vient ensuite l'histoire de $ \ vec {x} $.

Expression génétique et manipulation

Je suis finalement arrivé à la partie «génétique» de l'algorithme génétique. «L'héritage» est un gène. Ce gène est $ \ vec {x} $ lorsqu'il est écrit mathématiquement. La représentation génique est grossièrement divisée en deux, et lors du calcul de $ f (\ vec {x}) $, elle est exprimée par une chaîne binaire de 0/1, et elle est calculée en convertissant de 0/1 à la zone de définition de la fonction objectif. C'est une méthode appelée valeur réelle GA qui utilise la valeur numérique telle qu'elle est en tant que "gène".

Dans ** Crossing **, j'ai écrit que les gènes de mes parents sont hérités, mais je coupe et colle les gènes comme suit pour faire un enfant. L'endroit où couper est généralement décidé par un nombre aléatoire.

Père: 01101101 Mère: 11000011
Couper et coller au milieu (l'enfant 1 est la moitié gauche du père + la moitié droite de la mère, l'enfant 1 est la moitié gauche de la mère + la moitié droite du père)
Enfant 1: 01100011 Enfant 2: 11001101

** Mutation ** a une certaine probabilité d'inverser les bits.

Après croisement, mutation enfant 1 (extrémité gauche modifiée de 0 à 1)
Enfant 1: 11100011

La survie ou non de l'enfant ainsi créé dépend du degré d'aptitude (valeur de la fonction objective) de l'enfant. Ceci est la ** sélection **. Faites pivoter cette sélection, ce croisement et cette mutation. Ensuite, l'idée de GA est que les individus avec une grande aptitude (valeur de fonction objective élevée) survivent et la $ \ vec {x} $ (valeur de la variable de conception) souhaitée est obtenue.

Comment traverser (utiliser la technique de croisement), muter ou choisir doit dépendre de la nature du problème. Bien sûr, la nature du problème cible est souvent inconnue, il faut donc «essayer diverses choses».

Eh bien, cela fait longtemps, en disant que c'est facile, mais il est temps d'expliquer les points de DEAP.

Représentation individuelle au DEAP

Jetons un coup d'œil à la Présentation. Il y a d'abord l'expression individuelle. Lorsque nous disons «expression individuelle», nous devons considérer «comment mettre en œuvre le gène» et «comment mettre en œuvre le degré d'aptitude».

Mise en œuvre du fitness

Dans DEAP, la classe qui représente le degré de conformité est définie en premier. C'est déjà intéressant d'ici.

from deap import base, creator
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))

L'aperçu dit: "Cela créera une classe FitnessMin." Non, attendez, que signifie "créer une classe"? N'est-ce pas un appel de fonction? Vous ne pensez pas cela? Ensuite, jetez un œil à creator.create reference (le lien est en anglais)

deap.creator.create(name, base[, attribute[, ...]]) Créez une classe nommée nom qui hérite de base du module créateur. Vous pouvez définir les attributs spécifiés par les arguments de mot-clé après le troisième argument de cette classe. Si l'argument est une classe, l'objet de la classe passé dans l'argument sera créé et défini dans l'attribut lors de la création de l'objet de la classe à créer. Si l'argument n'est pas une classe, il sera défini comme un attribut statique de la classe de création.

La référence montre une définition de classe équivalente à l'écriture de creator.create pour la classe Foo, mais la précédente creator.create (" FitnessMin ", base.Fitness, weights = (-1.0,)) Si vous l'appliquez de la même manière, ce sera comme suit.

Sera exécuté dans le module créateur


class FitnessMin(base.Fitness):
    weights = (-1.0,)

Je savais comment cela fonctionnerait. Mais comment vas-tu? C'est là que ** Python a le concept que les classes sont aussi des objets de première classe ** [^ 1]. [Section d'objet principal de WIkipedia](https://ja.wikipedia.org/wiki/%E7%AC%AC%E4%B8%80%E7%B4%9A%E3%82%AA%E3% 83% 96% E3% 82% B8% E3% 82% A7% E3% 82% AF% E3% 83% 88), mais le plus important est ici.

[^ 1]: Aussi appelé objet de première classe, nous utiliserons le mot «classe» dans cet article car il est différent de la «classe» orientée objet.

Peut être construit au moment de l'exécution.

Oui, Python peut définir des classes lors de l'exécution. C'est rarement nécessaire lors de l'écriture d'un programme normalement, mais il est utile de pouvoir le faire lors de l'écriture d'un framework. Ensuite, jetons un coup d'œil aux Fonctions de type Référence Python.

class type(name, bases, dict) S'il a trois arguments, il renvoie un nouvel objet de type. C'est essentiellement une forme dynamique de déclaration de classe. La chaîne de nom est le nom de la classe et a l'attribut name. Le taple de base est une liste de classes de base qui ont l'attribut bases. Le dictionnaire dict est l'espace de noms qui contient la définition du corps de la classe et est copié dans le dictionnaire standard pour l'attribut dict.

creator.create utilise cette fonction de type pour [définir dynamiquement la classe](https://github.com/DEAP/deap/blob/1.3.0/deap/creator.py#L143 -L171). La fonction globals renvoie un dictionnaire de "variables globales dans un module". En utilisant cela, la classe est définie en l'affectant (elle ne peut pas être référencée à partir d'autres simplement en la créant avec la fonction type). Ne devrions-nous pas simplement définir la classe normalement? Ou que diriez-vous de créer une classe dans le module fourni? Je veux creuser dans diverses choses, mais c'est intéressant donc ça va (rires)

La source d'héritage base.Fitness est également intéressante, mais j'expliquerai le point moe un peu plus tard.

Mise en œuvre de l'individu

L'aperçu définit ensuite la classe individuelle.

creator.create("Individual", list, fitness=creator.FitnessMin)

Les classes suivantes seront définies dans le module créateur par l'opération de creator.create expliquée ci-dessus.

class Individual(list):
    def __init__(self):
        self.fitness = FitnessMin()

Le point important ici est que "un individu est une liste [^ 2]. Ce qu'il faut mettre dans la liste n'a pas été décidé à ce stade."

[^ 2]: Il est possible de faire autre chose qu'une liste de superclasse, et le document donne également un exemple d'héritage d'un ensemble.

Initialisation individuelle

GA génère généralement au hasard les premiers individus pour démarrer la boucle de sélection, de croisement et de mutation. La partie suivante définit la définition correspondante. Pour être précis, à ce stade, l'individu réel n'a pas été généré, juste la définition.

import random
from deap import tools

IND_SIZE = 10

toolbox = base.Toolbox()
toolbox.register("attribute", random.random)
toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attribute, n=IND_SIZE)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

Un nouvel élément est apparu. Classe de boîte à outils. Comme le nom de la boîte à outils l'indique, elle semble s'inscrire pour cela. Pour l'instant, jetez un œil à la référence Toolbox.register (https://deap.readthedocs.io/en/master/api/base.html#deap.base.Toolbox.register).

register(alias, method[, argument[, ...]]) Enregistrez la fonction (argument de méthode) avec l'alias de nom. Vous pouvez définir les arguments par défaut à transmettre à la fonction enregistrée. Il peut être écrasé lorsque la fonction est appelée.

Vérifiez à nouveau le code enregistré sous le nom «individuel».

toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attribute, n=IND_SIZE)

Vous devez consulter la référence tools.initRepeat (https://deap.readthedocs.io/en/master/api/tools.html#deap.tools.initRepeat) pour voir ce que cela fait Il y a.

deap.tools.initRepeat(container, func, n) Appelez la fonction func n fois et appelez la fonction conteneur avec elle comme argument.

Correspondant à la position de container est ʻIndividual. C'était une liste (une classe qui a hérité). func est toolbox.attribute. Ceci est juste un autre nom pour random.random. À partir de là, la méthode suivante est définie en appelant Toolbox.register (" individual ", tools.initRepeat, creator.Individual, toolbox.attribute, n = IND_SIZE)`.

def individual():
    return tools.initRepeat(creator.Individual, random.random, n=IND_SIZE)
    """
Si le traitement de initRepeat est encore développé, ce sera comme suit.
    return Individual([random.random() for _ in range(IND_SIZE)])
    """

En d'autres termes, en appelant ʻindividual () `, nous définissons une méthode qui génère 10 nombres aléatoires de [0, 1) et les emballe dans un individu. Cela signifie que "ce qu'il faut mettre dans la liste" a été défini en réponse au "ce qu'il faut mettre dans la liste n'a pas été décidé à ce stade" que j'ai écrit plus tôt. Cela affecte un peu la structure du programme selon que GA du gène binaire est effectué ou GA de la valeur réelle est effectué, mais dans DEAP, c'est l'un des points moe que "ce qui entre réellement dans la liste" peut être défini relativement facilement. ..

Application partielle

Eh bien, la partie intéressante est d'ici. Dans Toolbox.register," Définir l'argument par défaut sur la fonction passée et lui donner un alias "est terminé. Pourquoi est-ce possible? Ce qui ressort ici est l'idée de ** application partielle **. Pour l'instant, jetons un œil au Toolbox.register code. Collez celui extrait uniquement dans la partie importante.

py:deap/py:base.De py


    def register(self, alias, function, *args, **kargs):
        pfunc = partial(function, *args, **kargs)
        setattr(self, alias, pfunc)

partial est une fonction fournie par le module functools.

functools.partial(func, /, *args, **keywords) Renvoie un nouvel objet partiel. Lorsqu'il est appelé, cet objet se comporte comme une fonction appelée avec l'argument positionnel args et les mots-clés de l'argument mot-clé.

Jetons un coup d'œil à la définition de «population» pour générer une population pour expliquer ce qui est amusant avec une application partielle. La définition d '«individu» est également réimprimée à des fins de comparaison.

toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attribute, n=IND_SIZE)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

Dans ʻindividual, "tous les arguments sont spécifiés" dans ʻinitRepeat, mais dans population, "n n'est pas spécifié". Par conséquent, vous devez spécifier n lorsque vous appelez population.

pop = toolbox.population(n=50)

Lors de la résolution d'un problème avec GA, si vous décidez de l'expression (longueur du gène) du gène pour le problème cible, cela ne change généralement pas. En revanche, si le nombre d'individus est petit ou grand, il sera au milieu et "paramètres à changer de diverses manières". Par conséquent, n est spécifié à chaque fois. Avec une application partielle, vous pouvez créer une fonction plus spécialisée à l'aide d'une fonction à usage général et décrire le processus qui l'utilise.

Définition de la méthode dans DEAP

Maintenant que vous savez ce que fait le reste de la vue d'ensemble, je vais vous l'expliquer pour l'instant.

Il a expliqué que GA essaiera diverses méthodes de sélection, de croisement et de mutation. Chaque méthode a des paramètres spécifiques à la méthode. En revanche, dans le cas du croisement, "prend deux individus comme arguments et renvoie deux descendants", et dans le cas d'une mutation, "prend un individu comme argument et renvoie un individu muté". , S'il est sélectionné, "entrée / sortie générale de l'opération" telle que "prend la population et le nombre de survivants comme arguments et renvoie les individus survivants" est décidé. Une application partielle est également utilisée pour ces derniers, et une méthode est créée dans laquelle les paramètres uniques à la méthode sont partiellement appliqués à chacune des méthodes préparées.

def evaluate(individual):
    return sum(individual),

toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("evaluate", evaluate)

À ce stade, il est important de nommer mate, muter, sélectionner, évaluer lors de l'utilisation de "tout l'algorithme qui transforme GA". EaSimple, qui est l'un des "algorithmes complets", dit ce qui suit: ..

deap.algorithms.eaSimple(population, toolbox, cxpb, mutpb, ngen[, stats, halloffame, verbose]) Cette fonction suppose que l'accouplement, la mutation, la sélection et l'évaluation sont enregistrés dans la boîte à outils.

Cela signifie qu'il peut être appelé correctement en lui donnant un nom que le côté du framework attend.

Suppression du recalcul

Je l'ai écrit pendant longtemps et je l'ai oublié moi-même, mais le dernier point est le point le plus basique. Si vous regardez Tutoriels: Partie 2, vous trouverez quelque chose d'intéressant.

ind1.fitness.values = evaluate(ind1)
print ind1.fitness.valid    # True

Pourquoi valid devient True lorsqu'il est attribué à des valeurs? Ceci est réalisé avec ** Propriétés **. De plus, les valeurs elles-mêmes sont en fait des propriétés. Ici, lorsque l'affectation est faite, celle multipliée par les poids définis au début est conservée. [^ 3]

[^ 3]: Afin de gérer à la fois le problème de minimisation et le problème de maximisation de manière unifiée en inversant le code.

implémentation valide Implémentation des valeurs

Pourquoi y a-t-il quelque chose appelé valide comme ça? Ceci est dû au fait que les croisements et les mutations ont leurs propres taux de croisement et de mutation, respectivement, et en réalité, il y a des cas où «des gènes qui n'ont ni croisé ni muté peuvent être produits». Puisqu'il s'agit du même gène, la valeur de la fonction objective est naturellement la même. Dans ce cas, il est inutile de recalculer et de l'éviter [^ 4].

[^ 4]: Il semble que certaines questions de test prennent plusieurs minutes si ce sont de vraies questions. C'est une histoire sur la puissance de calcul que j'ai entendue il y a longtemps.

Résumé

Jusqu'à présent, nous avons examiné l'arrière-plan profond de DEAP. Certains des mystères Python que vous ne voyez généralement pas et que vous pourrez peut-être utiliser quelque part si vous les connaissez sont:

--Définition dynamique de la classe à l'aide de la fonction de type

J'adore les frameworks qui utilisent pleinement les fonctionnalités du langage, mais j'ai l'impression que DEAP utilise également pleinement Python.

Recommended Posts

Deep Python appris de DEAP
sql à sql
Apprentissage en profondeur Python
MeCab de Python
Apprentissage profond × Python
Apprentissage profond à partir de zéro - Conseils du chapitre 4 pour la théorie de l'apprentissage profond et la mise en œuvre apprise en Python
Résumé Python vs Ruby "Deep Learning from scratch"
Touchez MySQL depuis Python 3
Exploitez Filemaker depuis Python
Utiliser fluentd de python
Python: pratique du Deep Learning
Apprentissage profond à partir de zéro
Accéder à bitcoind depuis python
Changements de Python 3.0 à Python 3.5
Changements de Python 2 à Python 3.0
Python depuis ou import
Utilisez MySQL depuis Python
Exécutez Python à partir d'Excel
Installer Python à partir de la source
Exécuter des commandes depuis Python
Deep Learning from scratch La théorie et la mise en œuvre de l'apprentissage profond appris avec Python Chapitre 3
Iptables appris de la documentation
Faites fonctionner le neutron de Python!
Utiliser MySQL depuis Python
Faire fonctionner LXC depuis Python
Manipuler riak depuis python
Forcer Python depuis Fortran
Python: réglage du Deep Learning
Utilisez BigQuery depuis Python.
Exécuter la commande depuis Python
[Python] Lire depuis Stdin
Utilisez mecab-ipadic-neologd de Python
Aplatir à l'aide du rendement Python de
Appeler CPLEX depuis Python (DO cplex)
Bibliothèque de calcul d'évolution Python Deap
Apprentissage profond à partir de zéro 1 à 3 chapitres
Bibliothèque de calcul d'évolution Python Deap (3)
Publier de Python vers Slack
Refactoring appris avec Python (Basic)
Fonctionnalités de grammaire ajoutées à partir de Python3.6
Flirter de PHP à Python
Programmation tirée des livres le 8 mai
Rendre MeCab disponible à partir de Python 3
Informations obtenues à partir de tweet_id (Python)
OCR à partir de PDF en Python
Exécutez le script illustrator à partir de python
Utiliser MySQL depuis Anaconda (python)
Copie superficielle Python et copie profonde
Anaconda mis à jour de 4.2.0 à 4.3.0 (python3.5 mis à jour vers python3.6)
Étude de Python Hour4: orientée objet ②
Interroger Athena depuis Lambda Python
Accéder à Oracle DB depuis Python
Copie superficielle Python et copie profonde
Étude de Python Hour3: Fonctions
Démarrer / arrêter GCE à partir de python
Programmation tirée des livres le 9 mai
Classe Python pour apprendre avec la chimioinfomatique
Arrêtez Omxplayer à partir du code Python
Passer de python2.7 à python3.6 (centos7)
Connectez-vous à sqlite depuis python
Programmation tirée des livres du 11 mai