SciPy的optimize.minimize中的多个变量

77
根据SciPy文档,可以最小化具有多个变量的函数,但它并未说明如何优化这样的函数。
from scipy.optimize import minimize
from math import *

def f(c):
  return sqrt((sin(pi/2) + sin(0) + sin(c) - 2)**2 + (cos(pi/2) + cos(0) + cos(c) - 1)**2)

print(minimize(f, 3.14/2 + 3.14/7))

以上的代码试图最小化函数f,但是对于我的任务,我需要针对三个变量进行最小化。

只需引入第二个参数并相应地调整minimize即可,但会导致错误:

TypeError: f() takes exactly 2 arguments (1 given)

当使用多个变量进行最小化时,minimize函数是如何工作的?


1
你的代码只展示了一个标量决策变量 c,并没有给出其他两个决策变量的指示,这意味着这不是你想要解决的多元函数。相反,你想要优化三个决策变量,为一个未显示的函数进行优化,每个变量都是标量,即 abc。你是否有决策变量为 2 个向量的示例呢?例如,xy 是两个决策向量/数组,而不是标量。 - develarist
@develarist 我认为最好为你所问的问题提出一个单独的问题。但是,如果您需要优化两个向量,我会考虑将向量的每个元素视为要优化的变量。因此,如果您有两个3元素向量,则有6个要优化的变量。 - Henrik Hansen
2个回答

112

将多个变量打包成单个数组:

import scipy.optimize as optimize

def f(params):
    # print(params)  # <-- you'll see that params is a NumPy array
    a, b, c = params # <-- for readability you may wish to assign names to the component variables
    return a**2 + b**2 + c**2

initial_guess = [1, 1, 1]
result = optimize.minimize(f, initial_guess)
if result.success:
    fitted_params = result.x
    print(fitted_params)
else:
    raise ValueError(result.message)
产出。
[ -1.66705302e-08  -1.66705302e-08  -1.66705302e-08]

3
“print(params)” 显示了数组,但是它们是什么?我在函数调用中看不到任何输入“params”被发送到函数“f”,那么这些参数与被优化的函数有什么对应关系?为什么三个结果元素相同(“-1.66705302e-08”)?如果要优化多个“向量”决策变量而不是多个“标量”决策变量,该怎么做? - develarist

1

scipy.optimize.minimize有两个必需参数:目标函数和目标函数变量的初始猜测(因此len(initial)==len(variables) 必须为真)。由于它是一种迭代算法,因此需要变量的初始猜测才能收敛。因此,初始猜测必须是基于经验的猜测,否则算法可能无法收敛和/或结果将不正确。

此外,如果目标函数使用任何额外的参数(例如目标函数的系数),则不能将其作为kwargs传递,而必须通过minimizeargs=参数传递(该参数接受类似数组的参数)。

由于OP没有多变量目标函数,让我们使用一个常见的问题:最小二乘法

优化问题解决的是使目标函数达到最小值的值。正如unutbu所解释的那样,这些值必须作为单个对象(在下面的函数中表示为variables)传递给目标函数。正如之前提到的,我们必须对这些变量进行有根据的猜测,以便算法收敛。

def obj_func(variables, coefs):
    gap = coefs[:, 0] - (variables * coefs[:, 1:]).sum(axis=1)
    return (gap**2).sum()

initial = [0, 0]
coefs = np.array([[0.4, 1, 0], [2, 1, 1], [5, 1, 2], [7, 1, 3], [8, 1, 4], [11, 1, 5], [13, 1, 6], [14, 1, 7], [16, 1, 8], [19, 1, 9]])
result = minimize(obj_func, initial, args=coefs)

minimizers = result.x         # [0.50181826, 2.00848483]
minimum = result.fun          # 2.23806060606064

由于普通最小二乘法是OLS回归系数计算的方式,您可以通过以下方法验证以上计算是否正确:

from statsmodels.api import OLS
ols_coefs = OLS(coefs[:, 0], coefs[:, 1:]).fit().params
np.allclose(ols_coefs, minimizers)                         # True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接