DEAP: 使变异概率与世代数相关

2024-06-06 09:43:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用的是一个遗传算法,它是用Python的DEAP库实现的。为了避免早熟收敛,并迫使探索的特征空间,我希望变异的概率是高的,在第一代。但是为了防止它们一旦被识别就偏离极值,我希望最后几代的突变概率更低。我怎样才能让突变概率在几代人中降低呢?DEAP中有没有内置函数来完成这个任务?你知道吗

例如,当我注册一个变异函数时

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

indpb参数是一个float。我怎样才能使它成为其他东西的函数呢?你知道吗


Tags: 函数register空间toolbox特征概率tools内置
1条回答
网友
1楼 · 发布于 2024-06-06 09:43:11

听起来像是Callbackproxy的作业,每次调用函数参数时都对其求值。我添加了一个简单的示例,其中修改了官方的DEAPn-queen example 使得突变率被设置为2/N_GENS(任意选择只是为了说明问题)。你知道吗

请注意,Callbackproxy接收lambda,因此必须将突变率参数作为函数传递(可以使用完全展开的函数,也可以仅使用lambda)。不管怎样,结果是每次对indpb参数求值时,都会调用这个lambda,如果lambda包含对全局变量生成计数器的引用,就得到了所需的结果。你知道吗

#    This file is part of DEAP.
#
#    DEAP is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as
#    published by the Free Software Foundation, either version 3 of
#    the License, or (at your option) any later version.
#
#    DEAP is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#    GNU Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with DEAP. If not, see <http://www.gnu.org/licenses/>.

import random
from objproxies import CallbackProxy
import numpy

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

# Problem parameter
NB_QUEENS = 20
N_EVALS = 0
N_GENS = 1

def evalNQueens(individual):
    global N_EVALS, N_GENS
    """Evaluation function for the n-queens problem.
    The problem is to determine a configuration of n queens
    on a nxn chessboard such that no queen can be taken by
    one another. In this version, each queens is assigned
    to one column, and only one queen can be on each line.
    The evaluation function therefore only counts the number
    of conflicts along the diagonals.
    """
    size = len(individual)
    # Count the number of conflicts with other queens.
    # The conflicts can only be diagonal, count on each diagonal line
    left_diagonal = [0] * (2 * size - 1)
    right_diagonal = [0] * (2 * size - 1)

    # Sum the number of queens on each diagonal:
    for i in range(size):
        left_diagonal[i + individual[i]] += 1
        right_diagonal[size - 1 - i + individual[i]] += 1

    # Count the number of conflicts on each diagonal
    sum_ = 0
    for i in range(2 * size - 1):
        if left_diagonal[i] > 1:
            sum_ += left_diagonal[i] - 1
        if right_diagonal[i] > 1:
            sum_ += right_diagonal[i] - 1

    N_EVALS += 1
    if N_EVALS % 300 == 0:
        N_GENS += 1
    return sum_,


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

# Since there is only one queen per line,
# individual are represented by a permutation
toolbox = base.Toolbox()
toolbox.register("permutation", random.sample, range(NB_QUEENS), NB_QUEENS)

# Structure initializers
# An individual is a list that represents the position of each queen.
# Only the line is stored, the column is the index of the number in the list.
toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.permutation)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

toolbox.register("evaluate", evalNQueens)
toolbox.register("mate", tools.cxPartialyMatched)
toolbox.register("mutate", tools.mutShuffleIndexes, indpb=CallbackProxy(lambda: 2.0 / N_GENS))
toolbox.register("select", tools.selTournament, tournsize=3)





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

    pop = toolbox.population(n=300)
    hof = tools.HallOfFame(1)
    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register("Avg", numpy.mean)
    stats.register("Std", numpy.std)
    stats.register("Min", numpy.min)
    stats.register("Max", numpy.max)

    algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=1, ngen=100, stats=stats,
                        halloffame=hof, verbose=True)

    return pop, stats, hof


if __name__ == "__main__":
    main()

相关问题 更多 >