How to set up the Matrix variables to use Options = optimoptions('lsqcurvefit','algorithm','levenberg-marquardt')
2 次查看(过去 30 天)
显示 更早的评论
I have two sets of M1 and M2 vectors (1x20) of experimental values that correspond to two sets of K1 and K2 inputs (1x20) respectively. Theoretlcal values of M1 and M2 (call them M1T and M2T) have a relationship with K1 and K2 such that M1-T is a function of K1 and K2, and M2-T is also a function of K1 and K2 with a series of a1 to a6 coefficients.
I am trying to find those a1 to a6 coefficients by minimizing the error function Total Error = (M1 - M1T)^2 + (M2-M2T)^2 by the use of
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt'), however, I don't know how to set up my variables into these names/function (i.e. don't know the approriate coding syntax).
As an example;
the inputs are: M1 = [ i1 i2 i3 ............ i20], M2 = [ i1 i2 i3 .............i20], K1 = [ i1 i2 i3 ............ i20], K2 = [ i1 i2 i3 .............i20],
the relationship between theroretical values of M1, M2 and the K1 and K2 are:
M1T(i) = a1*K1(i) + a2*K1(i)*K2(i) + a3*K2(i) + a4*(K1(i))^2
M2T(i) = a2*K2(i) + a2*K1(i) + a5*(K2(i))^2 + a6*K1(i)*K2(i)
采纳的回答
Star Strider
2024-7-28
I am not certain how ‘M1T’ and ‘M2T’ enter into this, however witth the ‘K’ values as the independent variables, and the ‘M’ values as the dependent variables, this is how I would set this up. (I prefer column vectors and column-oriented matrices, so I transposed the original row vectors to column vectors here.)
Try this, with your actual data —
M1 = randn(1,20);
M2 = randn(1,20);
K1 = randn(1,20);
K2 = randn(1,20);
% M1T = randn(1,20);
% M2T = randn(1,20);
M = [M1; M2].';
K = [K1; K2].';
MT = [M1T; M2T].';
objfcn = @(a,K) [a(1).*K(:,1) + a(2).*K(:,1).*K(:,2) + a(3).*K(:,2) + a(4).*K(:,1).^2, a(2).*K(:,2) + a(2).*K(:,1) + a(5).*K(:,2).^2 + a(6).*K(:,1).*K(:,2)]
A0 = rand(6,1);
[A,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, A0, K, M);
Estimated_Parameters = A
I did not include the options call or options structure here, for simplicity. I usually lett lsqcurvefit pick the approopriate algorthm.
.
23 个评论
Selim
2024-7-28
Thank you - this is a great help. One comment and follow-up question; I defnitely need to incorporate the M1T and M2T since I am trying to estimate them based on combination inputs of K1 and K2. So, the goal is to find those a1 through a6 coefficients that would then give the minimum error between the experimental values of M1, M2 and the predicted of M1T and M2T for the each i= 1 to 20 data points.
Also, I am required to use the options structure as part of the comparision method.
Thanks again - greatly appreciated.
Star Strider
2024-7-28
编辑:Star Strider
2024-7-28
As always, my pleasure!
I believe that I understand how the ‘M’ and ‘K’ matrices are related, however I do not understand how a matching ‘MT’ matrix fits into it. Please describe that.
My guess is that it mightt go somethng like this —
M1 = randn(1,20);
M2 = randn(1,20);
K1 = randn(1,20);
K2 = randn(1,20);
M1T = randn(1,20);
M2T = randn(1,20);
M = [M1; M2].';
K = [K1; K2].';
MT = [M1T; M2T].';
objfcn = @(a,K) [a(1).*K(:,1) + a(2).*K(:,1).*K(:,2) + a(3).*K(:,2) + a(4).*K(:,1).^2, a(2).*K(:,2) + a(2).*K(:,1) + a(5).*K(:,2).^2 + a(6).*K(:,1).*K(:,2)];
A0 = rand(6,1);
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, A0, K, M, [], [], options);
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.
Estimated_Parameters = A
Estimated_Parameters = 6x1
0.1110
0.0106
0.5301
0.1358
-0.1990
-0.0467
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Mest = objfcn(A,K) % Fitted Values of 'M' From Regression
Mest = 20x2
0.5153 -0.1702
1.2665 -0.1943
0.0072 -0.0241
0.2855 0.0162
-0.6897 -0.4732
0.8010 -0.0193
0.3003 -0.0789
-0.1747 -0.0731
-0.5193 -0.2608
0.3886 0.0200
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Merr = MT - Mest % Matrix Of Differences
Merr = 20x2
-0.9136 0.9008
-2.4218 1.3586
0.1662 0.3310
0.0995 0.0920
2.2879 0.6085
0.5736 -0.8223
0.0818 -1.6282
2.0840 0.2712
0.8627 -0.2415
-0.5600 0.9696
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
MerrRMS = sqrt(mean(Merr.^2)) % Root-Mean_Squared Error
MerrRMS = 1x2
1.3816 0.8316
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[Ks, idx] = sort(K);
figure
col = 1;
plot(K(idx(:,col),col), M(idx(:,col),col), '.')
hold on
plot(K(idx(:,col),col), Mest(idx(:,col),col), '-r')
hold off
grid
xlabel("K(:,"+col+")")
ylabel("M(:,"+col+")")
figure
col = 2;
plot(K(idx(:,col),col), M(idx(:,col),col), '.')
hold on
plot(K(idx(:,col),col), Mest(idx(:,col),col), '-r')
hold off
grid
xlabel("K(:,"+col+")")
ylabel("M(:,"+col+")")
Micro$oft once again randomly crashed my computer, apparently because it is fun for them (since there is no obvious reason for it) while I was typing this. My apologies for the resulting delay.
EDIT — (28 Jui 2024 at 17:19)
Since the options structure is required, it is now added. Code otherwise unchanged.
.
Selim
2024-7-28
移动:Star Strider
2024-7-28
Thank you very much! - Meanwhile, I am exploring a slightly different modeling with the following M1T and M2T relationships to the independent variable K1 and K2.This time I have 7 coefficients (A through G).
M1T = 2*A*K1 + B*K2 + 3*D*(K1)^2 + 2*E*K1*K2 + F*(K2)^2;
M2T = B*K1 + 2*C*K2 + E*(K1)^2 + 2*F*K1*K2 + 3*G*(K2)^2
Like the last set, I have the K1, K2 independent values and their corresponding M1 and M2 dependent measurements.
My goal is again to determine the fit function for the K1 and K2 ( x-axis) based on the minimizing the error (similar to above) between (M1 and M1T) & (M2 and M2T) pairs using the same options function in order to derive the 7 coefficients. I think I should be able to use the same stucture you generated? Also, this time, I was thinking that I could even assign the unity matrix of 1s to the coefficients as their starting points rather than random integeters. Thanks again.
Star Strider
2024-7-28
As always, my pleasure!
That is relatively straightforward. I did not know how you wanted ot integrate the ‘M’ and ‘MT’ arrays into your code.
My code changes slightly to —
M1 = randn(1,20);
M2 = randn(1,20);
K1 = randn(1,20);
K2 = randn(1,20);
M1T = randn(1,20);
M2T = randn(1,20);
M = [M1; M2].';
K = [K1; K2].';
MT = [M1T; M2T].';
objfcn = @(a,K) [2*a(1).*K(:,1) + a(2).*K(:,2).*K(:,2) + 3*a(4).*K(:,1).^2 + a(5).*K(:,1).*K(:,2), a(2).*K(:,1) + 2*a(3).*K(:,2) + a(5).*K(:,2).^2 + a(6).*K(:,1).*K(:,2) + 3.*a(7).*K(:,1).^2];
A0 = rand(7,1);
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm1,Rsd1,ExFlg1,OptmInfo1,Lmda1,Jmat1] = lsqcurvefit(objfcn, A0, K, M, [], [], options);
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.
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1, 'RowNames',ParmNames)
M_Parameters = 7x1 table
A1
__________
A 0.23359
B 0.17204
C -0.0034356
D 0.072715
E 0.023078
F -0.22083
G -0.071126
M_est = objfcn(A1,K) % Fitted Values of 'M' From Regression
M_est = 20x2
-0.1065 -1.1130
-0.0042 -0.0178
-0.0682 -1.0381
-0.2495 -0.3619
-0.0041 -0.2390
1.0891 0.2467
-0.1451 -0.7540
-0.1674 -0.1271
0.6402 -0.0834
0.1359 0.0547
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[A2,Rsdnrm2,Rsd2,ExFlg2,OptmInfo2,Lmda2,Jmat2] = lsqcurvefit(objfcn, A0, K, MT, [], [], options);
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.
MT_Parameters = table(A2, 'RowNames',ParmNames)
MT_Parameters = 7x1 table
A2
__________
A -0.052173
B -0.0016726
C 0.1332
D -0.10325
E 0.036607
F 1.1643
G 0.063416
MT_est = objfcn(A2,K) % Fitted Values of 'M' From Regression
MT_est = 20x2
-0.8528 0.9717
0.0079 -0.0642
-1.0278 0.1142
-0.2042 0.1122
-0.0144 0.4419
-0.0350 0.1037
-0.7566 -0.1839
-0.0164 0.0512
-0.3521 0.5579
-0.0312 -0.2379
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
[Ks, idx] = sort(K);
figure
col = 1;
plot(K(idx(:,col),col), M(idx(:,col),col), '.')
hold on
plot(K(idx(:,col),col), M_est(idx(:,col),col), '-r')
hold off
grid
xlabel("K(:,"+col+")")
ylabel("M(:,"+col+")")
figure
col = 2;
plot(K(idx(:,col),col), M(idx(:,col),col), '.')
hold on
plot(K(idx(:,col),col), M_est(idx(:,col),col), '-r')
hold off
grid
xlabel("K(:,"+col+")")
ylabel("M(:,"+col+")")
figure
col = 1;
plot(K(idx(:,col),col), MT(idx(:,col),col), '.')
hold on
plot(K(idx(:,col),col), MT_est(idx(:,col),col), '-r')
hold off
grid
xlabel("K(:,"+col+")")
ylabel("MT(:,"+col+")")
figure
col = 2;
plot(K(idx(:,col),col), MT(idx(:,col),col), '.')
hold on
plot(K(idx(:,col),col), MT_est(idx(:,col),col), '-r')
hold off
grid
xlabel("K(:,"+col+")")
ylabel("MT(:,"+col+")")
This uses the new version of ‘objfcn’ however I suggest that you check it. Now, a(1)=A, ... a(7)=G.
Use the correct values for the relevant vectors, and this should do what you want. (The plots are optional. I included them because I like to see how the regressions look.)
.
Selim
2024-7-31
移动:Star Strider
2024-7-31
Hi again, I hope this question finds you and that you will be able to provide your feedback.
After running my data, things did not make sense. I realized that there were some error in my original variable names and set up. I modified the variables such that hopefully MT now it should make sense to you as well. Do you think the below code and syntax make sense?
%given
M1 = [5 11 18 25 32 39 46 52 60];
M2 = [9 10 11 12 13 15 16 18 21];
K1 = [0 0.2 0.36 0.44 0.49 0.51 0.52 0.54 0.55];
K2 = [0.75 0.77 0.8 0.84 0.88 0.94 0.98 1.0 1.02];
%Theoritical Calculation of M1 and M2 in terms of the coefficients and K1 and K2
%M1_Theory = 2*Cff(1)*K1 + Cff(2)*K2 + 3*Cff(4)*K1^2 + 2*Cff(5)*K1*K2 + Cff(6)*K2^2;
%M2_Theory = Cff(2)*K1 + 2*Cff(3)*K2 + Cff(5)*K1^2 + 2*Cff(6)*K1*K2 + 3*Cff(7)*K2^2;
K = [K1; K2].';
M = [M1; M2].';
M1_Theory = 2*Cff(1).*K(:,1) + Cff(2).*K(:,2) + 3*Cff(4).*K(:,1) + 2*Cff(5).*K(:,1).*K(:,2) + Cff(6).*K(:,2).^2;
Unrecognized function or variable 'Cff'.
M2_Theory = Cff(2).*K(:,1) + 2*Cff(3).*K(:,2) + Cff(5).*K(:,1)^2 + 2*Cff(6).*K(:,1).*K(:,2) + 3*Cff(7).*K(:,2).^2;
M_Theory = [M1_Theory; M2_THeory].';
objfcn = @(Cff,M_Theory) [(M1-M1_Theory)^2 -(M2-M2_Theory)^2]
Cff = ones (7,1);
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff, M, M_Theory, [], [], options);
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1,'RowNames',ParmNames)
M_Theory = objfcn(A1,M_Theory)
Star Strider
2024-7-31
编辑:Star Strider
2024-7-31
The best way to see if it makes sense is to run it.
I did my best to get this to run, and that required several significant changes. The problem is that ‘objfcn’ need to return a (9x2) matrix. Before my changes, your code would not run at all. After my changes, ‘objfcn’ returns a (9x18) matrix. I am not certain what you want to do, so I will leave tthis for the time being and check back when ‘objfcn’ works correctly, or at least that I understand what you want to do with it. I creeated a ‘Q’ variable to see what ‘objfcn’ returns. You can use it for that purpose, to get ‘objfcn’ to work correctly.
M1 = [5 11 18 25 32 39 46 52 60];
M2 = [9 10 11 12 13 15 16 18 21];
K1 = [0 0.2 0.36 0.44 0.49 0.51 0.52 0.54 0.55];
K2 = [0.75 0.77 0.8 0.84 0.88 0.94 0.98 1.0 1.02];
%Theoritical Calculation of M1 and M2 in terms of the coefficients and K1 and K2
%M1_Theory = 2*Cff(1)*K1 + Cff(2)*K2 + 3*Cff(4)*K1^2 + 2*Cff(5)*K1*K2 + Cff(6)*K2^2;
%M2_Theory = Cff(2)*K1 + 2*Cff(3)*K2 + Cff(5)*K1^2 + 2*Cff(6)*K1*K2 + 3*Cff(7)*K2^2;
K = [K1; K2].'
K = 9x2
0 0.7500
0.2000 0.7700
0.3600 0.8000
0.4400 0.8400
0.4900 0.8800
0.5100 0.9400
0.5200 0.9800
0.5400 1.0000
0.5500 1.0200
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
M = [M1; M2].'
M = 9x2
5 9
11 10
18 11
25 12
32 13
39 15
46 16
52 18
60 21
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
M1_Theory = @(Cff,K) 2*Cff(1).*K(:,1) + Cff(2).*K(:,2) + 3*Cff(4).*K(:,1) + 2*Cff(5).*K(:,1).*K(:,2) + Cff(6).*K(:,2).^2;
M2_Theory = @(Cff,K) Cff(2).*K(:,1) + 2*Cff(3).*K(:,2) + Cff(5).*K(:,1).^2 + 2*Cff(6).*K(:,1).*K(:,2) + 3*Cff(7).*K(:,2).^2;
M_Theory = @(Cff,K) [M1_Theory(Cff,K); M2_THeory(Cff,K)].';
objfcn = @(Cff,K) [(M1-M1_Theory(Cff,K)).^2 -(M2-M2_Theory(Cff,K)).^2];
Cff0 = ones(7,1);
Q = objfcn(Cff0,K) % Check: 'objfcn'
Q = 9x18
1.0e+03 *
0.0136 0.0938 0.2785 0.5611 0.9417 1.4203 1.9970 2.5692 3.4442 -0.0338 -0.0464 -0.0610 -0.0777 -0.0963 -0.1395 -0.1642 -0.2194 -0.3173
0.0054 0.0694 0.2350 0.4986 0.8602 1.3198 1.8774 2.4334 3.2866 -0.0264 -0.0376 -0.0509 -0.0662 -0.0834 -0.1240 -0.1472 -0.1998 -0.2935
0.0014 0.0516 0.2012 0.4488 0.7943 1.2379 1.7795 2.3217 3.1566 -0.0195 -0.0293 -0.0411 -0.0550 -0.0708 -0.1085 -0.1303 -0.1799 -0.2694
0.0003 0.0424 0.1827 0.4209 0.7571 1.1913 1.7235 2.2577 3.0819 -0.0147 -0.0233 -0.0340 -0.0467 -0.0613 -0.0966 -0.1173 -0.1646 -0.2506
0.0000 0.0364 0.1699 0.4013 0.7308 1.1583 1.6837 2.2121 3.0287 -0.0111 -0.0187 -0.0283 -0.0400 -0.0536 -0.0869 -0.1066 -0.1519 -0.2348
0.0001 0.0321 0.1605 0.3868 0.7112 1.1335 1.6539 2.1779 2.9885 -0.0075 -0.0140 -0.0225 -0.0330 -0.0454 -0.0764 -0.0949 -0.1378 -0.2173
0.0003 0.0296 0.1548 0.3779 0.6991 1.1183 1.6354 2.1567 2.9638 -0.0055 -0.0112 -0.0189 -0.0286 -0.0403 -0.0697 -0.0874 -0.1288 -0.2059
0.0006 0.0272 0.1493 0.3694 0.6875 1.1036 1.6176 2.1363 2.9398 -0.0044 -0.0095 -0.0167 -0.0259 -0.0371 -0.0654 -0.0826 -0.1230 -0.1985
0.0009 0.0257 0.1456 0.3636 0.6795 1.0935 1.6054 2.1222 2.9233 -0.0035 -0.0082 -0.0149 -0.0237 -0.0344 -0.0618 -0.0786 -0.1180 -0.1922
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
Error using lsqcurvefit (line 312)
Function value and YDATA sizes are not equal.
Function value and YDATA sizes are not equal.
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1,'RowNames',ParmNames)
M_Theory = objfcn(A1,M_Theory)
.
Selim
2024-8-1
Thank you SO MUCH for your time and efforts. I really appreciated it.
I am not quite sure how the below code works so I just tried to mimick it from your orginal one.
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
So, as you indicated when I ran it, I got the lsqcurvefit error.
I do know that somehow the solution involves the line:
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt') but not being familiar with the lsqcurvefit or the way it is called with the options, makes it difficult to work.
I admit that the experiment is somewhat straight forward but the use of the variables and the relationships are a bit cumbersome. Imagine on the x-axis we have K1 and on the y-axis we have M1 on one graph. ( the relationship is nonlinear with a total 9 pair data points). Likewise on the second graph, K2 and M2 on the x and y axes respectively. So, in other words, K1 and K2 are my inputs ( independent variables) and M1 and M2 are my outputs. (dependent variables). Now, since the M1 and M2 are experimental measurements, there is also the theoritical calculations of M1 and M2 which are derived from K1 and K2 and bunch of coefficents (A through G). So, let's say we knew those coefficients, then I would be able to plot on the M1_Theoritical on the first graph, and M2_Theoritical on the second graph. Now, having the M1 and M1_Theoritical values, I can also take their least squared sums for each of the 9 data points per graph. If I were to add these summed squares from graph1 and graph2, then i would get the total error. In my case, I don't know the values of the coefficients and I am trying to construct the code such that this error should be minimum.
I am going to think more about your comments and the modified program to see if I can somehow make progress. Thanks again. It is so nice to bounce back some ideas and get some guidance and help from an expert.
Star Strider
2024-8-1
编辑:Star Strider
2024-8-1
As always, my pleasure!
Note that ‘objfcn’ does not need to consider ‘[M1; M2].'’ so they do not belong in it. The lsqcurvefit function will calculate the values of ‘M1_Theory’ and ‘M2_Theory’ using the ‘Cff’ coefficients (that it estimates) and the ‘K’ matrix, so ‘M1’ and ‘M2’ should not be present in it, since they the dependent variables. The lsqcurvefit function calculates ‘objfcn’ using ‘K’ and estimates the values of ‘Cff’ to minimise the least-squares error between it and the ‘M’ matrix.
Try this —
M1 = [5 11 18 25 32 39 46 52 60];
M2 = [9 10 11 12 13 15 16 18 21];
K1 = [0 0.2 0.36 0.44 0.49 0.51 0.52 0.54 0.55];
K2 = [0.75 0.77 0.8 0.84 0.88 0.94 0.98 1.0 1.02];
K = [K1; K2].';
M = [M1; M2].';
M1_Theory = @(Cff,K) 2*Cff(1).*K(:,1) + Cff(2).*K(:,2) + 3*Cff(4).*K(:,1) + 2*Cff(5).*K(:,1).*K(:,2) + Cff(6).*K(:,2).^2;
M2_Theory = @(Cff,K) Cff(2).*K(:,1) + 2*Cff(3).*K(:,2) + Cff(5).*K(:,1).^2 + 2*Cff(6).*K(:,1).*K(:,2) + 3*Cff(7).*K(:,2).^2;
M_Theory = @(Cff,K) [M1_Theory(Cff,K); M2_THeory(Cff,K)].';
objfcn = @(Cff,K) [M1_Theory(Cff,K).^2 M2_Theory(Cff,K).^2];
Cff0 = rand(7,1);
Q = objfcn(Cff0,K)
Q = 9x2
0.4660 2.8271
2.2158 4.3295
4.7095 6.2091
6.6163 7.8526
8.2071 9.3678
9.5723 11.0816
10.4853 12.2748
11.3830 13.1920
12.0380 13.9546
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
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.
% options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
% [A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1,'RowNames',ParmNames)
M_Parameters = 7x1 table
A1
_______
A -3.6046
B 13.933
C -1.2449
D -6.3572
E 20.366
F -14.481
G 2.9709
M_Theory = objfcn(A1,K)
M_Theory = 9x2
5.3094 9.8974
9.9817 6.2915
17.2109 9.1603
24.7736 12.7198
32.8724 15.5213
41.2911 16.4318
46.7626 16.9165
52.6524 18.0294
56.8880 18.5718
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Err = M - M_Theory
Err = 9x2
-0.3094 -0.8974
1.0183 3.7085
0.7891 1.8397
0.2264 -0.7198
-0.8724 -2.5213
-2.2911 -1.4318
-0.7626 -0.9165
-0.6524 -0.0294
3.1120 2.4282
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
RMS_Err = sqrt(mean(Err.^2))
RMS_Err = 1x2
1.4341 1.9323
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
figure
col = 1;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
figure
col = 2;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
Now I understand how this is supposed to work!
The ‘M1_Theory’ regression fits quite well, however ‘M2_Theory’ does not, so you need to check it and make any necessary changes only to it (the code will adapt automatically, so no other changes are necessary), then run this code again.
.
EDIT — (01 Aug 2024 at 13:05)
objfcn = @(Cff,K) [M1_Theory(Cff,K).^2 -M2_Theory(Cff,K).^2];
to:
objfcn = @(Cff,K) [M1_Theory(Cff,K).^2 M2_Theory(Cff,K).^2];
and then re-ran the code to get the current result.
Code otherwise unchanged.
.
Selim
2024-8-1
移动:Star Strider
2024-8-1
This works! I noticed in the objfcn the minus sign needed to plus between M1_Theory and M2_Theory (since we are adding up the errors). I ran it afterwords, got the second graph as;
I think this is it - you did it :-) Thank you again,
On a side note, when I ran the code, it gives the yellow warnings of " Value assigned to variable might be unsued.Considr replacing the variable with ~ instead.". But obviously, this is just FYI.
Star Strider
2024-8-1
As always, my pleasure!
I am plesed that all this is now sorted!
I got no warnings, even after updating the code to remove the unary minus sign (see EDIT in my previoous Comment) and re-running it. I suspect that you got the warning because you are using the code inside a function.
Selim
2024-8-5
编辑:Walter Roberson
2024-8-5
Sorry to bother you but for some strange reason, now my code is not working. Anything that stands out for you? ( I am getting the error below)
My code is:
M1 = [5 11 18 25 32 39 46 52 60];
M2 = [9 10 11 12 13 15 16 18 21];
K1 = [0 0.2 0.36 0.44 0.49 0.51 0.52 0.54 0.55];
K2 = [0.75 0.77 0.8 0.84 0.88 0.94 0.98 1.0 1.02];
K = [K1; K2].';
M = [M1; M2].';
M1_Theory = @(Cff,K) 2*Cff(1).*K(:,1) + Cff(2).*K(:,2) + 3*Cff(4).*K(:,1) + 2*Cff(5).*K(:,1).*K(:,2) + Cff(6).*K(:,2).^2;
M2_Theory = @(Cff,K) Cff(2).*K(:,1) + 2*Cff(3).*K(:,2) + Cff(5).*K(:,1).^2 + 2*Cff(6).*K(:,1).*K(:,2) + 3*Cff(7).*K(:,2).^2;
M_Theory = @(Cff,K) [M1_Theory(Cff,K); M2_Theory(Cff,K)].';
objfcn = @(Cff,K) [(M1-M1_Theory(Cff,K)).^2 +(M2-M2_Theory(Cff,K)).^2];
Cff0 = rand(7,1);
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
Error using lsqcurvefit (line 312)
Function value and YDATA sizes are not equal.
Function value and YDATA sizes are not equal.
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1,'RowNames',ParmNames)
M_Theory = objfcn(A1,K)
Err = M - M_Theory
RMS_Err = sqrt(mean(Err.^2))
figure
col = 1;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
figure
col = 2;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
Torsten
2024-8-5
Use
M_Theory = @(Cff,K) [M1_Theory(Cff,K), M2_Theory(Cff,K)];
objfcn = @(Cff,K) M_Theory(Cff,K);
instead of
M_Theory = @(Cff,K) [M1_Theory(Cff,K); M2_Theory(Cff,K)].';
objfcn = @(Cff,K) [(M1-M1_Theory(Cff,K)).^2 +(M2-M2_Theory(Cff,K)).^2];
Selim
2024-8-5
M1 = [5 11 18 25 32 39 46 52 60];
M2 = [9 10 11 12 13 15 16 18 21];
K1 = [0 0.2 0.36 0.44 0.49 0.51 0.52 0.54 0.55];
K2 = [0.75 0.77 0.8 0.84 0.88 0.94 0.98 1.0 1.02];
K = [K1; K2].';
M = [M1; M2].';
M1_Theory = @(Cff,K) 2*Cff(1).*K(:,1) + Cff(2).*K(:,2) + 3*Cff(4).*K(:,1) + 2*Cff(5).*K(:,1).*K(:,2) + Cff(6).*K(:,2).^2;
M2_Theory = @(Cff,K) Cff(2).*K(:,1) + 2*Cff(3).*K(:,2) + Cff(5).*K(:,1).^2 + 2*Cff(6).*K(:,1).*K(:,2) + 3*Cff(7).*K(:,2).^2;
M_Theory = @(Cff,K) [M1_Theory(Cff,K); M2_Theory(Cff,K)];
objfcn = @(Cff,K) M_Theory(Cff,K);
Cff0 = rand(7,1);
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
Error using lsqcurvefit (line 312)
Function value and YDATA sizes are not equal.
Function value and YDATA sizes are not equal.
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1,'RowNames',ParmNames)
M_Theory = objfcn(A1,K)
Err = M - M_Theory
RMS_Err = sqrt(mean(Err.^2))
figure
col = 1;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
figure
col = 2;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
Star Strider
2024-8-5
‘Anything that stands out for you?’
Yes! When in doubt, see what ‘objfcn’ returns with the default parameter vector and an appropriate independent variable. Here, ‘objfcn’ is returning a (9x18) matrix instead of the (9x2) matriux that it should. This is because ‘M1’ and ‘M2’ are(1x9) row vectors, and the subtracting them uses ‘iimplicit expansion’ to do that, rather than throwing an error. (Automatic implicit expansion was introduced in R2014b and has caused these sort of problems ever since.) That is the reason the the ‘M’ matrix transposes ‘M1’ and ‘M2’ to column vectors before concatenating them into a matrix.
The solution is to revert to the original code for this that I wrote, because it does not consider ‘M1’ and ‘M2’ at all in ‘objfcn’ since lsqcurvefit does that comparison internally to fit ‘objfcn’ to ‘M’, so doing it in ‘objfcn’ will produce inaccurate results for the parameter vector ‘Cff’.
M1 = [5 11 18 25 32 39 46 52 60];
M2 = [9 10 11 12 13 15 16 18 21];
K1 = [0 0.2 0.36 0.44 0.49 0.51 0.52 0.54 0.55];
K2 = [0.75 0.77 0.8 0.84 0.88 0.94 0.98 1.0 1.02];
K = [K1; K2].';
M = [M1; M2].';
M1_Theory = @(Cff,K) 2*Cff(1).*K(:,1) + Cff(2).*K(:,2) + 3*Cff(4).*K(:,1) + 2*Cff(5).*K(:,1).*K(:,2) + Cff(6).*K(:,2).^2;
M2_Theory = @(Cff,K) Cff(2).*K(:,1) + 2*Cff(3).*K(:,2) + Cff(5).*K(:,1).^2 + 2*Cff(6).*K(:,1).*K(:,2) + 3*Cff(7).*K(:,2).^2;
M_Theory = @(Cff,K) [M1_Theory(Cff,K); M2_Theory(Cff,K)].';
% objfcn = @(Cff,K) [(M1-M1_Theory(Cff,K)).^2 +(M2-M2_Theory(Cff,K)).^2];% % Inaccurate
objfcn = @(Cff,K) [(M1_Theory(Cff,K)).^2 +(M2_Theory(Cff,K)).^2]; % Corrected
Cff0 = rand(7,1);
Check_objfcn = objfcn(Cff0,K)
Check_objfcn = 9x2
1.0267 1.7372
2.0513 3.0710
3.2265 4.7208
4.1175 6.2446
4.8720 7.7262
5.6255 9.6510
6.1382 11.0757
6.5582 12.0743
6.8908 12.9754
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
M
M = 9x2
5 9
11 10
18 11
25 12
32 13
39 15
46 16
52 18
60 21
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% return
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
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.
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
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.
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1,'RowNames',ParmNames)
M_Parameters = 7x1 table
A1
_______
A -4.3908
B 13.933
C -1.2448
D -5.8328
E 20.366
F -14.481
G 2.9708
M_Theory = objfcn(A1,K)
M_Theory = 9x2
5.3094 9.8975
9.9817 6.2917
17.2109 9.1605
24.7737 12.7199
32.8725 15.5214
41.2911 16.4318
46.7626 16.9165
52.6524 18.0293
56.8879 18.5717
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Err = M - M_Theory
Err = 9x2
-0.3094 -0.8975
1.0183 3.7083
0.7891 1.8395
0.2263 -0.7199
-0.8725 -2.5214
-2.2911 -1.4318
-0.7626 -0.9165
-0.6524 -0.0293
3.1121 2.4283
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
RMS_Err = sqrt(mean(Err.^2))
RMS_Err = 1x2
1.4341 1.9323
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
figure
col = 1;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
figure
col = 2;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
You can certainly change ‘objfcn’ to a new version with different expressions (that might be a better match to ‘M2’), however it is not appropriate to include ‘M1’ and ‘M2’ in it at all.
.
Selim
2024-8-5
This makes sense. I got myself confused I suppose. When I looked at objfcn
% objfcn = @(Cff,K) [(M1-M1_Theory(Cff,K)).^2 +(M2-M2_Theory(Cff,K)).^2];% % Inaccurate
objfcn = @(Cff,K) [(M1_Theory(Cff,K)).^2 +(M2_Theory(Cff,K)).^2]; % Corrected
I was thinking that it needed to have the squared difference between the experimental and theoritical as the objective, and just seeing the squares of the M1_Theory and M2_Theory made me second guess.
Thanks again. You are the best!
Torsten
2024-8-5
编辑:Torsten
2024-8-5
If you square M1_theory and M2_theory in
objfcn = @(Cff,K) [(M1_Theory(Cff,K)).^2 +(M2_Theory(Cff,K)).^2];
don't you also have to square M1 and M2 ?
In the case above, I think lsqcurvefit will try to minimize
sum_i ((M1_Theory(i)^2 - M1(i))^2 + (M2_theory(i)^2 - M2(i))^2)
I think
M_Theory = @(Cff,K) [M1_Theory(Cff,K), M2_Theory(Cff,K)];
objfcn = @(Cff,K) M_Theory(Cff,K);
is the correct choice.
Selim
2024-8-5
I trust your knowledge and experience. Thanks again. I have a feeling that this will not my last question :-)
Star Strider
2024-8-5
As always, my pleasure!
Thank you!
I did not initially pick up on the squaring, since I was concentrating on a different problem.
i believe that they shoud not be squared in any event, at least not in ‘objfcn’. Let lsqcurvefit take care of those details.
Squaring the difference would be appropriate for some optimisation functions such as fminsearch or fmincon in which it would be:
objfcn = @(Cff) [(M1.'-M1_Theory(Cff,K)).^2 (M2.'-M2_Theory(Cff,K)).^2];
inheriting ‘K’ from the workspace, and that would probably work (note the simple transpose operations denoted by.'). I did not test it with any of those functions.
Not squaring produces —
M1 = [5 11 18 25 32 39 46 52 60];
M2 = [9 10 11 12 13 15 16 18 21];
K1 = [0 0.2 0.36 0.44 0.49 0.51 0.52 0.54 0.55];
K2 = [0.75 0.77 0.8 0.84 0.88 0.94 0.98 1.0 1.02];
K = [K1; K2].';
M = [M1; M2].';
M1_Theory = @(Cff,K) 2*Cff(1).*K(:,1) + Cff(2).*K(:,2) + 3*Cff(4).*K(:,1) + 2*Cff(5).*K(:,1).*K(:,2) + Cff(6).*K(:,2).^2;
M2_Theory = @(Cff,K) Cff(2).*K(:,1) + 2*Cff(3).*K(:,2) + Cff(5).*K(:,1).^2 + 2*Cff(6).*K(:,1).*K(:,2) + 3*Cff(7).*K(:,2).^2;
M_Theory = @(Cff,K) [M1_Theory(Cff,K); M2_Theory(Cff,K)].';
% objfcn = @(Cff,K) [(M1-M1_Theory(Cff,K)).^2 +(M2-M2_Theory(Cff,K)).^2];% % Inaccurate
objfcn = @(Cff,K) [(M1_Theory(Cff,K)) (M2_Theory(Cff,K))]; % Corrected
Cff0 = rand(7,1);
Check_objfcn = objfcn(Cff0,K)
Check_objfcn = 9x2
0.2308 1.2562
0.6142 1.4026
0.9409 1.5906
1.1338 1.7550
1.2749 1.8984
1.3813 2.0619
1.4472 2.1699
1.5134 2.2419
1.5587 2.3031
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
M
M = 9x2
5 9
11 10
18 11
25 12
32 13
39 15
46 16
52 18
60 21
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% return
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
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.
% options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
% [A1,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(objfcn, Cff0, K, M, [], [], options);
ParmNames = {'A','B','C','D','E','F','G'};
M_Parameters = table(A1,'RowNames',ParmNames)
M_Parameters = 7x1 table
A1
_______
A -45.62
B 91.776
C -12.856
D -68.993
E 217.68
F -114.39
G 17.929
M_Theory = objfcn(A1,K)
M_Theory = 9x2
4.4866 10.9705
10.2458 3.9211
18.2340 9.2142
26.0685 14.3188
33.7764 17.6086
41.8111 17.1010
46.8625 16.4538
51.4385 17.5648
54.8129 17.7095
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Err = M - M_Theory
Err = 9x2
0.5134 -1.9705
0.7542 6.0789
-0.2340 1.7858
-1.0685 -2.3188
-1.7764 -4.6086
-2.8111 -2.1010
-0.8625 -0.4538
0.5615 0.4352
5.1871 3.2905
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
RMS_Err = sqrt(mean(Err.^2))
RMS_Err = 1x2
2.1357 3.0962
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
figure
col = 1;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
figure
col = 2;
plot(K(:,col), M(:,col), '.', 'DisplayName','Data')
hold on
plot(K(:,col), M_Theory(:,col), '-r', 'DisplayName','Regression')
hold off
grid
xlabel('K')
ylabel('M')
title("Column "+col)
legend('Location','best')
So not squaring produces different parameter estimates, however the same essential fit.
.
Star Strider
2024-8-5
‘Thanks again. I have a feeling that this will not my last question :-)
As always, my plesure!
I will do my best to provide an appropriate respoinse!
Torsten
2024-8-5
Squaring the difference would be appropriate for some optimisation functions such as fminsearch or fmincon in which it would be:
objfcn = @(Cff) [(M1.'-M1_Theory(Cff,K)).^2 (M2.'-M2_Theory(Cff,K)).^2];
inheriting ‘K’ from the workspace, and that would probably work (note the simple transpose operations denoted by.'). I did not test it with any of those functions.
For "fminsearch" or "fmincon", you even had to sum over the squared differences.
更多回答(0 个)
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)