Fitting two curves with shared parameters to two datasets

3 次查看(过去 30 天)
I want to fit the two functions
to a dataset of the form . Here are a dimensionless distance and two angles (degrees) respectively.
I am trying to follow the procedure describe here.
I generate the dataset using the above functions with some Gaussian noise on top. The data generation seems to work fine.
Yet, the call "lsqcurvefit(fun, x0, alpha_data_tab, beta_data_tab);" gives me an error which indicates that there are some dimension mismatch. However, I do not see it. Can anyone help me with this issue?
clc
close all
clear all
set(0,'defaulttextinterpreter','latex')
set(0,'defaultAxesTickLabelInterpreter','latex');
set(0,'defaultLegendInterpreter','latex');
set(0, 'DefaultLineLineWidth', 2);
set(0,'defaultAxesFontSize',15)
%True parameters
Af0_true = -0.017767; %Fast initial amplitude
As0_true = 0.017767; %Slow initial amplitude
lambda_f_true = -4.0571e-04; %Fast damping parameter; 1/cm
lambda_s_true = 6.4718e-05; %Slow damping parameter; 1/cm
angular_vel_f_true = 0.0228; %Angular velocity; rad/cm
angular_vel_s_true = 0.0050; %Angular velocity; rad/cm
dx = 0.01; %cm
s_true = 0:dx:1000; %cm
std = 0.1; %deg
spacing = 4;
s_data1 = 275:spacing:300;
s_data2 = 350:spacing:375;
s_data3 = 425:spacing:450;
s_data4 = 500:spacing:525;
s_data = [s_data1, s_data2, s_data3, s_data4];
[s, alpha, beta, s_data, alpha_data, beta_data] = dataMaker(Af0_true, As0_true, lambda_f_true, lambda_s_true, angular_vel_f_true, angular_vel_s_true, s_true, s_data, std);
alpha_data_tab = [s_data(:), alpha_data(:)]; % Concatenate Vectors
beta_data_tab = [s_data(:), beta_data(:)]; % Concatenate Vectors
fun1 = @(v,s_data)v(1)*exp(v(3)*s_data).*cos(v(5)*s_data) + v(2)*exp(v(4)*s_data).*cos(v(6)*s_data);
fun2 = @(v,s_data)v(1)*exp(v(3)*s_data).*sin(v(5)*s_data) + v(2)*exp(v(4)*s_data).*sin(v(6)*s_data);
fun = @(v,s_data)[fun1(v,s_data)', fun2(v,s_data)']; % Composite Function
%initial guess
percent = 0.2; %Percent deviation
x0 = [Af0_true-percent*Af0_true, As0_true-percent*As0_true, lambda_f_true-percent*lambda_f_true, lambda_s_true-percent*lambda_s_true,...
angular_vel_f_true-percent*angular_vel_f_true, angular_vel_s_true-percent*angular_vel_s_true];
fun(x0, s_data)
ans = 28×2
0.0027 0.0253 0.0016 0.0250 0.0005 0.0247 -0.0005 0.0244 -0.0015 0.0240 -0.0025 0.0235 -0.0034 0.0229 -0.0102 0.0130 -0.0102 0.0121 -0.0103 0.0112
X = lsqcurvefit(fun, x0, alpha_data_tab, beta_data_tab);
Error using lsqcurvefit
Function value and YDATA sizes are not equal.
function [s_total, alpha_total, beta_total, s_data, alpha_data, beta_data] = dataMaker(Af0_true, As0_true, lambda_f_true, lambda_s_true, angular_vel_f_true, angular_vel_s_true, s_total, s_data, std_deg)
s_total = s_total;
std_rad = std_deg*(pi/180); %rad
%True parameter vector
v0 = [Af0_true, As0_true, lambda_f_true, lambda_s_true, angular_vel_f_true, angular_vel_s_true];
alpha_total = v0(1)*exp(v0(3)*s_total).*cos(v0(5)*s_total) + v0(2)*exp(v0(4)*s_total).*cos(v0(6)*s_total);
beta_total = v0(1)*exp(v0(3)*s_total).*sin(v0(5)*s_total) + v0(2)*exp(v0(4)*s_total).*sin(v0(6)*s_total);
s_data = s_data;
alpha_data = v0(1)*exp(v0(3)*s_data).*cos(v0(5)*s_data) + v0(2)*exp(v0(4)*s_data).*cos(v0(6)*s_data);
beta_data = v0(1)*exp(v0(3)*s_data).*sin(v0(5)*s_data) + v0(2)*exp(v0(4)*s_data).*sin(v0(6)*s_data);
alpha_noise = std_rad*randn(1,length(s_data));
beta_noise = std_rad*randn(1,length(s_data));
alpha_data = alpha_data + alpha_noise;
beta_data = beta_data + beta_noise;
end

采纳的回答

Torsten
Torsten 2023-11-13
编辑:Torsten 2023-11-13
clc
close all
clear all
set(0,'defaulttextinterpreter','latex')
set(0,'defaultAxesTickLabelInterpreter','latex');
set(0,'defaultLegendInterpreter','latex');
set(0, 'DefaultLineLineWidth', 2);
set(0,'defaultAxesFontSize',15)
%True parameters
Af0_true = -0.017767; %Fast initial amplitude
As0_true = 0.017767; %Slow initial amplitude
lambda_f_true = -4.0571e-04; %Fast damping parameter; 1/cm
lambda_s_true = 6.4718e-05; %Slow damping parameter; 1/cm
angular_vel_f_true = 0.0228; %Angular velocity; rad/cm
angular_vel_s_true = 0.0050; %Angular velocity; rad/cm
dx = 0.01; %cm
s_true = 0:dx:1000; %cm
std = 0.1; %deg
spacing = 4;
s_data1 = 275:spacing:300;
s_data2 = 350:spacing:375;
s_data3 = 425:spacing:450;
s_data4 = 500:spacing:525;
s_data = [s_data1, s_data2, s_data3, s_data4];
[s, alpha, beta, s_data, alpha_data, beta_data] = dataMaker(Af0_true, As0_true, lambda_f_true, lambda_s_true, angular_vel_f_true, angular_vel_s_true, s_true, s_data, std);
%alpha_data_tab = [s_data(:), alpha_data(:)]; % Concatenate Vectors
%beta_data_tab = [s_data(:), beta_data(:)]; % Concatenate Vectors
xdata = s_data;
ydata = [alpha_data(:),beta_data(:)];
fun1 = @(v,s_data)v(1)*exp(v(3)*s_data).*cos(v(5)*s_data) + v(2)*exp(v(4)*s_data).*cos(v(6)*s_data);
fun2 = @(v,s_data)v(1)*exp(v(3)*s_data).*sin(v(5)*s_data) + v(2)*exp(v(4)*s_data).*sin(v(6)*s_data);
fun = @(v,s_data)[fun1(v,s_data)', fun2(v,s_data)']; % Composite Function
%initial guess
percent = 0.2; %Percent deviation
x0 = [Af0_true-percent*Af0_true, As0_true-percent*As0_true, lambda_f_true-percent*lambda_f_true, lambda_s_true-percent*lambda_s_true,...
angular_vel_f_true-percent*angular_vel_f_true, angular_vel_s_true-percent*angular_vel_s_true];
%X = lsqcurvefit(fun, x0, alpha_data_tab, beta_data_tab);
X = lsqcurvefit(fun, x0, xdata, ydata);
function [s_total, alpha_total, beta_total, s_data, alpha_data, beta_data] = dataMaker(Af0_true, As0_true, lambda_f_true, lambda_s_true, angular_vel_f_true, angular_vel_s_true, s_total, s_data, std_deg)
s_total = s_total;
std_rad = std_deg*(pi/180); %rad
%True parameter vector
v0 = [Af0_true, As0_true, lambda_f_true, lambda_s_true, angular_vel_f_true, angular_vel_s_true];
alpha_total = v0(1)*exp(v0(3)*s_total).*cos(v0(5)*s_total) + v0(2)*exp(v0(4)*s_total).*cos(v0(6)*s_total);
beta_total = v0(1)*exp(v0(3)*s_total).*sin(v0(5)*s_total) + v0(2)*exp(v0(4)*s_total).*sin(v0(6)*s_total);
s_data = s_data;
alpha_data = v0(1)*exp(v0(3)*s_data).*cos(v0(5)*s_data) + v0(2)*exp(v0(4)*s_data).*cos(v0(6)*s_data);
beta_data = v0(1)*exp(v0(3)*s_data).*sin(v0(5)*s_data) + v0(2)*exp(v0(4)*s_data).*sin(v0(6)*s_data);
alpha_noise = std_rad*randn(1,length(s_data));
beta_noise = std_rad*randn(1,length(s_data));
alpha_data = alpha_data + alpha_noise;
beta_data = beta_data + beta_noise;
end

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Get Started with Curve Fitting Toolbox 的更多信息

产品


版本

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by