Determinare rapidamente se una matrice densa è di livello inferiore


13

In un progetto software a cui sto lavorando, alcuni calcoli sono molto più facili per matrici dense di basso rango. Alcune istanze problematiche coinvolgono dense matrici di basso rango, ma mi vengono fornite per intero, piuttosto che come fattori, quindi dovrò controllare il rango e fatturare la matrice se voglio sfruttare la struttura di basso rango .

Le matrici in questione sono in genere completamente o quasi completamente dense, con n che vanno da cento a qualche migliaio. Se una matrice ha un rango basso (diciamo meno di 5 a 10), vale la pena calcolare il SVD e usarlo per una fattorizzazione di basso rango. Tuttavia, se la matrice non è di basso rango, lo sforzo sarebbe sprecato.

Quindi mi piacerebbe trovare un modo rapido e ragionevolmente affidabile per determinare se il grado è basso o meno prima di investire lo sforzo di fare una piena fattorizzazione SVD. Se in qualsiasi momento diventa chiaro che il rango è al di sopra del valore soglia, il processo può arrestarsi immediatamente. Se la procedura dichiara erroneamente che la matrice è di livello basso quando non lo è, questo non è un grosso problema, dal momento che farei comunque un SVD completo per confermare il livello basso e trovare una fattorizzazione di basso livello.

Le opzioni che ho considerato includono una classifica che rivela la fattorizzazione LU o QR seguita da un SVD completo come controllo. Ci sono altri approcci che dovrei considerare?

Risposte:


8

C'è un trucco che ho imparato recentemente da questo articolo . Inizi a fare QR rivelatori di rango e ti fermi dopo le prime Riflessioni dei proprietari di casa, quando hai una matrice della forma [ R 1 R 12 0 R 22 ] , con R 1 triangolare di dimensione k × k , e R 22 in genere no triangolare (da quando ci siamo fermati dopo le prime k iterazioni del nostro ciclo principale). A questo punto, controlli se R 22ε : se tiene, quindi Ak

[R1R120R22],
R1k×kR22kR22εAè al massimo da una matrice di rango k ; altrimenti non dovrebbe essere (salvo errori numerici).εk

Questa procedura costa per una matrice n × n densa .O(n2k)n×n


Questo è essenzialmente l'approccio che ho descritto nella domanda. Penso che la risposta proposta da Wolfgang Bangerth potrebbe fare meglio di . O(n2k)
Brian Borchers,

7

Il problema, ovviamente, è che il calcolo del rango reale (ad es. Tramite una decomposizione QR) non è in realtà più economico del calcolo di una rappresentazione di basso rango della matrice.

Il meglio che puoi probabilmente fare è usare un algoritmo randomizzato per trovare approssimazioni di basso rango. Questi possono, almeno in teoria, essere significativamente più veloci di lavorare sull'intera matrice perché, in sostanza, calcolano solo le decomposizioni per le proiezioni della matrice su sottospazi casuali.

100×100


Da quello che so di questi algoritmi, producono una matrice di basso rango che è ragionevolmente vicina alla norma alla matrice data. Ho bisogno di sapere se c'è o meno una matrice di grado 10 (o meno) molto vicina alla matrice data (diciamo un errore relativo di 1.0e-10 o migliore).
Brian Borchers

Sì, ma puoi anche effettuare una decomposizione QR della matrice proiettata (a bassa dimensione) e se tale decomposizione rivela una mancanza di rango completo, avrai anche una matrice originale carente di rango. Non era questo il criterio di cui avevi bisogno per fare una decomposizione QR sulla matrice originale?
Wolfgang Bangerth,

kkk1kAkknO(k2n)AO(kn2)

k=nkkn2n3

1

Un altro approccio che vale la pena provare è usare l'Adaptive Cross Approximation (ACA). È un algoritmo piuttosto popolare che ha molte implementazioni disponibili online. Per riferimento, puoi vedere il documento originale:

L'ACA e le sue variazioni (diciamo, ACA +, ibrido di approssimazione incrociata HCA) possono essere utilizzate in diversi scenari. Tu, avendo già calcolata l'intera matrice densa, sei uno dei favorevoli, poiché sarai in grado di calcolare i residui esattamente se necessario.

O(Nr)Nr(ϵ)rϵO(N2r)


0

A0xAxAATA

(ATA)A

from scipy.sparse.linalg import svds
sing = svds( A, k=20, tol=1e-4, return_singular_vectors=False )  # v0=random
# runtimes on random-normal n x n:
# n = 100, 1k, 2k
#       5, 130, 770 ms
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.