fitting is not working
古いコメントを表示
%% Luz-Meiboom fit of R2 vs pH
clear; clc; close all;
%% Data
pH = [1.88, 2.45, 3.39, 3.87, 4.53, 4.68, 5.12, 5.25, 5.55, 5.82, ...
6.01, 6.27, 6.66, 6.98, 7.75, 8.25, 8.96, 9.23];
R2 = [0.01137, 0.00973, 0.00803, 0.01824, 0.0547, 0.0712, 0.10246, ...
0.12065, 0.12992, 0.22537, 0.18405, 0.05077, 0.0203, 0.01554, ...
0.02122, 0.0371, 0.03736, 0.00611];
pH = pH(:);
R2 = R2(:);
%% Luz-Meiboom model function
% params(1) = R2m
% params(2) = tau
luzMeiboomFun = @(params, x) params(1) + params(2).* ...
(1 - (2.*params(2)./x).*tanh(x./(2.*params(2))));
%% Initial parameter guesses
R2m_guess = min(R2);
tau_guess = 0.963;
p0 = [R2m_guess, tau_guess];
%% Bounds (lower, upper)
lb = [0, 0, 1e-4];
ub = [1, 1000, 500];
%% Fit using lsqcurvefit (Optimization Toolbox)
opts = optimoptions('lsqcurvefit', 'Display', 'iter');
[params_fit, resnorm, residual, exitflag] = lsqcurvefit(luzMeiboomFun, p0, pH, R2, lb, ub, opts);
R2m_fit = params_fit(1);
tau_fit = params_fit(2);
fprintf('\n--- Fit results ---\n');
fprintf('R2m = %.5f\n', R2m_fit);
fprintf('tau = %.5f\n', tau_fit);
fprintf('Residual norm = %.5f\n', resnorm);
%% Generate smooth fitted curve for plotting
pH_fine = linspace(min(pH), max(pH), 300);
R2_fit_curve = luzMeiboomFun(params_fit, pH_fine);
%% Plot: pH vs R2
figure('Color','w');
plot(pH, R2, 'ko', 'MarkerFaceColor','r', 'MarkerSize',7, 'DisplayName','Data');
hold on;
plot(pH_fine, R2_fit_curve, 'b-', 'LineWidth', 1.8, 'DisplayName','Luz-Meiboom fit');
xlabel('pH', 'FontSize', 12);
ylabel('R_2 (s^{-1})', 'FontSize', 12);
title('R_2 vs pH — Luz-Meiboom Fit', 'FontSize', 13);
legend('Location','best');
grid on;
box on;
hold off;
1 件のコメント
Walter Roberson
約1時間 前
Your upper and lower bounds are three elements each, but you are only searching over 2 parameters.
回答 (1 件)
As far as I can see, the function f(x) = p*(1-2*p./x.*tanh(x/(2*p))) is monotonically increasing (the first parameter params(1) is not important in the analysis since it's only a translation of the curve in the upward or downward direction). Thus you will never get the bellshape of your experimental data for a fit result. Try plotting the function from above for different values of p, and you will see what I mean.
Thus in short: the model function is not suited to reflect your experimental data.
x = 1:14;
p = [0.003;0.03;0.3;3;30;300];
f = p.*(1-2*p./x.*tanh(x./(2*p)));
plot(x,f)
9 件のコメント
It appears you (both) may be using the wrong model form. That is, when I look online for that model, I see a different form.
In there (aswell in all other places I saw that model), the form appears to have an extra 1/x term in it. Something more like this (again, I've dropped extraneous constants so we can see the fundamental shape.)
f = @(x,p) 1./x.*(1-2*p./x.*tanh(x./(2*p)));
figure
fplot(@(x) f(x,1),[0,50],'r')
hold on
fplot(@(x) f(x,2),[0,50],'g')
fplot(@(x) f(x,3),[0,50],'b')
Anyway, this now has a skewed bell shape to it. At the same time, the shape is still not terribly consistent with the data provided, so I doubt it will help greatly.
Ehtisham
約6時間 前
Replace
luzMeiboomFun = @(params, x) params(1) + params(2).* ...
(1 - (2.*params(2)./x).*tanh(x./(2.*params(2))));
by the modified model function.
Torsten
約5時間 前
I don't see changes in
luzMeiboomFun = @(params, x) params(1) + params(2).* ...
(1 - (2.*params(2)./x).*tanh(x./(2.*params(2))));
compared to your previous code.
And you still use three-element vectors for lower and upper bounds on the parameters instead of two-element vectors.
Walter Roberson
約3時間 前
Your code
luzMeiboomFun = @(params, x) params(1) + params(2).* ...
(1 - (2.*params(2)./x).*tanh(x./(2.*params(2))));
does not contain a 1./x term.
Ehtisham
約3時間 前
I didn't say to use
luzMeiboomFun = @(params, x) params(1) + params(2).* ...
(1 - (2.*params(2)./x).*tanh(x./(2.*params(2))));
- this is what you implemented right from the beginning and which will for sure be inadequate for your experimental data. I said to replace this function by the correct model function (which we don't know how it looks). As far as I understand, @John D'Errico made the suggestion to use
luzMeiboomFun = @(params, x) params(1) + params(2)./x.* ...
(1 - (2.*params(2)./x).*tanh(x./(2.*params(2))));
instead, but his last comment makes me guess that it won't improve things greatly.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!





