Nelder mead 没有收敛 (scipy)。为什么只有一个初始点?
Nelder mead isn't converging (scipy). Why is there only one initial point?
这是一个最小的可重现示例。如果我将 x_0
设置为 0
,优化器似乎无法从中移动。如果我将 x_0
设置为 10
,它会收敛到全局最小值。知道那是什么吗?它与 Nelder-Mead algorithm 的工作方式有关吗?
我知道它可能在收敛之前卡住了并终止并且优化器有时对初始猜测很敏感但是我发现这很难检查因为我们只给出一个初始点并且 Nelder-Mead 算法开始有(维数 + 1)个点,所以这里我们应该从两个点开始?? 显然,我们只给 SciPy 一个初始猜测,所以我的问题是: SciPy 采取的第二点是什么,如果我使用 x0 = 0
为什么会导致不收敛?
与x_0 = 0
import numpy as np
from scipy.optimize import minimize, Bounds
def func(x):
return ((x - 1000) ** 2 + (x - 10000) ** 2) + 440 ** (3 / 2) * np.sqrt(x)
x0 = np.array([0])
x_bounds = Bounds(0, 25000)
res = minimize(func, x0, method='Nelder-Mead', tol=1e-6, bounds=x_bounds)
print("Best:", res.x)
print("Loss:", func(res.x[0]))
输出:
Best: [0.]
Loss: 101000000.0
与x0 = 10
:
import numpy as np
from scipy.optimize import minimize, Bounds
def func(x):
return ((x - 1000) ** 2 + (x - 10000) ** 2) + 440 ** (3 / 2) * np.sqrt(x)
x0 = np.array([10])
x_bounds = Bounds(0, 25000)
res = minimize(func, x0, method='Nelder-Mead', tol=1e-6, bounds=x_bounds)
print("Best:", res.x)
print("Loss:", func(res.x[0]))
输出:
Best: [5484.42156982]
Loss: 41183994.677765995
我在最小化的 scipy documentation of Nelder-Mead. Neither could I on the scipy documentation 上找不到太多内容。
https://machinelearningmastery.com/how-to-use-nelder-mead-optimization-in-python/
"必须为算法提供一个起点,可以是另一个全局优化算法的终点,也可以是从域中抽取的随机点。
鉴于算法可能会卡住,从不同的起点多次重启可能会受益。
该算法通过使用由 n + 1 个点(顶点)组成的形状结构(称为单纯形)来工作,其中 n 是函数的输入维数。“
为什么你只提供一个初始点的答案在这里:
https://github.com/scipy/scipy/blob/b5d8bab88af61d61de09641243848df63380a67f/scipy/optimize/_optimize.py#L743
所以单纯形是由 n + 1 个点构建的,每个点都是你的起点(复制)。所以维数是点数以外的东西。
这是一个最小的可重现示例。如果我将 x_0
设置为 0
,优化器似乎无法从中移动。如果我将 x_0
设置为 10
,它会收敛到全局最小值。知道那是什么吗?它与 Nelder-Mead algorithm 的工作方式有关吗?
我知道它可能在收敛之前卡住了并终止并且优化器有时对初始猜测很敏感但是我发现这很难检查因为我们只给出一个初始点并且 Nelder-Mead 算法开始有(维数 + 1)个点,所以这里我们应该从两个点开始?? 显然,我们只给 SciPy 一个初始猜测,所以我的问题是: SciPy 采取的第二点是什么,如果我使用 x0 = 0
为什么会导致不收敛?
与x_0 = 0
import numpy as np
from scipy.optimize import minimize, Bounds
def func(x):
return ((x - 1000) ** 2 + (x - 10000) ** 2) + 440 ** (3 / 2) * np.sqrt(x)
x0 = np.array([0])
x_bounds = Bounds(0, 25000)
res = minimize(func, x0, method='Nelder-Mead', tol=1e-6, bounds=x_bounds)
print("Best:", res.x)
print("Loss:", func(res.x[0]))
输出:
Best: [0.]
Loss: 101000000.0
与x0 = 10
:
import numpy as np
from scipy.optimize import minimize, Bounds
def func(x):
return ((x - 1000) ** 2 + (x - 10000) ** 2) + 440 ** (3 / 2) * np.sqrt(x)
x0 = np.array([10])
x_bounds = Bounds(0, 25000)
res = minimize(func, x0, method='Nelder-Mead', tol=1e-6, bounds=x_bounds)
print("Best:", res.x)
print("Loss:", func(res.x[0]))
输出:
Best: [5484.42156982]
Loss: 41183994.677765995
我在最小化的 scipy documentation of Nelder-Mead. Neither could I on the scipy documentation 上找不到太多内容。
https://machinelearningmastery.com/how-to-use-nelder-mead-optimization-in-python/
"必须为算法提供一个起点,可以是另一个全局优化算法的终点,也可以是从域中抽取的随机点。
鉴于算法可能会卡住,从不同的起点多次重启可能会受益。
该算法通过使用由 n + 1 个点(顶点)组成的形状结构(称为单纯形)来工作,其中 n 是函数的输入维数。“
为什么你只提供一个初始点的答案在这里: https://github.com/scipy/scipy/blob/b5d8bab88af61d61de09641243848df63380a67f/scipy/optimize/_optimize.py#L743
所以单纯形是由 n + 1 个点构建的,每个点都是你的起点(复制)。所以维数是点数以外的东西。