用 MATLAB 拟合模型

model fitting with MATLAB

我有一组在给定距离 (d) 处的信号接收功率 (p) 测量值和一个具有未知系数 n1 和 n2 的模型。我必须做的是找到最小化 RMS 误差的 n1 和 n2 的值。我见过使用 lsqnonlin 的解决方案,但不是针对分段定义的函数。我是一个真正的matlab菜鸟,我遇到了很多麻烦,请帮忙!

给定的模型是:

到目前为止,我已经定义了一个 model.m 脚本,它定义了上面的等式:

function y = modelo(d,ht,hr,h0,f,data)
y=NaN(size(d));
c=3*10^8;
lambda=c/f;
rbp = 4*(ht-h0)*(hr-h0)/lambda
if d <= rbp
    y = 20*log10(4*pi/lambda)+10*@(x)x(1)*log10(d)-data;
else
    y =20*log10(4*pi/lambda)+10*@(x)x(1)*log10(d) + 10*@(x)x(2)*log10(d)-data;
end

d 参数是距离向量,数据是在该距离处测得的功率。所有其他参数都是固定的数字。

然后我尝试使用 lsqnonlin,但它不起作用。关于如何解决这个问题的任何想法?

看来我没有足够的声誉来评论您的问题并澄清一些事情,我已经继续并尽力推断您正在尝试做什么。那么让我们开始吧。

假设

  1. lsqnonlinfit 最小化您传入的函数的 SSE。因此,您将赋予它的函数必须输出差值(测量 - 预测)。

您的代码有问题

  1. 您的 if 语句不检查以确保满足分段函数的条件。您的 if 检查 d <= dbp,但不检查 dref <= d.
  2. if 语句不会像您想象的那样起作用。当您执行 d <= dbp 之类的操作并且 d 不是标量时,您的 return 将与 d 具有相同的大小。 if 语句将不起作用。
  3. 这行代码 y = 20*log10(4*pi/lambda)+10*@(x)x(1)*log10(d)-data; 不起作用(另一行也不起作用)。您在这里所做的是尝试将一个数字 (20*log10(4*pi/lambda)) 和一个匿名函数 (10*@(x)x(1)*log10(d)-data);
  4. 相加
  5. 您的模型函数没有 n1 和 n2 作为传递给它的参数。

我尝试修复你的模型函数

下面是应该工作的matlab函数。文件末尾后有一些重要的实现细节。

function diff = modelo(ns, d, p, lambda, dRef, dBp)
% Extracting n1 and n2 so that code is easier to read.
n1 = ns(1);
n2 = ns(2);

% Preallocating the size of PL
PL = NaN(size(d));

% Indicies for the two sections of the piecewise function 
i1 = (dRef <= d) & (d <= dBp);
i2 = (d > dBp);

% Calculating the output value for the d values that fall in the first
% range
PL(i1) = ...
    20 .* log10(4 .* pi .* dRef ./ lambda) + ...
    10 .* n1 .* log10(d(i1) ./ dRef);

% Calculating the output values for the d values taht fall in the second
% range
PL(i2) = ...
    20 .* log10(4 .* pi .* dRef ./ lambda) + ...
    10 .* n1 .* log10(dBp ./ dRef) + ...
    10 .* n2 + log10(d(i2) ./ dBp);

% Note that by initializing PL to NaN, any values of d outside of the two
% ranges of this function will result in a output of NaN.

% Calculates the difference between the estimated value (PL) and the
% measure value (p).
diff = PL - p;
end

注意:lsqnonlin 要求输入函数的形式为 func(x),其中 x 是您要拟合的值。在这种情况下,我们的 modelo 函数的形式为 modelo(ns, d, p, lambda, dRef, dBp)。为了完成这项工作,我们必须使用匿名函数。所以你从中调用 lsqnonlin 的文件看起来像这样:

% Initial guesses for n1 and n2, n1 will be the 1st entry and n2 the 2nd.
n0 = ...;
% Distance data, as a vector
D = ...;
% Power data, as a vector
P = ...;
% Value of lambda
LAMBDA = ...;
% Value of dRef
DREF = ...;
% Value of dBp
DBP = ...;

% Calling lsqnonlin
ns = lsqnonlin(@(n) modelo(n, D, P, LAMDA, DREF, DBP), n0);

对 lsqnonlin 的调用内部发生的事情是我们正在将对 modelo 的调用包装在一个匿名函数中。匿名函数接受单个变量 (n),因此它符合 lsqnonlin 的要求。请注意,modelo 仍然需要将所有其他信息传递给它,我们在匿名函数中执行此操作。我将传递给它的变量名大写以强调这一事实。