Esempio pratico del perché non è bene invertire una matrice


16

Sono consapevole che invertire una matrice per risolvere un sistema lineare non è una buona idea, dal momento che non è così preciso ed efficiente come risolvere direttamente il sistema o usare la decomposizione LU, Cholesky o QR.

Tuttavia, non sono stato in grado di verificarlo con un esempio pratico. Ho provato questo codice (in MATLAB)

M   = 500;    
A   = rand(M,M);
A   = real(expm(1i*(A+A.')));
b   = rand(M,1);

x1  = A\b;
x2  = inv(A)*b;

disp(norm(b-A*x1))
disp(norm(b-A*x2))

e i residui sono sempre dello stesso ordine (10 ^ -13).

Qualcuno potrebbe fornire un esempio pratico in cui inv (A) * b è molto meno impreciso di A \ b?

------ Aggiornamento delle domande ------

Grazie per le tue risposte. Tuttavia, supponiamo che dobbiamo risolvere volte un sistema A x = b , dove A è sempre la stessa matrice. Considera chenAx=bA

- è completa, e quindi A - 1 richiede la stessa memoria di A .AA1A

-Il numero della condizione di è piccolo, quindi A - 1 può essere calcolato con precisione.AA1

In tal caso, non sarebbe più efficiente calcolare piuttosto che usare una decomposizione LU? Ad esempio, ho provato questo codice Matlab:A1

%Set A and b:
M           = 1000; 
A           = rand(M,M);
A           = real(expm(1i*(A+A.')));
b           = rand(M,1);

%Times we solve the system:
n           = 3000;

%Performing LU decomposition:
disp('Performing LU decomposition')
tic
[L,U,P]     = lu(A);
toc
fprintf('\n')

%Solving the system n times with LU decomposition:
optsL.LT    = true;   %Options for linsolve
optsU.UT    = true;
disp('Solving the system n times using LU decomposition')
tic
for ii=1:n
    x1      = linsolve(U, linsolve(L,P*b,optsL) , optsU);
end
toc
fprintf('\n')

%Computing inverse of A:
disp('Computing inverse of A')
tic
Ainv        = inv(A);
toc
fprintf('\n')

%Solving the system n times with Ainv:
disp('Solving the system n times with A inv')
tic
for ii=1:n
    x2  = Ainv*b;
end
toc
fprintf('\n')

disp('Residuals')
disp(norm(b-A*x1))
disp(norm(b-A*x2))

disp('Condition number of A')
disp(cond(A))

Per una matrice con numero di condizione circa 450, i residui sono in entrambi i casi, ma ci vogliono 19 secondi per risolvere il sistema n volte usando la decomposizione LU, mentre usando l'inverso di A ci vogliono solo 9 secondi.O(1011)


8
la pagina di aiuto di MATLAB per inv fornisce un buon esempio. Guarda sotto la sezione intitolata Solve Linear System .
GoHokies,

1
a proposito, qual è il numero di condizione della tua matrice ? Non ho MATLAB sul mio PC al lavoro, quindi non posso controllare, ma presumo che sia abbastanza piccolo per ottenere un inverso accurato ...A
GoHokies

2
Ho dato un'occhiata a Trefethen e Bau (esercizio 21.4), e lo descrivono semplicemente in termini di costo di calcolo, flop contro 22n3 flop. Quindi, anche se trovi residui simili (hai provato a controllare matrici più scarsamente condizionate, come nel commento di GoHokies?), Il costo di calcolo non necessario da solo vale probabilmente il consiglio. 23n3
Kirill

3
La dimensione della tua matrice è troppo piccola e ben condizionata per questo confronto. Non che non ci siano problemi rilevanti in cui hai tali matrici, ma l'opinione ricevuta che non dovresti invertire è pensata per una diversa impostazione (ad esempio, quella menzionata da Chris Rackauckas nella sua risposta). In effetti, per matrici piccole e - in modo certi - ben condizionate, calcolare l'inverso potrebbe effettivamente essere l'opzione migliore. Un caso estremo sarebbero le matrici di rotazione 3x3 (o, più realisticamente, trasformazione affine).
Christian Clason,

1
Se è necessario risolvere più volte Ax=b con lo stesso Aed è abbastanza piccolo da prendere l'inverso, puoi invece salvare la fattorizzazione LU e riutilizzarla.
Chris Rackauckas,

Risposte:


11

Normalmente ci sono alcuni motivi principali per preferire risolvere un sistema lineare rispetto all'uso dell'inverso. Brevemente:

  • problema con il numero condizionale (commento @GoHokies)
  • problema nel caso scarso (risposta @ChrisRackauckas)
  • efficienza (commento di @Kirill)

Comunque, come ha osservato @ChristianClason nei commenti, possono essere alcuni casi in cui l'uso dell'inverso è una buona opzione.

Nella nota / articolo di Alex Druinsky, Sivan Toledo, How Accurate is inv (A) * b? ci sono alcune considerazioni su questo problema.

Secondo l'articolo, il motivo principale della preferenza generale da utilizzare per risolvere il sistema lineare è all'interno di queste due stime (x

inverse||xVx||O(κ2(A)ϵmachine) backward stable (LU, QR,...)||xbackwardstablex||O(κ(A)ϵmachine)

xV

V

V

V||xV||||x||

bA

Quindi l'opportunità di usare o meno l'inverso dipende dall'applicazione, puoi controllare l'articolo e vedere se il tuo caso soddisfa la condizione per ottenere la stabilità all'indietro o se non ne hai bisogno.

In generale, secondo me, è più sicuro risolvere il sistema lineare.


12

Ecco un breve esempio che è molto pratico legato all'uso della memoria nei PDE. Quando si discretizza l'operatore Laplace,Δu, ad esempio, nell'equazione del calore

ut=Δu+f(t,u).

Per risolverlo numericamente, si finisce con matrici sparse UNe quindi risolve un metodo di discretizzazione delle linee

ut=UNu+f(t,u)

L'esempio canonico 1D è la matrice di Strang. I metodi impliciti dovranno invertireUNo una qualche forma di io-γUN. Per una discretizzazione con 5 punti nello spazio, vediamo cosa succede a questo operatore. Possiamo generarlo facilmente in Julia usando SpecialMatrices.jl:

julia> using SpecialMatrices
julia> Strang(5)
5×5 SpecialMatrices.Strang{Float64}:
 2.0  -1.0   0.0   0.0   0.0
-1.0   2.0  -1.0   0.0   0.0
 0.0  -1.0   2.0  -1.0   0.0
 0.0   0.0  -1.0   2.0  -1.0
 0.0   0.0   0.0  -1.0   2.0

Questa matrice speciale è tridiagonale (molte altre discretizzazioni sono raggruppate e quindi ancora scarse). Ciò significa che è possibile memorizzarlo memorizzando solo 3 array o, in questo caso, può essere "pigro" (ovvero, non è necessario alcun array e si può avere un tipo "pseudo-array" che genera i valori su richiesta). Ciò significa che anche per discretizzazioni spaziali molto grandi conn punti, formati di matrici sparse possono archiviarlo in O(3n) memoria (e formati pigri possono farlo in O(1)!).

Tuttavia, supponiamo di voler invertire la matrice.

julia> inv(collect(Strang(5)))
5×5 Array{Float64,2}:
 0.833333  0.666667  0.5  0.333333  0.166667
 0.666667  1.33333   1.0  0.666667  0.333333
 0.5       1.0       1.5  1.0       0.5
 0.333333  0.666667  1.0  1.33333   0.666667
 0.166667  0.333333  0.5  0.666667  0.833333

Si noti che l'inverso di questa matrice sparsa è denso. Pertanto, se non conosciamo la soluzione analitica dell'inverso (che è vera per la maggior parte delle matrici sparse derivanti dalle discretizzazioni PDE), la quantità di memoria che sarà richiesta per l'inverso èO(n2). Ciò significa che l'inverso occuperà una grande quantità di memoria aggiuntiva e il limite di memoria sarà quindi determinato dalla dimensione della matrice inversa densa.

Invece, risolveranno i metodi del risolutore diretto \e i solutori iterativi come quelli inIterativeSolvers.jlUNX=B senza mai calcolare UN-1e quindi hanno solo il requisito di memoria di dover archiviare UN. Ciò può aumentare notevolmente le dimensioni dei PDE che è possibile risolvere.

Come altri hanno già detto, il numero di condizione e l'errore numerico sono un'altra ragione, ma il fatto che l'inverso di una matrice sparsa sia densa dà una chiara idea "questa è una cattiva idea".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.