0
点赞
收藏
分享

微信扫一扫

使用VMD(Variational-Modal-Decomposition)分解多维信号

1.VMD分解原理

很多博客都说的比较好了

2.VMD源码

vrcarva/vmdpy: Variational mode decomposition (VMD) in Python (github.com)icon-default.png?t=M3K6https://github.com/vrcarva/vmdpyGitHub已经将matlab里的实现方法用Python写出来了

并且也已经有了大佬做解读

(10条消息) 变分模态分解(VMD)运算步骤及源码解读_comli_cn的博客-CSDN博客_变分模态分解icon-default.png?t=M3K6https://blog.csdn.net/comli_cn/article/details/110647039

3.源码的改进

来自

zhangzhaoweii/Variational-Modal-Decomposition-for-1D-and-nD-signal: Variational mode decomposition (VMD) for 1D and nD signal in Python (github.com)icon-default.png?t=M3K6https://github.com/zhangzhaoweii/Variational-Modal-Decomposition-for-1D-and-nD-signal

从源码里得知在初始化和计算迭代\lambda,\omega ,u的时候,预分配的矩阵都将迭代次数Niter加入到了计算矩阵的维度里,导致空间复杂度提高

omega_plus = np.zeros([Niter, K])
lambda_hat = np.zeros([Niter, len(freqs)], dtype = complex)
u_hat_plus = np.zeros([Niter, len(freqs), K],dtype=complex)   

因此考虑使用暂存矩阵的方法不断迭代交替,这样在预分配矩阵的时候就不需要考虑迭代次数这一维度

u_hat_plus_cur=np.zeros([f.shape[0], T, K],dtype=complex)  
lambda_hat_cur=np.zeros([f.shape[0], T], dtype = complex)
omega_plus_cur=np.zeros([f.shape[0], K])    

u_hat_plus_pre=copy.deepcopy(u_hat_plus)
lambda_hat_pre=copy.deepcopy(lambda_hat)
omega_plus_pre=copy.deepcopy(omega_plus)

u_hat_plus=copy.deepcopy(u_hat_plus_cur)
lambda_hat=copy.deepcopy(lambda_hat_cur)
omega_plus=copy.deepcopy(omega_plus_cur)
import numpy as np
import copy
import scipy.fftpack as fftpack
#f中的行向量为一维信号
def VMD_for_1D_signal(f,alpha,tau,K,tol,Niter):
    ltemp = len(f)//2 
    fs=1./len(f)
    fMirr =  np.append(np.flip(f[:ltemp],axis = 0),f)  
    fMirr = np.append(fMirr,np.flip(f[-ltemp:],axis = 0))
    T = len(fMirr)
    t = np.arange(1,T+1)/T  
    freqs = t-0.5-(1/T)
    f_hat=np.zeros([1, K])
    f_hat = fftpack.fftshift((fftpack.fft(fMirr)))
    #对fMirr进行快速傅立叶变换,然后将变换后的直流分量移到频谱中央
    f_hat_plus = np.copy(f_hat)
    f_hat_plus[:T//2] = 0
    omega_plus = np.zeros([1, K])
    lambda_hat = np.zeros([1, T], dtype = complex)
    uDiff = tol+np.spacing(1) 
    n = 0 
    sum_uk = 0
    u_hat_plus = np.zeros([1, T, K],dtype=complex)  
    u_hat_plus_cur=np.zeros([1, T, K],dtype=complex)  
    lambda_hat_cur=np.zeros([1, T], dtype = complex)
    omega_plus_cur=np.zeros([1, K])
    #预分配矩阵空间,抛弃迭代维数    
    while ( uDiff > tol and  n < Niter-1 ): # not converged and below iterations limit
        k = 0
        sum_uk = u_hat_plus[:,:,K-1] + sum_uk - u_hat_plus[:,:,0]
        a=(f_hat_plus - sum_uk - lambda_hat[:]/2)
        b=(1.+alpha*(freqs - omega_plus[:,k])**2)
        u_hat_plus_cur[:,:,k]= a/b
        # 通过残差的维纳滤波器更新第一模态的频谱
        c1=abs(u_hat_plus_cur[:,T//2:T,k])**2
        d1=freqs[T//2:T]
        e1=np.dot(c1,d1.T)
        f1=np.sum(abs(u_hat_plus_cur[:,T//2:T,k])**2)
        omega_plus_cur[:,k] = e1/f1
        #更新第一个omega
        for k in np.arange(1,K):
            sum_uk = u_hat_plus_cur[:,:,k-1] + sum_uk - u_hat_plus[:,:,k]
            u_hat_plus_cur[:,:,k] = (f_hat_plus - sum_uk - lambda_hat[:]/2)/(1+alpha* 
             (freqs - omega_plus[:,k])**2)
            c2=abs(u_hat_plus_cur[:,T//2:T,k])**2
            d2=freqs[T//2:T]
            e2=np.dot(c2,d2.T)
            f2=np.sum(abs(u_hat_plus_cur[:,T//2:T,k])**2)
            omega_plus_cur[:,k] = e2/f2
        #更新k个模态的频谱和频率
        lambda_hat_cur[:,:] = lambda_hat[:,:] + tau*(np.sum(u_hat_plus_cur[:,:,:],axis = 
        2) - f_hat_plus)
        uDiff = np.spacing(1)
        for i in range(K):
            uDiff = uDiff + (1/T)*np.dot((u_hat_plus_cur[:,:,i]- 
        u_hat_plus[:,:,i]),np.transpose(np.conj((u_hat_plus_cur[:,:,i]- 
        u_hat_plus[:,:,i]))))

        uDiff = np.abs(uDiff)   
        #n=n+1
        u_hat_plus_pre=copy.deepcopy(u_hat_plus)
        lambda_hat_pre=copy.deepcopy(lambda_hat)
        omega_plus_pre=copy.deepcopy(omega_plus)
        u_hat_plus=copy.deepcopy(u_hat_plus_cur)
        lambda_hat=copy.deepcopy(lambda_hat_cur)
        omega_plus=copy.deepcopy(omega_plus_cur)
        n=n+1
        #矩阵暂存迭代,节省空间,注意区分需要的矩阵
    omega = omega_plus_pre
    idxs = np.flip(np.arange(1,T//2+1),axis = 0)
    u_hat = np.zeros([1, T, K],dtype=complex)
    u_hat[:,T//2:T,:] = u_hat_plus_pre[:,T//2:T,:]
    u_hat[:,idxs,:] = np.conj(u_hat_plus_pre[:,T//2:T,:])
    u_hat[:,0,:] = np.conj(u_hat_plus_pre[:,-1,:])   
    u = np.zeros([1,K,T])
    for k in range(K):
        u[:,k,:] = np.real(np.fft.ifft(np.fft.ifftshift(u_hat[:,:,k])))
    u = u[:,:,T//4:3*T//4]
    u_hat = np.zeros([f.shape[0],u.shape[2], K],dtype=complex)
    for k in range(K):
        u_hat[:,:,k] = fftpack.fftshift(fftpack.fft(u[:,k,:]), axes=(1,))
    #后处理与信号还原
    return u, u_hat, omega

同样地,利用这个思想,设计计算多维信号的方法,每个一维信号作为矩阵的一组


import numpy as np
import copy
import scipy.fftpack as fftpack
#f中的每一行为一维信号
def VMD_for_nD_signal(f,alpha,tau,K,tol,Niter):
    ltemp = f.shape[1]//2 
    fs=1./f.shape[1]
    fMirr1=np.flip(f[:,ltemp:],1)
    fMirr2=np.flip(f[:,:ltemp],1)
    fMirr =np.concatenate((fMirr2,f),axis=1) 
    fMirr =np.concatenate((fMirr,fMirr1),axis=1) 
    T=fMirr.shape[1]
    t1 = np.arange(1,T+1)/T  
    t=np.tile(t1,(f.shape[0],1))
    freqs = t-0.5-(1/T)
    f_hat=np.zeros([f.shape[0], K])
    f_hat= fftpack.fftshift((fftpack.fft(fMirr)), axes=(1,))
    f_hat_plus = np.copy(f_hat) #copy f_hat
    f_hat_plus[:,:T//2] = 0
    omega_plus = np.zeros([f.shape[0], K])
    lambda_hat = np.zeros([f.shape[0], T], dtype = complex)
    lambda_hat_temp=copy.deepcopy(lambda_hat)
    uDiff = tol+np.spacing(1)
    uDiff_max=uDiff
    n = 0 
    sum_uk = 0
    u_hat_plus = np.zeros([f.shape[0], T, K],dtype=complex)  
    u_hat_plus_cur=np.zeros([f.shape[0], T, K],dtype=complex)  
    lambda_hat_cur=np.zeros([f.shape[0], T], dtype = complex)
    omega_plus_cur=np.zeros([f.shape[0], K])    
    #预分配矩阵空间,抛弃迭代维数,需要 f.shape[0]组   
    while ( uDiff_max > tol and  n < Niter-1 ):
        k = 0
        sum_uk = u_hat_plus[:,:,K-1] + sum_uk - u_hat_plus[:,:,0]
        a=(f_hat_plus - sum_uk - lambda_hat[:]/2)
        b=(1.+alpha*(freqs - np.tile(omega_plus[:,k].reshape(f.shape[0],1),(1,T)))**2)
        u_hat_plus_cur[:,:,k]= a/b
        c1=abs(u_hat_plus_cur[:,T//2:T,k])**2
        d1=freqs[:,T//2:T]
        e1=np.diagonal(np.dot(c1,d1.T))
        f1=np.sum(abs(u_hat_plus_cur[:,T//2:T,k])**2,1)
        omega_plus_cur[:,k] = e1/f1
        for k in np.arange(1,K):
            sum_uk = u_hat_plus_cur[:,:,k-1] + sum_uk - u_hat_plus[:,:,k]
            a=(f_hat_plus - sum_uk - lambda_hat[:]/2)
            b=(1.+alpha*(freqs - np.tile(omega_plus[:,k].reshape(f.shape[0],1),(1,T)))**2)
            u_hat_plus_cur[:,:,k]= a/b
            c2=abs(u_hat_plus_cur[:,T//2:T,k])**2
            d2=freqs[:,T//2:T]
            e2=np.diagonal(np.dot(c2,d2.T))
            f2=np.sum(abs(u_hat_plus_cur[:,T//2:T,k])**2,1)
            omega_plus_cur[:,k] = e2/f2
        lambda_hat_cur[:,:] = lambda_hat[:,:] + tau*(np.sum(u_hat_plus_cur[:,:,:],axis = 2) - f_hat_plus)
        uDiff = np.spacing(1)
        for i in range(K):
            uDiff = uDiff + (1/T)*np.dot((u_hat_plus_cur[:,:,i]-u_hat_plus[:,:,i]),np.transpose(np.conj((u_hat_plus_cur[:,:,i]-u_hat_plus[:,:,i]))))
        uDiff = np.abs(uDiff)   
        uDiff_max=max(np.diagonal(uDiff))
        u_hat_plus_pre=copy.deepcopy(u_hat_plus)
        lambda_hat_pre=copy.deepcopy(lambda_hat)
        omega_plus_pre=copy.deepcopy(omega_plus)
        u_hat_plus=copy.deepcopy(u_hat_plus_cur)
        lambda_hat=copy.deepcopy(lambda_hat_cur)
        omega_plus=copy.deepcopy(omega_plus_cur)
        n=n+1        
    omega = omega_plus_pre
    idxs = np.flip(np.arange(1,T//2+1),axis = 0)
    u_hat = np.zeros([f.shape[0], T, K],dtype=complex)
    u_hat[:,T//2:T,:] = u_hat_plus_pre[:,T//2:T,:]
    u_hat[:,idxs,:] = np.conj(u_hat_plus_pre[:,T//2:T,:])
    u_hat[:,0,:] = np.conj(u_hat_plus_pre[:,-1,:])   
    u = np.zeros([f.shape[0],K,T])
    for k in range(K):
        u[:,k,:] = np.real(fftpack.ifft(fftpack.ifftshift(u_hat[:,:,k], axes=(1,))))
    u = u[:,:,T//4:3*T//4]
    u_hat = np.zeros([f.shape[0],u.shape[2], K],dtype=complex)
    for k in range(K):
        u_hat[:,:,k] = fftpack.fftshift(fftpack.fft(u[:,k,:]), axes=(1,))
    return u, u_hat, omega

对于需要一次性计算的多组信号数据,将每一组作为矩阵f的行向量

举报

相关推荐

0 条评论