2

我有一些实验数据和一个我想尝试拟合的理论模型。我已经用模型制作了一个函数文件 - 代码如下所示

function [ Q,P ] = RodFit(k,C )
% Function file for the theoretical scattering from a Rod
% R = radius, L = length

R = 10; %  radius in Å
L = 1000; % length in Å
Q = 0.001:0.0001:0.5;

fun = @(x)  (   (2.*besselj(1,Q.*R.*sin(x)))./...
            (Q.*R.*sin(x)).*...
            (sin(Q.*L.*cos(x)./2))./...
            (Q.*L.*cos(x)./2)...
            ).^2.*sin(x);

P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;

end

Q 是 x 值,P 是 y 值。我可以从 matlab 命令行很好地调用该函数,它工作正常,例如 [Q,P] = RodFit(1,0.001) 给了我一个我可以使用绘图的结果plot(Q,P)

但我不知道如何最好地找到适合某些实验数据的方法。理想情况下,我想使用优化工具箱和 lsqcurvefit,因为这样我也可以优化 R 和 L 参数。但我不知道如何将(x,y)数据传递给 lsqcurvefit。我已经尝试使用下面的代码,但它不起作用

File = 30; % the specific observation you want to fit the model to
ydata = DataFiles{1,File}.data(:,2)';
% RAdius = linspace(10,1000,length(ydata));
% LEngth = linspace(100,10000,length(ydata));
Multiplier = linspace(1e-3,1e3,length(ydata));
Constant = linspace(0,1,length(ydata));
xdata = [Multiplier; Constant]; % RAdius; LEngth;
L = lsqcurvefit(@RodFit,[1;0],xdata,ydata);

它给了我错误信息:

Error using  * 
Inner matrix dimensions must agree.
Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
Error in lsqcurvefit (line 199)
        initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot      continue.

我尝试过 i) 使所有向量/矩阵的长度相同,并且 ii) 尝试.*改用。没有任何效果,我给出了同样的错误信息

任何形式的帮助都将不胜感激,无论是关于应该使用什么方法的建议,对我的代码的建议还是第三点。

编辑回答 Osmoses: 一个非常好的观点,但我不认为这是问题所在。刚刚检查了所有向量/矩阵的大小,它们应该没问题

>> size(Q)
ans =
       1        1780

>> size(P)
ans =
       1        1780

>> size(xdata)
ans =
       2        1780

>> size([1;0.001]) - the initial guess/start point for xdata (x0)
ans =
       2     1

>> size(ydata)
ans =
       1        1780

更新

我想我已经确定了问题所在。当我直接指定输入时,RodFit 函数可以正常工作,例如[Q,P] = RodFit(1,0.001);

但是,如果我将 x0 定义为x0 = [1,0.001]我无法将 x0 传递给函数

>> x0 = [1;0.001]

x0 =

1.0000
0.0010

>> RodFit(x0);
Error using  * 
Inner matrix dimensions must agree.

Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;

如果我x0 = [1,0.001] 清楚地使用,也会发生同样的情况,matlab 仅将 x0 解释为输入,k并尝试多重播放长度(ydata)的向量和长度(x0)的向量,这显然失败了。

所以我的问题是我需要编写代码,以便lsqcurvefit了解 xdata 和 x0 的第一列是k变量,而 xdata 和 x0 的第二列是C变量。根据文档 -传递矩阵参数- 我应该能够将 x0 作为矩阵传递给求解器。然后,求解器还应该以与 x0 相同的格式传递 xdata。

4

2 回答 2

0

我已经能够解决一些问题。我的代码中的一个错误是目标函数没有使用向量 a 变量,而是采用了两个变量 - k 和 C。更改代码以接受向量解决了这个问题

function [ Q,P ] = RodFit(X)
% Function file for the theoretical scattering from a Rod
% R = radius, L = length

% Q = 0.001:0.0001:0.5;
Q = linspace(0.11198,4.46904,1780);
fun = @(x)  (   (2.*besselj(1,Q.*R.*sin(x)))./...
           (Q.*R.*sin(x)).*...
           (sin(Q.*L.*cos(x)./2))./...
           (Q.*L.*cos(x)./2)...
           ).^2.*sin(x);

P = (integral(fun,0,pi/2,'ArrayValued',true))*X(1)+X(2);

使用上面的代码,我可以将 x0 定义为x0 = [1 0.001];,并将其传递给 RodFit 并获得结果。我也可以将 xdata 传递给函数并得到结果,例如[Q,P] = RodFit(xdata(2,:));

请注意,我已经更改了所有向量的方向,因此它们现在是行向量并且 xdata 具有大小size(xdata) = 1780 2

所以我以为我已经完全解决了这个问题,但是当我运行 lsqcurvefit 时我仍然遇到问题。我收到错误消息

Error using RodFit
Too many input arguments.

Error in lsqcurvefit (line 199)
        initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});

Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot     continue.

我不知道为什么 - 有没有人知道为什么 Rodfit 在我调用lsqcurvefit时会收到许多输入参数,但在我使用 xdata 运行功能手册时却没有?

于 2013-10-02T13:38:37.160 回答
0

您是否尝试过(有时是错误的)查看输入数据的方向(例如,如果 xdata 和 ydata 都是行/列向量?)。除此之外,您的代码看起来应该可以工作。

于 2013-10-01T16:00:37.507 回答