Estou tentando entender as FFTs, eis o que tenho até agora:
Para encontrar a magnitude das frequências em uma forma de onda, é preciso investigá-las multiplicando a onda pela frequência que estão procurando, em duas fases diferentes (sin e cos) e fazendo a média de cada uma. A fase é encontrada por sua relação com as duas, e o código para isso é algo como isto:
//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;
}
Para fazer isso com muitas frequências muito rapidamente, as FFTs usam muitos truques.
Quais são alguns dos truques usados para tornar as FFTs muito mais rápidas que a DFT?
PS: Tentei analisar os algoritmos FFT completos na Web, mas todos os truques tendem a ser condensados em um belo pedaço de código sem muita explicação. O que eu preciso primeiro, antes que eu possa entender tudo, é uma introdução a cada uma dessas mudanças eficientes como conceitos.
Obrigado.
fft
dft
algorithms
Seph Reed
fonte
fonte
sudo
no seu exemplo de código pode ser confuso, pois esse é um comando bem conhecido no mundo dos computadores. Você provavelmente quis dizer psuedocode.Respostas:
A implementação simples de um -ponto DFT é basicamente uma multiplicação por um N × N matriz. Isso resulta em uma complexidade de O ( N 2 ) .N N×N O(N2)
Um dos algoritmos mais comuns da Transformada Rápida de Fourier (FFT) é o algoritmo FFT radix-2 Cooley-Tukey Decimation-in-Time. Essa é uma abordagem básica de dividir e conquistar.
j≜√
isso pode ser reescrito como onde e são as transformações DFT no ponto das amostras pares e ímpares de respectivamente. Então, acabamos de transformar uma única DFT de ponto em duas DFTs menores de . Isso reduz o custo computacional porque quando .
Podemos então reiterar o mesmo processo nessas duas DFTs menores. Essa abordagem de dividir e conquistar permite alcançar a complexidade de , que é muito melhor que o que tivemos com a ingênua implementação de DFT (como é ilustrado em grande parte pela resposta da esquerda ).O (NregistroN) O ( N2)
fonte
W
,j
,X()
,N
ek
ainda não têm definições para mim.http://nbviewer.jupyter.org/gist/leftaroundabout/83df89a7d3bdc24373ea470fb50be629
DFT, tamanho 16
FFT, tamanho 16
A diferença de complexidade é bastante evidente disso, não é?
Aqui está como eu entendo a FFT.
Primeiramente, eu sempre pensaria nas transformadas de Fourier principalmente como transformadas de funções contínuas , ou seja, um mapeamento bijetivo . Sob essa luz, fica claro que não pode ser realmente necessário ir para o "nível mais profundo" e fazer um loop sobre elementos individuais , porque os "elementos individuais" são pontos únicos na linha real, dos quais existem quantidades infinitamente infinitas .FT : L2( R ) → L2( R )
Então, como essa transformação ainda está bem definida? Bem, é crucial que ele opere não no espaço de função geral mas apenas no espaço das funções integráveis (Lebesgue-, square-) . Agora, essa integrabilidade não é uma propriedade muito forte (muito mais fraca que a diferenciabilidade, etc.), mas exige que a função se torne “localmente describível com informações contáveis”. Essa descrição é dada pelos coeficientes de uma transformada de Fourier de curta duração . †R → C O caso mais simples é que sua função é contínua e você a divide em regiões tão pequenas que é basicamente constante em cada uma delas. Então, cada um dos STFTs tem um termo mais zerótico. Se você ignorar os outros coeficientes (de qualquer forma deteriorados), cada domínio será apenas um único ponto de dados. De todos esses coeficientes de curto prazo - limite LF, você pode fazer uma transformação de Fourier discreta. Na verdade, é exatamente isso que você faz ao realizar qualquer TF em dados medidos do mundo real!
Os dados medidos não precisam necessariamente corresponder a uma quantidade física fundamental. Por exemplo, quando você mede alguma intensidade de luz , está realmente apenas medindo a amplitude de uma onda eletromagnética cuja frequência é alta demais para ser amostrada com um ADC. Mas é claro que você também pode calcular a DFT de um sinal de intensidade de luz amostrado, e de forma barata, apesar da frequência insana da onda de luz.
Isso pode ser entendido como a razão mais importante pela qual a FFT é barata:
Não se preocupe em tentar ver os ciclos de oscilação individuais do nível mais alto. Em vez disso, transforme apenas informações de alto nível que já foram pré-processadas localmente.
Isso não é tudo o que existe, no entanto. O melhor da FFT é que ela ainda fornece todas as informações que uma DFT completa daria . Ou seja, todas as informações que você também obteria ao experimentar a onda eletromagnética exata de um feixe de luz. Isso pode ser conseguido através da transformação de um sinal de fotodiodo? - você pode medir a frequência de luz exata disso?
Bem, a resposta é não, você não pode. Ou seja, a menos que você aplique truques extras.Δ ν= 1 / Δ t
Primeiro de tudo, você precisa medir pelo menos aproximadamente a frequência nos curtos blocos de tempo. Bem, isso é possível com um espectrógrafo. Mas só é possível até uma precisão de , uma típica relação de incerteza ‡ .
Por termos um período de tempo mais longo, também devemos reduzir a incerteza de frequência. E isso é realmente possível, se você medir localmente não apenas a frequência aproximada, mas também a fase da onda. Você sabe que um sinal de 1000 Hz terá exatamente a mesma fase se você o observar um segundo depois. Enquanto um sinal de 1000,5 Hz, embora indistinguível em pequena escala, terá a fase invertida um segundo depois.
Felizmente, essa informação de fase pode muito bem ser armazenada em um único número complexo. E é assim que a FFT funciona! Tudo começa com muitas pequenas transformações locais. Eles são baratos - por um lado, obviamente, porque eles usam apenas uma pequena quantidade de dados, mas, em segundo lugar, porque eles sabem que, devido ao curto período de tempo, eles não conseguem resolver a frequência com muita precisão de qualquer maneira - por isso ainda é acessível, mesmo que você faça muitas dessas transformações.
No entanto, eles também registram a fase e, a partir disso, é possível tornar a resolução da frequência mais exata no nível superior. A transformação necessária é novamente barata, porque ela mesma não se preocupa com oscilações de alta frequência, mas apenas com os dados de baixa frequência pré-processados.
† Sim, minha argumentação é um pouco circular neste momento. Vamos chamá-lo de recursivo e estamos bem ...
‡ Essa relação não é mecânica quântica, mas a incerteza de Heisenberg tem realmente a mesma razão fundamental.
fonte
Aqui está uma figura a ser adicionada à boa resposta de Robert, demonstrando a "reutilização" das operações, neste caso para uma DFT de 8 pontos. Os "Fatores de Twiddle" são representados no diagrama usando a notação que é igual aWn kN ej 2 πn kN
Observe o caminho mostrado e a equação abaixo mostra o resultado para o compartimento de frequência X (1), conforme indicado pela equação de Robert.
As linhas tracejadas não são diferentes das linhas sólidas apenas para esclarecer onde estão as somatórias.
fonte
essencialmente, ao calcular o DFT ingênuo diretamente do somatório:
existem pesquisas de tabela para o fator twiddle , multiplicações complexas e adições de . e isso é apenas para um valor de e uma instância de . então o DFT ingênuo joga fora todos esses dados intermediários e repassa todos eles novamente para .N NN-1X[k]kX[k+1]ej 2 πn kN N N- 1 X[ k ] k X[ k + 1 ]
fonte
Eu sou uma pessoa visual. Prefiro imaginar a FFT como um truque de matriz, e não como um truque de soma.
Para explicar em um nível alto:
Um DFT ingênuo calcula cada amostra de saída independentemente e usa todas as amostras de entrada em cada cálculo (algoritmo N² clássico).
Uma FFT comum usa simetrias e padrões na definição de DFT para fazer o cálculo em "camadas" (log N layers), cada camada com requisitos de tempo constante por amostra, criando um algoritmo N log N.
Mais detalhes:
Uma maneira de visualizar essas simetrias é olhar para o DFT como uma entrada da matriz 1 × N multiplicada por uma matriz NxN de todos os seus exponenciais complexos. Vamos começar com o caso "radix 2". Vamos dividir as linhas pares e ímpares da matriz (correspondendo às amostras de entrada pares e ímpares) e considerá-las como duas multiplicações de matrizes separadas que se somam para obter o mesmo resultado final.
Agora observe estas matrizes: na primeira a metade esquerda é idêntica à metade direita. Na outra, a metade direita é a metade esquerda x −1. Isso significa que realmente precisamos usar a metade esquerda dessas matrizes para multiplicação e criar a metade direita mais barata multiplicando por 1 ou -1. Em seguida, observe que a segunda matriz difere da primeira matriz por fatores iguais em cada coluna, para que possamos fatorá-la e multiplicá-la na entrada. Agora, amostras pares e ímpares usam a mesma matriz, mas requerem um multiplicador primeiro. E a etapa final é observar que essa matriz N / 2 × N / 2 resultante é idêntica a uma matriz N / 2 DFT e podemos fazer isso repetidamente até chegarmos a uma matriz 1 × 1 onde a DFT é uma função de identidade.
Para generalizar além do radix 2, você pode dividir a cada terceira linha e ver três pedaços de colunas ou a cada quarta, etc.
No caso de entradas de tamanho primário, existe um método para zerar, FFT e truncar adequadamente, mas isso está além do escopo desta resposta.
Veja: http://whoiskylefinn.com/MatrixFFT.html
fonte
A DFT faz uma matriz N ^ 2 de força bruta se multiplicar.
As FFTs fazem truques inteligentes, explorando propriedades da matriz (degeneralizando a matriz multiplicada) para reduzir o custo computacional.
Vamos primeiro olhar para uma pequena DFT:
W = pés (olho (4));
x = rand (4,1) + 1j * rand (4,1);
X_ref = fft (x);
X = W * x;
assert (max (abs (X-X_ref)) <1e-7)
Ótimo, portanto, podemos substituir a chamada MATLABs da biblioteca FFTW por uma pequena multiplicação de matriz 4x4 (complexa) preenchendo uma matriz a partir da função FFT. Então, como é essa matriz?
N = 4
Wn = exp (-1j * 2 * pi / N),
f = ((0: N-1) '* (0: N-1))
f =
W = Wn. ^ F
W =
1 1 1 1
1 -i -1 i
1 -1 1 -1
1 i -1 -i
Cada elemento é +1, -1, + 1j ou -1j. Obviamente, isso significa que podemos evitar multiplicações complexas completas. Além disso, a primeira coluna é idêntica, o que significa que multiplicamos o primeiro elemento de x repetidamente pelo mesmo fator.
Acontece que os produtos tensores da Kronecker, "fatores duplos" e uma matriz de permutação em que o índice é alterado de acordo com a representação binária invertida são compactos e oferecem uma perspectiva alternativa de como as FFTs são computadas como um conjunto de operações de matriz esparsa.
As linhas abaixo são uma FFT simples de Decimation in Frequency (DIF) radix 2 forward. Embora as etapas possam parecer complicadas, é conveniente reutilizar para FFT direta / inversa, radix4 / split-radix ou dizimação no tempo, enquanto é uma representação justa de como as FFTs locais tendem a ser implementadas no mundo real, Acredito.
N = 4;
x = padrão (N, 1) + 1j * padrão (N, 1);
T1 = exp (-1j * 2 * pi * ([zeros (1, N / 2), 0: (N / 2-1)]). '/ N),
M0 = kron (olho (2), fft (olho (2))),
M1 = kron (fft (olho (2)), olho (2)),
X = ordem de bits (x. '* M1 * diag (T1) * M0),
X_ref = fft (x)
assert (max (abs (X (:) - X_ref (:))) <1e-6)
CF Van Loan tem um ótimo livro sobre esse assunto.
fonte
Se você quiser beber da Mangueira de Fogo da Sabedoria, sugiro:
"Transformações rápidas - algoritmos, análises, aplicações" por Douglas F. Elliott, K. Ramamohan Rao
Abrange FFT, Hartley, Winograd e aplicações.
Um ponto forte é que mostra como a FFT é um conjunto de fatorações de matriz esparsas com ordenação de reversão de bits.
fonte