当前位置: 首页 > news >正文

VMD例程(Matlab 2021b可直接使用)

VMD已是该领域大家熟知的算法了,各种教程与解析已经铺天盖地了,本文仅给出算法供大家调用验证,不进行解析。

function [u, u_hat, omega] = VMD(signal, fs, alpha, tau, K, DC, init, tol)
% Variational Mode Decomposition (Modified Version)
% Authors: Konstantin Dragomiretskiy and Dominique Zosso
% Modified by: [Your Name/Organization], [Date]
% 
% Input Parameters:
% -----------------
% signal  - 输入信号 (1D 时域信号)
% fs      - 采样频率 (Hz) [添加实际采样频率]
% alpha   - 数据保真度约束的平衡参数
% tau     - 对偶上升的时间步长 (噪声容限,取0表示无松弛)
% K       - 要恢复的模态数量
% DC      - 是否将第一模态设为直流分量 (true/false)
% init    - 中心频率初始化方式:
%           0 = 全部从0开始
%           1 = 均匀分布初始化
%           2 = 随机初始化
% tol     - 收敛容差 (推荐 1e-6)
%
% Output:
% -------
% u       - 分解后的模态集合 (K x 信号长度)
% u_hat   - 模态的频谱 (信号长度 x K)
% omega   - 估计的模态中心频率 (Hz) [输出实际频率]
%
% 参考文献:
% K. Dragomiretskiy, D. Zosso, Variational Mode Decomposition, 
% IEEE Trans. on Signal Processing, 62(3):531-544, 2014
% DOI: 10.1109/TSP.2013.2288675% ---------- 准备工作 ----------
save_T = length(signal);  % 原始信号长度
T = save_T;               % 当前信号长度% 通过镜像延拓处理边界效应
f_mirror(1:T/2) = signal(T/2:-1:1);
f_mirror(T/2+1:3*T/2) = signal;
f_mirror(3*T/2+1:2*T) = signal(T:-1:T/2+1);
f = f_mirror;% 延拓后的时间域 (0 到 T)
T = length(f);
t = (1:T)/T;% 频谱域离散化 (归一化频率 -0.5 到 0.5)
freqs_norm = t - 0.5 - 1/T;% 最大迭代次数
N = 500;% 为每个模态设置alpha参数
Alpha = alpha * ones(1, K);% FFT计算及中心化处理
f_hat = fftshift(fft(f));
f_hat_plus = f_hat;
f_hat_plus(1:T/2) = 0;  % 仅保留正频率部分% 预分配存储空间 (优化:只存储当前和上一次迭代)
u_hat_plus = zeros(2, length(freqs_norm), K); % 改为循环缓冲区
lambda_hat = zeros(2, length(freqs_norm));     % 对偶变量存储% 中心频率初始化
omega_plus = zeros(2, K); % [当前, 上一次]
switch initcase 1  % 均匀分布for i = 1:Komega_plus(1, i) = (0.5/K) * (i-1);endcase 2  % 随机初始化 (使用实际频率范围)omega_plus(1, :) = sort(rand(1, K) * (fs/2)); % 使用实际频率otherwise  % 全零初始化omega_plus(1, :) = 0;
end% 如果要求DC模式,强制第一个中心频率为0
if DComega_plus(1, 1) = 0;
end% 迭代控制变量
uDiff = tol + eps;  % 更新步长
n = 1;             % 迭代计数器
sum_uk = 0;        % 累加器% ---------- 主迭代循环 ----------
while (uDiff > tol && n < N)% 使用循环缓冲区索引 (1=当前, 2=上一次)curr = mod(n-1, 2) + 1;next = mod(n, 2) + 1;% 更新第一个模态k = 1;sum_uk = u_hat_plus(curr, :, K) + sum_uk - u_hat_plus(curr, :, 1);% 通过维纳滤波器更新模态频谱u_hat_plus(next, :, k) = (f_hat_plus - sum_uk - lambda_hat(curr, :)/2) ./ ...(1 + Alpha(k) * (freqs_norm - omega_plus(curr, k)).^2);% 更新中心频率 (非DC模式)if ~DCidx = (T/2+1):T;  % 正频率索引spec = abs(u_hat_plus(next, idx, k)).^2;omega_plus(next, k) = sum(freqs_norm(idx) .* spec) / sum(spec);elseomega_plus(next, k) = omega_plus(curr, k);end% 更新其他模态for k = 2:Ksum_uk = u_hat_plus(next, :, k-1) + sum_uk - u_hat_plus(curr, :, k);% 模态频谱更新u_hat_plus(next, :, k) = (f_hat_plus - sum_uk - lambda_hat(curr, :)/2) ./ ...(1 + Alpha(k) * (freqs_norm - omega_plus(curr, k)).^2);% 中心频率更新idx = (T/2+1):T;spec = abs(u_hat_plus(next, idx, k)).^2;omega_plus(next, k) = sum(freqs_norm(idx) .* spec) / sum(spec);end% 对偶上升 (更新拉格朗日乘子)lambda_hat(next, :) = lambda_hat(curr, :) + ...tau * (sum(u_hat_plus(next, :, :), 3) - f_hat_plus);% 计算收敛条件uDiff = 0;for k = 1:Kdiff_spec = u_hat_plus(next, :, k) - u_hat_plus(curr, :, k);uDiff = uDiff + (1/T) * (diff_spec * diff_spec');enduDiff = abs(uDiff);% 迭代计数器更新n = n + 1;
end% ---------- 后处理 ----------
% 最终迭代索引
final_idx = mod(n-1, 2) + 1;% 信号重构
u_hat = zeros(T, K);
u_hat((T/2+1):T, :) = squeeze(u_hat_plus(final_idx, (T/2+1):T, :));
u_hat((T/2+1):-1:2, :) = conj(squeeze(u_hat_plus(final_idx, (T/2+1):T, :)));
u_hat(1, :) = conj(u_hat(end, :));% 时域模态重建
u = zeros(K, T);
for k = 1:Ku(k, :) = real(ifft(ifftshift(u_hat(:, k).')));
end% 移除镜像部分
u = u(:, T/4+1:3*T/4);% 重新计算实际长度信号的频谱
u_hat = zeros(save_T, K);
for k = 1:Ku_hat(:, k) = fftshift(fft(u(k, :))).';
end% 转换中心频率到实际频率 (Hz) [关键修复]
omega = omega_plus(final_idx, :) * fs;end

测试:

% 生成测试信号
fs = 1000;          % 采样频率 1000 Hz
t = 0:1/fs:1-1/fs;  % 1秒时长
f1 = 50;            % 50Hz分量
f2 = 120;           % 120Hz分量
signal = sin(2*pi*f1*t) + 0.5*cos(2*pi*f2*t);% 设置VMD参数
alpha = 2000;       % 平衡参数
tau = 0;            % 无噪声松弛
K = 5;              % 分解2个模态
DC = false;         % 无直流分量
init = 1;           % 均匀初始化
tol = 1e-6;         % 收敛容差% 执行VMD分解
[u, u_hat, omega] = VMD(signal, fs, alpha, tau, K, DC, init, tol);% 显示结果
disp('估计的中心频率 (Hz):');
disp(omega);% 绘制结果
figure;
subplot(K+1, 1, 1);
plot(t, signal);
title('原始信号');for k = 1:Ksubplot(K+1, 1, k+1);plot(t, u(k, :));title(sprintf('模态 %d: %.1f Hz', k, omega(k)));
end

可视化:

http://www.dtcms.com/a/326692.html

相关文章:

  • 从“目标烂尾”到“100%交付”:谷歌OKR追踪系统如何用“透明化+强问责”打造职场责任闭环
  • 小白入门指南:Edge SCDN 轻松上手
  • Dify 从入门到精通(第 28/100 篇):Dify 的多租户架构
  • 【学习嵌入式day-21-Linux编程-shell命令】
  • 第九篇:调试工具:Three.js Inspector使用
  • 武汉火影数字|VR大空间是什么?如何打造VR大空间项目
  • 【华为机试】648. 单词替换
  • SciChart图形库应用
  • 专题:2025人形机器人与服务机器人技术及市场报告|附130+份报告PDF汇总下载
  • TCGA数据集下载工具gdc-client下载慢解决方案
  • mysql参数调优之 innodb_buffer_pool_size和innodb_buffer_pool_instances (三)
  • Java AI生成长篇小说的实用
  • VirtualBox虚拟机网卡配置
  • NR,LTE基于CSI的PMI-RI码本选择
  • 【算法训练营Day23】贪心算法part1
  • nginx高新能web服务器
  • UVM验证—UVM 简述
  • 从0-1搭建webpack的前端工程化项目
  • MySQL杂项
  • OpenBMC中phosphor-dbus-interfaces深度解析:架构、原理与应用实践
  • 安装AI高性能推理框架llama.cpp
  • Untiy_SpriteShape
  • VSCode编辑器常用24款基础插件
  • QT QVersionNumber 比较版本号大小
  • 自主泊车算法
  • OFD一键转PDF格式,支持批量转换!
  • 客户端连接redis,redis如何配置
  • 钓鱼鱼饵制作的方式(红队)
  • 定义短的魔术数字时小心负数的整型提升
  • AIStarter修复macOS 15兼容问题:跨平台AI项目管理新体验