参考链接:
https://en.wikipedia.org/wiki/Nelder%E2%80%93Mead_method
http://www.scholarpedia.org/article/Nelder-Mead_algorithm
http://home.agh.edu.pl/~pba/pdfdoc/Numerical_Optimization.pdf
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
http://www.jasoncantarella.com/downloads/NelderMeadProof.pdf
Nelder–Mead algorithm ( NM算法 )其实是一种非常简单易懂的适用于在线最优化的算法。。。总的来说这个算法有些无脑。。。
收敛速度慢,效果一般般,因为适用范围较广(或者说unconstrained optimization,无固定模型也可以)
核心就是:向着最优的解收敛,不断抛弃更新现有的解
简介:
n维空间中,由n+1个顶点,可以组成“最简单”的图形,叫单纯形。
NM算法就是先构造一个初始的,包含给定点的单纯形。
然后使用可能的三种手段(反射,扩展,压缩)去替换函数值最差的顶点。
在以上三种手段失效的时候,使用收缩。
知道该单纯形的半径足够的小。
(半径的定义可以有很多,比如两两点的距离,两两点构成的向量中最大的维度的值,
只要当“半径”趋近与0的时候,该单纯形趋于一个点即可)
理解:
Reflection:以最优点为中心,做最差点的反射点,来达到抛弃最差点的目的。
Expansion:扩大最优点的优势,尝试是否能够得到更优的解。
Contraction:收缩搜索范围。
Shrink:整体向着最优解收缩。
# optimize.py 中的_minimize_neldermead() 是 Nelder–Mead Simplex 算法的核心程序,迭代算法集中体现在以下的这个循环中。 while (fcalls[0] < maxfun and iterations < maxiter): if (numpy.max(numpy.ravel(numpy.abs(sim[1:] - sim[0]))) <= xatol and numpy.max(numpy.abs(fsim[0] - fsim[1:])) <= fatol): break xbar = numpy.add.reduce(sim[:-1], 0) / N #得到centroid xr = (1 + rho) * xbar - rho * sim[-1] #rho=1 得到新的点xr fxr = func(xr) // 对应的fxr函数值 doshrink = 0 if fxr < fsim[0]: xe = (1 + rho * chi) * xbar - rho * chi * sim[-1] # chi=2 fxe = func(xe) # xe 就是x(-2) if fxe < fxr: # 算法步骤2.1 sim[-1] = xe fsim[-1] = fxe else: # 算法步骤2.2 sim[-1] = xr fsim[-1] = fxr else: # fsim[0] <= fxr if fxr < fsim[-2]: # 算法步骤1 sim[-1] = xr fsim[-1] = fxr else: # fxr >= fsim[-2] # Perform contraction # 算法步骤3 if fxr < fsim[-1]: xc = (1 + psi * rho) * xbar - psi * rho * sim[-1] # psi = 0.5 算法步骤3.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) # 算法步骤3.2 if fxcc < fsim[-1]: sim[-1] = xcc fsim[-1] = fxcc else: doshrink = 1 if doshrink: #算法步骤4 整体收缩 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])
example:
>>> import numpy as np >>> from scipy.optimize import minimize >>> >>> def rosen(x): ... """The Rosenbrock function""" ... return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0) >>> >>> x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2]) >>> res = minimize(rosen, x0, method='nelder-mead', ... options={'xtol': 1e-8, 'disp': True}) Optimization terminated successfully. Current function value: 0.000000 Iterations: 339 Function evaluations: 571 >>> >>> print(res.x) [1. 1. 1. 1. 1.]