MATLAB: How to get a good exponential fit using either the curve fitting toolbox or the lines of code

curve fitting

I have several sets of data, which I label xdata_p and ydata_p. Unfortunately, it's a large set, so I didn't see much way around just putting the data points in individually. To clean up the program, what I did was put these in their own function, called HeliumData_Voyager, ProtonData_Voyager, and others (since I'm actually repeating this process for several data sets). So in the program below, you'll see it call that program, which is how I generate the data sets.
xdata = [0.051120874,0.07516499,0.11051797,0.14458315,0.5287479,0.6836915,...
0.81462735,0.99358326,1.1977779,1.4271679,1.5853835,1.7406857,1.911201,...
2.09842,2.3039784,2.529673,2.7452202,3.0853872,3.387628,3.676279,4.0364027,...
4.4838777,4.865937,5.3425984,6.075168,6.516251,7.3236966,8.041117,8.828814,...
9.469823,10.519647,11.5501375,12.830584,13.923845,15.287807,16.785381,18.429657]; %This will be the energy
ydata = [953.125,914.0625,877.6042,848.9583,502.60416,507.8125,513.0208,513.0208,...
507.8125,502.60416,489.58334,481.77084,473.95834,463.54166,450.52084,440.10416,...
427.08334,411.45834,390.625,375.0,361.97916,335.9375,315.10416,299.47916,...
273.4375,260.41666,231.77083,216.14583,195.3125,171.875,153.64583,130.20833,...
114.583336,88.541664,70.3125,41.666668,26.041668]; %This will be the flux
I have to call these values into a function which plots them, and then which tries to do a best fit line. I originally tried linearizing the data and re-exponentiating it, and that didn't work at all too well. Here is my attempt there:
clc
clear all
ElectronData_Voyager;%This simply calls the data file which we are to use. The reason for this

%is to simply save space in the event of huge data files.
m =1; %this allows us to choose the power of the polynomial function
E = polyfit(log(xdata),log(ydata),m); %This is the function we are attempting to use in order
%to get the best polynomial fit. It pops it out in order A_n...A_2, A_1, A_0
Z = polyval(E,log(xdata));
A = norm(ydata-Z);%used below in RMS

n = length(ydata);%used below in RMS
rms = A/sqrt(n)%This will allow me to assess the quality of the fit.
loglog(xdata,ydata,'o')
title('Plot of the Original Data')
xlabel('KE')
ylabel('Flux')
grid on
The above seems to do OK at plotting the points, but not much else. I then tried to use the curve fitting toolbox in matlab. What it does, when I choose exponential, is give me an exponential curve, but the curve is completely wrong (i.e. the concavity is flipped).
So then, I tried this code just to see what happens:
clc
clear all
ElectronData_Voyager;%This simply calls the data file which we are to use. The reason for this
%is to simply save space in the event of huge data files.
f = fit(xdata',ydata','exp2')
loglog(xdata',ydata','o')
Once again, it yields me with an exponential that is clearly the wrong function. So my question is how can I get a good fit to the data, and/or where is it that I'm going wrong in my code?
Also, the first image is what the data should look like, the second is what it looks like either using the curvefitting toolbox or the above line of code.
Thanks in advance!

Best Answer

What is the physical process that describes your data?
What are you modeling? Is there a function that describes it?
If you simply want to model an exponential function without transforming to logs (it is always best to model the data without transformation), this works:
f = @(b,x) b(1) .* exp(-b(2).*x);
b0 = [1000; 0.1];
B = nlinfit(xdata, ydata, f, b0);
figure(1)
plot(xdata, ydata, 'bp')
hold on
plot(xdata, f(B,xdata))
hold off
grid
I don’t have the Curve Fitting Toolbox (Statistics and Optimization do all I need), but this function would likely work with it as a ‘custom funciton’.