我有一个包含 3 个变量的函数,我想优化它。不幸的是,这些变量具有不同的数量级,这意味着该问题是非常病态的。我通过将优化变量乘以条件矩阵来处理这个问题。 (在下面的示例中,我的条件矩阵是对角的,因此我将其实现为向量。非对角条件矩阵可能有应用。)
import numpy as np
from scipy.optimize import minimize
def penalty(x):
# do stuff
return # result
conditioner = np.array([1000, 1, 0.1])
x0 = np.array([0.003, 1.415, 9.265]) * conditioner
optim_result = minimize(penalty, x0)
bestfit = optim_result.x / conditioner
有没有一种方法可以做到这一点,不需要手动应用
conditioner
或要求我跟踪哪些数据经过调节(例如,bestfit
)和哪些数据没有经过调节(例如,optim_result
)?
我想我可以将一些算术放在惩罚函数中,如下所示:
def penalty(x):
x_cond = x * conditioner
# do stuff
return # result
但这只解决了一半问题。
一个简单的方法是为
minimize()
编写一个包装器,它处理转换到这个新坐标系和从这个新坐标系转换出来的任务。
这个包装器至少需要做三件事:
可以这样做:
import scipy
def minimize_with_parameter_scaling(f, x0, typical_x_value=None, *args, **kwargs):
def wrapped_f(x, *args, **kwargs):
return f(x * typical_x_value, *args, **kwargs)
x0 = np.asarray(x0)
if typical_x_value is None:
typical_x_value = np.ones_like(x0)
typical_x_value = np.asarray(typical_x_value)
assert (typical_x_value != 0).all(), "parameter scale cannot be zero"
x0_scaled = x0 / typical_x_value
result = scipy.optimize.minimize(wrapped_f, x0_scaled, *args, **kwargs)
result.x = result.x * typical_x_value
return result
警告:在您的示例中,
typical_x_value
具有与conditioner
相反的含义,而是代表典型x值的比例。
我们还可以在一个示例问题上尝试一下,看看调节会有所帮助的假设是否正确。
我选择的示例问题是 rosenbrock 函数,这是一个旨在测试非线性优化器的函数。它是一个具有全局最小值的非线性函数,其导数会误导优化器,这就是为什么它是一个难题。
为了解决比例尺不合适的问题,我使其中一个坐标的比例尺与其他坐标不同。
def wacky_rosenbrock(x):
# Code copied from scipy.optimize.rosen
x = np.asarray(x)
x[1] *= 100 # Second coordinate is multiplied by 100
r = np.sum(100.0 * (x[1:] - x[:-1]**2.0)**2.0 + (1 - x[:-1])**2.0,
axis=0)
return r
然后我尝试在三个维度上解决
wacky_rosenbrock()
。我尝试在不缩放的情况下解决它,并使用 [1, 0.01, 1]
的缩放。 nfev 是获得解决方案所需的函数调用次数。该误差是优化器找到的解决方案与实际最佳解决方案的百分比误差。最后一列是在没有缩放的情况下需要多少次函数调用。我还尝试了各种 SciPy 求解器。
方法 | 错误(无缩放) | nfev(无缩放) | 错误(缩放) | nfev(缩放) | 函数调用计数的改进 |
---|---|---|---|---|---|
内尔德米德 | 0.001% | 305 | 0.003% | 289 | 1.05536 |
鲍威尔 | 0.0% | 862 | 0.0% | 886 | 0.972912 |
CG | 0.239% | 1772 | 0.0% | 248 | 7.14516 |
bfgs | 0.035% | 340 | 0.001% | 148 | 2.2973 |
l-bfgs-b | 0.023% | 268 | 0.0% | 140 | 1.91429 |
tnc | 37.086% | 404 | 0.015% | 400 | 1.01 |
科比拉 | 98.729% | 39 | 11.214% | 4087 | 0.00954245 |
科比卡 | 0.008% | 1406 | 0.0% | 157 | 8.95541 |
slsqp | 0.042% | 128 | 0.049% | 112 | 1.14286 |
信任建设 | 0.038% | 264 | 0.001% | 232 | 1.13793 |
在这些结果中,我想指出以下几点: