这个问题包含三个组成部分:
- 一个三维向量A。
- “平滑”函数F。
- 所需的向量B(也是三维的)。
我们想找到一个向量A,当它通过F时会产生向量B。
F(A) = B
F可以是以某种方式以某种方式改变或扭曲A的任何东西。关键是我们要迭代调用F(A)直到产生B。
问题是:
我们如何做到这一点,但在找到等于B的向量(在合理阈值内)之前调用F的次数最少?
这个问题包含三个组成部分:
我们想找到一个向量A,当它通过F时会产生向量B。
F(A) = B
F可以是以某种方式以某种方式改变或扭曲A的任何东西。关键是我们要迭代调用F(A)直到产生B。
问题是:
我们如何做到这一点,但在找到等于B的向量(在合理阈值内)之前调用F的次数最少?
假设 F(A)=B,F,B 已知而 A 仍然未知,您可以从简单的梯度搜索开始:
F(A)~= F(C) + F'(C)*(A-C)~=B
在 C 点评估的 F() 的梯度在哪里F'(C)
。我假设你现在可以通过分析计算这个梯度。
因此,您可以选择一个您估计离解不远的点 C 并通过以下方式进行迭代:
C= Co;
While(true)
{
Ai = inverse(F'(C))*(B-F(C)) + C;
convergence = Abs(Ai-C);
C=Ai;
if(convergence<someThreshold)
break;
}
如果 F() 的梯度无法解析计算,您可以估计它。设Ei, i=1:3
为正交向量,则
Fi'(C) = (F(C+Ei*d) - F(C-Ei*d))/(2*d);
F'(C) = [F1'(C) | F2'(C) | F3'(C)];
并且d
可以选择为固定的或作为收敛值的函数。
这些算法存在局部最大值、零梯度区域等问题,因此为了使其工作,起点 (Co) 必须离函数 F() 表现单调的解不是很远
我假设您所说的“平滑”等于可微分。由于平滑的概念仅在有理数/实数中才有意义,我还将假设您正在解决基于浮点的问题。
在这种情况下,我会将问题表述为非线性规划问题。即最小化 f(A) 和 B 之间差异的平方范数,由下式给出
(F(A)_1 -B_1)² + (F(A)_2 - B_2)² + (F(A)_3 - B_3)²
应该清楚的是,当且仅当 f(A) = B 时,该表达式为零,否则为正。因此,您希望将其最小化。
scipy
例如,您可以使用优化套件中内置的求解器(可用于 python):
from scipy.optimize import minimize
# Example function
f = lambda x : [x[0] + 1, x[2], 2*x[1]]
# Optimization objective
fsq = lambda x : sum(v*v for v in f(x))
# Initial guess
x0 = [0,0,0]
res = minimize(fsq, x0, tol=1e-6)
# res.x is the solution, in this case
# array([-1.00000000e+00, 2.49999999e+00, -5.84117172e-09])
二进制搜索(如上所述)仅在函数为 1-d 时才有效,此处并非如此。method="name"
您可以通过在调用中添加 来尝试不同的优化方法minimize
,请参阅API。在不了解函数性质的情况下,并不总是清楚哪种方法最适合您的问题。根据经验,您向求解器提供的信息越多越好。如果您可以显式计算 的导数F
,则将其传递给求解器将有助于减少所需评估的数量。如果F
有 Hessian(即,如果它是两次可微分的),则提供 Hessian 也会有所帮助。
作为替代方案,您可以least_squares
直接F
通过res = least_squares(f, x0)
. 这可能会更快,因为求解器可以处理您正在解决最小二乘问题而不是通用优化问题的事实。
从更一般的角度来看,恢复产生给定值的函数参数的问题称为逆问题。这些问题已被广泛研究。