Два предложения для Nelder-Mead:
1) привязать все x
к сетке, скажем 0,01, внутри функции:
x = np.round( x / grid ) * grid
f = ...
Это действует как простой шумФильтр больших размеров (в 2d или 3d, не беспокойтесь).
2) начинайте с лучших d + 1 из 2d + 1 ближайших точек вместо обычных d + 1:
def neard1( func, x, h, verbose=1 ):
""" eval func at 2d+1 points x, x +- h
sort
-> f[ d+1 best values ], X[ d+1 ]
to start or restart Nelder-Mead
"""
dim = len(x)
I = np.eye(dim)
np.fill_diagonal( I, h ) # scalar or vec
X = x + np.vstack(( np.zeros(dim), I, - I ))
fnear = np.array([ func( x ) for x in X ]) # 2d+1
f0 = fnear[0]
up = np.argsort( fnear ) # vec func: |fnear|
if verbose:
print "neard1: f %g +- %s around x %s" % (
f0, fnear[up] - f0, x )
bestd1 = up[:dim+1]
return fnear[bestd1], X[bestd1]
Также неплохо бы посмотреть на значения neard1 () после Nelder-Mead, чтобы понять, как там выглядит func ().
Если какие-то соседи лучше, чем NM "лучше всего, перезапустите NM с этого нового симплекса.(Можно чередовать neard1, NM, neard1, NM: легко, но очень проблемно-зависимо.)
Сколько у вас переменных и насколько шумна ваша функция?
Надеюсь, это поможет