One - One Code All

Blog Content

Nelder–Mead method

Python 算法 金融投资   2011-07-20 15:44:39

参考链接:

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.]



上一篇:python中pandas之drop_duplicates去除重复项
下一篇:pandas的to_csv()使用方法

The minute you think of giving up, think of the reason why you held on so long.