How to fit a biexponential decay function
    51 views (last 30 days)
  
       Show older comments
    
I am having trouble fitting this biexponential decay function, any suggestions? Maybe lsqcurvefit is not the best for this purpose, I am not sure.

Where D1 through D4 are unknown fitting parameters, B is given x axis and B0 is the initial known B.
As some help, D1+D3 should approximately be = 1.
clear; clc; clf; close all;
%%
B = [23.11277703	27.4672621	55.28799957	77.30318258	128.4435712	144.59607	150.1007715	178.348134	178.3800029	186.8782579	262.1289782	289.5852833	387.9146522	404.3098886	414.7168762	438.7555353	460.9984083	463.9649687	622.263271	637.1680637	736.5544189	796.517528	823.94181	834.148104	875.3224784	883.5748864	1120.051524	1135.690878	1196.020072	1260.164236	1372.270872	1417.958217	1421.352213	1437.177887	1738.235663	1766.311611	1802.411799	1829.695659	2059.704061	2099.087613	2124.773971	2155.740229	2447.429036	2491.720482	2505.111798	2622.426034	2886.241378	2908.528677	2946.363137	3047.494139	3239.372347	3286.412652	3380.505981	3595.733583	3849.675405	3851.882823	3901.945387	4093.219946	4142.141544	4173.598221	4404.59216	4722.334446	4922.527799	4956.628395	4991.520719	5155.736628	5166.668506	5292.917652	5563.979018	6002.228624	6127.085857	6200.478095	6215.089135	6265.623506	6280.157597	6646.587256	6858.666555	7435.416116	7463.34958	7470.463221	7515.404453	7572.650633	7583.431923	8154.228757	8288.654772	8781.187652	8861.477195	8931.318967	9021.896921	9064.205214	9105.489879	9815.842157	9853.943669	10197.7968	10318.37582	10530.99402	10689.75288	10761.67104	10766.65196	11554.53325	11631.42746	11720.29066	11886.10034	12262.37474	12449.29363	12566.91817	12654.73847	13348.66924	13390.4235	13564.65074	13600.98465	14125.46112	14342.82746	14506.28851	14701.09922	15082.93253	15354.02702	15361.61444	15724.51375	16370.35437	16584.76298	16900.75329	16923.08054	17254.2292	17468.10605	18002.01474	18531.87437	18802.34157	18869.11326	19253.70066	19709.89835	20433.48763	20827.38744	20921.0307	21159.02429	22086.99132	23018.93242	23078.83285	23256.89361	23654.81114	24599.38498	25758.3491	25820.39285	26289.70212	27247.07931	28517.88518	28651.73769	30030.07432	31699.09817	34900.43055	38255.73483];
y = [1	1	1	1	1	1	0.931938171	1	0.956559088	1	0.870266512	0.847039689	0.819706047	0.828390985	0.820051375	0.817313288	0.859815135	0.854877764	0.690813826	0.654914521	0.683075897	0.638696623	0.622781558	0.630439319	0.724997201	0.655188661	0.474937192	0.507599749	0.53700173	0.487243326	0.452908865	0.453747137	0.587406267	0.486231391	0.332199872	0.403521204	0.347536005	0.370257005	0.330503095	0.450762837	0.35864512	0.327000256	0.28955166	0.232696502	0.281911772	0.230350445	0.245922383	0.325485137	0.246350406	0.239027624	0.191768251	0.212565359	0.160778372	0.14856721	0.222365205	0.178102728	0.196251022	0.171584923	0.129942067	0.155410041	0.106192265	0.093225369	0.142592864	0.119221524	0.136018225	0.082431061	0.107723572	0.1139216	0.061249575	0.056398596	0.086408465	0.07132462	0.08647058	0.069306234	0.050232351	0.067788085	0.036482203	0.032246077	0.049572052	0.041494183	0.029684983	0.049760318	0.038130662	0.036214727	0.018926179	0.022604606	0.017131299	0.027475932	0.017451191	0.026141832	0.018448348	0.017620037	0.009337477	0.012321971	0.009783651	0.014762149	0.012895101	0.009050812	0.008452548	0.004582352	0.008153299	0.006376435	0.005740571	0.008224445	0.006262219	0.003883995	0.004694069	0.003368699	0.002409039	0.003584668	0.003811612	0.005099296	0.003120894	0.001951461	0.002628413	0.001891251	0.002514979	0.001513604	0.001975856	0.001713393	0.001142865	0.00167866	0.001150661	0.001987164	0.001172911	0.001219744	0.001045124	0.000792151	0.000740858	0.001330426	0.000980825	0.000928473	0.000732892	0.000567673	0.000572429	0.000921887	0.000734829	0.000361819	0.000473032	0.000472086	0.000804721	0.000584736	0.00038979	0.000361897	0.000726435	0.000697616	0.000535132	0.000676624	0.000467918	0.00036719	0.000318515];
D_guess = [0.5 0.001 0.5 0.001];
figure
fun = @(D,B) D(1)*exp(-(B-B(1)).*D(2))+D(3)*(eBp(-(B-B(1)).*D(4)));
[fit_y, rsb_y] = lsqcurvefit(fun, D_guess, B, y);
semilogy(B, y, 'ko', B, fun(fit_y,B), 'r-')
0 Comments
Answers (2)
  John D'Errico
      
      
 on 13 Apr 2023
        
      Edited: John D'Errico
      
      
 on 14 Apr 2023
  
      First, NEVER set up a solver to fit exponential models with the SAME initial rate parameters for both terms!!!!!!!! So this is flat out BAD:
D_guess = [0.5 0.001 0.5 0.001];
That will result in an immediate problem for the solver. You can have them the same for the amplitude terms out front, but the rate terms SHOULD NOT BE THE SAME.
B = [23.11277703	27.4672621	55.28799957	77.30318258	128.4435712	144.59607	150.1007715	178.348134	178.3800029	186.8782579	262.1289782	289.5852833	387.9146522	404.3098886	414.7168762	438.7555353	460.9984083	463.9649687	622.263271	637.1680637	736.5544189	796.517528	823.94181	834.148104	875.3224784	883.5748864	1120.051524	1135.690878	1196.020072	1260.164236	1372.270872	1417.958217	1421.352213	1437.177887	1738.235663	1766.311611	1802.411799	1829.695659	2059.704061	2099.087613	2124.773971	2155.740229	2447.429036	2491.720482	2505.111798	2622.426034	2886.241378	2908.528677	2946.363137	3047.494139	3239.372347	3286.412652	3380.505981	3595.733583	3849.675405	3851.882823	3901.945387	4093.219946	4142.141544	4173.598221	4404.59216	4722.334446	4922.527799	4956.628395	4991.520719	5155.736628	5166.668506	5292.917652	5563.979018	6002.228624	6127.085857	6200.478095	6215.089135	6265.623506	6280.157597	6646.587256	6858.666555	7435.416116	7463.34958	7470.463221	7515.404453	7572.650633	7583.431923	8154.228757	8288.654772	8781.187652	8861.477195	8931.318967	9021.896921	9064.205214	9105.489879	9815.842157	9853.943669	10197.7968	10318.37582	10530.99402	10689.75288	10761.67104	10766.65196	11554.53325	11631.42746	11720.29066	11886.10034	12262.37474	12449.29363	12566.91817	12654.73847	13348.66924	13390.4235	13564.65074	13600.98465	14125.46112	14342.82746	14506.28851	14701.09922	15082.93253	15354.02702	15361.61444	15724.51375	16370.35437	16584.76298	16900.75329	16923.08054	17254.2292	17468.10605	18002.01474	18531.87437	18802.34157	18869.11326	19253.70066	19709.89835	20433.48763	20827.38744	20921.0307	21159.02429	22086.99132	23018.93242	23078.83285	23256.89361	23654.81114	24599.38498	25758.3491	25820.39285	26289.70212	27247.07931	28517.88518	28651.73769	30030.07432	31699.09817	34900.43055	38255.73483];
y = [1	1	1	1	1	1	0.931938171	1	0.956559088	1	0.870266512	0.847039689	0.819706047	0.828390985	0.820051375	0.817313288	0.859815135	0.854877764	0.690813826	0.654914521	0.683075897	0.638696623	0.622781558	0.630439319	0.724997201	0.655188661	0.474937192	0.507599749	0.53700173	0.487243326	0.452908865	0.453747137	0.587406267	0.486231391	0.332199872	0.403521204	0.347536005	0.370257005	0.330503095	0.450762837	0.35864512	0.327000256	0.28955166	0.232696502	0.281911772	0.230350445	0.245922383	0.325485137	0.246350406	0.239027624	0.191768251	0.212565359	0.160778372	0.14856721	0.222365205	0.178102728	0.196251022	0.171584923	0.129942067	0.155410041	0.106192265	0.093225369	0.142592864	0.119221524	0.136018225	0.082431061	0.107723572	0.1139216	0.061249575	0.056398596	0.086408465	0.07132462	0.08647058	0.069306234	0.050232351	0.067788085	0.036482203	0.032246077	0.049572052	0.041494183	0.029684983	0.049760318	0.038130662	0.036214727	0.018926179	0.022604606	0.017131299	0.027475932	0.017451191	0.026141832	0.018448348	0.017620037	0.009337477	0.012321971	0.009783651	0.014762149	0.012895101	0.009050812	0.008452548	0.004582352	0.008153299	0.006376435	0.005740571	0.008224445	0.006262219	0.003883995	0.004694069	0.003368699	0.002409039	0.003584668	0.003811612	0.005099296	0.003120894	0.001951461	0.002628413	0.001891251	0.002514979	0.001513604	0.001975856	0.001713393	0.001142865	0.00167866	0.001150661	0.001987164	0.001172911	0.001219744	0.001045124	0.000792151	0.000740858	0.001330426	0.000980825	0.000928473	0.000732892	0.000567673	0.000572429	0.000921887	0.000734829	0.000361819	0.000473032	0.000472086	0.000804721	0.000584736	0.00038979	0.000361897	0.000726435	0.000697616	0.000535132	0.000676624	0.000467918	0.00036719	0.000318515];
Next, lets plot the data. How good is it? You have much data, but it seems pretty noisy.
plot(B,y,'.')
And that tells me little. Except what I should have known to do in the first place. (I did include the first plot, just to show my thinking.)
semilogy(B,y,'.')
grid on
Again, pretty darn noisy. It almost seems as if you have multiple sets of data overlaid on top of each other. But the first part is pretty linear in the logged plot. And that suggests we will be able to model at least one term well. 
Now to try a fit.
min(B)
mdl = fittype('D1*exp(-(B-23.11277703)*D2) + D3*exp(-(B-23.11277703)*D4)','indep','B')
Dstart = [.5 .001 .5 .0001];
fittedmdl = fit(B',y',mdl,'start',Dstart)
Bplot = min(B):max(B);
ypred = fittedmdl(Bplot);
plot(B,y,'b.')
hold on
plot(Bplot,ypred,'r-')
hold off
And that seems to fit reasonably well. But now log the axes, and we see:
semilogy(B,y,'b.')
hold on
semilogy(Bplot,ypred,'r-')
hold off
Pretty crappy here. The fit is terrible in the log plot. It suggests again something I knew before, but I need to motivate what I am doing. Otherwise, I'll just get peppered with questions later on anyway.
We should be doing the fit in a log domain. Except, if we do that, then we have numerical problems, because we will be taking the logs of negative numbers at times. (Trust me here.)
So instead, I'll use weights that will mimic the same process.
W = 1./y';
fittedmdl2 = fit(B',y',mdl,'start',Dstart,'weight',W)
ypred = fittedmdl2(Bplot);
plot(B,y,'b.')
hold on
plot(Bplot,ypred,'r-')
hold off
semilogy(B,y,'b.')
hold on
semilogy(Bplot,ypred,'r-')
hold off
Still, the fit is crapola down low. And that suggests your model does not expllain the data. This is apparently not well fit by a sum of exponentials. There is other stuff happening in the tail, something different happening down low. Possibly that is just noise, and we should discard all the data above B==15000 or so. I'll try 20k.
k = B<=20000;
fittedmdl3 = fit(B(k)',y(k)',mdl,'start',Dstart,'weight',W(k))
Bplotk = min(B):20000;
ypredk = fittedmdl2(Bplotk);
semilogy(B(k),y(k),'b.')
hold on
semilogy(Bplotk,ypredk,'r-')
hold off
Finally, that seems quasi-reasonable. The amplitude parameters D(1) and D(3) sum to quite close to 1.
0 Comments
  Walter Roberson
      
      
 on 13 Apr 2023
        To be honest, you should probably give up on trying to use lsqcurvefit to fit that model, unless you happen to have reason to know quite good approximations of the model parameters.
The sum of exponentials is notoriously difficult to fit using least squared approaches. There is a very large tendency for one of the exponentials to become very wide, effectively a constant line or fairly slight slope, and for the other exponential to be left to try to do all of the fitting work.
This is especially true if the coefficients are not constrained: with the forms of the two terms being the same, exchanging the three model parameters between the two terms gives you the same function value, so the fitting cannot possibly decide whether (for example) it is the first term or the second term that should be multiplied by 0.83. When you are doing a fitting you either need the terms to be biased or you need constraints to prevent the proposed coefficients from swapping places.
You might perhaps be able to use the curve fitting app asking for sum of two exponentials. Or use some other approach.
A year or two ago I did see a paper that proposed a way to fit sum of exponentials, but I could not tell how practical it was.
In the short term, you could consider ga or other evolutionary algorithm approaches, in that they run many different model parameter sets simultaneously, increasing the chances that at least one set will happen to land in the sweet spot.
1 Comment
  John D'Errico
      
      
 on 13 Apr 2023
				I tried a few things, not all of them shown in my answer. The data does not seem to be fully fit well by that model, though with some effort, I did manage to find a fit to the first 2/3 of the curve. Down in the bottom end it seems like noise (or some extraneous factor) is corrupting the data beyond the point that the data in the tail is of any value for the model.
See Also
Categories
				Find more on Get Started with Curve Fitting Toolbox in Help Center and File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!








