Bibliothèque de calcul d'évolution Python Deap (2)

Symbolic Regression Ceci est une continuation de l'introduction de la bibliothèque de calcul d'évolution Python Deap publiée la dernière fois. Cette fois, nous examinerons la régression symbolique dans l'exemple de programmation génétique (GP). GP permet de manipuler le génotype de l'algorithme génétique (GA) avec une structure arborescente ou une structure graphique, et la régression symbolique est un problème typique de la GP. Le contenu spécifique est le problème de l'identification des fonctions quaternaires suivantes dans la plage $ [-1, 1] $.

f(x)=x^4+x^3+x^2+x

La fonction d'évaluation est exprimée par l'erreur entre l'équation estimée $ prog (x) $ et la vraie équation $ f (x) $ à 20 points entre -1 et 1.

\sum_{i=1}^{20} |prog(x_i) - f(x_i)|^2

Regardons en fait le contenu de l'exemple. Tout d'abord, importez le module.

import operator
import math
import random

import numpy

from deap import algorithms
from deap import base
from deap import creator
from deap import tools
from deap import gp

Ensuite, créez un ensemble de primitives qui seront chaque nœud de la structure arborescente. Ici, les opérations arithmétiques de base, les fonctions triangulaires et les nombres aléatoires temporaires sont inclus dans l'ensemble.

# Define new functions
def safeDiv(left, right):
    try:
        return left / right
    except ZeroDivisionError:
        return 0

pset = gp.PrimitiveSet("MAIN", 1)
pset.addPrimitive(operator.add, 2)
pset.addPrimitive(operator.sub, 2)
pset.addPrimitive(operator.mul, 2)
pset.addPrimitive(safeDiv, 2)
pset.addPrimitive(operator.neg, 1)
pset.addPrimitive(math.cos, 1)
pset.addPrimitive(math.sin, 1)
pset.addEphemeralConstant("rand101", lambda: random.randint(-1,1))
pset.renameArguments(ARG0='x')

Afin d'éviter l'erreur due à la division zéro, la division est nouvellement définie et ajoutée à la primitive, et les autres utilisent les fonctions du module opérateur et du module mathématique de python. Le deuxième argument de addPrimitive indique le nombre d'arguments pour la fonction primitive. addEphemeralConstant est utilisé lorsque la fin d'un nœud utilise une valeur générée à partir d'une fonction telle qu'un nombre aléatoire au lieu d'une constante. Ici vous pouvez voir que nous définissons un nombre aléatoire qui générera l'un de -1,0,1. Je ne pense pas que ce sera beaucoup choisi dans ce numéro, mais ... Le deuxième argument du PrimitiveSet indique le nombre d'entrées de programme. Cette fois, il n'y en a qu'un, il est nommé "ARG0" par défaut, mais je l'ai renommé en "x" dans renameArguments.

creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", gp.PrimitiveTree, fitness=creator.FitnessMin)

Ensuite, comme dans l'exemple GA précédent, utilisez ** creator ** pour définir le problème de minimisation et le type individuel.


toolbox = base.Toolbox()
toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=2)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("compile", gp.compile, pset=pset)

def evalSymbReg(individual, points):
    #Conversion de la représentation arborescente en fonction
    func = toolbox.compile(expr=individual)
    #Calcul de l'erreur quadratique moyenne entre la formule estimée et la formule vraie
    sqerrors = ((func(x) - x**4 - x**3 - x**2 - x)**2 for x in points)
    return math.fsum(sqerrors) / len(points),

toolbox.register("evaluate", evalSymbReg, points=[x/10. for x in range(-10,10)])
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("mate", gp.cxOnePoint)
toolbox.register("expr_mut", gp.genFull, min_=0, max_=2)
toolbox.register("mutate", gp.mutUniform, expr=toolbox.expr_mut, pset=pset)

Ensuite, en utilisant ** toolbox **, nous créerons des méthodes de génération d'individus et de population, des fonctions d'évaluation, des intersections, des mutations, des méthodes de sélection, etc. gp.genHalfAndHalf est une fonction qui crée des arbres, mais min_ et max_ spécifient les profondeurs minimale et maximale de l'arbre, et genGrow (génération d'arbres où la profondeur de chaque nœud feuille peut être différente) Il est conçu pour faire genFull (génération d'arbres avec la même profondeur de chaque nœud de feuille) en deux. gp.compile crée une fonction qui peut réellement être exécutée à partir d'un individu. À la fin, la mutation est spécifiée en ajoutant un nouveau sous-arbre au nœud.

def main():
    random.seed(318)

    pop = toolbox.population(n=300)
    hof = tools.HallOfFame(1)
    
    stats_fit = tools.Statistics(lambda ind: ind.fitness.values)
    stats_size = tools.Statistics(len)
    mstats = tools.MultiStatistics(fitness=stats_fit, size=stats_size)
    mstats.register("avg", numpy.mean)
    mstats.register("std", numpy.std)
    mstats.register("min", numpy.min)
    mstats.register("max", numpy.max)

    pop, log = algorithms.eaSimple(pop, toolbox, 0.5, 0.1, 40, stats=mstats,
                                   halloffame=hof, verbose=True)
    #Afficher le journal
    return pop, log, hof
if __name__ == "__main__":
    main()

Ensuite, créez la fonction principale et exécutez-la. Tout d'abord, définissez les informations statistiques que vous souhaitez calculer afin d'obtenir les informations statistiques, puis générez la population initiale et effectuez le calcul d'évolution avec eaSimple. Lorsqu'elles sont exécutées, les informations statistiques pour chaque génération seront sorties comme indiqué ci-dessous.

   	      	                fitness                	              size             
   	      	---------------------------------------	-------------------------------
gen	nevals	avg    	max    	min     	std    	avg    	max	min	std    
0  	300   	2.36554	59.2093	0.165572	4.63581	3.69667	7  	2  	1.61389
1  	146   	1.07596	10.05  	0.165572	0.820853	3.85333	13 	1  	1.79401
2  	169   	0.894383	6.3679 	0.165572	0.712427	4.2    	13 	1  	2.06398
3  	167   	0.843668	9.6327 	0.165572	0.860971	4.73333	13 	1  	2.36549
4  	158   	0.790841	16.4823	0.165572	1.32922 	5.02   	13 	1  	2.37338
5  	157   	0.836829	67.637 	0.165572	3.97761 	5.59667	13 	1  	2.20771
6  	179   	0.475982	3.53043	0.150643	0.505782	6.01   	14 	1  	2.02564
7  	176   	0.404081	2.54124	0.150643	0.431554	6.42   	13 	1  	2.05352
8  	164   	0.39734 	2.99872	0.150643	0.424689	6.60333	14 	3  	2.10063
9  	161   	0.402689	13.5996	0.150643	0.860105	6.61333	13 	3  	2.05519
10 	148   	0.392393	2.9829 	0.103868	0.445793	6.74333	15 	1  	2.39669
11 	155   	0.39596 	7.28126	0.0416322	0.578673	7.26333	15 	1  	2.53784
12 	163   	0.484725	9.45796	0.00925063	0.733674	8.16   	17 	1  	2.74489
13 	155   	0.478033	11.0636	0.0158757 	0.835315	8.72333	21 	1  	3.04633
14 	184   	0.46447 	2.65913	0.0158757 	0.562739	9.84333	23 	1  	3.17681
15 	161   	0.446362	5.74933	0.0158757 	0.700987	10.5367	23 	2  	3.29676
16 	187   	0.514291	19.6728	0.013838  	1.44413 	11.8067	25 	1  	4.25237
17 	178   	0.357693	3.69339	0.00925063	0.456012	12.7767	29 	1  	5.3672 
18 	163   	0.377407	14.2468	0.00925063	0.949661	13.4733	35 	1  	5.67885
19 	155   	0.280784	9.55288	0.00925063	0.691295	15.2333	36 	2  	5.7884 
20 	165   	0.247941	2.89093	0.00925063	0.416445	15.63  	31 	3  	5.66508
21 	160   	0.229175	2.9329 	0.00182347	0.406363	16.5033	37 	2  	6.44593
22 	165   	0.183025	3.07225	0.00182347	0.333659	16.99  	32 	2  	5.77205
23 	156   	0.22139 	2.49124	0.00182347	0.407663	17.5   	42 	1  	6.7382 
24 	167   	0.168575	1.98247	5.12297e-33	0.272764	17.48  	43 	3  	6.21902
25 	166   	0.177509	2.3179 	5.12297e-33	0.330852	16.9433	36 	1  	6.6908 
26 	152   	0.187417	2.75742	5.12297e-33	0.382165	17.2267	47 	3  	6.21734
27 	169   	0.216263	3.37474	5.12297e-33	0.419851	17.1967	47 	3  	6.00483
28 	176   	0.183346	2.75742	5.12297e-33	0.295578	16.7733	42 	3  	5.85052
29 	159   	0.167077	2.90958	5.12297e-33	0.333926	16.59  	45 	2  	5.75169
30 	171   	0.192057	2.75742	5.12297e-33	0.341461	16.2267	53 	3  	5.48895
31 	209   	0.279078	3.04517	5.12297e-33	0.455884	15.84  	32 	3  	5.60188
32 	161   	0.291415	19.9536	5.12297e-33	1.22461 	16.0267	35 	3  	5.45276
33 	157   	0.16533 	2.54124	5.12297e-33	0.316613	15.5033	33 	2  	5.08232
34 	159   	0.164494	2.99681	5.12297e-33	0.316094	15.4567	33 	1  	4.99347
35 	157   	0.158183	2.9829 	5.12297e-33	0.309021	15.3133	34 	2  	4.54113
36 	172   	0.203184	3.00665	5.12297e-33	0.380584	15.12  	29 	1  	4.70804
37 	181   	0.251027	4.66987	5.12297e-33	0.483365	15.18  	36 	1  	5.6587 
38 	141   	0.249193	12.8906	5.12297e-33	0.848809	15.1633	36 	1  	5.38114
39 	158   	0.188209	2.33071	5.12297e-33	0.346345	15.1967	32 	1  	4.82887
40 	165   	0.220244	2.3179 	5.12297e-33	0.381864	15.44  	33 	2  	5.70787
    expr = toolbox.individual()
    nodes, edges, labels = gp.graph(expr)
    import matplotlib.pyplot as plt
    import networkx as nx

    g = nx.Graph()
    g.add_nodes_from(nodes)
    g.add_edges_from(edges)
    pos = nx.graphviz_layout(g, prog="dot")

    nx.draw_networkx_nodes(g, pos)
    nx.draw_networkx_edges(g, pos)
    nx.draw_networkx_labels(g, pos, labels)
    plt.show()

Enfin, essayons de dessiner l'arbre finalement optimisé. Networkx et matplotlib sont utilisés pour le dessin. Ci-dessous, la structure de l'arbre obtenue par cette optimisation.

symreg.png

Faisons un graphique pour voir si une fonction proche de la fonction réelle est vraiment obtenue. Le rouge est la vraie fonction et le vert est le résultat de l'estimation, mais ce n'est pas bon. Il peut être amélioré en ajoutant d'autres profondeurs d'arbres et primitives, mais pour l'instant, laissons-le ici.

diff_func.png

référence

Exemple de régression symbolique: http://deap.gel.ulaval.ca/doc/dev/examples/gp_symbreg.html

Recommended Posts

Bibliothèque de calcul d'évolution Python Deap
Bibliothèque de calcul d'évolution Python Deap (3)
Bibliothèque de calcul d'évolution Python Deap (2)
Bibliothèque de messagerie Python 3.6
Bibliothèque Python AST
Note sur la bibliothèque Python
Perceuse de calcul Python
bibliothèque de commerce d'algorithmes python
Bibliothèque d'optimisation Python Pulp
Exercice de calcul Python (extension)
Aim Python Library Master (48) Autopep8
Aim Python Library Master (36) json2html
Aim Python Library Master (49) psidialogs
Aim Python Library Master (26) easyxml
Aim python library master (29) table_printer
Espaces de noms Aim Python Library Master (55)
AIM Python Library Master (46) BrowserPlus
Aim Python Library Master (30) Chronyk
AIM Python Library Master (3) Workalendar
Aim Python Library Master (42) Speedrecorder
Aim Python Library Master (37) Slimurl
Recommandation de la bibliothèque binpacking de python
Aim Python Library Master (44) pynetviz
Aim Python Library Master (8) Rolex
Aim Python Library Master (52) Marktime
Aim Python Library Master (7) Numparser
Aim Python Library Master (21) hy
Viser les requêtes du maître de bibliothèque python (18)
Windows10: installation de la bibliothèque dlib pour python
Aim Python Library Master (13) Easydev
Aim Python Library Master (20) Pyyaml
Aim Python Library Master (34) simultané
Viser la segmentation de mots du maître de la bibliothèque python
Aim Python Library Master (43) cpmoptimize
Aim Python Library Master (68) pazudorasolver
Aim Python Library Master (58) Faker
Aim Python Library Master (11) nlist
Aim Python Library Master (65) Geopy
Journal de bord Aim Python Library Master (59)
Aim Python Library Master (51) Pyautogui
Aim Python Library Master (10) Timeit
Aim Python Library Master (66) youtube-dl
Remplacer les fonctions de bibliothèque en Python
Aim Python Library Master (53) psutil
Aim Python Library Master (22) HTMltag
Aim Python Library Master (67) httpie
Aim Python Library Master (45) xlsxwriter
Aim Python Library Master (9) WebHelpers
Aim Python Library Master (32) SQL
Aim Python Library Master (60) Colourettu
Viser maître de la bibliothèque python (64) pretty_cron
Aim Python Library Master (56) colorthief
Aim Python Library Master (61) recherche imbriquée
Aim Python Library Master (17) Rangeparser
Aim Python Library Master (47) Deckor
Aim Python Library Master (25) Orderset
Viser le maître de la bibliothèque python (62)
Aim Python Library Master (12) Excel
Aim Python Library Master (24) combi