
Help needed to set proper curve fitting constraints for a comprehensive solution for fitting data to custom models
조회 수: 29 (최근 30일)
이전 댓글 표시
Hello,
Trying to fit a custom model to my data but unable to get any results. So far tried playing with a bunch of curve fitting parameters like step size tolerance etc. but I don't think I have a proper understanding of the different parameters in the curvefitter app. Need help finding details/examples for the parameters in the advanced options section of the app.
Currently using the lsqcurvefit function with expected intitial value for the coefficients. Need to know which parameters to tweak to get any fit at all. I have tried curtailing my data to fit a section of it intead of the whole thing. See the attached code and data below:
Thanks!
clc
close all
clear
data = csvread('AT COAX, OPEN ELECTRODE3.CSV',3,0,[3,0,1603,2]);
datax = data(:,1);
datay = data(:,2);
freq = datax(650:850);
%freq = data(:,1);
realZ = datay(650:850);
%realZ = data(:,2);
fun = @(x, R_E, C_E, C_C, L_E) ((R_E.*C_E.^2)./...
(((C_C.*C_E.*L_E.*(2*pi*x).^2).^2) + ...
((C_C.*C_E.*R_E.*(2*pi*x)).^2) + (C_C.^2) + ...
(C_E.^2) + 2*C_C.*C_E - 2*(C_C.^2).*C_E.*L_E.*((2*pi*x).^2) - ...
2*(C_E.^2).*C_C.*L_E.*((2*pi*x).^2)));
%options = optimoptions(@lsqcurvefit,'StepTolerance',1e-10)
sol = lsqcurvefit(@(x,xdata) fun(xdata,x(1),x(2),x(3),x(4)) , [1, 100e-12, 100e-12, 100e-9], freq, realZ);
hold on
plot(freq, realZ)
plot(freq,fun(freq,sol(1),sol(2),sol(3),sol(4)))
hold off
댓글 수: 0
답변 (2개)
Sam Chak
2025년 11월 17일
Hi @sxh
It appears you used the Witch of Agnesi, a well-known bell-shaped function (technically, the derivative of the arctangent function) to fit the curve. A closer look shows that the frequency‑response data are not perfectly symmetric.
However, the following composite bell‑shaped function can approximate the curve where the generalized Gaussian controls the peak sharpness, while the hyperbolic secant shapes the decaying tails.

data = csvread('AT COAX, OPEN ELECTRODE3.CSV',3,0,[3,0,1603,2]);
datax = data(:,1);
datay = data(:,2);
freq = datax(650:850);
realZ = datay(650:850);
xdata = freq/max(freq);
ydata = realZ/max(realZ);
fun = @(p, xdata) p(4)*exp(- abs((xdata - p(1))/p(2)).^(2/p(3))) + (1 - p(4))*sech(p(5)*(xdata - p(1)));
lb = [0.8, 0.005, 1.0, 0.8, 29.0];
ub = [0.9, 0.015, 2.0, 1.0, 49.0];
p0 = [0.87 0.010, 1.7, 0.9, 2.0];
sol = lsqcurvefit(fun, p0, xdata, ydata, lb, ub)
hold on
plot(freq, realZ, '.'), grid on % data
plot(freq, max(realZ)*fun(sol, freq/max(freq))) % fitted model
hold off
xlabel('freq')
ylabel('realZ')
title('Frequency‑response curve')
legend('data', 'fitted model')
댓글 수: 0
Sam Chak
2025년 11월 17일
Hi @sxh
The Witch of Agnesi provides a very good fit for the curve, although your original "witch" function needs proper centering and scaling. I will leave solving the simultaneous equations for the parameters
,
,
,
, and the center point as an exercise.

Note that the Witch of Agnesi has 3 critical parameters, whereas your original "witch" function has 5 variables, including the center point. A system with more variables (5) than equations (3) is underdetermined because it has either infinitely many solutions or none. However, you may fix the center point and choose 2 of the 4 variables {
,
,
,
} as free parameters.
data = csvread('AT COAX, OPEN ELECTRODE3.CSV', 3, 0, [3, 0, 1603, 2]);
datax = data(:,1);
datay = data(:,2);
freq = datax(650:850);
realZ = datay(650:850);
xdata = freq/max(freq);
ydata = realZ/max(realZ);
%% Original "Witch of Agnesi"
% fun = @(x, R_E, C_E, C_C, L_E, ctr) ...
% ( ...
% (R_E.*C_E.^2)./...
% ( ...
% (C_C.*C_E.*L_E.*(2*pi*(x - ctr)).^2).^2 + ...
% (C_C.*C_E.*R_E.*(2*pi*(x - ctr)) ).^2 + ...
% C_C.^2 + C_E.^2 + 2*C_C.*C_E - ... % the constant
% 2*(C_C.^2).*C_E.*L_E.*(2*pi*(x - ctr)).^2 - ...
% 2*(C_E.^2).*C_C.*L_E.*(2*pi*(x - ctr)).^2 ...
% ) ...
% );
% sol = lsqcurvefit(@(p, xdata) fun(xdata, p(1), p(2), p(3), p(4), p(5)) , [1, 1, 1, 1, 0.8671], xdata, ydata)
figure
plot(xdata, ydata), grid minor
title('Normalized data')
xlabel('xdata')
ylabel('ydata')
% Simplified form of the Witch of Agnesi
fun = @(x, p1, p2, p3) p1./(p3*(x - p2).^2 + p1);
lb = [0.008, 0.80, 90];
ub = [0.010, 0.90, 110];
p0 = [0.009, 0.85, 100];
sol = lsqcurvefit(@(p, xdata) fun(xdata, p(1), p(2), p(3)), p0, xdata, ydata, lb, ub)
figure
hold on
plot(freq, realZ, '.'), grid on % data
plot(freq, max(realZ)*fun(freq/max(freq), sol(1), sol(2), sol(3))) % fitted model
hold off
xlabel('freq')
ylabel('realZ')
title('Fit Frequency‑response curve with the Witch of Agnesi')
legend('data', 'fitted model')
댓글 수: 3
Sam Chak
2025년 11월 17일
Thanks @Torsten. I believe the OP ultimately wants to determine the fundamental electrical properties, resistance
, capacitances
and
, and inductance
from the fitted curve. Would the solve() function be preferred over fsolve() for solving a system of nonlinear equations in this case?
참고 항목
카테고리
Help Center 및 File Exchange에서 Linear and Nonlinear Regression에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



