AFD(自适应傅立叶变换)的matlab实现

简介: AFD(Adaptive Fourier Decomposition,自适应傅里叶分解)是一种先进的信号分解方法,它通过一种贪婪算法,自适应地从信号中选取最具能量的单分量(Monocomponent),最终将信号表示为一系列正交的核函数(通常是经过放缩和平移的复指数函数)的线性组合。

AFD(Adaptive Fourier Decomposition,自适应傅里叶分解)是一种先进的信号分解方法,它通过一种贪婪算法,自适应地从信号中选取最具能量的单分量(Monocomponent),最终将信号表示为一系列正交的核函数(通常是经过放缩和平移的复指数函数)的线性组合。

与传统的傅里叶变换相比,AFD能更好地处理非平稳信号,并具有更快的收敛速度。

1. 核心函数:AFD_Core.m

函数实现了AFD的核心迭代过程。

function [Coeffs, Basis, rm] = AFD_Core(signal, t, MaxIter, Threshold, precompute_ae)
% AFD_CORE 自适应傅里叶分解核心算法
%
% 输入:
%   signal      - 输入信号(行或列向量)
%   t           - 时间轴或采样点坐标
%   MaxIter     - 最大分解迭代次数
%   Threshold   - 能量剩余阈值,当剩余信号能量低于此值时停止迭代
%   precompute_ae - 预计算所有a值对应的基函数,速度快但耗内存。设为false更省内存但慢。
%
% 输出:
%   Coeffs      - 分解系数 [c1, c2, ..., cN]
%   Basis       - 基函数(每一列是一个基函数)
%   rm          - 每次迭代后的剩余信号(每一列是一个剩余信号)

if nargin < 5
    precompute_ae = true; % 默认预计算以提高速度
end

% 将信号转换为列向量
signal = signal(:);
N = length(signal);
rm = zeros(N, MaxIter); % 初始化剩余信号存储
Coeffs = zeros(1, MaxIter); % 初始化系数存储
Basis = zeros(N, MaxIter); % 初始化基函数存储

% 归一化时间轴到 [0, 1] 或保持原样,确保复指数基定义正确。
% 这里假设 t 已经是 [0, 1] 区间,或者是一个任意的采样序列。
% 关键是保证基函数 e^{
   i * w * t} 定义一致。

% 初始剩余信号就是原始信号
R_current = signal;

% 创建一个搜索网格来寻找最佳参数 'a'
% 'a' 是一个复数,|a| < 1,在单位圆盘内。
% 我们创建一个网格进行搜索
num_search_points = 1000;
% 在单位圆盘内生成搜索点 (r * exp(1i*theta))
r_vals = linspace(0, 0.99, 30); % 半径从00.99
theta_vals = linspace(0, 2*pi, 50); % 角度从0到2pi
[R, Theta] = meshgrid(r_vals, theta_vals);
a_search_grid = R .* exp(1i * Theta);
a_search_grid = a_search_grid(:); % 展平为列向量

% 预计算所有搜索点a对应的基函数e_a(t)(如果选择此模式)
if precompute_ae
    % 预计算所有基函数 (庞大矩阵: N x num_search_points)
    all_basis = zeros(N, length(a_search_grid));
    for idx = 1:length(a_search_grid)
        a = a_search_grid(idx);
        % 计算核函数 e_a(t) = sqrt(1-|a|^2) / (1 - conj(a) * exp(1i * w * t)) 
        % 这里简化处理:假设 w 对应 2*pi* (01的频率变化)
        % 注意:这是一个标准化的核函数,构成单位圆盘上的正交基
        kernel = sqrt(1 - abs(a)^2) ./ (1 - conj(a) * exp(1i * 2*pi * t));
        kernel = kernel / norm(kernel); % 确保基函数是单位范数的
        all_basis(:, idx) = kernel;
    end
end

% AFD 贪婪迭代分解
for iter = 1:MaxIter
    % 计算当前剩余信号的能量
    energy_rm = norm(R_current)^2;
    if energy_rm < Threshold
        fprintf('迭代在第 %d 次停止,剩余能量低于阈值。\n', iter);
        % 截断输出
        Coeffs = Coeffs(1:iter-1);
        Basis = Basis(:, 1:iter-1);
        rm = rm(:, 1:iter-1);
        return;
    end

    % 在搜索网格上寻找最佳 'a',使得投影系数绝对值最大
    max_proj_val = 0;
    best_a = 0;
    best_basis = zeros(N, 1);

    if precompute_ae
        % 模式1:使用预计算的基函数(速度快)
        proj_vals = R_current' * all_basis; % 计算所有投影
        [max_proj_val, max_idx] = max(abs(proj_vals)); % 找到最大投影
        best_a = a_search_grid(max_idx);
        best_basis = all_basis(:, max_idx);
    else
        % 模式2:动态计算基函数(节省内存)
        for idx = 1:length(a_search_grid)
            a = a_search_grid(idx);
            % 动态计算核函数 e_a(t)
            kernel = sqrt(1 - abs(a)^2) ./ (1 - conj(a) * exp(1i * 2*pi * t));
            kernel = kernel / norm(kernel);

            proj_val = dot(R_current, kernel); % 计算投影
            if abs(proj_val) > max_proj_val
                max_proj_val = abs(proj_val);
                best_a = a_search_grid(idx);
                best_basis = kernel;
            end
        end
    end

    % 计算最佳系数 c_m = <R_{
   m-1}, e_{
   a_m}>
    c_m = dot(R_current, best_basis);

    % 存储结果
    Coeffs(iter) = c_m;
    Basis(:, iter) = best_basis;

    % 更新剩余信号: R_m = R_{
   m-1} - c_m * e_{
   a_m}
    R_current = R_current - c_m * best_basis;
    rm(:, iter) = R_current;

    fprintf('迭代 %d: 系数 = %.4f%+.4fi, 参数 a = %.4f%+.4fi, 剩余能量 = %.6f\n', ...
            iter, real(c_m), imag(c_m), real(best_a), imag(best_a), energy_rm);
end

fprintf('达到最大迭代次数 %d。\n', MaxIter);
end

2. 重构函数:AFD_Reconstruct.m

这个函数使用AFD分解得到的系数和基函数来重构信号。

function reconstructed_signal = AFD_Reconstruct(Coeffs, Basis)
% AFD_RECONSTRUCT 使用AFD分解的系数和基函数重构信号
%
% 输入:
%   Coeffs  - 来自 AFD_Core 的系数向量
%   Basis   - 来自 AFD_Core 的基函数矩阵(每一列是一个基)
%
% 输出:
%   reconstructed_signal - 重构出的信号

    % 简单地将基函数按系数线性组合
    reconstructed_signal = Basis * Coeffs(:);
end

3. 演示脚本:Demo_AFD.m

这个脚本展示了如何使用AFD分解一个合成信号并重构它。

% Demo_AFD.m
% 自适应傅立叶分解 (AFD) 演示

clear; close all; clc;

%% 1. 生成一个测试信号
fs = 1000;          % 采样率
T = 1;              % 信号时长
t = 0:1/fs:T-1/fs;  % 时间向量
N = length(t);

% 构造一个由多个频率成分组成的信号
f1 = 5;    f2 = 20;   f3 = 45;
component1 = 2 * sin(2*pi*f1*t);
component2 = 1 * sin(2*pi*f2*t + pi/4);
component3 = 0.5 * sin(2*pi*f3*t + pi/2);

signal = component1 + component2 + component3;
% 添加一些噪声
noise_level = 0.1;
signal = signal + noise_level * randn(1, N);

signal = signal'; % 转换为列向量

%% 2. 执行AFD分解
MaxIter = 20;          % 最大迭代次数
Threshold = 1e-6;      % 停止阈值

fprintf('开始AFD分解...\n');
[Coeffs, Basis, rm] = AFD_Core(signal, t, MaxIter, Threshold, true);

%% 3. 重构信号
reconstructed_signal = AFD_Reconstruct(Coeffs, Basis);

%% 4. 结果可视化
figure('Position', [100, 100, 1200, 800]);

% 4.1 绘制原始信号和重构信号
subplot(3, 2, [1, 2]);
plot(t, signal, 'b', 'LineWidth', 1.5, 'DisplayName', '原始信号');
hold on;
plot(t, reconstructed_signal, 'r--', 'LineWidth', 1.5, 'DisplayName', 'AFD重构');
title('原始信号 vs. AFD重构信号');
xlabel('时间 (s)');
ylabel('幅度');
legend('show');
grid on;

% 4.2 绘制分解系数(复数,显示幅度和相位)
subplot(3, 2, 3);
stem(1:length(Coeffs), abs(Coeffs), 'filled');
title('AFD系数幅度');
xlabel('分量索引');
ylabel('系数幅度');
grid on;

subplot(3, 2, 4);
stem(1:length(Coeffs), angle(Coeffs), 'filled');
title('AFD系数相位');
xlabel('分量索引');
ylabel('系数相位 (rad)');
grid on;

% 4.3 绘制前几个基函数的实部
subplot(3, 2, 5);
num_basis_to_plot = min(4, size(Basis, 2));
for i = 1:num_basis_to_plot
    plot(t, real(Basis(:, i)), 'DisplayName', ['基 ', num2str(i)]);
    hold on;
end
title('前几个基函数 (实部)');
xlabel('时间 (s)');
ylabel('幅度');
legend('show');
grid on;

% 4.4 绘制剩余信号能量衰减
subplot(3, 2, 6);
residual_energy = sum(rm.^2, 1); % 计算每次迭代的剩余能量
semilogy(1:length(residual_energy), residual_energy, 'o-', 'LineWidth', 1.5);
title('剩余信号能量衰减');
xlabel('迭代次数');
ylabel('能量 (对数尺度)');
grid on;

%% 5. 计算并显示误差
final_error = norm(signal - reconstructed_signal) / norm(signal);
fprintf('\nAFD分解完成。\n');
fprintf('使用的分量数量: %d\n', length(Coeffs));
fprintf('最终相对重构误差: %.4f%%\n', final_error * 100);

参考代码 AFD(自适应傅立叶变换)的matlab实现代码 www.youwenfan.com/contentalf/101061.html

运行演示:

只需在MATLAB命令窗口中运行 Demo_AFD。脚本将生成一个测试信号,对其进行分解,并绘制原始信号、重构信号、分解系数、基函数和能量衰减图。

这个实现是AFD的一个基础版本。对于更高级的应用(如2D-AFD用于图像处理),核心思想是相似的,但基函数和搜索过程需要扩展到更高维度。

相关文章
|
22天前
|
数据采集 人工智能 自然语言处理
爬虫是怎么工作的?从原理到用途
爬虫是自动采集网页数据的程序,像“探险家”遍历链接抓取信息,广泛用于搜索引擎、数据分析和网站迁移。但需遵守robots协议,尊重隐私与版权,规避法律风险。技术有边界,使用需合规,做有道德的“网页探险者”。
484 1
|
2月前
|
人工智能 运维 Kubernetes
Serverless 应用引擎 SAE:为传统应用托底,为 AI 创新加速
在容器技术持续演进与 AI 全面爆发的当下,企业既要稳健托管传统业务,又要高效落地 AI 创新,如何在复杂的基础设施与频繁的版本变化中保持敏捷、稳定与低成本,成了所有技术团队的共同挑战。阿里云 Serverless 应用引擎(SAE)正是为应对这一时代挑战而生的破局者,SAE 以“免运维、强稳定、极致降本”为核心,通过一站式的应用级托管能力,同时支撑传统应用与 AI 应用,让企业把更多精力投入到业务创新。
425 29
|
11天前
|
开发者 Python
别再粗暴打印了!用Python F-string解锁高效调试与日志
别再粗暴打印了!用Python F-string解锁高效调试与日志
172 122
|
11天前
|
开发者 Python
告别冗长:用Python的Walrus运算符为你的代码“减肥”
告别冗长:用Python的Walrus运算符为你的代码“减肥”
227 118
|
19天前
|
人工智能 安全 算法
数据共享又怕泄露?聊聊隐私计算:让数据“可用不可见”的绝活儿
数据共享又怕泄露?聊聊隐私计算:让数据“可用不可见”的绝活儿
255 15
|
19天前
|
安全 开发者 Docker
Docker
Docker以轻量级容器技术重塑软件开发,实现应用构建、交付与运行的一体化。它打破环境差异,提升资源利用率,推动微服务与云原生架构发展,构建高效CI/CD流水线,成为现代软件开发的核心基石。(238字)
|
12天前
|
数据采集 人工智能 监控
[数据集]作弊行为检测数据集(1100张图片已划分)[目标检测]
基于视觉 AI 的作弊行为检测正逐渐走向成熟,从简单的屏幕监控、人工复查逐步迈向自动化、实时化与精准识别。本数据集的构建,旨在为研究者与开发者提供一套轻量但高价值的训练数据,使智能监考系统能更好地识别作弊动作,尤其是使用手机等严重违规行为。
177 49
[数据集]作弊行为检测数据集(1100张图片已划分)[目标检测]
|
28天前
|
人工智能 并行计算 算法
为什么 OpenSearch 向量检索能提速 13 倍?
本文介绍在最新的 OpenSearch 实践中,引入 GPU 并行计算能力 与 NN-Descent 索引构建算法,成功将亿级数据规模下的向量索引构建速度提升至原来的 13 倍。
569 24
为什么 OpenSearch 向量检索能提速 13 倍?
|
17天前
|
机器学习/深度学习 人工智能 算法
PAIFuser:面向图像视频的训练推理加速框架
阿里云PAI推出PAIFuser框架,专为视频生成模型设计,通过模型并行、量化优化、稀疏运算等技术,显著提升DiT架构的训练与推理效率。实测显示,推理耗时最高降低82.96%,训练时间减少28.13%,助力高效低成本AI视频生成。
157 22

热门文章

最新文章