Fitting a complicated function

I'm trying fit a complicated function involving an infinite sum of a hypergeometric divided by a gamma function.
it looks like this
Exp(-x/R) + Exp(-x/R)* Sum(((-.48*x^(1 - m))^n)* Hypergeom(-m*n, 1 + n - m*n, x/R)/Gamma(1 + n - m*n), {n, 1, 50})
where R and m are the parameters i'm fitting and the infinite sum is approximated to 50 terms. Is there anyway to do this in matlab? I dont have Cftool but would it be have to handle this kind of function if I were to buy it? If not are there any other suggestions?

Answers (1)

In principle, you could use the nlinfit() function to do this. Here is a simple example with a much simpler function:
% Here is an example of using nlinfit(). For simplicity, none of
% of the fitted parameters are actually nonlinear!
% Define the data to be fit
x=(0:1:10)'; % Explanatory variable
y = 5 + 3*x + 7*x.^2; % Response variable (if response were perfect)
y = y + 20*randn((size(x)));% Add some noise to response variable
% Define function that will be used to fit data
% (F is a vector of fitting parameters)
f = @(F,x) F(1) + F(2).*x + F(3).*x.^2;
F_fitted = nlinfit(x,y,f,[1 1 1]);
% Display fitted coefficients
disp(['F = ',num2str(F_fitted)])
% Plot the data and fit
figure(1)
plot(x,y,'*',x,f(F_fitted,x),'g');
legend('data','fit')
In practice, I am not sure that fitting 50 terms will be sensible, numerically.

11 Comments

So there is an error that comes from the nlinfit() function when I use my equation. I just did the first term to see if it would work. this is what I have:
%data
A = x218_c_2_a_life_norm;
L=length(A);
%function
F = @(a,x) (a(2).*exp(-x./a(1)).*(((-.48.*x.^(1-a(3))).^1).*hypergeom(-a(3).*1,1+1-a(3).*1, x./a(1))./gamma(1+1-a(3).*1)));
%fitting
F_fitted = nlinfit(A(1:L,1),A(1:L,2),F,[.000000001 1 .00001]);
plot(A(1:L,1),A(1:L,2));
%plotting
disp(['F = ',num2str(F_fitted)])
plot(A(1:L,1),A(1:L,2),A(1:L,1),F(F_fitted,A(1:L,1)),'g')
legend('data','fit')
and here is the error:
??? Error using ==>
nlinfit>checkFunVals at 375
MODELFUN has returned Inf
or NaN values.
Error in ==> nlinfit at 142
if funValCheck &&
~isfinite(sse),
checkFunVals(r); end
Error in ==>
Lifetime_Fitting at 11
F_fitted =
nlinfit(A(1:L,1),A(1:L,2),F,[.000000001
1 .00001]);
can you think of any way around this?
I can't glean the reason for it. (I don't have your data, and I don't have the hypergeom function from the symbolic math toolbox.) You'll have to do some detective work.
I don't know if there are any restrictions on using sym functions within the nlinfit() function (but probably not). My recommendation would be to try to go step-by-step from my function (assuming you got that to work), then progressively making it just a bit closer to yours. Maybe you can identify the problem.
I don't know why you bother with raising to the power of 1, or multiplying by 1, or having 1+1 .
The first parameter ("a" in your code) is the one that nlinfit() is varying, right? And if a(1) becomes 0 then you have x/0 = sign(x) * inf flying around in your calculations. Looks to me as if you would end up with inf in the results when that happened.
nlinfit() has no upperbound or lowerbound constraints on the parameters it generates, so if your function can generate a singularity at a finite data point, then you need to design your function to handle the case smoothly.
I was able to get your code to work with a simple exponential decay. There seems to be no problem with the function itself. I was thinking that it might have to do with the guess values (at the end).
@walter
This is part of a series and i was just looking to get the first term to work before expanding it to more terms.
Is essentially what you're saying that if my function has the possibility for vertical asymptotes that nlinfit will have trouble fitting?
Yes, exactly, you have an asymptotic problem ;-(
It could be that when you were using the function in a mathematics context that you would never use the parameters that create the problem, but nlinfit() does not know that those regions are to be avoided.
The documentation from nlinfit() hints that if you return NaN from your function that the corresponding row will be ignored; I don't know if that would be a suitable approach for you or not. e.g., test whether the values are in range and return NaN if they are not, and otherwise do the computation.
I'm not exactly sure how I would go about testing this. from what I can tell there is no way to restrict the range of the variable i'm fitting for.
In your function, does it make sense to be taking Gamma of a negative value? If so then what if the expression works out as a negative integer?
Looking briefly at your original expression, I get the impression that it could maybe be simplified if you were to expand the hypergeom and gamma in terms of representation of the pochhammer function. Maybe.
I've been attempting to add constraints to the parameters but I haven't found anything that will let me do that. nlinfit does not have a constraining option. Is there another function that will allow me to constrain the parameters? This could help avoid the infinities produced by the function.
I am not familiar with non-linear fitting. Looking at the stats toolbox, it appears to me that even their most general model of nonlinear fitting does not allow for constraints; see http://www.mathworks.com/help/toolbox/stats/nonlinearmodelclass.html
I do not know what you should do to proceed.
One function that will let you constrain parameter estimates is ‘lsqcurvefit’. Since you have an extremely large (50-term) objective function, I suggest that you consider setting an options structure to report each iteration, at least for the first few times you run it.

Sign in to comment.

Asked:

on 19 Jun 2012

Community Treasure Hunt

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

Start Hunting!