用MATLAB进行模型拟合

时间:2017-06-23 19:58:42

标签: matlab math mathematical-optimization curve-fitting piecewise

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

给定的模型是:model

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

5/9/2017    9.96    NA
5/8/2017    9.77    NA
5/5/2017    10.57   NA
5/4/2017    10.46   NA
5/3/2017    10.68   NA
5/2/2017    10.59   NA
5/1/2017    10.11   0.91
4/28/2017   10.82   NA
4/27/2017   10.36   NA
4/26/2017   10.85   NA
4/25/2017   10.76   NA
4/24/2017   10.84   NA
4/21/2017   14.63   NA
4/20/2017   14.15   NA
4/19/2017   14.93   NA
4/18/2017   14.42   NA
4/17/2017   14.66   NA
4/13/2017   15.96   NA
4/12/2017   15.77   NA
4/11/2017   15.07   NA
4/10/2017   14.05   NA
4/7/2017    12.87   NA
4/6/2017    12.39   NA
4/5/2017    12.89   NA
4/4/2017    11.79   NA
4/3/2017    12.38   NA
4/1/2017    NA  0.9
3/31/2017   12.37   NA
3/30/2017   11.54   NA
3/29/2017   11.42   NA
3/28/2017   11.53   NA
3/27/2017   12.5    NA
3/24/2017   12.96   NA
3/23/2017   13.12   NA
3/22/2017   12.81   NA
3/21/2017   12.47   NA
3/20/2017   11.34   NA
3/17/2017   11.28   NA
3/16/2017   11.21   NA
3/15/2017   11.63   NA
3/14/2017   12.3    NA
3/13/2017   11.35   NA
3/10/2017   11.66   NA
3/9/2017    12.3    NA
3/8/2017    11.86   NA
3/7/2017    11.45   NA
3/6/2017    11.24   NA
3/3/2017    10.96   NA
3/2/2017    11.81   NA
3/1/2017    12.54   0.79

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

然后我试图使用lsqnonlin,但它没有用。关于如何解决这个问题的任何想法?

1 个答案:

答案 0 :(得分:1)

由于我似乎没有足够的声誉对您的问题发表评论并澄清我已经采取的一些事情,并尽力推断您要做的事情。让我们开始吧。

<强>假设

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

    1. 您的if语句不会检查以确保满足分段函数的条件。你的if检查d&lt; = dbp,但不是dref&lt; = d。
    2. if语句不会按您认为的方式运行。当你做d <= dbp之类的事情并且d不是标量时,你的回报将与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. 你的modelo函数没有n1和n2作为传递给它的参数。
    5. 我尝试修复你的模拟功能

      以下是应该工作的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仍然需要将所有其他信息传递给它,我们在匿名函数中执行此操作。我已经将传递给它的变量名大写,以强调这一事实。