detrend去趋势函数的Matlab、Python与C实现

趋势分量对频域分析的影响

在对信号做频域分析时,如果有趋势项的存在,会对分析形成干扰。仿真一个有斜率的线性信号,仿真信号及其经过傅里叶转换后的频谱如下图(左图为时域图、右图为频域图)。由此可见斜坡信号中低频信号幅值较大,随着频率增加,幅值减小。
在这里插入图片描述
我们再来仿真一个线性信号与正弦信号的叠加信号。正弦信号周期为100s,幅值为0.2。该信号的时域图和频谱图如下图所示(左图为时域图、右图为频域图)。由于我们已知正弦信号的周期,因此这个信号应该在频率为0.01Hz处,如红圈标注所示。但是我们会发现红圈处的幅值并不是0.2,对比上图可知,这其实是由于线性信号在0.01Hz处也有一个分量,所以两个信号叠加之后,幅值比0.2大。
在这里插入图片描述
由上述示例可知,趋势项的存在会影响频谱分析,因此需要对信号或者数据去趋势。

detrend去趋势函数(Matlab、Python)

Maltab对该函数的官方介绍detrend, Remove polynomial trend。detrend函数通过设置参数,不仅可以移除线性趋势,也能移除多阶趋势。

下面是一个官方示例:

t = 0:20;
x = 3*sin(t) + t;
y = detrend(x);
plot(t,x,t,y,t,x-y,':k')
legend('Input Data','Detrended Data','Trend','Location','northwest') 

在这里插入图片描述
Python中也有这个函数,官方介绍scipy.signal.detrend,不过只能移除线性趋势。如果要移除多阶趋势,需要使用obspy.signal.detrend.polynomial

detrend的C语言实现

在博客 预处理丨去趋势(Matlab和C++)中提到了来自lppier 的C代码实现,不过这里的detrend函数目前只能移除线性趋势,代码如下。

/************************************************************************************
    Function    : void detrend_IP(T *y, T *x, int m)
    Description : Remove the linear trend of the input floating point data. Note that this
                  will initialize a work buffer inside the function. So if you are calling
                  this many, many times, create your work buffer in the calling scope and call
                  detrend(T *y, T*x, int m) instead to avoid initializing memory over and over
                  again.
    Inputs      : y - Floating point input data
                 m - Input data length
    Outputs     : y - Data with linear trend removed
    Copyright   : DSO National Laboratories
    History     : 01/02/2008, TCK, Adapted from HYC code
                  01/12/2008, TCK, Added in return value
                  25/01/2016, Pier, Changed into template type, removed need for work buffer
    *************************************************************************************/
template<typename T>
void Detrend::detrend_IP(T *y, int m)
{
    T xmean, ymean;
    int i;
    T temp;
    T Sxy;
    T Sxx;

    T grad;
    T yint;

    std::unique_ptr<T[]> x(new T[m]);

    /********************************
    Set the X axis Liner Values
    *********************************/
    for (i = 0; i < m; i++)
        x[i] = i;

    /********************************
    Calculate the mean of x and y
    *********************************/
    xmean = 0;
    ymean = 0;
    for (i = 0; i < m; i++)
    {
        xmean += x[i];
        ymean += y[i];
    }
    xmean /= m;
    ymean /= m;

    /********************************
    Calculate Covariance
    *********************************/
    temp = 0;
    for (i = 0; i < m; i++)
        temp += x[i] * y[i];
    Sxy = temp / m - xmean * ymean;

    temp = 0;
    for (i = 0; i < m; i++)
        temp += x[i] * x[i];
    Sxx = temp / m - xmean * xmean;

    /********************************
    Calculate Gradient and Y intercept
    *********************************/
    grad = Sxy / Sxx;
    yint = -grad * xmean + ymean;

    /********************************
    Removing Linear Trend
    *********************************/
    for (i = 0; i < m; i++)
        y[i] = y[i] - (grad * i + yint);
}

该段代码的实现原理实际使用了简单线性回归模型
趋势项模型如下:
在这里插入图片描述
优化的指标函数设置为残差的平方,残差越小,则找了效果最好的线性回归:
在这里插入图片描述
为了使残差最小,通过对b求偏导,使其导数为0,则:
在这里插入图片描述

对a求偏导,使其导数为0,则:

在这里插入图片描述
将公式对照代码,就可以知道斜率、截距参数是如何计算得到的。

### 轴承故障诊断中的电流信号预处理 在轴承故障诊断中,电流信号是一种常用的间接监测手段,尤其适用于无法直接获取振动信号的情况。为了提高后续特征提取和模式识别的效果,对原始电流信号进行有效的预处理是非常必要的。以下是几种常见的电流信号预处理方法和技术: #### 1. **滤波噪** 电流信号往往受到多种干扰源的影响,例如电磁干扰、电源波动等,这些噪声会掩盖真实的故障特征。因此,在分析之前需要除噪声成分。 - 使用低通滤波器保留低频分量,掉高频噪声[^2]。 - 利用小波变换或小波包分解技术分离出故障相关的频率范围内的信号[^3]。这种方法可以有效减少背景噪声的同时保持信号的主要特性不变。 ```matlab % MATLAB代码示例:使用小波包分解进行噪 load noisysignal; wp = wpdec(noisysignal, 3, 'sym4', 'shannon'); thr = wthrmngr('wpd','penalhi',wp); wden_wp = wdencmp('gbl',wp,'threshold',[],'s',thr); plot(wden_wp); % 显示噪后的信号 ``` #### 2. **趋势项消除** 长期记录的电流信号可能存在缓慢变化的趋势项(Trend),这会影响后续分析结果的真实性。可以通过多项式拟合法或者移动平均法移除这种趋势。 - 多项式拟合后减拟合曲线得到平稳化的序列。 ```python import numpy as np from scipy.signal import detrend # Python代码示例:除线性趋势 current_signal = np.random.rand(1000) + np.linspace(0, 5, 1000) detrended_signal = detrend(current_signal) plt.plot(detrended_signal) # 绘制趋势后的信号图 ``` #### 3. **标准化/归一化** 为了让不同条件下的测量数据具备可比性,通常会对电流幅值做标准化处理。这样不仅有助于提升机器学习模型训练过程中的数值稳定性,还能加快收敛速度。 - Z-score标准化使均值为零标准差为一时的数据分布[^4]; - Min-Max缩放则把所有样本映射到指定区间比如[0,1]之间。 ```python from sklearn.preprocessing import StandardScaler, MinMaxScaler scaler_std = StandardScaler() standardized_data = scaler_std.fit_transform(data.reshape(-1, 1)) scaler_minmax = MinMaxScaler(feature_range=(0, 1)) normalized_data = scaler_minmax.fit_transform(data.reshape(-1, 1)) ``` #### 4. **特征增强** 针对特定类型的故障设计专门的特征增强策略也是重要的一环。例如通过希尔伯特黄变换(HHT),经验模态分解(EMD)等方式突出隐藏在复杂信号背后的周期性和瞬变现象[^1]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值