美文网首页
Differential Evolution: A Survey

Differential Evolution: A Survey

作者: 馒头and花卷 | 来源:发表于2020-04-13 23:46 被阅读0次

    @[TOC]

    Das S, Suganthan P N. Differential Evolution: A Survey of the State-of-the-Art[J]. IEEE Transactions on Evolutionary Computation, 2011, 15(1): 4-31.

    @article{das2011differential,
    title={Differential Evolution: A Survey of the State-of-the-Art},
    author={Das, Swagatam and Suganthan, P N},
    journal={IEEE Transactions on Evolutionary Computation},
    volume={15},
    number={1},
    pages={4--31},
    year={2011}}

    这是一篇关于Differential Evolution (DE) 的综述, 由于对这类方法并不熟悉, 只能简单地做个记录.

    主要内容

    考虑如下问题,
    \min \: f(X),
    其中X=(x_1,\ldots,x_D).

    我所知的, 如梯度下降方法, 贝叶斯优化可以用来处理这类问题, 但是还有诸如 evolutionary algorithm (EA), evolutionary programming (EP), evolution strategies(ESs), genetic algorithm (GA), 以及本文介绍的 DE (后面的基本都不了解).

    DE/rand/1/bin

    先给出最初的形式, 称之为DE/rand/1/bin:

    Input: scale factor F, crossover rate Cr, population size NP.
    1:G=0, 并随机初始化P_G=\{ X_{1,G},\ldots, X_{NP,G}\}.
    2: While the stopping criterion is not satisfied Do:

    • For i=1,\ldots, NP do:
    1. Mutation step:
      V_{i,G} = X_{r_1^i,G} + F \cdot (X_{r_2^i,G} - X_{r_3^i,G}).
    2. Crossover step: 按照如下方式生成U_{i,G}=(u_{1,i,G},\ldots, u_{D,i,G})
      u_{j,i,G} = \left \{ \begin{array}{ll} v_{j,i,G} & if \: \mathrm{rand}[0,1] \le Cr \: or \: j=j_{rand} \\ x_{j,i,G} & otherwise. \end{array} \right.
    3. Selection step:
      X_{i,G} = \left \{ \begin{array}{ll} U_{i,G} & if \: f(U_{i,G}) \le f(X_{i,G}) \\ X_{i,G} & otherwise. \end{array} \right.
    • End For.
    • G=G+1.
      End While.

    其中X_{i,G}=(x_{j,i,G}, \ldots, x_{D,i,G}), j_{rand}是预先随机生成的一个属于[1,D]的整数, 以保证U相对于X至少有些许变化产生, X_{r_1^i,G}, X_{r_2^i,G},X_{r_3^i,G}是从P_G中随机抽取且互异的.

    在接下来我们可以发现很多变种, 而这些变种往往是Mutation step 和 Crossover step的变体.

    DE/?/?/?

    DE/rand/1/exp

    这是crossover step步的的一个变种:

    随机从[1, D]中抽取整数nL, 然后
    u_{j,i,G} = \left \{ \begin{array}{ll} v_{j,i,G} & if \: n \le j \le n+L-1\\ x_{j,i,G} & otherwise. \end{array} \right.
    L可以通过下面的步骤生成

    • L=0
    • while \mathrm{rand}[0,1] \le Cr and L\le D:
      L=L+1.

    DE/best/1

    V_{i,G}=X_{best,G} + F\cdot (X_{r_1^i,G} - X_{r_2^i,G}),
    其中X_{best,G}P_{G}中的最优的点.

    DE/best/2

    V_{i,G}=X_{best,G} + F\cdot (X_{r_1^i,G} - X_{r_2^i,G}) + F\cdot (X_{r_3^i,G} - X_{r_4^i,G}).

    DE/rand/2

    V_{i,G}=X_{r_1^i,G} + F\cdot (X_{r_2^i,G} - X_{r_3^i,G}) + F\cdot (X_{r_4^i,G} - X_{r_5^i,G}),

    超参数的选择

    真的没有细看, 文中粗略地介绍了几处, 还有很多需要查原文.

    F的选择

    有的推荐[0.4, 1](最佳0.5), 有的推荐0.6, 有的推荐[0.4, 0.95](最佳0.9).

    还有一些自适应的选择, 如
    F = \left \{ \begin{array}{ll} \max \{l_{\min}, 1- |\frac{f_{\max}}{f_{\min}}|\} & if : |\frac{f_{\max}}{f_{\min}}|<1 \\ \max \{l_{\min}, 1- |\frac{f_{\max}}{f_{\min}}|\} & otherwise, \end{array} \right.
    我比较疑惑的是难道|\frac{f_{\max}}{f_{\min}}|不是大于等于1吗?

    F_{i,G+1} = \left \{ \begin{array}{ll} \mathrm{rand}[F_l, F_{u}] & with \: probability \:\tau \\ F_{i,G} & else, \end{array} \right.
    其中F_l, F_u分别为F取值的下界和上界.

    NP的选择

    有的推荐[5D,10D], 有的推荐[3D, 8D].

    Cr的选择

    有的推荐[0.3, 0.9].

    还有
    Cr_{i,G+1} = \left \{ \begin{array}{ll} \mathrm{rand}[0, 1] & with \: probability \:\tau \\ Cr_{i,G} & else, \end{array} \right.

    一些连续变体

    A

    p=f(X_{r_1})+f(X_{r_2}) + f(X_{r_3}) \\ p_1 = f(X_{r_1})/p \\ p_2 = f(X_{r_2}) / p \\ p_3 = f(X_{r_1}) / p.
    如果\mathrm{rand}[0,1] < \Gamma(\Gamma是给定的):
    \begin{array}{ll} V_{i,G+1} = & (X_{r_1}+X_{r_2}+X_{r_3})/3 +(p_2-p_1)(X_{r_1}-X_{r_2}) \\ &+ (p_3-p_2)(X_{r_2} - X_{r_3}) + (p_1-p_3) (X_{r_3}- X_{r_1}), \end{array}
    否则
    V_{i,G+1} = X_{r_1} + F \cdot (X_{r_2}-X_{r_3}).

    B

    U_{i,G}=X_{i, G}+k_i \cdot (X_{r_1,G}-X_{i,G})+F' \cdot (X_{r_2,G}-X_{r_3, G}),
    其中k_i给定, F'=k_i \cdot F.

    C

    在这里插入图片描述

    D

    即在考虑x的时候, 还需要考虑其反a+b-x, 假定x \in [a, b], [a,b]为我们给定范围, X的反类似的构造.

    E

    在这里插入图片描述
    其中表示在的的近邻中的最优点, .
    在这里插入图片描述
    其中为中的最优点.

    V_{i,G}= w \cdot g_{i, G} + (1-w) \cdot L_{i, G}.

    G

    在这里插入图片描述

    剩下的在复杂环境下的应用就不记录了(只是单纯讲了该怎么做).

    一些缺点

    1. 高维问题不易处理;
    2. 容易被一些问题欺骗, 而现如局部最优解;
    3. 对不能分解的函数效果不是很好;
    4. 路径往往不会太大(即探索不充分);
    5. 缺少收敛性的理论的保证.

    代码

    f(x,y)=x^2+50y^2.

    在这里插入图片描述
    {
      "dim": 2,
      "F": 0.5,
      "NP": 5,
      "Cr": 0.35
    }
    
    
    
    """
    de.py
    """
    
    import numpy as np
    from scipy import stats
    import random
    
    
    
    
    class Parameter:
    
        def __init__(self, dim, xmin, xmax):
            self.dim = dim
            self.xmin = xmin
            self.xmax = xmax
            self.initial()
    
    
        def initial(self):
            self.para = stats.uniform.rvs(
                self.xmin, self.xmax - self.xmin
            )
    
        @property
        def data(self):
            return self.para
    
        def __getitem__(self, item):
            return self.para[item]
    
        def __setitem__(self, key, value):
            self.para[key] = value
    
        def __len__(self):
            return len(self.para)
    
        def __add__(self, other):
            return self.para + other
    
        def __mul__(self, other):
            return self.para * other
    
        def __pow__(self, power):
            return self.para ** power
    
        def __neg__(self):
            return -self.para
    
        def __sub__(self, other):
            return self.para - other
    
        def __truediv__(self, other):
            return self.para / other
    
    
    class DE:
    
        def __init__(self, func, dim ,F=0.5, NP=50,
                     Cr=0.35, xmin=-10, xmax=10,
                     require_history=True):
            self.func = func
            self.dim = dim
            self.F = F
            self.NP = NP
            self.Cr = Cr
            self.xmin = np.array(xmin)
            self.xmax = np.array(xmax)
            assert all(self.xmin <= self.xmax), "Invalid xmin or xmax"
            self.require_history = require_history
            self.init_x()
            if self.require_history:
                self.build_history()
    
    
        def init_x(self):
            self.paras = [Parameter(self.dim, self.xmin, self.xmax)
                          for i in range(self.NP)]
    
        @property
        def data(self):
            return [para.data for para in self.paras]
    
        def build_history(self):
            self.paras_history = [self.data]
    
        def add_history(self):
            self.paras_history.append(self.data)
    
        def choose(self, size=3):
            return random.sample(self.paras, k=size)
    
        def mutation(self):
            x1, x2, x3 = self.choose(3)
            return x1 + self.F * (x2 - x3)
    
        def crossover(self, v, x):
            u = np.zeros_like(v)
            for i, _ in enumerate(v):
                jrand = random.randint(0, self.dim)
                if np.random.rand() < self.Cr or i is jrand:
                    u[i] = v[i]
                else:
                    u[i] = x[i]
                u[i] = v[i] if np.random.rand() < self.Cr else x[i]
            return u
    
        def selection(self, u, x):
            if self.func(u) < self.func(x):
                x.para = u
            else:
                pass
    
        def step(self):
            donors = [self.mutation()
                      for i in range(self.NP)]
    
            for i, donor in enumerate(donors):
                x = self.paras[i]
                u = self.crossover(donor, x)
                self.selection(u, x)
            if self.require_history:
                self.add_history()
    
        def multi_steps(self, times):
            for i in range(times):
                self.step()
    
    
    
    
    
    class DEbest1(DE):
    
        def bestone(self):
            y = np.array([self.func(para)
                 for para in self.paras])
            return self.paras[np.argmax(y)]
    
        def mutation(self, bestone):
            x1, x2 = self.choose(2)
            return bestone + self.F * (x1 - x2)
    
        def step(self):
            bestone = self.bestone()
            donors = [self.mutation(bestone)
                      for i in range(self.NP)]
    
            for i, donor in enumerate(donors):
                x = self.paras[i]
                u = self.crossover(donor, x)
                self.selection(u, x)
            if self.require_history:
                self.add_history()
    
    class DEbest2(DEbest1):
    
        def mutation(self, bestone):
            x1, x2, x3, x4 = self.choose(4)
            return bestone + self.F * (x1 - x2) \
                    + self.F * (x3 - x4)
    
    class DErand2(DE):
    
        def mutation(self):
            x1, x2, x3, x4, x5 = self.choose(5)
            return x1 + self.F * (x2 - x3) \
                    + self.F * (x4 - x5)
    
    
    class DErandTM(DE):
    
        def mutation(self):
            x = self.choose(3)
            y = np.array(list(map(self.func, x)))
            p = y / y.sum()
            part1 = (x[0] + x[1] + x[2]) / 3
            part2 = (p[1] - p[0]) * (x[0] - x[1])
            part3 = (p[2] - p[1]) * (x[2] - x[1])
            part4 = (p[0] - p[2]) * (x[2] - x[0])
            return part1 + part2 + part3 + part4
    
    

    相关文章

      网友评论

          本文标题:Differential Evolution: A Survey

          本文链接:https://www.haomeiwen.com/subject/nckamhtx.html