1

Ich verwende scipy.optimize.minimize, mit der Standardmethode ('Neldear-Mead'). Die Funktion, die ich zu minimieren versuche, ist nicht streng konvex. In einigen wichtigen Bereichen bleibt es gleich.minimiert nicht-konvexe Funktion mit Nelder-Mead

Das Problem, das ich habe, ist, dass die Schritte des Algorithmus zu klein sind. Zum Beispiel hat mein Startpunkt eine erste Koordinate x0 = 0.2. Ich weiß, dass die Funktion nur für einen signifikanten Schritt einen anderen Wert ergibt, zum Beispiel um 0,05. Leider kann ich sehen, dass der Algorithmus einen sehr kleinen Schritt macht (ungefähr 0,000001). Als Ergebnis gibt meine Funktion denselben Wert zurück, und der Algorithmus konvergiert nicht. Kann ich dieses Verhalten ändern?

Der Einfachheit halber ist hier der scipy Code:

def _minimize_neldermead(func, x0, args=(), callback=None, 
         xtol=1e-4, ftol=1e-4, maxiter=None, maxfev=None, 
         disp=False, return_all=False, 
         **unknown_options): 
    """ 
    Minimization of scalar function of one or more variables using the 
    Nelder-Mead algorithm. 

    Options for the Nelder-Mead algorithm are: 
     disp : bool 
      Set to True to print convergence messages. 
     xtol : float 
      Relative error in solution `xopt` acceptable for convergence. 
     ftol : float 
      Relative error in ``fun(xopt)`` acceptable for convergence. 
     maxiter : int 
      Maximum number of iterations to perform. 
     maxfev : int 
      Maximum number of function evaluations to make. 

    This function is called by the `minimize` function with 
    `method=Nelder-Mead`. It is not supposed to be called directly. 
    """ 
    _check_unknown_options(unknown_options) 
    maxfun = maxfev 
    retall = return_all 

    fcalls, func = wrap_function(func, args) 
    x0 = asfarray(x0).flatten() 
    N = len(x0) 
    rank = len(x0.shape) 
    if not -1 < rank < 2: 
     raise ValueError("Initial guess must be a scalar or rank-1 sequence.") 
    if maxiter is None: 
     maxiter = N * 200 
    if maxfun is None: 
     maxfun = N * 200 

    rho = 1 
    chi = 2 
    psi = 0.5 
    sigma = 0.5 
    one2np1 = list(range(1, N + 1)) 

    if rank == 0: 
     sim = numpy.zeros((N + 1,), dtype=x0.dtype) 
    else: 
     sim = numpy.zeros((N + 1, N), dtype=x0.dtype) 
    fsim = numpy.zeros((N + 1,), float) 
    sim[0] = x0 
    if retall: 
     allvecs = [sim[0]] 
    fsim[0] = func(x0) 
    nonzdelt = 0.05 
    zdelt = 0.00025 
    for k in range(0, N): 
     y = numpy.array(x0, copy=True) 
     if y[k] != 0: 
      y[k] = (1 + nonzdelt)*y[k] 
     else: 
      y[k] = zdelt 

     sim[k + 1] = y 
     f = func(y) 
     fsim[k + 1] = f 

    ind = numpy.argsort(fsim) 
    fsim = numpy.take(fsim, ind, 0) 
    # sort so sim[0,:] has the lowest function value 
    sim = numpy.take(sim, ind, 0) 

    iterations = 1 

    while (fcalls[0] < maxfun and iterations < maxiter): 
     if (numpy.max(numpy.ravel(numpy.abs(sim[1:] - sim[0]))) <= xtol and 
       numpy.max(numpy.abs(fsim[0] - fsim[1:])) <= ftol): 
      break 

     xbar = numpy.add.reduce(sim[:-1], 0)/N 
     xr = (1 + rho) * xbar - rho * sim[-1] 
     fxr = func(xr) 
     doshrink = 0 

     if fxr < fsim[0]: 
      xe = (1 + rho * chi) * xbar - rho * chi * sim[-1] 
      fxe = func(xe) 

      if fxe < fxr: 
       sim[-1] = xe 
       fsim[-1] = fxe 
      else: 
       sim[-1] = xr 
       fsim[-1] = fxr 
     else: # fsim[0] <= fxr 
      if fxr < fsim[-2]: 
       sim[-1] = xr 
       fsim[-1] = fxr 
      else: # fxr >= fsim[-2] 
       # Perform contraction 
       if fxr < fsim[-1]: 
        xc = (1 + psi * rho) * xbar - psi * rho * sim[-1] 
        fxc = func(xc) 

        if fxc <= fxr: 
         sim[-1] = xc 
         fsim[-1] = fxc 
        else: 
         doshrink = 1 
       else: 
        # Perform an inside contraction 
        xcc = (1 - psi) * xbar + psi * sim[-1] 
        fxcc = func(xcc) 

        if fxcc < fsim[-1]: 
         sim[-1] = xcc 
         fsim[-1] = fxcc 
        else: 
         doshrink = 1 

       if doshrink: 
        for j in one2np1: 
         sim[j] = sim[0] + sigma * (sim[j] - sim[0]) 
         fsim[j] = func(sim[j]) 

     ind = numpy.argsort(fsim) 
     sim = numpy.take(sim, ind, 0) 
     fsim = numpy.take(fsim, ind, 0) 
     if callback is not None: 
      callback(sim[0]) 
     iterations += 1 
     if retall: 
      allvecs.append(sim[0]) 

    x = sim[0] 
    fval = numpy.min(fsim) 
    warnflag = 0 

    if fcalls[0] >= maxfun: 
     warnflag = 1 
     msg = _status_message['maxfev'] 
     if disp: 
      print('Warning: ' + msg) 
    elif iterations >= maxiter: 
     warnflag = 2 
     msg = _status_message['maxiter'] 
     if disp: 
      print('Warning: ' + msg) 
    else: 
     msg = _status_message['success'] 
     if disp: 
      print(msg) 
      print("   Current function value: %f" % fval) 
      print("   Iterations: %d" % iterations) 
      print("   Function evaluations: %d" % fcalls[0]) 

    result = OptimizeResult(fun=fval, nit=iterations, nfev=fcalls[0], 
          status=warnflag, success=(warnflag == 0), 
          message=msg, x=x) 
    if retall: 
     result['allvecs'] = allvecs 
    return result 
+0

Aus meiner Erfahrung mit Nelder Mead versuchen, sie arbeiten gut mit konvexen Probleme sind aber nicht für allgemeine Zwecke nicht-konvexe Probleme geeignet. Ohne genau zu wissen, welchen Parameterraum Sie mit Nelder Mead verwenden werden, ist es schwer zu sagen, ob eine Verschiebung um 0,05 immer eine Lösung darstellt. – Spinor8

+0

Das macht Sinn. Haben Sie einen Vorschlag für eine nicht konvexe Funktion? – DevShark

+0

Die Funktion ist für Sie zu definieren. Nach Ihrer Beschreibung gibt es zumindest eine Region, in der es ein flaches Plateau gibt. Gibt es auch lokale Mindestwerte? Das Tolle an Nelder Mead ist, dass es sehr physisch ist. Sie können es buchstäblich als Wasser betrachten, das in eine physische Landschaft fließt. – Spinor8

Antwort

1

Ich habe vor Nelder-Mead lange Zeit verwendet, aber wie ich erinnere mich, dass Sie verschiedene lokale Minima finden, wenn Sie aus verschiedenen beginnen points.You didn Start ‚t geben Sie uns Ihre Funktion, so konnten wir nur erahnen, was beste Strategie sein sollte für you.You auch diese

http://www.webpages.uidaho.edu/~fuchang/res/ANMS.pdf

lesen sollten

Dann können Sie reine Python-Implementierung

https://github.com/fchollet/nelder-mead/blob/master/nelder_mead.py

+0

Danke für Ihre Hilfe. Ich bin mir bewusst, verschiedene lokale Minima zu haben, und ich kümmere mich darum. Ich werde Ihre Links durchgehen. – DevShark

Verwandte Themen