• 数字信号处理-8-自相关


    1 皮尔森相关系数

    假设 x 和 y 均为 N 个样本的数组,皮尔森公式如下:
    在这里插入图片描述
    皮尔森相关系数总是在 -1 到 +1 之间(包含这两个字)。ρ 的绝对值意味着相关性的强度。ρ 接近 +1 表示强正相关;ρ 接近 -1 表示强负相关,即随着一个值的增大另一个值减小。

    如计算两个相位差为 1 的 sin 函数的相关性,从图形中可以看出两者具有相关性,一个升高,另一个也升高:
    在这里插入图片描述
    皮尔森相关系数矩阵如下,两者相关性为 0.52
    在这里插入图片描述
    皮尔森相关性计算代码:

    # jupyter notebook 中运行
    # 导入需要的包
    import numpy as np
    from matplotlib import pyplot as plt
    import math
    
    # 常数值 2π
    # jupyter notebook 中运行
    # 导入需要的包
    import numpy as np
    from matplotlib import pyplot as plt
    import math
    
    # 常数值 2π
    PI2 = math.pi * 2
    #采样率
    framerate = 11025
    # 采样时长:秒
    duration = 0.01
    
    def make_ys(amp=1, f=440, offset=0):
        """
        amp:振幅
        f:频率
        offset:相位偏移
        
        """
        # 样本数
        n = round(duration * framerate)
        # 采样时间点
        ts = np.arange(n) / framerate
        ys = amp * np.sin(PI2*f*ts + offset)
        return ys
    
    wave1 = make_ys(offset=0)
    wave2 = make_ys(offset=1)
    # ddof=0 表示corrcoef 应该除以 N,而不是默认的 N-1
    corr_matrix = np.corrcoef(ys1, ys2, ddof=0)
    corr_matrix
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    2 序列相关

    信号代表的是随时间变化的数值的度量。比如声音信号代表的是对电压的度量,对应于空气压力的变化,也即我们所感知到的声音。

    这样的信号前后序列之间是相关的,为计算序列相关性,我们可以平移信号,然后计算平移之后的信号与原始信号之间的相关性。

    # 上一节函数,产生序列
    wave1 = make_ys(offset=0)
    # 计算自相关
    def serial_corr(wave, lag=1):
        # 序列长度
        n = len(wave)
        y1 = wave[lag:]
        y2 = wave[:n-lag]
        # 相关系数值
        corr = np.corrcoef(y1, y2, ddof=0)[0,1]
        return corr
    serial_corr(wave1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    结果为 0.969655978695559

    3 自相关

    上一节只计算了 lag=1 的相关性,实际上可以设 lag 为不同值,从而得到一个不同 lag 对应的相关性值序列。

    def autocorr(wave):
    	# 最大 lag 为波形长度的一半,因为超过一半的话前后序列就不相交了
        lags = range(len(wave)//2)
        corrs = [serial_corr(wave, lag) for lag in lags]
        return lags, corrs
    lags, corrs = autocorr(wave1)
    plt.plot(lags, corrs)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    lags 是一串从 0 到半个波形长的整数序列,corrs 是对应各个 lag 的序列相关性值的数组。
    在这里插入图片描述

    因为 sin 函数是周期函数,所以间隔一定 lag 之后,它的波形与原始波形又变为相同,相关性为 1。

    据此在一段任意的波形中,通过计算序列自相关性找到最大的自相关位置,该位置我们就可以认为是此波形的周期

    3.1 通过自相关计算频率

    如上图所示,自相关最大的第一个 lag 位置为 0(排除),随后 lag 滞后 25 相关性变最大,因此该点即为周期点。滞后 25 个样本之后波形变得重复,采样率为 11025,25个样本对应时间为 25/11025 秒,因此周期为 25/11025 秒。频率为周期的倒数,所以频率为 441Hz=11025/25。非常接近与我们设定的 440Hz。

    3.2 Numpy 计算自相关

    NumPy 提供了一个函数 correlate 来计算两个函数之间的相关性或者一个函数的自相关。

    # mode='same' 对应的时滞范围为 -N/2 到 N/2,N为波形数组长度
    corrs2 = np.correlate(wave1,wave1,mode='same')
    N = len(corrs2)
    x = range(-N//2, N//2, 1)
    plt.plot(x, corrs2)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    结果是对称的,这是因为针对同一个信号,一个信号的负时滞和对另一个结果的正时滞是一样的,所以取一半即可

    # 时滞取一半,后一半
    N = len(corrs2)
    half = corrs2[N//2:]
    # np.correlate 计算相关时,并没有除序列长度,可以通过除序列长度纠正
    lengths = range(N, N//2, -1)
    half /= lengths
    # 结果归一化,这样 lag=0 时的相关性为 1
    half /= half[0]
    plt.plot(half)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    与之前定义的函数结果相同 autocorr(wave)
    在这里插入图片描述

    参考

    漫画傅里叶解析
    Python数字信号处理应用

  • 相关阅读:
    HarmonyOS/OpenHarmony原生应用开发-华为Serverless认证服务说明(二)
    java之冒泡排序和选择排序和直接插入排序原理
    模型预测控制(Model predictive control,MPC)
    【C++】map和set
    c#基础逻辑练习案例
    国庆作业day6
    Ubuntu23.10将推出全磁盘加密功能,提高系统安全性
    Promise从入门到精通(第4章 async 和 await)
    vue3 v-md-editor markdown编辑器(VMdEditor)和预览组件(VMdPreview )的使用
    C++ 环境变量 二
  • 原文地址:https://blog.csdn.net/weixin_40994552/article/details/127996802