Quali sono alcune delle differenze tra DFT e FFT che rendono FFT così veloce?


16

Sto cercando di capire le FFT, ecco cosa ho finora:

Per trovare l'entità delle frequenze in una forma d'onda, si deve sondare per loro moltiplicando l'onda per la frequenza che stanno cercando, in due diverse fasi (sin e cos) e calcolando la media di ciascuna. La fase si trova dalla sua relazione con i due, e il codice per questo è qualcosa del genere:

//simple pseudocode
var wave = [...];                //an array of floats representing amplitude of wave
var numSamples = wave.length;
var spectrum = [1,2,3,4,5,6...]  //all frequencies being tested for.  

function getMagnitudesOfSpectrum() {
   var magnitudesOut = [];
   var phasesOut = [];

   for(freq in spectrum) {
       var magnitudeSin = 0;
       var magnitudeCos = 0;

       for(sample in numSamples) {
          magnitudeSin += amplitudeSinAt(sample, freq) * wave[sample];
          magnitudeCos += amplitudeCosAt(sample, freq) * wave[sample];
       }

       magnitudesOut[freq] = (magnitudeSin + magnitudeCos)/numSamples;
       phasesOut[freq] = //based off magnitudeSin and magnitudeCos
   }

   return magnitudesOut and phasesOut;
}

Per fare ciò per moltissime frequenze molto rapidamente, gli FFT usano molti trucchi.

Quali sono alcuni dei trucchi utilizzati per rendere le FFT molto più veloci della DFT?

PS Ho provato a guardare gli algoritmi FFT completi sul web, ma tutti i trucchi tendono ad essere condensati in un bellissimo pezzo di codice senza molte spiegazioni. Ciò di cui ho bisogno prima, prima di poter capire tutto, è una breve introduzione a ciascuno di questi cambiamenti efficienti come concetti.

Grazie.


7
"DFT" non si riferisce a un algoritmo: si riferisce a un'operazione matematica. "FFT" si riferisce a una classe di metodi per calcolare tale operazione.

1
Volevo solo sottolineare che l'uso del sudotuo esempio di codice potrebbe essere fonte di confusione, in quanto si tratta di un comando ben noto nel mondo dei computer. Probabilmente intendevi psuedocode.
rwfeather,

1
@nwfeather Probabilmente intendeva "pseudocodice".
user207421

Risposte:


20

L'implementazione ingenua di un DFT point è sostanzialmente una moltiplicazione per una matrice N × N. Ciò si traduce in una complessità di O ( N 2 ) .NN×NO(N2)

Uno degli algoritmi FFT (Fast Fourier Transform) più comuni è l'algoritmo FFT radix-2 Cooley-Tukey Decimation-in-Time. Questo è un approccio di base alla divisione e alla conquista.

Per prima cosa definire il "fattore di twiddle " come: dovej

WNej2πN
è l'unità immaginaria, quindi il DFTX[k]dix[n]è dato da X[k]= N - 1 n = 0 x[n]j1X[k]x[n] Se N è pari (e N
X[k]=n=0N1x[n]WNkn.
N è un numero intero), la somma può quindi essere divisa in due somme come segue X[k]= N / 2 - 1 n=0x[2n]W 2 k n N + N / 2 - 1 n=0x[2n+1]W k ( 2 n + 1 ) NN2
X[k]=n=0N/21x[2n]WN2kn+n=0N/21x[2n+1]WNk(2n+1)
dove la prima sommatoria si occupa dei campioni pari di e la seconda dei campioni dispari di x [ n ] . Definendo x e [ n ] x [ 2 n ] e x o [ n ] x [ 2 n + 1 ] e usando il fatto chex[n]x[n]xe[n]x[2n]xo[n]x[2n+1]
  1. eWNk(2n+1)=WN2knWNk
  2. WN2kn=WN/2kn

X[k]=n=0N/21xe[n]WN/2kn+WNkn=0N/21xo[n]WN/2kn=Xe[k]+WNkXo[k]
Xe[k]Xo[k]N2x[n]NN2
2(N2)2+N<N2
N>2

O(NlogN)O(N2)


saresti disposto a elencare cosa rappresenta ciascuna delle variabili? Sono piuttosto nuovo a questo, quindi W, j, X(), Ne knon hanno ancora le definizioni per me.
Seph Reed,

Wkn

19

http://nbviewer.jupyter.org/gist/leftaroundabout/83df89a7d3bdc24373ea470fb50be629

DFT, taglia 16

Diagramma delle operazioni in un DFT ingenuo di dimensioni 16

FFT, taglia 16

Diagramma delle operazioni in una FFT radix-2 taglia 16

La differenza di complessità è piuttosto evidente da ciò, non è vero?


Ecco come capisco FFT.

FT:L2(R)L2(R)

RCIl caso più semplice è che la tua funzione è continua e la dividi in regioni così piccole che è praticamente costante in ognuna di esse. Quindi ciascuno degli STFT ha un termine fortemente zeroth. Se si ignorano gli altri coefficienti (comunque in decomposizione), ciascun dominio è solo un singolo punto dati. Di tutti questi coefficienti limite di breve durata-LF, è possibile eseguire una trasformata di Fourier discreta. In effetti, è esattamente quello che fai quando esegui qualsiasi FT su dati misurati nel mondo reale!

Tuttavia, i dati misurati non devono necessariamente corrispondere a una quantità fisica fondamentale. Ad esempio, quando misuri un po ' di intensità luminosa , stai davvero solo misurando l' ampiezza di un'onda elettromagnetica la cui frequenza è di per sé troppo alta per essere campionata con un ADC. Ma chiaramente puoi anche calcolare il DFT di un segnale di intensità di luce campionato, e così a buon mercato, nonostante la folle frequenza dell'onda luminosa.

Questo potrebbe essere inteso come il motivo più importante per cui FFT è economico:

Non preoccuparti di provare a vedere i singoli cicli di oscillazione dal livello più alto. Invece, trasforma solo informazioni di livello piuttosto alto che sono già state preelaborate localmente.

Non è tutto quello che c'è da fare, però. La cosa grandiosa di FFT è che ti dà ancora tutte le informazioni che un DFT completo fornirebbe . Cioè tutte le informazioni che avresti anche quando campionerai l'esatta onda elettromagnetica di un raggio di luce. Ciò può essere realizzato trasformando un segnale fotodiodo? - puoi misurare la frequenza della luce esatta da quella?


Δν=1/Δt

Avendo nel complesso un arco di tempo più lungo, dovremmo anche essere in grado di ridurre l'incertezza della frequenza. E questo è davvero possibile, se si misura localmente non solo la frequenza approssimativa ma anche la fase dell'onda. Sai che un segnale da 1000 Hz avrà esattamente la stessa fase se lo guardi un secondo dopo. Considerando che un segnale da 1000,5 Hz, pur essendo indistinguibile sulla scala breve, avrà invertito la fase un secondo dopo.

Fortunatamente, le informazioni sulla fase possono benissimo essere memorizzate in un singolo numero complesso. Ed è così che funziona FFT! Inizia con molte piccole trasformazioni locali. Questi sono economici - ovviamente perché usano solo una piccola quantità di dati, ma in secondo luogo perché sanno che, a causa del breve lasso di tempo, non possono comunque risolvere la frequenza in modo molto preciso - quindi è comunque conveniente anche se tu fare molte di queste trasformazioni.

Questi, tuttavia, registrano anche la fase e da quel momento è possibile rendere più precisa la risoluzione della frequenza al livello più alto. La trasformazione richiesta è di nuovo economica, perché non si preoccupa da sola delle oscillazioni ad alta frequenza, ma solo con i dati a bassa frequenza pre-elaborati.


Sì, la mia argomentazione è un po 'circolare a questo punto. Chiamiamolo ricorsivo e stiamo bene ...

Questa relazione non è meccanica quantistica, ma l' incertezza di Heisenberg ha in realtà la stessa ragione fondamentale.


2
bella rappresentazione pittorica del problema. :-)
robert bristow-johnson,

2
Non ami i diagrammi che si ripetono dappertutto e che in realtà non vengono mai spiegati da nessuna parte :)
user541686,

1
Ho capito la foto dopo aver appena letto la risposta di Anpar.
JDługosz,

15

WNnkej2πnkN

Nota il percorso mostrato e l'equazione sottostante mostra il risultato per il bin di frequenza X (1), come dato dall'equazione di Robert.

Le linee tratteggiate non sono diverse dalle linee continue solo per chiarire dove si trovano i join di sommatoria.

Implementazione FFT


8

essenzialmente, nel calcolare l'ingenuo DFT direttamente dalla somma:

X[k]=n=0N1x[n]ej2πnkN

Nej2πnkNNN1X[k]kX[k+1]

  1. quindi la FFT mantiene alcuni dati intermedi.
  2. la FFT utilizzerà anche un po 'il factoring del fattore twiddle in modo che lo stesso fattore possa essere usato per una combinazione intermedia di dati.

4

Sono una persona visiva. Preferisco immaginare la FFT come un trucco di matrice piuttosto che come un trucco di sommatoria.

Per spiegare ad alto livello:

Un ingenuo DFT calcola ogni campione di output in modo indipendente e utilizza ogni campione di input in ciascun calcolo (algoritmo N² classico).

Un FFT comune utilizza simmetrie e modelli nella definizione DFT per eseguire il calcolo in "livelli" (log N layer), ogni layer con requisiti di tempo costante per campione creando un algoritmo N log N.

Più specifici:

Un modo per visualizzare queste simmetrie è guardare al DFT come un input di matrice 1 × N moltiplicato per una matrice NxN di tutti i tuoi esponenziali complessi. Cominciamo con il caso "radix 2". Divideremo le righe pari e dispari della matrice (corrispondenti ai campioni di input pari e dispari) e le considereremo come due moltiplicazioni di matrice separate che si sommano per ottenere lo stesso risultato finale.

Ora guarda queste matrici: nella prima la metà sinistra è identica alla metà destra. Nell'altra, la metà destra è la metà sinistra x −1. Ciò significa che dobbiamo davvero usare solo la metà sinistra di queste matrici per la moltiplicazione e creare la metà destra in modo economico moltiplicando per 1 o −1. Successivamente, osserva che la seconda matrice differisce dalla prima matrice per fattori uguali in ciascuna colonna, quindi possiamo fattorizzarla e moltiplicarla nell'input, quindi ora sia i campioni pari che quelli dispari usano la stessa matrice, ma richiedono un moltiplicatore primo. E il passaggio finale è osservare che questa risultante matrice N / 2 × N / 2 è identica a una matrice DFT N / 2 e possiamo farlo ancora e ancora fino a raggiungere una matrice 1 × 1 in cui il DFT è una funzione di identità.

Per generalizzare oltre radix 2, puoi guardare a dividere ogni terza fila e guardare tre pezzi di colonne, o ogni 4 ° ecc.

In caso di input di dimensioni primi, esiste un metodo per zero-pad, FFT e troncamento, ma questo va oltre lo scopo di questa risposta.

Vedi: http://whoiskylefinn.com/MatrixFFT.html


prime FFT , varie FFT . L'uso dello zero pad non è l'unica opzione. Mi dispiace, trovo solo il padding zero abusato. Una piccola domanda, non capisco cosa intendi per "ogni strato con requisiti di tempo costante per campione", se potessi spiegare, sarebbe fantastico.
Evil

1
Mi dispiace non volevo dire che lo zero padding fosse IL modo giusto, volevo solo indicare ulteriori letture. E "layer" significa una ricorsione, o una traduzione da un N DFT a 2 N / 2 DFT, con tempo costante per campione che significa che questo passaggio è O (N).
kylefinn,

Finora, tra tutte le descrizioni, questa sembra la più vicina a rendere semplice un problema complesso. La cosa grande che manca, però, è un esempio di queste matrici. Ti capita di averne uno?
Seph Reed,

Caricato questo, dovrebbe aiutare: whoiskylefinn.com/MatrixFFT.html
kylefinn

1

Il DFT fa moltiplicare la matrice di forza bruta N ^ 2.

Gli FFT eseguono acrobazie intelligenti, sfruttando le proprietà della matrice (degenerando la matrice moltiplicando) al fine di ridurre i costi di calcolo.

Diamo prima un'occhiata a un piccolo DFT:

W = FFT (occhio (4));

x = rand (4,1) + 1j * rand (4,1);

X_ref = fft (x);

X = W * x;

assert (max (abs (X-X_ref)) <1e-7)

Fantastico, quindi siamo in grado di sostituire la chiamata MATLAB alla libreria FFTW con una piccola moltiplicazione di matrice 4x4 (complessa) riempiendo una matrice dalla funzione FFT. Che aspetto ha questa matrice?

N = 4,

Wn = exp (-1j * 2 * pi / N),

f = ((0: N-1) '* (0: N-1))

f =

 0     0     0     0
 0     1     2     3
 0     2     4     6
 0     3     6     9

W = Wn. ^ F

W =

1 1 1 1

1 -i -1 i

1 -1 1 -1

1 i -1 -i

Ogni elemento può essere +1, -1, + 1j o -1j. Ovviamente, ciò significa che possiamo evitare moltiplicazioni complesse. Inoltre, la prima colonna è identica, nel senso che stiamo moltiplicando ripetutamente il primo elemento di x per lo stesso fattore.

Si scopre che i prodotti tensoriali di Kronecker, i "fattori di twiddle" e una matrice di permutazione in cui l'indice viene modificato in base alla rappresentazione binaria capovolta sono entrambi compatti e offrono una prospettiva alternativa su come gli FFT vengono calcolati come un insieme di operazioni di matrice sparse.

Le righe sottostanti sono una semplice decimazione in frequenza (DIF) radix 2 forward FFT. Mentre i passaggi possono sembrare ingombranti, è conveniente riutilizzarli per FFT forward / inverse, radix4 / split-radix o decimation-in-time, pur rappresentando equamente come FFT sul posto tende ad essere implementato nel mondo reale, Credo.

N = 4;

x = randn (N, 1) + 1j * randn (N, 1);

T1 = exp (-1j * 2 * pi * ([zeri (1, N / 2), 0: (N / 2-1)]). '/ N),

M0 = kron (occhio (2), fft (occhio (2))),

M1 = kron (fft (occhio (2)), occhio (2)),

X = bitrevorder (x. '* * M1 diag (T1) * M0),

X_ref = FFT (x)

assert (max (abs (X (:) - X_ref (:))) <1e-6)

CF Van Loan ha un ottimo libro su questo argomento.


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.