Какие различия между DFT и FFT делают FFT настолько быстрым?


16

Я пытаюсь понять БПФ, вот что у меня так далеко:

Для того, чтобы найти величину частот в форме волны, нужно проверить их, умножив волну на частоту, которую они ищут, в двух разных фазах (sin и cos) и усреднив каждую. Фаза находится по ее отношению к двум, и код для этого выглядит примерно так:

//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;
}

Чтобы сделать это для очень многих частот очень быстро, БПФ используют много уловок.

Какие приемы используются для создания БПФ намного быстрее, чем ДПФ?

PS Я попытался просмотреть законченные алгоритмы FFT в Интернете, но все хитрости, как правило, сводятся в один прекрасный кусок кода без особых объяснений. Прежде чем я смогу понять все это, мне нужно некоторое введение в каждое из этих эффективных изменений как концепций.

Спасибо.


7
«DFT» не относится к алгоритму: это относится к математической операции. «БПФ» относится к классу методов для вычисления этой операции.

1
Просто хотел бы отметить, что использование sudoв вашем примере кода может привести к путанице, поскольку это хорошо известная команда в компьютерном мире. Вы, вероятно, имели в виду psuedocode.
rwfeather

1
@nwfeather Он, вероятно, имел в виду «псевдокод».
user207421

Ответы:


20

Наивная реализация точечного ДПФ представляет собой умножение на матрицуЭто приводит к сложности .N × N O ( N 2 )NN×NO(N2)

Одним из наиболее распространенных алгоритмов быстрого преобразования Фурье (БПФ) является алгоритм БПФ-преобразования Кули-Тьюки во времени с основанием-2 . Это основной подход «разделяй и властвуй».

Сначала определите «коэффициент » как: где - мнимая единица, затем ДПФ из определяется как Если четное (а является целым числом), тогда сумму можно разделить на две суммы следующим образом: где первое суммирование относится к четным выборкам из , а второй с нечетными образцами . Определение и j

WNej2πN
X[k]x[n]X[k]= N - 1 n = 0 x[n]j1X[k]x[n]N N
X[k]=n=0N1x[n]WNkn.
N 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 ) N x[n]x[n]xeN2
X[k]=n=0N/21x[2n]WN2kn+n=0N/21x[2n+1]WNk(2n+1)
x[n]x[n]xe[n]x[2n]xo[n]x[2n+1] и используя тот факт, что
  1. WNk(2n+1)=WN2knWNk и
  2. WN2kn=WN/2kn ,

это можно переписать как где и являются DFT-преобразованиями -точки четных и нечетных выборок соответственно. Таким образом, мы просто преобразовали одно точечное ДПФ в два меньших -точечных ДПФ. Это снижает вычислительные затраты, потому что когда .

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

Затем мы можем повторить тот же процесс на этих двух меньших ДПФ. Этот подход «разделяй и властвуй» позволяет достичь сложности , что намного лучше, чем мы имели в наивной реализации DFT (как в значительной степени иллюстрируется ответом leftaroundabout ).O(NlogN)O(N2)


Вы хотели бы перечислить, что означает каждая из переменных? Я довольно новый для этого, так что W, j, X(), Nи kеще не имеет определения для меня.
Сеф Рид

W уже определен в моем ответе. Я попытался лучше определить некоторые другие обозначения. обозначает индекс в частотной области и индекс во временной области. kn
anpar

19

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

ДПФ, размер 16

Диаграмма операций в формате 16 наивного ДПФ

БПФ, размер 16

Схема операций в формате 16 с основанием-2 БПФ

Разница в сложности довольно очевидна из этого, не так ли?


Вот как я понимаю БПФ.

FT:L2(р)L2(р)

RCВ простейшем случае ваша функция непрерывна, и вы делите ее на настолько маленькие области, что она в основном постоянна в каждой из них. Тогда каждый из STFT имеет наиболее сильный нулевой член. Если вы игнорируете (в любом случае затухающие) другие коэффициенты, то каждый домен - это просто одна точка данных. Из всех этих кратковременных LF-предельных коэффициентов вы можете взять дискретное преобразование Фурье. Фактически, это именно то, что вы делаете, выполняя любой FT на измеренных реальных данных!

Однако измеренные данные не обязательно должны соответствовать фундаментальной физической величине. Например, когда вы измеряете некоторую интенсивность света , вы на самом деле просто измеряете амплитуду электромагнитной волны, частота которой сама по себе слишком высока, чтобы ее можно было дискретизировать с помощью АЦП. Но очевидно, что вы также можете вычислить ДПФ для дискретизированного сигнала интенсивности света, причем дешево, несмотря на безумную частоту световой волны.

Это можно понять как наиболее важную причину дешевизны БПФ:

Не пытайтесь увидеть отдельные циклы колебаний с самого высокого уровня. Вместо этого преобразуйте только несколько высокоуровневую информацию, которая уже была предварительно обработана локально.

Но это еще не все. Самое замечательное в FFT - это то, что он по- прежнему дает вам всю информацию, которую мог бы предоставить полный DFT . Т.е. вся информация, которую вы также получите, когда будете отбирать точную электромагнитную волну светового луча. Может ли это быть достигнуто путем преобразования сигнала фотодиода? - Вы можете измерить точную частоту света от этого?


Δνзнак равно1/ΔT

Имея в целом более длительный промежуток времени, мы также сможем сузить частотную неопределенность. И это действительно возможно, если вы измеряете локально не только грубую частоту, но и фазу волны. Вы знаете, что сигнал 1000 Гц будет иметь точно такую ​​же фазу, если вы посмотрите на него через секунду. Принимая во внимание, что сигнал с частотой 1000,5 Гц, будучи неразличимым на короткой шкале, через секунду перевернет фазу.

К счастью, эта фазовая информация очень хорошо может быть сохранена в одном комплексном числе. И вот как работает БПФ! Это начинается с множества небольших локальных преобразований. Они дешевы - во-первых, очевидно, потому что они используют только небольшой объем данных, а во-вторых, потому что они знают, что из-за короткого промежутка времени они не могут точно разрешить частоту в любом случае - так что это по-прежнему доступно, даже если вы сделать много таких преобразований.

Однако они также записывают фазу , и из этого вы можете сделать разрешение частоты более точным на верхнем уровне. Требуемое преобразование опять-таки дешево, поскольку оно само по себе не беспокоит высокочастотные колебания, а только предварительно обработанные низкочастотные данные.


Да, моя аргументация на данный момент немного круглая. Давайте просто назовем это рекурсивным, и мы в порядке ...

Это соотношение не является квантово-механическим, но неопределенность Гейзенберга имеет фактически ту же фундаментальную причину.


2
хорошее графическое изображение вопроса. :-)
Роберт Бристоу-Джонсон

2
Разве вы не любите диаграммы, которые повторяются везде и никогда нигде не объясняются :)
user541686

1
Я понял картину после того, как только что прочитал ответ Анпар.
JDługosz

15

WNnkej2πnkN

Обратите внимание на показанный путь и приведенное ниже уравнение показывает результат для частотного бина X (1), как указано в уравнении Роберта.

Пунктирные линии ничем не отличаются от сплошных, чтобы прояснить, где находятся объединения суммирования.

БПФ реализация


8

по сути, при вычислении наивного ДПФ непосредственно из суммы:

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

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

  1. поэтому БПФ держит некоторые промежуточные данные.
  2. БПФ также будет использовать факторный коэффициент немного, чтобы тот же коэффициент можно было использовать для промежуточной комбинации данных.

4

Я визуальный человек. Я предпочитаю представлять БПФ как матричный трюк, а не как трюк суммирования.

Чтобы объяснить на высоком уровне:

Наивный DFT вычисляет каждую выходную выборку независимо и использует каждую входную выборку в каждом вычислении (классический алгоритм N²).

Обычный FFT использует симметрии и шаблоны в определении DFT для выполнения вычислений в «слоях» (log N слоев), каждый уровень с требованием постоянного времени на выборку создает алгоритм N log N.

Больше подробностей:

Один из способов визуализации этих симметрий состоит в том, чтобы рассматривать ДПФ как матричный вход 1 × N, умноженный на матрицу NxN всех ваших комплексных экспонент. Давайте начнем с случая "radix 2". Мы собираемся разделить четные и нечетные строки матрицы (соответствующие четным и нечетным входным выборкам) и рассматривать их как два отдельных умножения матрицы, которые складываются вместе, чтобы получить один и тот же конечный результат.

Теперь посмотрим на эти матрицы: в первой левая половина идентична правой половине. В другой, правая половина - это левая половина x − 1. Это означает, что нам действительно нужно использовать левую половину этих матриц для умножения и создать правую половину дешево, умножив на 1 или -1. Далее, обратите внимание, что вторая матрица отличается от первой матрицы коэффициентами, которые одинаковы в каждом столбце, поэтому мы можем вычленить это и умножить на входные значения, чтобы теперь и для четных, и для нечетных выборок использовалась одна и та же матрица, но требуется множитель первый. И последний шаг - наблюдение, что получающаяся матрица N / 2 × N / 2 идентична матрице N / 2 DFT, и мы можем делать это снова и снова, пока не достигнем матрицы 1 × 1, где DFT является тождественной функцией.

Чтобы обобщить не только основание 2, вы можете посмотреть на разбиение каждого третьего ряда и просмотр трех фрагментов столбцов или каждого четвертого и т. Д.

В случае простых входных данных существует метод для правильного заполнения нуля, FFT и усечения, но это выходит за рамки этого ответа.

Смотрите: http://whoiskylefinn.com/MatrixFFT.html


простые БПФ , различные БПФ . Использование нуля не является единственной возможностью. Извините, я просто считаю, что заполнение нулями чрезмерно. Один маленький вопрос, я не понимаю, что вы подразумеваете под «каждым слоем с требованием постоянного времени на образец», если бы вы могли объяснить, это было бы здорово.
Зло

1
Извините, я не хотел сказать, что нулевое заполнение было НАСТОЯЩИМ, просто хотел указать на дальнейшее чтение. И «слой» означает рекурсию или перевод из N DFT в 2 N / 2 DFT, с постоянным временем на выборку, означающим, что этот шаг равен O (N).
kylefinn

Пока что из всех описаний это кажется наиболее близким к простому сложному вопросу. Однако то, чего не хватает, - это пример этих матриц. У вас бывают такие?
Сеф Рид

Загрузил это, должно помочь: whoiskylefinn.com/MatrixFFT.html
kylefinn

1

ДПФ выполняет умножение матрицы грубой силы N ^ 2.

БПФ делает хитрые трюки, используя свойства матрицы (вырожденное умножение матрицы), чтобы уменьшить вычислительные затраты.

Давайте сначала посмотрим на небольшой DFT:

W = FFT (глаз (4));

x = ранд (4,1) + 1j * ранд (4,1);

X_ref = fft (x);

Х = Ш * х;

подтвердить (max (abs (X-X_ref)) <1e-7)

Отлично, поэтому мы можем заменить вызов MATLABs в библиотеку FFTW небольшим матричным умножением 4x4, заполнив матрицу из функции FFT. Так как же выглядит эта матрица?

N = 4,

Wn = ехр (-1j * 2 * пи / 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. МкмкФ

W =

1 1 1 1

1-я -1 я

1 -1 1 -1

1 я -1-я

Каждый элемент равен +1, -1, + 1j или -1j. Очевидно, это означает, что мы можем избежать полных сложных умножений. Кроме того, первый столбец идентичен, это означает, что мы умножаем первый элемент x снова и снова на один и тот же коэффициент.

Оказывается, что тензорные произведения Кронекера, «факторы твида» и матрица перестановок, в которых индекс изменяется в соответствии с перевернутым двоичным представлением, являются компактными и дают альтернативную перспективу того, как БПФ вычисляются как набор разреженных матричных операций.

Строки ниже - это простое БПФ для десятичного преобразования частоты (DIF) с основанием 2. Хотя эти шаги могут показаться громоздкими, удобно повторно использовать для прямого / обратного БПФ, radix4 / split-radix или прореживания во времени, в то же время являясь достоверным представлением о том, как БПФ на местах имеют тенденцию быть реализованными в реальном мире, Я верю.

N = 4;

x = рандн (N, 1) + 1j * рандн (N, 1);

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

M0 = крон (глаз (2), ффт (глаз (2))),

M1 = крон (ффт (глаз (2)), глаз (2)),

Х = bitrevorder (х. * M1 * Diag (Т1) * М0),

X_ref = FFT (х)

утверждают (макс (абс (Х (:) - X_ref (:))) <1e-6)

CF Van Loan имеет отличную книгу на эту тему.


1

Если вы хотите пить из Огненного шланга Мудрости, я предлагаю:

«Быстрые преобразования - алгоритмы, анализ, приложения» Дуглас Ф. Эллиотт, К. Рамамохан Рао

Он охватывает FFT, Hartley, Winograd и приложения.

Одним из сильных моментов является то, что это показывает, как БПФ представляет собой набор разреженных матричных факторизаций с упорядочением обращения битов.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.