Основы нормализации взаимной корреляции с целью сравнения сигналов - PullRequest
0 голосов
/ 21 января 2019

Я пытаюсь понять, как используется взаимная корреляция, чтобы определить сходство двух сигналов. Этот урок предлагает очень четкое объяснение основ, но я до сих пор не понимаю, как эффективно использовать нормализацию, чтобы не допустить доминирования сильных сигналов в измерении взаимной корреляции, когда у вас есть сигналы с различными уровнями энергии.Тот же наставник, Дэвид Дорран, обсуждает вопрос нормализации здесь и объясняет, как нормализовать корреляцию с помощью точечного произведения, но у меня все еще есть некоторые вопросы.

Я написал эту подпрограмму Python для перекрестной корреляции между каждой парой сигналов из группы сигналов:

import numpy as np
import pandas as pd

def mycorrelate2d(df, normalized=False):
    # initialize cross correlation matrix with zeros
    ccm = np.zeros(shape=df.shape, dtype=list)
    for i, row_dict1 in enumerate(
                        df.to_dict(orient='records')):
        outer_row = list(row_dict1.values())    
        for j, row_dict2 in enumerate(
                            df.to_dict(orient='records')):
            inner_row = list(row_dict2.values())   
            x = np.correlate(inner_row, outer_row)
            if normalized:
                n = np.dot(inner_row, outer_row)                
                x = x / n
            ccm[i][j] = x
    return ccm

Предположим, у меня есть 3 сигнала возрастающей величины: [1, 2,3], [4, 5, 6] и [7, 8, 9]

Я хочу взаимно коррелировать эти три сигнала, чтобы увидеть, какие пары похожи, но когда я передаю эти 3 сигнала в процедуруЯ написал, я не получаю меру сходства.Размер значений взаимной корреляции является просто функцией энергетического сигнала.Период.Даже взаимная корреляция сигнала с самим собой дает более низкие значения, чем взаимная корреляция этого же сигнала с другим сигналом более высокой энергии.

df_x3 = pd.DataFrame(
        np.array([[1, 2, 3], 
                  [4, 5, 6], 
                  [7, 8, 9]]).reshape(3, -1))
mycorrelate2d(df_x3)

Это дает:

array([[array([ 3,  8, 14,  8,  3]), 
        array([12, 23, 32, 17,  6]),
        array([21, 38, 50, 26,  9])],
       [array([ 6, 17, 32, 23, 12]), 
        array([24, 50, 77, 50, 24]),
        array([ 42,  83, 122,  77,  36])],
       [array([ 9, 26, 50, 38, 21]), 
        array([ 36,  77, 122,  83,  42]),
        array([ 63, 128, 194, 128,  63])]], dtype=object)

Теперь я передаю те же 3 сигнала, но на этот раз я указываю, что хочу получить нормализованные результаты:

mycorrelate2d(df_x3, normalized=True)

Это дает:

array([[array([ 0.2142, 0.5714,  1., 0.5714, 0.2142]),
        array([ 0.375,  0.71875, 1., 0.5312, 0.1875]),
        array([ 0.42,   0.76,    1., 0.52,   0.18])],
       [array([ 0.1875, 0.5312,  1., 0.7187, 0.375]),
        array([ 0.3116, 0.6493,  1., 0.6493, 0.3116]),
        array([ 0.3442, 0.6803,  1., 0.6311, 0.2950])],
       [array([ 0.18,   0.52,    1., 0.76,   0.42]),
        array([ 0.2950, 0.6311,  1., 0.6803, 0.3442]),
        array([ 0.3247, 0.6597,  1., 0.6597, 0.3247])]],
        dtype=object)

Все максимальные значения теперь равны 1 !!Таким образом, мы перешли от максимального значения, основанного на ложных различиях, к отсутствию разницы между максимальными значениями!Я с готовностью признаю, что не понимаю, как взаимная корреляция используется для обнаружения сходства между сигналами.Каков аналитический рабочий процесс того, кто сравнивает сигналы с взаимной корреляцией?

1 Ответ

0 голосов
/ 21 января 2019

Взгляните на Вычислить нормализованную взаимную корреляцию в Python

Так что формула, которую вы используете для нормализации, не совсем верна.Нормализация происходит до того, как мы коррелируем в NCC, а затем мы делим ответ на длину вектора, как показано в этой формуле Википедии https://en.wikipedia.org/wiki/Cross-correlation#Zero-normalized_cross-correlation_(ZNCC)

Так что вам нужно что-то вроде

import numpy as np


def mycorrelate2d(df, normalized=False):
    # initialize cross correlation matrix with zeros
    ccm = np.zeros((3,3))
    for i in range(3):
        outer_row = df[i][:]
        for j in range(3):
            inner_row = df[j][:]
            if(not normalized):
                x = np.correlate(inner_row, outer_row)
            else:
                a = (inner_row-np.mean(inner_row))/(np.std(inner_row)*len(inner_row))
                #print(a)
                b = (outer_row-np.mean(outer_row))/(np.std(outer_row))
                #print(b)
                x = np.correlate(a,b)
            ccm[i][j] = x
    return ccm

df_x3 =np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]]).reshape(3, -1)
print(mycorrelate2d(df_x3,True))
df_x3 =np.array([[1, 2, 3],
                  [9, 5, 6],
                  [74, 8, 9]]).reshape(3, -1)
print(mycorrelate2d(df_x3,True))

Выходные данные

[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
[[ 1.         -0.72057669 -0.85933941]
 [-0.72057669  1.          0.97381599]
 [-0.85933941  0.97381599  1.        ]]
...