我知道这不是一件实际的事情(我提出这个问题只是为了让我能理解发生了什么),但我想知道为什么 SciPy 不能最小化以下线性组合(它返回初始权重)并且只进行 1 次迭代):
from scipy.optimize import minimize
import numpy as np
mean = np.array([[0.00149066, 0.00076633]])
def constrain1(w):
return w[0] + w[1] - 1
def minimize_func(w):
return (w[0]*mean[0,0] + w[1]*mean[0,1])*(-1)
initial_guess = [0.5,0.5]
bound = (0,1)
bounds = [bound for i in range(2)]
con1 = {"type": "eq", "fun": constrain1}
cons = [con1]
sol = minimize(minimize_func, initial_guess,
method="SLSQP", bounds=bounds, constraints=cons)
最佳答案
这里没有什么太神秘的。通过改变函数的参数,目标函数并没有太大改善。
minimize
以数值方式估计雅可比行列式(目标的一阶导数)。很容易看出这只是-mean
。然而,mean
中的值很小。并且考虑到参数总和为 1 的进一步约束,因此参数也必须很小,这意味着 minimize_func
的输出不会随着 minimize
搜索参数而发生很大变化空间。也就是说,目标在参数空间上非常相似。
让我们把这个具体化。考虑一下您最初的 (0.5, 0.5)
客人。这里目标的值(value)是:
>>> minimize_func((0.5, 0.5))
-0.001128495
minimize
将对这些参数进行小扰动,并重新计算目标,以确定这些更改是否会改善目标。由于您尚未指定任何曲率信息(Hessian 或二阶导数),因此该函数会选择启发式步长,在本例中为 1e-8
。 (您可以通过在目标函数中打印 w
来查看这一点。)
那么这对目标有多大改变?
>>> minimize_func((0.5, 0.5)) - minimize_func((0.5 + 1e-8, 0.5 - 1e-8))
7.243299926865121e-12
不幸的是,不多。这远低于 default tolerance of 1e-6对于这个求解器。
我们可以看到,通过指定较低的容差,minimize
实际上会执行进一步的迭代。
>>> minimize(minimize_func, (0.5, 0.5), method="SLSQP", bounds=bounds, constraints=cons, options={'disp': True}, tol=1e-8)
Optimization terminated successfully (Exit mode 0)
Current function value: -0.0014906599999999996
Iterations: 7
Function evaluations: 21
Gradient evaluations: 7
fun: -0.0014906599999999996
jac: array([-0.00149066, -0.00076633])
message: 'Optimization terminated successfully'
nfev: 21
nit: 7
njev: 7
status: 0
success: True
x: array([1.00000000e+00, 5.55111512e-16])
关于python - 最小化简单的线性组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70490161/