这是一种简单、有效但可能有点幼稚的方法。
首先确保通过这两个函数创建一个通用插值器。这样您就可以在给定的数据点之间评估这两个函数。我使用了三次样条插值器,因为这对于您提供的平滑函数类型来说似乎足够通用(并且不需要额外的工具箱)。
然后在大量点上评估源函数(“原始”)。将此数字也用作内联函数中的参数,该函数作为输入X
,其中
X = [a b]
(如ax+b
)。对于任何输入X
,此内联函数将计算
目标函数在相同 x 位置处的函数值,但随后分别按 和 缩放和a
偏移b
。
结果函数值与您之前计算的源函数值之间的平方差之和。
将此内联函数fminsearch
与一些初始估计(您通过视觉或通过自动方式获得的估计)一起使用。对于您提供的示例,我使用了一些随机的,它们都收敛到接近最佳的拟合。
以上所有代码:
function s = findScaleOffset
%% initialize
f2 = [0;0.450541598502498;0.0838213779969326;0.228976968716819;0.91333736150167;0.152378018969223;0.825816977489547;0.538342435260057;0.996134716626885;0.0781755287531837;0.442678269775446;0];
f1 = [-0.029171964726699;-0.0278570165494982;0.0331454732535324;0.187656956432487;0.358856370923984;0.449974662483267;0.391341738643094;0.244800719791534;0.111797007617227;0.0721767235173722;0.0854437239807415;0.143888234591602;0.251750993723227;0.478953530572365;0.748209818420035;0.908044924557262;0.811960826711455;0.512568916956487;0.22669198638799;0.168136111568694;0.365578085161896;0.644996661336714;0.823562159983554;0.792812945867018;0.656803251999341;0.545799498053254;0.587013303815021;0.777464637372241;0.962722388208354;0.980537136457874;0.734416947254272;0.375435649393553;0.106489547770962;0.0892376361668696;0.242467741982851;0.40610516900965;0.427497319032133;0.301874099075184;0.128396341665384;0.00246347624097456;-0.0322120242872125];
figure(1), clf, hold on
h(1) = subplot(2,1,1); hold on
plot(f1);
legend('Original')
h(2) = subplot(2,1,2); hold on
plot(f2);
linkaxes(h)
axis([0 max(length(f1),length(f2)), min(min(f1),min(f2)),max(max(f1),max(f2))])
%% make cubic interpolators and test points
pp1 = spline(1:numel(f1), f1);
pp2 = spline(1:numel(f2), f2);
maxX = max(numel(f1), numel(f2));
N = 100 * maxX;
x2 = linspace(1, maxX, N);
y1 = ppval(pp1, x2);
%% search for parameters
s = fminsearch(@(X) sum( (y1 - ppval(pp2,X(1)*x2+X(2))).^2 ), [0 0])
%% plot results
y2 = ppval( pp2, s(1)*x2+s(2));
figure(1), hold on
subplot(2,1,2), hold on
plot(x2,y2, 'r')
legend('before', 'after')
end
结果:
s =
2.886234493867320e-001 3.734482822175923e-001
请注意,这会计算与您生成数据时使用的相反的转换。反转数字:
>> 1/s(1)
ans =
3.464721948700991e+000 % seems pretty decent
>> -s(2)
ans =
-3.734482822175923e-001 % hmmm...rather different from 7/11!
(我不确定您提供的 7/11 值;使用您提供的精确值来制作绘图会导致对源函数的近似不太准确……您确定 7/11 吗?)
准确性可以通过以下方式提高
- 使用不同的优化器(
fmincon
,fminunc
等)
- 要求更高的精度从
fminsearch
通过optimset
- 在两者中都有更多的样本点
f1
并f2
提高插值的质量
- 使用更好的初始估计
无论如何,这种方法非常通用,并给出了很好的结果。它也不需要工具箱。
但它有一个主要缺点——找到的解决方案可能不是全局优化器,例如,这种方法的结果质量可能对您提供的初始估计非常敏感。因此,请始终制作(差异)图以确保最终解决方案是准确的,或者如果您有大量此类事情要做,请计算某种品质因数,您决定在此基础上使用不同的方法重新开始优化初步估计。
当然,很可能使用傅里叶+梅林变换的结果(如下面的 chaohuang 所建议的)作为对该方法的初始估计。对于您提供的简单示例来说,这可能有点过头了,但我可以很容易地想象出这确实非常有用的情况。