【问题标题】:Why scipy.optimize.differential_evolution does not return last population?为什么 scipy.optimize.differential_evolution 不返回最后一个人口?
【发布时间】:2021-12-27 09:18:46
【问题描述】:

差分进化是基于种群的算法。但是,scipy.optimize.differential_evolution 返回结果为OptimizeResult,它只给出了人口中最优秀的精英,而忽略了其他一代。

有人如何保存有关最后人口的信息?

【问题讨论】:

    标签: optimization genetic-algorithm scipy-optimize evolutionary-algorithm differential-evolution


    【解决方案1】:

    我发现返回最后一个种群的一种方法是下载 source code 并直接使用 DifferentialEvolutionSolver 类:

    solver = DifferentialEvolutionSolver(fun, bounds, arg**)
    solver.init_population_random()
    solver.__next__() # for each generation
    
    last_pop = solver.population
    las_pop_costs = solver.population_energies
    

    【讨论】:

    • 这个答案是正确的,但请记住 DifferentialEvolutionSolver 类是私有的(你不能 from scipy.optimize import DifferentialEvolutionSolver),因此可能会发生变化。例如。该类可能会被重命名,等等。
    【解决方案2】:

    使用workers 关键字的能力可以在每次迭代中保持试验总体,以接受类似于地图的callable,该callable 被发送整个试验总体并预期返回一个包含评估函数值的数组对于整个试验人群:

    from scipy.optimize import rosen, differential_evolution
    bounds=[(0, 10), (0, 10)]
    
    # pop will retain the trial population at each iteration of the minimisation
    pop = []
    energies = []
    
    def maplike_fun(func, x):
        # x.shape == (S, N), where S is the size of the population and N
        # is the number of parameters. The rosen function is vectorised,
        # so calling rosen with x.T will return an array of shape (S,)
        # you could also do:
        # v = np.array(list(map(func, x)))
        pop.append(np.copy(x))
        e = func(x.T)
        energies.append(e)
        return e
    
    res = differential_evolution(rosen, bounds, workers=maplike_fun, polish=False, updating='deferred')
    # the initial evaluation of the population is not counted in the number
    # of iterations, so pop[0] is the initial population.
    assert res.nit == len(pop) - 1
    

    要在每次迭代中获得实际总体,您需要遍历试验总体列表并连续更新pop[0]

    pop_up = [pop[0]]
    energies_up = [energies[0]]
    for i in range(1, len(pop)):
        new_energies = np.copy(energies_up[-1])
        new_pop = np.copy(pop_up[-1])
    
        pos = energies[i] < new_energies
        new_energies[pos] = energies[i][pos]
        new_pop[pos] = pop[i][pos]
        
        pop_up.append(new_pop)
        energies_up.append(new_energies)
    

    然后由pop_up 描述实际的种群进化。

    从 scipy 1.9 开始,还有一个 vectorized 关键字,它将在每次迭代时将整个试验群体发送到目标函数。

    【讨论】:

      猜你喜欢
      • 2016-05-07
      • 2020-02-07
      • 1970-01-01
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      • 2021-05-24
      • 2021-09-20
      相关资源
      最近更新 更多