VMD算法的MATLAB实现

%主程序

%--------------- Preparation

clear all;

close all;

clc;

% Time Domain 0 to T

T = 1000;

fs = 1/T;

t = (1:T)/T;

freqs = 2*pi*(t-0.5-1/T)/(fs);

% center frequencies of components

f_1 = 2;

f_2 = 24;

f_3 = 288;

% modes

v_1 = (cos(2*pi*f_1*t));

v_2 = 1/4*(cos(2*pi*f_2*t));

v_3 = 1/16*(cos(2*pi*f_3*t));

% for visualization purposes

wsub{1} = 2*pi*f_1;

wsub{2} = 2*pi*f_2;

wsub{3} = 2*pi*f_3;

% composite signal, including noise

f = v_1 + v_2 + v_3 + 0.1*randn(size(v_1));

% some sample parameters for VMD

alpha = 2000;        % moderate bandwidth constraint

tau = 0;            % noise-tolerance (no strict fidelity enforcement)

K = 4;              % 4 modes

DC = 0;             % no DC part imposed

init = 1;           % initialize omegas uniformly

tol = 1e-7;

 

%--------------- Run actual VMD code

[u, u_hat, omega] = VMD(f, alpha, tau, K, DC, init, tol);

subplot(size(u,1)+1,2,1);

plot(t,f,'k');grid on;

title('VMD分解');

subplot(size(u,1)+1,2,2);

plot(freqs,abs(fft(f)),'k');grid on;

title('对应频谱');

for i = 2:size(u,1)+1

    subplot(size(u,1)+1,2,i*2-1);

    plot(t,u(i-1,:),'k');grid on;

    subplot(size(u,1)+1,2,i*2);

    plot(freqs,abs(fft(u(i-1,:))),'k');grid on;

end

 

%---------------run EMD code

imf = emd(f);

figure;

subplot(size(imf,1)+1,2,1);

plot(t,f,'k');grid on;

title('EMD分解');

subplot(size(imf,1)+1,2,2);

plot(freqs,abs(fft(f)),'k');grid on;

title('对应频谱');

for i = 2:size(imf,1)+1

    subplot(size(imf,1)+1,2,i*2-1);

    plot(t,imf(i-1,:),'k');grid on;

    subplot(size(imf,1)+1,2,i*2);

    plot(freqs,abs(fft(imf(i-1,:))),'k');grid on;

end

 

 

 

%%%%函数部分

function [u, u_hat, omega] = VMD(signal, alpha, tau, K, DC, init, tol)

% Variational Mode Decomposition

% Authors: Konstantin Dragomiretskiy and Dominique Zosso

% [email protected] --- http://www.math.ucla.edu/~zosso

% Initial release 2013-12-12 (c) 2013

%

% Input and Parameters:

% ---------------------

% signal  - the time domain signal (1D) to be decomposed

% alpha   - the balancing parameter of the data-fidelity constraint

% tau     - time-step of the dual ascent ( pick 0 for noise-slack )

% K       - the number of modes to be recovered

% DC      - true if the first mode is put and kept at DC (0-freq)

% init    - 0 = all omegas start at 0

%                    1 = all omegas start uniformly distributed

%                    2 = all omegas initialized randomly

% tol     - tolerance of convergence criterion; typically around 1e-6

%

% Output:

% -------

% u       - the collection of decomposed modes

% u_hat   - spectra of the modes

% omega   - estimated mode center-frequencies

%

% When using this code, please do cite our paper:

% -----------------------------------------------

% K. Dragomiretskiy, D. Zosso, Variational Mode Decomposition, IEEE Trans.

% on Signal Processing (in press)

% please check here for update reference:

%          http://dx.doi.org/10.1109/TSP.2013.2288675

 

 

 

%---------- Preparations

 

% Period and sampling frequency of input signal

save_T = length(signal);

fs = 1/save_T;

 

% extend the signal by mirroring

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;

 

% Time Domain 0 to T (of mirrored signal)

T = length(f);

t = (1:T)/T;

 

% Spectral Domain discretization

freqs = t-0.5-1/T;

 

% Maximum number of iterations (if not converged yet, then it won't anyway)

N = 500;

 

% For future generalizations: individual alpha for each mode

Alpha = alpha*ones(1,K);

 

% Construct and center f_hat

f_hat = fftshift((fft(f)));

f_hat_plus = f_hat;

f_hat_plus(1:T/2) = 0;

 

% matrix keeping track of every iterant // could be discarded for mem

u_hat_plus = zeros(N, length(freqs), K);

 

% Initialization of omega_k

omega_plus = zeros(N, K);

switch init

    case 1

        for i = 1:K

            omega_plus(1,i) = (0.5/K)*(i-1);

        end

    case 2

        omega_plus(1,:) = sort(exp(log(fs) + (log(0.5)-log(fs))*rand(1,K)));

    otherwise

        omega_plus(1,:) = 0;

end

 

% if DC mode imposed, set its omega to 0

if DC

    omega_plus(1,1) = 0;

end

 

% start with empty dual variables

lambda_hat = zeros(N, length(freqs));

 

% other inits

uDiff = tol+eps% update step

n = 1; % loop counter

sum_uk = 0; % accumulator

 

 

 

% ----------- Main loop for iterative updates

 

 

 

 

while ( uDiff > tol &&  n < N ) % not converged and below iterations limit

     

    % update first mode accumulator

    k = 1;

    sum_uk = u_hat_plus(n,:,K) + sum_uk - u_hat_plus(n,:,1);

     

    % update spectrum of first mode through Wiener filter of residuals

    u_hat_plus(n+1,:,k) = (f_hat_plus - sum_uk - lambda_hat(n,:)/2)./(1+Alpha(1,k)*(freqs - omega_plus(n,k)).^2);

     

    % update first omega if not held at 0

    if ~DC

        omega_plus(n+1,k) = (freqs(T/2+1:T)*(abs(u_hat_plus(n+1, T/2+1:T, k)).^2)')/sum(abs(u_hat_plus(n+1,T/2+1:T,k)).^2);

    end

     

    % update of any other mode

    for k=2:K

         

        % accumulator

        sum_uk = u_hat_plus(n+1,:,k-1) + sum_uk - u_hat_plus(n,:,k);

         

        % mode spectrum

        u_hat_plus(n+1,:,k) = (f_hat_plus - sum_uk - lambda_hat(n,:)/2)./(1+Alpha(1,k)*(freqs - omega_plus(n,k)).^2);

         

        % center frequencies

        omega_plus(n+1,k) = (freqs(T/2+1:T)*(abs(u_hat_plus(n+1, T/2+1:T, k)).^2)')/sum(abs(u_hat_plus(n+1,T/2+1:T,k)).^2);

         

    end

     

    % Dual ascent

    lambda_hat(n+1,:) = lambda_hat(n,:) + tau*(sum(u_hat_plus(n+1,:,:),3) - f_hat_plus);

     

    % loop counter

    n = n+1;

     

    % converged yet?

    uDiff = eps;

    for i=1:K

        uDiff = uDiff + 1/T*(u_hat_plus(n,:,i)-u_hat_plus(n-1,:,i))*conj((u_hat_plus(n,:,i)-u_hat_plus(n-1,:,i)))';

    end

    uDiff = abs(uDiff);

     

end

 

 

%------ Postprocessing and cleanup

 

 

% discard empty space if converged early

N = min(N,n);

omega = omega_plus(1:N,:);

 

% Signal reconstruction

u_hat = zeros(T, K);

u_hat((T/2+1):T,:) = squeeze(u_hat_plus(N,(T/2+1):T,:));

u_hat((T/2+1):-1:2,:) = squeeze(conj(u_hat_plus(N,(T/2+1):T,:)));

u_hat(1,:) = conj(u_hat(end,:));

 

u = zeros(K,length(t));

 

for k = 1:K

    u(k,:)=real(ifft(ifftshift(u_hat(:,k))));

end

 

% remove mirror part

u = u(:,T/4+1:3*T/4);

 

% recompute spectrum

clear u_hat;

for k = 1:K

    u_hat(:,k)=fftshift(fft(u(k,:)))';

end

 

end

 

你可能感兴趣的:(VMD算法的MATLAB实现)