scipy.optimize能否最小化复杂变量的函数?如何进行操作?

5

我正在尝试使用scipy.optimize来最小化一个复杂(向量)变量的函数。到目前为止,我的结果表明可能不可能实现。为了调查这个问题,我实现了一个简单的例子 - 最小化带有偏移量的复杂向量的2范数:

import numpy as np
from scipy.optimize import fmin

def fun(x):
    return np.linalg.norm(x - 1j * np.ones(2), 2)

sol = fmin(fun, x0=np.ones(2) + 0j)

输出结果为:
Optimization terminated successfully.
         Current function value: 2.000000
         Iterations: 38
         Function evaluations: 69

>>> sol
array([-2.10235293e-05,  2.54845649e-05])

显然,解决方案应该是
array([0.+1.j, 0.+1.j])

对于这个结果感到失望,我也尝试了scipy.optimize.minimize

from scipy.optimize import minimize

def fun(x):
    return np.linalg.norm(x - 1j * np.ones(2), 1)

sol = minimize(fun, x0=np.ones(2) + 0j)

输出结果为:
>>> sol
      fun: 2.0
 hess_inv: array([[ 9.99997339e-01, -2.66135332e-06],
       [-2.66135332e-06,  9.99997339e-01]])
      jac: array([0., 0.])
  message: 'Optimization terminated successfully.'
     nfev: 24
      nit: 5
     njev: 6
   status: 0
  success: True
        x: array([6.18479071e-09+0.j, 6.18479071e-09+0.j])

情况也不太理想。我已经尝试了所有可能的 minimize 方法(根据需要提供Jacobian和Hessian),但它们都无法获得正确的结果。大部分方法会导致 ComplexWarning: Casting complex values to real discards the imaginary part,这表明它们不能正确处理复数。

使用 scipy.optimize 是否有可能解决问题呢?

如果有可能,请告诉我我的错误之处,非常感谢。

如果不行,您是否可以提供其他优化工具的建议(用于Python),使其能够处理此类问题?

2个回答

10

SciPy的最小化方法仅适用于实数参数。但是在复数空间Cn上进行最小化相当于在R2n上进行最小化,复数的代数从未被考虑。因此,通过添加两个转换包装器,从Cn到R2n,再回去,您可以优化复数。

def real_to_complex(z):      # real vector of length 2n -> complex of length n
    return z[:len(z)//2] + 1j * z[len(z)//2:]

def complex_to_real(z):      # complex vector of length n -> real of length 2n
    return np.concatenate((np.real(z), np.imag(z)))

sol = minimize(lambda z: fun(real_to_complex(z)), x0=complex_to_real(np.ones(2) + 0j))
print(real_to_complex(sol.x))   # [-7.40376620e-09+1.j -8.77719406e-09+1.j]

你提到了Jacobian和Hessian,但是最小化只对实值函数有意义,而这些函数在复变量方面从未可导。Jacobian和Hessian必须在R2n上计算,将实数和虚数部分视为独立变量。


我不确定我完全理解:您是否在说,如果$x$和/或$c$是复数,那么我不能将$|x - c|_2$最小化?复向量的范数对我来说似乎是有意义的,因此这个小例子的最小化器是$x=c$。 - Thomas Arildsen
我并不是在说那个。我是在说被最小化的函数是 f(x) = ||x-c||,它是实值的,因此在复杂意义下不可微分。 - user6655984

1

我需要将一个复合值模型函数在实域上的复合值参数最小化。

以下是一个玩具例子:

def f(x, a, b):
    ab = complex(a,b);
    return np.exp(x*ab)

假设我有数据DATAx = np.arange(N)。请注意,x是实数。

我的做法如下:

def helper(x, a, b):
    return abs(f(x,a,b) - DATA[x])

然后我可以使用curve_fit()

curve_fit(helper, np.arange(N), np.zeros(N), p0 = [1,0])

正在发生的事情是:通过从模型函数中减去数据,新的“理想”输出都为零,这必须是真实的,以便curve_fit()能够工作。复杂参数ab = a + jb已被分解为其实部和虚部。helper()函数返回模型与数据之间差异的绝对值。
一个关键问题是,curve_fit()不会评估除你提供的x值之外的任何其他x值。否则DATA[x]将失败。
请注意,通过使用abs()我实现了L1拟合(或多或少)。也可以使用abs()**2来获得L2拟合……但为什么要使用L1或L2是另一天的话题。
你可能会担心,“假设x[]不是整数(而是实数)?”我的代码需要这样。好吧,这很容易做到,只需将它们放入数组中并对其进行索引即可。可能有一些聪明的黑客使用字典来解决这个问题。 抱歉,代码格式化有误;我还没有弄清楚标记。

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