How to fit imposing some conditions?

11 views (last 30 days)
Fc Fc
Fc Fc on 4 Apr 2018
Edited: Matt J on 13 Apr 2018
Hi every one, I've a matlab program. In the program there is a call to an external program for the fit function. This is the external program
function [estimates, model] = fitcurvedemo(xdata, ydata)
% Call fminsearch with a random starting point.
global ckgraconv_n ckdian
global A lambda sse R2
start_point = rand(1,2);%%scegli un valore casuale per tutti i parametri
model = @fun;
estimates = fminsearch(model, start_point);
function [sse, FittedCurve] = fun(params)
A = params(1);
lambda = params(2);
FittedCurve =( A.*ckgraconv_n + lambda.*ckdian); %%picco gaussiano allargato
ymean = mean(ydata);
SS = ydata-ymean;
SSt =sum(SS.^2);
ErrorVector = FittedCurve - ydata;
sse = sum(ErrorVector .^ 2);
R2 = 1 - sse/SSt;
end
end
The y data are called ydata and the fit function is:
A.*ckgraconv_n + lambda.*ckdian
I must edit the fit so that the residual values are all positive, that is
(ydata-A.*ckgraconv_n - lambda.*ckdian)>0.
Then I must fit the data (finding A and lambda values) and imposing the condition
(ydata-A.*ckgraconv_n - lambda.*ckdian)>0.
I tried writing
function [sse, FittedCurve] = fun(params)
params=fminsearch(model,ydata-params(1).*ckgraconv_n - params(2).*ckdian>0);
A = params(1);
lambda = params(2);
but I get the error
Error using fminsearch (line 96)
FMINSEARCH accepts inputs only of data type double.
Error in fitcurvedemo/fun (line 11)
params=fminsearch(model,ydata-params(1)*ckgraconv_n - params(2)*ckdian>0);
Error in fminsearch (line 200)
fv(:,1) = funfcn(x,varargin{:});
Error in fitcurvedemo (line 8)
estimates = fminsearch(model, start_point);
Error in sp2sp3diff_Titantah (line 659)
[estimates, model] = fitcurvedemo(xdata,ydata);
Please, can someone help me? Best regards

Accepted Answer

Matt J
Matt J on 4 Apr 2018
It is a linear fit, so lsqlin would be appropriate
C=[ckgraconv_n(:) , ckdian(:)];
d=ydata(:);
Aineq=C;
bineq=d;
solution=lsqlin(C,d,Aineq,bineq);
  12 Comments
Matt J
Matt J on 13 Apr 2018
As Walter said, just use the options input to select a different algorithm
Fc Fc
Fc Fc on 13 Apr 2018
Edited: Matt J on 13 Apr 2018
Thank you, I will try it! Please, can you help me also in this https://it.mathworks.com/matlabcentral/answers/394080-calculating-and-plotting-fwhm please?

Sign in to comment.

More Answers (3)

Walter Roberson
Walter Roberson on 7 Apr 2018
You are passing in
ydata-params(1).*ckgraconv_n - params(2).*ckdian>0
In MATLAB, > has lower priority than the arithmetic operations, so this expression is
(ydata-params(1).*ckgraconv_n - params(2).*ckdian)>0
which is of data type logical.
If you want to check params(2).*ckdian and subtract 1 in the locations it is greater than 0, then you would use
ydata-params(1).*ckgraconv_n - (params(2).*ckdian>0)

Jeff Miller
Jeff Miller on 7 Apr 2018
If you want to keep the residuals positive, trying building in an extra penalty for negative residuals. In your original model fun, for example, you might use:
sse = sum(ErrorVector .^ 2) + 1000*sum(ErrorVector(ErrorVector<0) .^ 2);
Seems like that would quickly drive fminsearch away from solutions that give any negative residuals.

Fc Fc
Fc Fc on 7 Apr 2018
Edited: Fc Fc on 11 Apr 2018
Thank you both for your reply. @Walter
(ydata-params(1).*ckgraconv_n - params(2).*ckdian)>0
it is exactly what I must obtain. To understnand it, look my plot
Residuals are plotted by red line. As you can see, in the ranges [283;285] and [290.5;294] residuals are negative. Instead, I must obtain this plot
Here you can see that in all energy range, residuals (red line) are positive.
@Jeff I edited the fitcurvedemo.m file writing your code
sse = sum(ErrorVector .^ 2) + 1000*sum(ErrorVector(ErrorVector<0) .^ 2);
instead of sse = sum(ErrorVector .^ 2) but, as you can see by next plot, in this case I obtain negative residuals in most of the range.
Thanks
PS. About your comment
Seems like that would quickly drive fminsearch away from solutions that give any negative residuals.
To obtain positive residuals, It isn't my demand, but my supervisor ones...
  1 Comment
Jeff Miller
Jeff Miller on 7 Apr 2018
Looks like I got the sign wrong and it should have been 1000*sum(ErrorVector(ErrorVector>0) .^ 2);

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!