Ефективний розрахунок автокореляції за допомогою FFT


12

Я намагаюся обчислити автокореляцію на платформі, де єдиним у мене прискореним примітивом є (I) FFT. У мене все-таки проблема.

Я прототипував це в MATLAB . Я, проте, трохи розгублений. Я припускав, що це працює просто так (це з пам’яті, тож вибачте, якщо я зрозумів це трохи неправильно).

 autocorr = ifft( complex( abs( fft( inputData ) ), 0 ) )

Однак я отримую інший результат, ніж я отримую від використання xcorrфункції. Тепер я повністю сподіваюсь не отримати ліву частину автоматичної кореляції (оскільки це відображення правої сторони і, таким чином, не потрібно в будь-якому випадку). Однак проблема в тому, що моя права сторона, здається, сама відображена на півдорозі. Що фактично означає, що я отримую приблизно половину тієї кількості даних, яку я очікую.

Тож я впевнений, що я повинен робити щось дуже просте неправильно, але я просто не можу зрозуміти, що.


1
Будь обережний. Якщо дані не є детермінованими, ми зазвичай можемо оцінити лише послідовність автокореляції. Існує дві загальні версії оцінок автокореляції: упереджена та неупереджена. Об'єктивні результати приводять до оцінок автокореляції, які є статистично неупередженими. Однак дисперсія може бути дуже великою для відставань високого порядку, що призводить до проблем, якщо, наприклад, оцінка автокореляції використовується в матричних інверсіях. Зміщені зразки демонструють статистичне зміщення, але з меншою дисперсією (і середньоквадратичною помилкою). Обидва статистично несуперечливі. Ви маєте ненормалізовану упереджену оцінку вище.
Брайан

Відповіді:


16

вірні пішенети, звичайно. FFT реалізує кругову згортку, тоді як xcorr () заснований на лінійній згортці. Крім того, вам потрібно також квадратне абсолютне значення в частотній області. Ось фрагмент коду, який обробляє всі нульові прокладки, зрушення та обрізки.

%% Cross correlation through a FFT
n = 1024;
x = randn(n,1);
% cross correlation reference
xref = xcorr(x,x);

%FFT method based on zero padding
fx = fft([x; zeros(n,1)]); % zero pad and FFT
x2 = ifft(fx.*conj(fx)); % abs()^2 and IFFT
% circulate to get the peak in the middle and drop one
% excess zero to get to 2*n-1 samples
x2 = [x2(n+2:end); x2(1:n)];
% calculate the error
d = x2-xref; % difference, this is actually zero
fprintf('Max error = %6.2f\n',max(abs(d)));

Нічого собі, що працював красунь. Пряма версія C (однопоточна, без SIMD) мого трекера тону працювала за 0,8 секунди, використовуючи вищевказаний метод, на відміну від примітивної версії Intel, що працювала за 0,4 секунди. Це дивовижно! Спасибі
Гоз


3

N2N1[(N1),N1]0

2N12N12N12N1

N2N1N

N1N2N102N12N1

Якщо коротко: вам слід було це зробити (щоб бути адаптованим до вашої мови програмування):

autocorr = ifft( complex( abs(fft(inputData, n=2*N-1))**2, 0 ) )

Або в MATLAB:

autocorr = ifft(abs(fft(inputData, 2*N-1)).^2)

0

Основна причина, щоб бажаний вихід функції xcorr був не подібний до того, який застосовують функції FFT та IFFT, полягає в тому, що при застосуванні цих функцій до сигналів кінцевий результат кругоподібний .

Основну різницю між лінійною згорткою і круговою згорткою можна знайти в лінійній і круговій згортці .

Проблему можна вирішити, спочатку подаючи нуль сигналу та обрізаючи кінцевий вихід IFFT .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.