关于scipy.optimize.least_squares非线性最小二乘法

用scipy.optimize.least_squares解决带有变量边界的非线性最小二乘问题

scipy.optimize.least_squares 是一个功能强大的工具,用于解决带有变量边界的非线性最小二乘问题。它通过给定残差和损失函数,寻找目标函数的局部最小值。

目标函数及损失函数

这个函数的主要目标是最小化成本函数 F(x),表示为:

该函数最小化残差平方和,受限于 lb <= x <= ub 的变量边界。

参数及其功能

least_squares 函数具有各种参数,以促进优化过程:

  • func: 一个可调用的函数,用于计算残差向量。
  • x0: 独立变量的初始猜测值。
  • jac: 计算雅可比矩阵(残差的偏导数)的方法。
  • bounds: 指定独立变量的边界。
  • method: 执行最小化的算法。
  • ftolxtolgtol: 基于成本函数变化、变量变化和梯度范数的终止条件的容差。
  • x_scale: 每个变量的特征尺度,以提高收敛性。
  • loss: 确定损失函数,减少异常值对解决方案的影响。

返回结果

least_squares 函数的返回结果包括 OptimizeResult 中定义的以下字段:

  • x: 找到的解决方案。
  • cost: 解决方案处的成本函数值。
  • fun: 解决方案处的残差向量。
  • jac: 解决方案处的修改雅可比矩阵。
  • grad: 解决方案处的成本函数梯度。
  • optimality: 一阶最优性度量。
  • active_mask: 活动约束的二进制掩码。
  • nfevnjev: 函数和雅可比矩阵的评估次数。
  • status: 算法终止的原因。
  • message: 终止原因的文本描述。
  • success: 是否满足收敛条件。

scipy.optimize.least_squares 是解决非线性最小二乘问题的重要工具,它的参数和返回结果提供了广泛的灵活性和功能性,可用于各种优化问题的求解。

优化

scipy.optimize.least_squares优化方法详解

scipy.optimize.least_squares模块提供了多种优化方法,每种方法针对特定问题类型。了解这些方法的细微差别对根据问题性质选择合适的方法至关重要。让我们深入了解下面提供的各种方法:

Levenberg-Marquardt方法('lm')

'lm'方法调用MINPACK中实现的最小二乘算法(lmder,lmdif)的包装器。它运行的是Levenberg-Marquardt算法,作为一种信赖域类型算法进行构建。这个实现基于文献[JJMore],非常强大、高效,具备许多巧妙的技巧。对于无约束问题,这应该是您的首选。但需要注意的是,它不支持约束条件。另外,当方程数(m)小于变量数(n)时,该方法无法工作。

Trust Region Reflective方法('trf')

'trf'方法的动机来自解决方程组,这些方程组构成了边界约束最小化问题的一阶最优性条件,详见[STIR]。该算法通过迭代求解增加了特殊对角二次项的信赖域子问题,并且信赖域的形状由到边界的距离和梯度方向确定。这些增强功能有助于避免直接走向边界,并有效地探索所有变量空间。为了进一步提高收敛性,该算法考虑从边界反射的搜索方向。为了满足理论要求,该算法始终保持迭代的严格可行性。对于稠密雅可比矩阵,信赖域子问题的求解方法与[JJMore]中描述的方法非常相似(并在MINPACK中实现)。与MINPACK实现的不同之处在于,每次迭代只进行一次雅可比矩阵的奇异值分解,而不是QR分解和一系列的Givens旋转消元。对于大型稀疏雅可比矩阵,采用了一个二维子空间方法来求解信赖域子问题[STIR],[Byrd]。这个子空间由一个缩放梯度和由scipy.sparse.linalg.lsmr提供的近似Gauss-Newton解构成。当没有约束条件时,该算法与MINPACK非常相似,并且通常具有可比较的性能。该算法在无约束和有界问题中表现出相当的鲁棒性,因此被选择为默认算法。

Dogbox方法

'dogbox'方法在信赖域框架内运行,但考虑的是矩形信赖域,而不是传统的椭球体[Voglis]。当前信赖域和初始边界的交集也是矩形的,因此在每次迭代中,通过Powell的dogleg方法[NumOpt]近似地求解受边界约束的二次最小化问题。对于稠密雅可比矩阵,可以精确计算所需的Gauss-Newton步长,或者对于大型稀疏雅可比矩阵,可以近似计算,使用scipy.sparse.linalg.lsmr。当雅可比矩阵的秩小于变量数时,该算法可能收敛较慢。然而,该算法在变量较少的有界问题中通常优于'trf'方法。

鲁棒损失函数

鲁棒损失函数的实现如[BA]所述。其思想是在每次迭代中修改残差向量和雅可比矩阵,使计算出的梯度和Gauss-Newton Hessian近似值与成本函数的真实梯度和Hessian近似值相匹配。然后算法继续以正常方式运行,也就是说,鲁棒损失函数被实现为对标准最小二乘算法的简单包装器。

例子1

  • 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> y ^ = A K a L b \hat{y} = AK^aL^b </math>y^=AKaLb
py 复制代码
from scipy.optimize import least_squares
import numpy as np

def func3(params ,x,y):
    A,a, b = params
    return y - (A * x.iloc[:,0] ** a * x.iloc[:,1] ** b)

init_vals = [0.5, 0.5, 0.5]  # 对应参数的初始值

# 进行拟合
ret = least_squares(func3, x0=init_vals, args=(X,y))

ret


 message: `ftol` termination condition is satisfied.
     success: True
      status: 2
         fun: [-1.614e+02 -9.926e+00 ...  5.070e+02 -1.831e+02]
           x: [ 4.074e-01  8.683e-01  2.698e-01]
        cost: 4324284.827539758
         jac: [[-9.291e+03 -2.736e+04 -4.013e+04]
               [-9.751e+03 -2.891e+04 -4.220e+04]
               ...
               [-5.338e+04 -1.970e+05 -2.436e+05]
               [-5.996e+04 -2.244e+05 -2.738e+05]]
        grad: [-2.737e-01 -7.448e-01 -4.288e-01]
  optimality: 0.7448098897038893
 active_mask: [ 0.000e+00  0.000e+00  0.000e+00]
        nfev: 38
        njev: 31

官方例子

以下是关于scipy.optimize.least_squares模块的一些示例的中文解释:

在第一个示例中,我们使用无约束独立变量找到了Rosenbrock函数的最小值。

Rosenbrock函数如下:

python 复制代码
pythonCopy code
import numpy as np

def fun_rosenbrock(x):
    return np.array([10 * (x[1] - x[0]**2), (1 - x[0])])

需要注意的是,我们只提供了残差向量。算法将构建成本函数作为残差平方和,得到Rosenbrock函数。精确的最小值在 x = [1.0, 1.0] 处。

ini 复制代码
from scipy.optimize import least_squares

x0_rosenbrock = np.array([2, 2])
res_1 = least_squares(fun_rosenbrock, x0_rosenbrock)
res_1.x  # 最小值点
res_1.cost  # 成本函数值
res_1.optimality  # 最优性度量

接下来,我们对变量进行约束,使得先前的解决方案变得不可行。具体而言,我们要求 x[1] >= 1.5,而 x[0] 保持不受约束。为此,在least_squares中指定bounds参数以进行约束。

同时,我们还提供了解析雅可比矩阵:

python 复制代码
def jac_rosenbrock(x):
    return np.array([
        [-20 * x[0], 10],
        [-1, 0]])

将所有这些内容放在一起,我们发现新的解决方案位于边界上:

ini 复制代码
res_2 = least_squares(fun_rosenbrock, x0_rosenbrock, jac_rosenbrock,
                      bounds=([-np.inf, 1.5], np.inf))
res_2.x  # 新的最小值点
res_2.cost  # 新的成本函数值
res_2.optimality  # 新的最优性度量

接着,我们解决了一个包含10万个变量的Broyden三对角向量值函数组成的方程组(即在最小值处,成本函数应为零):

ini 复制代码
def fun_broyden(x):
    f = (3 - x) * x + 1
    f[1:] -= x[:-1]
    f[:-1] -= 2 * x[1:]
    return f

# 针对稀疏雅可比矩阵,通过有限差分来估计,并提供雅可比矩阵的稀疏结构以显著加快此过程。
from scipy.sparse import lil_matrix

def sparsity_broyden(n):
    sparsity = lil_matrix((n, n), dtype=int)
    i = np.arange(n)
    sparsity[i, i] = 1
    i = np.arange(1, n)
    sparsity[i, i - 1] = 1
    i = np.arange(n - 1)
    sparsity[i, i + 1] = 1
    return sparsity

n = 100000
x0_broyden = -np.ones(n)

res_3 = least_squares(fun_broyden, x0_broyden,
                      jac_sparsity=sparsity_broyden(n))
res_3.cost  # 成本函数值
res_3.optimality  # 最优性度量

res_3.cost
4.5687069299604613e-23
>>> res_3.optimality
1.1650454296851518e-11

在下一个示例中,我们展示了如何使用least_squares()优化具有复变量的复值残差函数。考虑以下函数:

python 复制代码
def f(z):
    return z - (0.5 + 0.5j)

我们将其包装成一个关于实变量的函数,通过简单处理实部和虚部作为独立变量:

scss 复制代码
def f_wrap(x):
    fx = f(x[0] + 1j*x[1])
    return np.array([fx.real, fx.imag])

因此,我们将原始的n个复变量的m维复函数优化为2n个实变量的2m维实函数:

scss 复制代码
res_wrapped = least_squares(f_wrap, (0.1, 0.1), bounds=([0, 0], [1, 1]))
z = res_wrapped.x[0] + res_wrapped.x[1]*1j  # 得到最小值点

(0.49999999999925893+0.49999999999925893j)

参考

官方文档

相关推荐
红豆和绿豆7 分钟前
大语言模型的发展-OPENBMB
人工智能·语言模型·自然语言处理
ITdgr16 分钟前
更高效的搜索工具,国内免费好用的AI智能搜索引擎工具
人工智能·搜索引擎
鸽芷咕18 分钟前
【Python报错已解决】ModuleNotFoundError: No module named ‘tensorflow‘
python·机器学习·tensorflow·bug·neo4j
fydw_71527 分钟前
PyTorch 激活函数及非线性变换详解
人工智能·pytorch·python
Apache Flink30 分钟前
Apache Flink 流批融合技术介绍
人工智能·flink·apache
南 阳41 分钟前
阿里开源多模态大模型Ovis1.6,重塑出海电商AI格局
网络·人工智能·chatgpt
HyperAI超神经1 小时前
在线教程丨1 步生成 SOTA 级别图像,Hyper-SD 一键启动教程上线!
人工智能·机器学习·stable diffusion
学习前端的小z1 小时前
【AI视频】Runway:Gen-2 运镜详解
人工智能·aigc·音视频
魔力之心1 小时前
人工智能与机器学习原理精解【23】
人工智能·机器学习
虚假程序设计1 小时前
pythonnet python图像 C# .NET图像 互转
开发语言·人工智能·python·opencv·c#·.net