Warning: Matrix is singular, close to singular or badly scaled: Help with finding error in code
Show older comments
Greetings, I am working on a code for my numerical methods class and am having some trouble understanding why my code is not operating properly. I keep getting the warning "Matrix is singular, close to singular, or badly scaled.
The goal of my code is to vary Y to fit experimental data using a non-linear numerical model. I believe it will be a simple fix with the line: dY = (Z'*Z)\(Z'*D); but I am not sure what fix it would require.
I have checked the sizes of the matrixes, they are as follow: Z 9x3 D 9x1 dY 3x3
In my pseudo code dY should only be a 3x1. I have a basic understanding of matrix math but not enough to work through this with google searches and my know knowledge. Any ideas would be of help. Code is below.
Thanks in advance! Vinny Morasko
clear; clc;
clear all;
%data
T=60;
Y=[0.0021;0.2628;0.5769];
Activity =
[1;0.951693618101212;0.787050622169703;0.703301583776796;0.611130056863694;0.430688946871704;0.217509576417032;0.058196064746889;0.007090117454854];
t= [0;30;120;180;240;360;720;1440;2880];
%plot data
figure(1); clf(1)
plot(t,Activity,'o')
%iterate
for iter=1:10;
%build matricies
n=length(t);
m=3;
Z=zeros(n,m);
D=zeros(n,1);
for k=1:n
Z(k,1)= ((Y(1)^2*t(k)-Y(1)*t(k)*Y(2)+Y(2)*exp(-Y(1)*t(k))*Y(3))/...
((Y(1)-Y(2))^2))-((exp(-t(k)*Y(2))*Y(2)*Y(3))/((Y(1)-Y(2))^2));
Z(k,2)= (((Y(2)*t(k)-t(k)*Y(1)+1)*exp(-Y(2)*t(k))*Y(1)*Y(3))/...
((Y(2)-Y(1))^2))-((exp(-t(k)*Y(1))*Y(1)*Y(3))/((Y(2)-Y(1))^2));
Z(k,3)= ((exp(-t(k)*Y(2))*Y(1))/(Y(1)-Y(2)))-((exp(-t(k)*Y(1))*...
Y(1))/(Y(1)-Y(2)));
D(k,1)= Activity(k)-(1+(Y(3)*Y(1))/(Y(2)-Y(1))*exp(-Y(1)*t(k)))-...
((Y(1)*Y(3))/(Y(2)-Y(1))*exp(-Y(2)*t(k)));
end
%solve for dY
dY = (Z'*Z)\(Z'*D);
%update Y's
Y=Y+dY;
%plot fit
xf=linspace(min(t)-0.5,max(t+0.5),100);
yf=(1+(Y(3)*Y(1))/(Y(2)-Y(1))*exp(-Y(1)*xf))-...
((Y(1)*Y(3))/(Y(2)-Y(1))*exp(-Y(2)*xf));
hold on
plot (xf,yf)
pause (0.5)
end
Answers (1)
John D'Errico
on 23 Apr 2017
Edited: John D'Errico
on 23 Apr 2017
One hint:
If you knowhow to use backslash, then why are you using it as
%solve for dY
dY = (Z'*Z)\(Z'*D);
Instead, use backslash as it is designed to be used!
%solve for dY
dY = Z\D;
The solution that you are using squares the condition number. So if a linear system is already poorly scaled, then it is scaled far more poorly using the form you used.
Next, any time you have exponentials in a problem, expect things to be poorly scaled. Now, reread what I said above.
To learn more about your problem, try this:
cond(Z)
what does it tell you? You can learn even more about the problem by this:
svd(Z)
What does it show?
I cannot go further, since I cannot even test your code, lacking the data you are reading in.
2 Comments
Vincent Morasko
on 23 Apr 2017
John D'Errico
on 24 Apr 2017
Edited: John D'Errico
on 24 Apr 2017
Sigh. My point is that the form you use for a linear least squares is a POOR one. backslash is already able to solve the problem directly as I wrote, which works for non-square systems.
The reason you use backslash in the form
%solve for dY
dY = Z\D;
is because backslash was written using high quality numerical methods to AVOID squaring the condition number of the problem. REREAD MY ANSWER.
That the condition number is infinite and SVD returns ZERO for some of the singular values means that your matrix is singular. You can NEVER solve that linear system, at least at that point.
It MAY reflect that you have chosen poor stating values. But as well, it begs the question, WHY ARE YOU WRITING YOUR OWN NONLINEAR ESTIMATION CODE? If you don't know how to effectively solve a simple linear system well, then why do you think you can write high quality nonlinear estimation code? (Sorry, but that is a completely valid question from my point of view.)
Use high quality tools written by professionals in the art rather than writing your own code from scratch.
Categories
Find more on Ordinary Differential Equations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!