Matlab inverse operation and warning

2019-06-05 16:38发布

问题:

Not quite sure what this means. "Warning: Matrix is singular to working precision."

I have a 3x4 matrix called matrix bestM matrix Q is 3x3 of bestM and matrix m is the last column of bestM

I would like to do C = -Inverse matrix of Q * matrix m and I get that warning and C =[Inf Inf Inf] which isn't right because i am calculating for the camera center in the world

bestM = [-0.0031 -0.0002 0.0005 0.9788;
         -0.0003 -0.0006 0.0028 0.2047;
         -0.0000 -0.0000 0.0000 0.0013];   

Q = bestM(1:3,1:3);
m = bestM(:,4);

X = inv(Q);
C = -X*m;
disp(C);

回答1:

A singular matrix can be thought of as the matrix equivalent of zero, when you try to invert 0 it blows up (goes to infinity) which is what you are getting here. user 1281385 is absolutely wrong about using the format command to increase precision; the format command is used to change the format of what is shown to you. In fact the very first line of the help command for format says

format does not affect how MATLAB computations are done.



回答2:

As found here, a singular matrix is one that does not have an inverse. As dvreed77 already pointed out, you can think of this as 1/0 for matrices.

Why I'm answering, is to tell you that using inv explicitly is almost never a good idea. If you need the same inverse a few hundred times, it might be worth it, however, in most circumstances you're interested in the product C:

C = -inv(Q)*m

which can be computed much more accurately and faster in Matlab using the backslash operator:

C = -Q\m

Type help slash for more information on that. And even if you happen to find yourself in a situation where you really need the inverse explicitly, I'd still advise you to avoid inv:

invQ = Q\eye(size(Q))

Below is a little performance test to demonstrate one of the very few situations where the explicit inverse can be handy:

% This test will demonstrate the one case I ever encountered where
% an explicit inverse proved useful. Unfortunately, I cannot disclose
% the full details without breaking the law, but roughly, it came down
% to this: The (large) design matrix A, a result of a few hundred 
% co-registrated images, needed to be used to solve several thousands 
% of systems, where the result matrices b came from processing the 
% images one-by-one. 
%
% That means the same design matrix was re-used thousands of times, to 
% solve thousands of systems at a time. To add to the fun, the images
% were also complex-valued, but I'll leave that one out of consideration
% for now :)  

clear; clc

% parameters for this demo
its = 1e2;
sz  = 2e3;
Bsz = 2e2;

% initialize design matrix
A = rand(sz);

% initialize cell-array to prevent allocating memory from consuming 
% unfair amounts of time in the first loop. 
% Also, initialize them, NOT copy them (as in D=C,E=D), because Matlab 
% follows a lazy copy-on-write scheme, which would influence the results
C = {cellfun(@(~) zeros(sz,Bsz), cell(its,1), 'uni', false)   zeros(its,1)};
D = {cellfun(@(~) zeros(sz,Bsz), cell(its,1), 'uni', false)   zeros(its,1)};
E = {cellfun(@(~) zeros(sz,Bsz), cell(its,1), 'uni', false)   zeros(its,1)};

% The impact of rand() is the same in both loops, so it has no 
% effect, it just gives a longer total run time. Still, we do the 
% rand explicitly to *include* the indexing operation in the test. 
% Also, caching will most definitely influence the results, because 
% any compiler (JIT), even without optimizations, might recognize the 
% easy performance gain when the code computes the same array over and 
% over again. It probably will, but we have no control over when and 
% wherethat happens. So, we prevent that from happening at all, by 
% re-initializing b at every iteration. 

% The assignment to cell is a necessary part of the demonstration; 
% it is the desired output of the whole calculation. Assigning to cell 
% instead of overwriting 'ans' takes some time, which is to be included 
% in the demonstration, again for cache reasons: the extra time is now
% guaranteed to be equal in both loops, so it really does not matter -- 
% only the total run time will be affected.

% Direct computation
start = tic;
for ii = 1:its    
    b = rand(sz,Bsz);    
    C{ii,1} = A\b;
    C{ii,2} = max(max(abs( A*C{ii,1}-b )));
end
time0 = toc(start);
[max([C{:,2}])   mean([C{:,2}])   std([C{:,2}])]

% LU factorization (everyone's
start = tic;
[L,U,P] = lu(A, 'vector');
for ii = 1:its    
    b = rand(sz,Bsz);    
    D{ii,1} = U\(L\b(P,:));
    D{ii,2} = max(max(abs( A*D{ii,1}-b )));
end
time1 = toc(start);
[max([D{:,2}])   mean([D{:,2}])   std([D{:,2}])]


% explicit inv
start = tic;
invA = A\eye(size(A)); % NOTE: DON'T EVER USE INV()!
for ii = 1:its
    b = rand(sz,Bsz);
    E{ii,1} = invA*b;
    E{ii,2} = max(max(abs( A*E{ii,1}-b )));
end
time2 = toc(start);
[max([E{:,2}])   mean([E{:,2}])   std([E{:,2}])]

speedup0_1 = (time0/time1-1)*100
speedup1_2 = (time1/time2-1)*100
speedup0_2 = (time0/time2-1)*100

Results:

% |Ax-b|
1.0e-12 * % max.   mean     st.dev.
          0.1121   0.0764   0.0159 % A\b   
          0.1167   0.0784   0.0183 % U\(L\b(P,;))
          0.0968   0.0845   0.0078 % invA*b

speedup0_1 = 352.57 % percent
speedup1_2 =  12.86 % percent
speedup0_2 = 410.80 % percent

It should be clear that an explicit inverse has its uses, but just as a goto construct in any language -- use it sparingly and wisely.