Можно ли использовать DEAP для мультимодальной оптимизации?

Из документации и примеров (здесь, здесь, здесь) для DEAP я нашел несколько примеров использования DEAP для многоцелевой оптимизации, но ничего о многомодальной оптимизации.

Можно ли использовать структуру DEAP для эволюционной мультимодальной оптимизации, аналогично тому, что описано в эта статья? Есть ли примеры того, как это делается?


comment
Да и нет. У генетических алгоритмов есть средства избежать локальных решений (мутаций). Но поскольку это просто эвристики, они обычно не находят глобального оптимального решения. Конечно, во многих практических случаях хорошее решение может оказаться вполне приемлемым.   -  person Erwin Kalvelagen    schedule 30.10.2019
comment
@ErwinKalvelagen Спасибо, что нашли время оставить комментарий. Однако я не понимаю, как это относится к моему вопросу. Генетические алгоритмы можно использовать для мультимодальной оптимизации с использованием стратегий нишевого/краудсорсинга. Я хотел бы знать, есть ли примеры использования DEAP для этого.   -  person usernumber    schedule 30.10.2019


Ответы (1)


DEAP не имеет встроенной поддержки мультимодальной оптимизации. Однако его можно использовать для решения таких задач, просто указав правильную фитнес-функцию.

import numpy as np
import random
import math
import matplotlib.pyplot as plt
from scipy.spatial import distance_matrix
from deap import base, tools, creator, algorithms

npop = 1000
sigma = 0.3
alpha = 2

# Here is a function with many local maxima
def objective(x, y):
    return np.exp(-9*abs(x*y)) * np.sin(3*math.pi*x)**2 * np.sin(3*math.pi*y)**2

def fitness(individual):
    return objective(individual[0], individual[1]),

xrange = np.arange(0., 1., 0.01)
X, Y = np.meshgrid(xrange, xrange)
zs = np.array(objective(np.ravel(X), np.ravel(Y)))
Z = zs.reshape(X.shape)

# Setup the DEAP toolbox
toolbox = base.Toolbox()

creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)
toolbox.register("individual", tools.initRepeat, creator.Individual, random.random, n=2)

toolbox.register("population", tools.initRepeat, list, toolbox.individual)

toolbox.register('mutate', tools.mutPolynomialBounded, eta=.6, low=[0,0], up=[1,1], indpb=0.1)
toolbox.register('mate', tools.cxUniform, indpb=0.5)
toolbox.register('select', tools.selBest)

# Register a shared fitness function
def sharing(distance, sigma, alpha):
    res = 0
    if distance<sigma:
        res += 1 - (distance/sigma)**alpha
    return res

def shared_fitness(individual, population, sigma, alpha):
    num = fitness(individual)[0]

    dists = distance_matrix([individual], population)[0]
    tmp = [sharing(d, sigma, alpha) for d in dists]
    den = sum(tmp)

    return num/den,

pop = toolbox.population(n=npop)

toolbox.register('evaluate', shared_fitness, population=pop, sigma=sigma, alpha=alpha)

# Run the optimization algorithm
mu = int(len(pop)*0.5)
lambda_ = int(len(pop)*0.5)
cxpb = 0.4
mutpb = 0.5
ngen = 10

pop, logbook = algorithms.eaMuPlusLambda(pop, toolbox, mu, lambda_, cxpb, mutpb, ngen)

fig = plt.figure()
ax = fig.add_subplot(111)
sc = ax.scatter(X, Y, c=Z)
plt.colorbar(sc) 
ax.scatter(*zip(*pop), color='red')

При этом популяция распределяется по нишам, и можно выделить каждый локальный максимум.

Конечный результат

person usernumber    schedule 12.11.2019
comment
Работает как рекламируется, спасибо. Небольшая рекомендация: в функции shared_fitness() вы можете получить предупреждения NumPy о делении на ноль. Подумайте о том, чтобы поймать их. - person Laryx Decidua; 12.11.2019
comment
@LaryxDecidua Ловушка? - person usernumber; 13.11.2019
comment
захват в смысле if abs(den) < 1.0e-7: ..., т. е. определение, когда знаменатель близок к 0,0, а затем его обработка. NumPy выдает предупреждение и продолжает работу. Стандартный Python вызовет исключение. - person Laryx Decidua; 13.11.2019
comment
@LaryxDecidua Расстояние от точки до самой себя равно 0, а sharing(0,...) равно 1. Таким образом, знаменатель представляет собой сумму 1 плюс некоторые положительные значения. Это означает, что знаменатель всегда должен быть больше 1, и поэтому никогда не возникает ошибка деления на ноль. - person usernumber; 19.11.2019
comment
Хм, интересно, я получал такие сообщения об ошибках. Нужно еще раз проверить код. Спасибо - person Laryx Decidua; 19.11.2019
comment
@LaryxDecidua Я понял, откуда может появиться такое сообщение об ошибке. При оценке потомства особи потомства еще не включены в список населения. Таким образом, общая пригодность этих потомков может быть очень близка к 0. - person usernumber; 19.11.2019
comment
Решением было бы проверить, входит ли человек в популяцию, и если нет, то добавить 1 к знаменателю. - person usernumber; 19.11.2019
comment
@LaryxDecidua спасибо, что указали на это. Это подняло интересные вопросы о внутренней работе алгоритма. - person usernumber; 19.11.2019