Appy lsqcurvefit to multiple data sets with multiple parameters

Hello everyone,
I have a number of experimental data sets for which I need a general correlation with three coefficients, so I though using lsqcurvefit (or fitnlm).
The structure of one data set looks like this:
Xdata_1 = (x1, x2, x3, x4, x5, x6), each xi is a column vector,
Ydata_1 = (y1), a response column vector,
fun = @(c,X) c(1)*X(:,3).^(1-c(2)).* (X(:,2).*X(:,4)).^c(2).* 1./X(:,1).^(1+c(2)).* (X(:,5)./X(:,6)).^c(3);
c0 = [0.1, 0.8, 0.33];
I am able to apply a fitting function to one data set like:
c = lsqcurvefit(fun,c0,Xdata_1,Ydata_1);
However what I need is to fit fun to multiple Xdata_i, Ydata_i to obtain the 'best' set of c-coefficients? Of course I could loop it and get for each input a set of c's, but that is not of interest.
If that is possible then I don't know the syntax. Does anyone have an idea?
Thank you.

Respuestas (2)

Jon
Jon el 1 de Jun. de 2023
Can you stack your data, so that if for example, using your terminology, Xdata_1,Xdata__,.. Ydata_1, Ydata_2,...
Then fit Xdata = [Xdata_1(:);Xdata_2(:);...], Ydata = [Ydata_1(:);Ydata_2,...]

4 comentarios

But then Xdata and Ydata will have dimensions of nXnumel(Xdata_i), rather than nX6 and nX1 as required by fun, right?
With your suggestion I get:
Index in position 2 exceeds array bounds. Index must not exceed 1.
Also, assuming that basic idea works for you, I would recommend that you not include the indexing in your variable names. So if all of your data sets are the same length then put the collection of data sets in an array, where each column corresponds to a test run. So if all of your data were put into arrays X and Y, you could just fit X(:),Y(:).
If your data sets are not eqaul length then you could still store the collection of data sets in a cell array with a column for each data set. In this case if your, N data sets were in 1 by N cells X and Y you could then fit Xfit = cell2mat(X(:)), and Yfit = cell2mat(X(:))
How will the function fun look like then? For example, X has currently the dimension of nX6, using X(:) it will be nX1, so the function fun won't accept it. I assume this is what you mean by getting rid of the indexing. But my Matlab skill stop here :)
Sorry, I should have looked more carefully at your problem statement. I missed that X had 6 columns. Assuming you had many data sets, each with a different number of rows, it would still be preferable to store the whole collection in one variable rather than working with a variable for each data set, e.g Xdata_1, Xdata_2, etc.
For this purpose you could make one cell array, call it Xdata, and put all of the data in it (just to illustrate)
Xall = {rand(20,6),rand(12,6),rand(4,6),rand(11,6)}
You could then stack your data, and and apply your function to it using
X = cell2mat(Xall(:))
Note, if you only have a few data sets, its not too bad to just vertically concatenate them as @Star Strider showed using something like
X = [Xdata_1;Xdata_2]
But if you have more than a few, it would probably be better to not include the indexing in the variable names, and do something like I show above

Iniciar sesión para comentar.

If I understand the problem correctly, and all the data sets contain column vectors and are the same column size (they do not have to have the same row size), one option is to vertically concatenate them —
Xdata_1 = rand(5,6);
Ydata_1 = rand(5,1);
Xdata_2 = rand(6,6);
Ydata_2 = rand(6,1);
fun = @(c,X) c(1)*X(:,3).^(1-c(2)).* (X(:,2).*X(:,4)).^c(2).* 1./X(:,1).^(1+c(2)).* (X(:,5)./X(:,6)).^c(3);
c0 = [0.1, 0.8, 0.33];
Xdata_All = [Xdata_1; Xdata_2]
Xdata_All = 11×6
0.5455 0.2325 0.3362 0.3171 0.4276 0.3432 0.4677 0.5301 0.8489 0.1221 0.3210 0.2615 0.9070 0.7753 0.1527 0.5464 0.9224 0.8892 0.3912 0.9904 0.4704 0.0657 0.0804 0.3063 0.5342 0.0494 0.8931 0.8891 0.4500 0.1055 0.2925 0.5194 0.5435 0.0228 0.4696 0.1555 0.7444 0.8860 0.5599 0.2235 0.3908 0.6603 0.7241 0.5284 0.2532 0.3332 0.8996 0.1589 0.0140 0.1112 0.9787 0.9927 0.6766 0.2714 0.2487 0.9226 0.6634 0.0111 0.4708 0.6328
Ydata_All = [Ydata_1; Ydata_2]
Ydata_All = 11×1
0.2129 0.0203 0.0741 0.9078 0.5425 0.4604 0.9899 0.8271 0.8167 0.1850
c = lsqcurvefit(fun,c0,Xdata_1,Ydata_1) % Separately
Local minimum possible. lsqcurvefit stopped because the final change in the sum of squares relative to its initial value is less than the value of the function tolerance.
c = 1×3
0.4026 0.4592 -0.8011
c = lsqcurvefit(fun,c0,Xdata_2,Ydata_2) % Separately
Local minimum possible. lsqcurvefit stopped because the final change in the sum of squares relative to its initial value is less than the value of the function tolerance.
c = 1×3
0.0126 -0.6136 1.3589
c = lsqcurvefit(fun,c0,Xdata_All,Ydata_All) % Conocatenated
Local minimum possible. lsqcurvefit stopped because the final change in the sum of squares relative to its initial value is less than the value of the function tolerance.
c = 1×3
0.0125 -0.5977 1.3180
Try this to see if it produces the result you want.
.

2 comentarios

That seems exactly what I needed. I will try it out and report.
Thank you!
My pleasure!

Iniciar sesión para comentar.

Productos

Versión

R2022b

Preguntada:

el 1 de Jun. de 2023

Comentada:

Jon
el 2 de Jun. de 2023

Community Treasure Hunt

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

Start Hunting!

Translated by