Почему NUMPY коррелят и corrcoef возвращают разные значения и как «нормализовать» коррелят в «полном» режиме? - PullRequest
18 голосов
/ 12 апреля 2011

Я пытаюсь использовать анализ временных рядов в Python, используя Numpy.

У меня есть две серии несколько средних размеров, каждая из которых содержит 20 тыс. Значений, и я хочу проверить скользящую корреляцию.

Corrcoef дает мне в качестве вывода Матрицу автокорреляции / коэффициентов корреляции. Само по себе ничего полезного в моем случае нет, так как одна из серий содержит задержку.

Функция корреляции (in mode = "full") возвращает список из 40 тыс. Элементов, который действительно выглядит как результат, к которому я стремлюсь (пиковое значение находится так же далеко от центра списка, как и задержка) ), но значения все странные - до 500, когда я ожидал что-то от -1 до 1.

Я не могу просто разделить все на максимальное значение; Я знаю, что максимальная корреляция не равна 1.

Как можно нормализовать "взаимную корреляцию" (корреляцию в "полном" режиме), чтобы возвращаемые значения были корреляцией на каждом шаге запаздывания вместо этих очень больших, странных значений?

Ответы [ 2 ]

27 голосов
/ 12 апреля 2011

Вы ищете нормализованную взаимную корреляцию. Эта опция еще не доступна в Numpy, но патч ожидает проверки, которая делает именно то, что вы хотите. Это не должно быть слишком трудно применить это, я думаю. Большая часть патча - просто строковая документация. Единственные строки кода, которые он добавляет, это

if normalize:
    a = (a - mean(a)) / (std(a) * len(a))
    v = (v - mean(v)) /  std(v)

где a и v - введенные массивы, для которых вы находите взаимную корреляцию. Нетрудно добавить их в свой собственный дистрибутив Numpy или просто скопировать функцию корреляции и добавить туда строки. Я бы сделал последнее лично, если бы выбрал этот путь.

Другая, возможно, лучшая альтернатива - просто выполнить нормализацию для входных векторов, прежде чем отправлять их для корреляции. Вам решать, каким образом вы хотели бы это сделать.

Кстати, похоже, это правильная нормализация согласно странице Википедии о взаимной корреляции за исключением деления на len(a), а не (len(a)-1). Я чувствую, что расхождение похоже на стандартное отклонение выборки против стандартного отклонения выборки и, на мой взгляд, не будет иметь большого значения.

0 голосов
/ 22 января 2018

Согласно этому слайду , я бы предложил сделать это следующим образом:

def cross_correlation(a1, a2):
        lags = range(-len(a1)+1, len(a2))
        cs = []
        for lag in lags:
            idx_lower_a1 = max(lag, 0)
            idx_lower_a2 = max(-lag, 0)
            idx_upper_a1 = min(len(a1), len(a1)+lag)
            idx_upper_a2 = min(len(a2), len(a2)-lag)
            b1 = a1[idx_lower_a1:idx_upper_a1]
            b2 = a2[idx_lower_a2:idx_upper_a2]
            c = np.correlate(b1, b2)[0]
            c = c / np.sqrt((b1**2).sum() * (b2**2).sum())
            cs.append(c)
        return cs
...