how to write a python code that takes in a 7-dim individual and do the NSGA-III genetic programming

74 Views Asked by At

I am not familiar with python library DEAP but I need to use genetic programming. So I searched the documentation and found this example. Basically what i wanna do is using the random forest algorithm to calculate each x[i]'s corresponding y_pred[i],I have successfully trained the random forest model,but now I failed when rewriting the problem class and register my own function in the toolbox,because it seems that the initRepeat() func in toolbox can not take in 7 dimentional individual?

I tried to rewrite the problem class and redefine the Uniform function in the tool box,but they are not working.Also,I dont know how to add my own constraints to do the optimization.Here is my code

import numpy as np from pymop.problem import Problem


# load s
s_data_dict =[75.975675, 86.552998, 77.722619, 74.639755, 73.769642, 76.993251, 74.959511]
# load a
a_data_dict = [   3.733890,3.648111, 3.475229, 3.378360,3.252198,3.120699,  2.997476]


class MyCustomProblem(Problem):
    def __init__(self):
        # 定义问题属性,如变量数目、目标数目、变量边界等
        super().__init__(n_var=7, n_obj=2, n_constr=0, xl=[3.7, 3.7, 3.7, 3.7, 3.7,3.7, 3.7],xu=[10, 10,10,10, 10, 10, 10] )
        self.s_data_dict = s_data_dict
        self.a_data_dict = a_data_dict
        self.rf_regressor = rf_regressor

    def _evaluate(self, x, out, *args, **kwargs):
        # 实现问题的评估函数
        # x是个体的决策变量值
        # out是包含目标函数值的数组
        y_pred=[]
        for i in range(self.n_var):
            x_to_predict=x[i]
            tem=rf_regressor.predict(x_to_predict)
            y_pred.append(tem[0])

        # 计算目标函数值
        for i in range(self.n_var):
            f1 += (y_pred[i] - self.s_data_dict[i])**2
            f2 += y_pred[i] * (x[i] - self.a_data_dict[i])
        

        # 将目标函数值存储在out数组中
        out["F"] = [f1, f2]


from math import factorial
import random

import matplotlib.pyplot as plt
import numpy
import pymop.factory

from deap import algorithms
from deap import base
from deap.benchmarks.tools import igd
from deap import creator
from deap import tools

# Problem definition
PROBLEM = "dtlz2"
NOBJ = 3
K = 10
NDIM = NOBJ + K - 1
P = 12
H = factorial(NOBJ + P - 1) / (factorial(P) * factorial(NOBJ - 1))
BOUND_LOW = [3.7, 3.7, 3.7, 3.7, 3.7,3.7, 3.7]  # 下界列表
BOUND_UP = [10, 10,10,10, 10, 10, 10]  # 上界列表
problem = pymop.factory.get_problem(PROBLEM, n_var=NDIM, n_obj=NOBJ)
##

# Algorithm parameters
MU = int(H + (4 - H % 4))
NGEN = 400
CXPB = 1.0
MUTPB = 1.0
##

# Create uniform reference point
ref_points = tools.uniform_reference_points(NOBJ, P)

# Create classes
creator.create("FitnessMin", base.Fitness, weights=(-1.0,) * NOBJ)
creator.create("Individual", list, fitness=creator.FitnessMin)
##

def uniform(low, up):
    return [random.uniform(a, b) for a, b in zip(low, up)]
#not working



toolbox = base.Toolbox()
toolbox.register("attr_float", uniform, [BOUND_LOW] * 7, [BOUND_UP] * 7)
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.attr_float)#表示现在是7元变量
toolbox.register("population", tools.initRepeat, list, toolbox.individual)


toolbox.register("evaluate", problem.evaluate, return_values_of=["F"])
toolbox.register("mate", tools.cxSimulatedBinaryBounded, low=BOUND_LOW, up=BOUND_UP, eta=30.0)
toolbox.register("mutate", tools.mutPolynomialBounded, low=BOUND_LOW, up=BOUND_UP, eta=20.0, indpb=1.0/NDIM)
toolbox.register("select", tools.selNSGA3, ref_points=ref_points)
##


def main(seed=None):
    random.seed(seed)

    # Initialize statistics object
    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("avg", numpy.mean, axis=0)
    stats.register("std", numpy.std, axis=0)
    stats.register("min", numpy.min, axis=0)
    stats.register("max", numpy.max, axis=0)

    logbook = tools.Logbook()
    logbook.header = "gen", "evals", "std", "min", "avg", "max"

    pop = toolbox.population(n=MU)

    # Evaluate the individuals with an invalid fitness
    invalid_ind = [ind for ind in pop if not ind.fitness.valid]
    fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
    for ind, fit in zip(invalid_ind, fitnesses):
        ind.fitness.values = fit

    # Compile statistics about the population
    record = stats.compile(pop)
    logbook.record(gen=0, evals=len(invalid_ind), **record)
    print(logbook.stream)

    # Begin the generational process
    for gen in range(1, NGEN):
        offspring = algorithms.varAnd(pop, toolbox, CXPB, MUTPB)

        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = toolbox.map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # Select the next generation population from parents and offspring
        pop = toolbox.select(pop + offspring, MU)

        # Compile statistics about the new population
        record = stats.compile(pop)
        logbook.record(gen=gen, evals=len(invalid_ind), **record)
        print(logbook.stream)

    return pop, logbook


if __name__ == "__main__":
    pop, stats = main()
    pop_fit = numpy.array([ind.fitness.values for ind in pop])

    pf = problem.pareto_front(ref_points)
    print(igd(pop_fit, pf))

    import matplotlib.pyplot as plt
    import mpl_toolkits.mplot3d as Axes3d

    fig = plt.figure(figsize=(7, 7))
    ax = fig.add_subplot(111, projection="3d")

    p = numpy.array([ind.fitness.values for ind in pop])
    ax.scatter(p[:, 0], p[:, 1], p[:, 2], marker="o", s=24, label="Final Population")

    ax.scatter(pf[:, 0], pf[:, 1], pf[:, 2], marker="x", c="k", s=32, label="Ideal Pareto Front")

    ref_points = tools.uniform_reference_points(NOBJ, P)

    ax.scatter(ref_points[:, 0], ref_points[:, 1], ref_points[:, 2], marker="o", s=24, label="Reference Points")

    ax.view_init(elev=11, azim=-25)
    ax.autoscale(tight=True)
    plt.legend()
    plt.tight_layout()
    plt.savefig("nsga3.png")

It gives me this error message:

520 def uniform(self, a, b): 521 "Get a random number in the range [a, b) or [a, b] depending on rounding." --> 522 return a + (b - a) * self.random() TypeError: unsupported operand type(s) for -: 'list' and 'list'

0

There are 0 best solutions below