Проблемы реализации FFT: исправление бессмысленных результатов
Узнайте, как исправить проблемы реализации FFT, вызывающие бессмысленные результаты. Изучите правильное масштабирование частоты, оконные функции и методы нормализации для точного анализа сигналов.
Я пытаюсь выполнить быстрое преобразование Фурье (FFT) над набором данных, содержащим значения времени и амплитуды, для анализа периодичности сигнала. В наборе данных содержится 2,793 выборок с частотой дискретизации 25 Гц, а общее время исследования составляет 111,76 секунд.
Вот мой текущий код:
# FFT
N = 2793 # Количество выборок
fs = 25.0 # частота сигнала
T = 1 / fs
Ny = fs / 2.0 # частота Найквиста
# создать массив, соответствующий значениям в сигнале
yf = fft(y) # выполнить FFT над сигналом
xf = np.linspace(0.0, Ny, N // 2) # создать новую ось X: частота
# построить график
plt.plot(xf, 2.0 / N * np.abs(yf[:N // 2]))
plt.grid(True)
plt.show()
Однако полученный график не показывает осмысленных данных. Я не эксперт по FFT, поэтому не уверен, что может вызывать эту проблему.
Дополнительная информация:
- Значения амплитуды масштабированы с коэффициентом 10
- Данные могут быть не идеально периодическими, поэтому я использую FFT
- Вот образец формата данных:
номер_строки, время(с), амплитуда, фаза, метка_времени, ...
0, 0.00, -190.919, 0.0698, 0, ...
1, 0.04, -190.814, 0.1397, 40, ...
2, 0.08, -190.769, 0.2094, 80, ...
...
2793, 111.72, -184.862, 0.8796, 111720, ...
Может ли кто-то с опытом работы с FFT помочь мне определить, что может быть не так с моим подходом или кодом?
Реализация FFT: распространенные проблемы и решения
В вашей реализации FFT присутствуют несколько проблем, которые могут приводить к бессмысленным результатам. Основные проблемы связаны с неправильным масштабированием частотной оси, возможным отсутствием оконной функции для непериодических сигналов и неправильной нормализацией FFT. Давайте предоставим comprehensive анализ и решение.
Содержание
- Распространенные проблемы реализации FFT
- Корректировка частотной оси
- Правильное масштабирование и нормализация FFT
- Оконные функции для непериодических сигналов
- Полная исправленная реализация
- Дополнительные лучшие практики
Распространенные проблемы реализации FFT
На основе результатов исследования, в вашем коде присутствуют несколько распространенных ловушек FFT:
-
Неправильный расчет частотной оси: Использование
np.linspace(0.0, Ny, N // 2)создает равномерно распределенный массив частот, но это не учитывает фактическое частотное разрешение вашего FFT. -
Спектральная утечка: Поскольку ваши данные могут быть не идеально периодическими, вы, вероятно, сталкиваетесь со спектральной утечкой, когда энергия одной частотной компоненты распространяется по нескольким частотным корзинам.
-
Отсутствие оконной функции: Без применения оконной функции разрывы на границах сигнала могут создавать артефакты в частотной области.
-
Проблемы с масштабированием амплитуд: Факт того, что ваши амплитуды масштабированы с коэффициентом 10, необходимо учитывать в результатах FFT.
Согласно Signal Processing Stack Exchange, “Причина коэффициента 2 заключается в том, что мы хотим компенсировать построение одностороннего спектра, поскольку энергия разделена между положительными и отрицательными частотами.”
Корректировка частотной оси
Расчет частотной оси в вашем коде неправильный. Для правильного анализа FFT следует использовать np.fft.fftfreq() или вычислять частотные корзины на основе частоты дискретизации и длины записи.
# Правильный расчет частотной оси
freq = np.fft.fftfreq(N, T)[:N//2] # Получаем только положительные частоты
Как объясняется в обсуждении на Stack Overflow, частотная ось должна рассчитываться с использованием:
freq = np.linspace(0.0, fs/2, N//2) # fs/2 - частота Найквиста
Однако fftfreq() более точен, так как он учитывает фактические частотные корзины FFT.
Правильное масштабирование и нормализация FFT
Ваш текущий коэффициент масштабирования 2.0/N частично правильный, но может потребовать корректировки в зависимости от вашего конкретного применения. Как отмечено в исследовании, “Ваше решение нормировать или не нормировать не меняет точности вашего ответа, так как это просто коэффициент масштабирования.”
Для одностороннего спектра действительных сигналов правильное масштабирование должно быть:
# Масштабирование одностороннего спектра
yf = np.fft.fft(y)
yf_scaled = 2.0 * np.abs(yf[:N//2]) / N
Коэффициент 2 компенсирует энергию, которая разделена между положительными и отрицательными частотами в действительном сигнале.
Оконные функции для непериодических сигналов
Поскольку ваши данные могут быть не идеально периодическими, применение оконной функции является критически важным для уменьшения спектральной утечки. Как упоминается в советах на LinkedIn, “Оконная функция - это математическая функция, которую вы применяете к своим выборкам перед выполнением FFT.”
Распространенные оконные функции включают:
from scipy import signal
# Применение оконной функции
window = signal.windows.hann(N) # Окно Ханна
y_windowed = y * window
# Затем выполняем FFT для данных с оконной функцией
yf = np.fft.fft(y_windowed)
У разных окон разные характеристики:
- Окно Ханна: Хорошее универсальное окно
- Окно Хэмминга: Похожее на окно Ханна, но с другими характеристиками боковых лепестков
- Окно Блэкмана: Лучше подавляет боковые лепестки, но имеет более широкий главный лепесток
Как отмечено в обзоре на ScienceDirect, “усреднение может значительно улучшить отношение сигнал/шум в отображении FFT, но с той же стоимостью замедления скорости измерения.”
Полная исправленная реализация
Вот полная исправленная реализация, которая решает все проблемы:
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# Ваши параметры
N = 2793 # Количество выборок
fs = 25.0 # Частота дискретизации (Гц)
T = 1.0 / fs # Интервал между выборками (секунды)
total_time = N * T # Общее время (должно быть 111.72 секунд)
# Загрузка ваших данных (предполагаем, что y - ваш массив амплитуд)
# y = ваши_данные_амплитуд # Здесь должны быть ваши 2793 значения амплитуд
# Применение оконной функции для уменьшения спектральной утечки
window = signal.windows.hann(N)
y_windowed = y * window
# Выполнение FFT
yf = np.fft.fft(y_windowed)
# Расчет частотной оси
freq = np.fft.fftfreq(N, T)[:N//2] # Только положительные частоты
# Масштабирование результатов FFT для одностороннего спектра
yf_scaled = 2.0 * np.abs(yf[:N//2]) / N
# Учет коэффициента масштабирования амплитуд 10
yf_scaled = yf_scaled / 10 # Поскольку ваши данные масштабированы на 10
# Построение графиков
plt.figure(figsize=(12, 6))
plt.plot(freq, yf_scaled)
plt.grid(True)
plt.xlabel('Частота (Гц)')
plt.ylabel('Амплитуда')
plt.title('Анализ FFT сигнала')
plt.xlim(0, fs/2) # Показывать до частоты Найквиста
plt.show()
# Опционально: преобразование в децибелы для лучшей визуализации
yf_dB = 20 * np.log10(yf_scaled + 1e-10) # Добавляем малое значение, чтобы избежать log(0)
plt.figure(figsize=(12, 6))
plt.plot(freq, yf_dB)
plt.grid(True)
plt.xlabel('Частота (Гц)')
plt.ylabel('Амплитуда (дБ)')
plt.title('Анализ FFT сигнала (шкала дБ)')
plt.xlim(0, fs/2)
plt.show()
Дополнительные лучшие практики
-
Увеличение частотного разрешения: Как отмечено в обсуждении на Stack Overflow, “Не заполняйте нулями, а увеличьте временной интервал вашего сигнала для повышения частотного разрешения.”
-
Работа со стационарными сигналами: Запись в Википедии предупреждает, что “FFT может быть плохим выбором для анализа сигналов со нестационарным частотным содержимым - где частотные характеристики меняются со временем.” Для таких сигналов рассмотрите использование кратковременного FFT (STFT) или вейвлет-преобразований.
-
Проверка на периодичность: Как предлагается в документации Analog Devices, сначала следует изучить сигнал во временной области, чтобы понять его характеристики, прежде чем применять FFT.
-
Учет вычислительной эффективности: Для приложений реального времени учебное пособие MIT по FFT обсуждает аппаратную реализацию и время выполнения, что может быть актуально для вашего приложения.
-
Валидация с известными сигналами: Протестируйте вашу реализацию с простым синусоидальным сигналом известной частоты, чтобы убедиться, что все работает правильно перед анализом ваших реальных данных.
Ключевая идея из DSP Guide заключается в том, что “Когда два комплексных переменных умножаются, четыре отдельных компонента должны быть объединены для формирования двух компонентов произведения.” Эта сложность в расчетах FFT подчеркивает важность использования хорошо проверенных реализаций вместо написания собственной с нуля.
Источники
- Как правильно масштабировать частотную ось в Быстром Преобразовании Фурье?
- Следует ли нормировать FFT в Python?
- Построение быстрого преобразования Фурье в Python
- Масштабирование графиков после FFT
- Быстрое Преобразование Фурье - обзор
- Какие лучшие практики или советы по использованию FFT в DSP-проектах или исследованиях?
- Как работает FFT
- Улучшение разрешения FFT - масштабирование Y оси
- Как построить FFT сигнала с правильными частотами на оси X?
Заключение
Чтобы исправить вашу реализацию FFT, сосредоточьтесь на этих ключевых областях:
- Используйте правильный расчет частотной оси с помощью
np.fft.fftfreq()вместоnp.linspace() - Применяйте оконные функции, такие как окно Ханна или Хэмминга, для уменьшения спектральной утечки
- Правильное масштабирование с коэффициентом
2.0/Nдля односторонних спектров и учет вашего коэффициента масштабирования амплитуд - Рассмотрите использование шкалы децибел для лучшей визуализации слабых частотных компонент
- Тестируйте с известными сигналами для валидации вашей реализации
Основная проблема вашего текущего подхода - сочетание неправильного расчета частотной оси и отсутствия оконной функции, что создает вводящие в заблуждение результаты. Реализовав эти исправления, вы сможете правильно анализировать периодичность вашего сигнала и идентифицировать значимые частотные компоненты.