我有一些实验数据和理论模型,我想尝试和适合。我已经用模型制作了一个函数文件 - 代码如下所示
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的第二列是{ {1}}变量。根据文档 - Passing Matrix Arguments - 我应该能够将x0作为矩阵传递给求解器。然后,解算器也应该以与x0相同的格式传递xdata。
答案 0 :(得分:0)
您是否尝试过(有时是错误的)查看输入数据的方向(例如,如果xdata和amp数据都是行/列向量?)。除此之外,您的代码看起来应该可以正常工作。
答案 1 :(得分:0)
我已经能够解决一些问题。我的代码中的一个错误是目标函数没有使用向量变量而是使用了两个变量 - 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.
我不知道为什么 - 当我调用 lsqcurvefit 时,有没有人知道为什么Rodfit会收到很多输入参数但是当我使用xdata运行函数手册时却没有?