Почему NUMPY коррелирует и corrcoef возвращает разные значения и как "нормализовать" коррелятор в "полном" режиме?
Я пытаюсь использовать некоторый анализ временных рядов на Python, используя Numpy.
У меня две серии среднего размера, каждая из которых содержит 20 тыс., и я хочу проверить скользящую корреляцию.
Corrcoef дает мне в качестве вывода матрицу коэффициентов автокорреляции/корреляции. Ничего полезного в моем случае, поскольку одна из серий содержит задержку.
Функция корреляции (в режиме = "полная" ) возвращает список элементов размером 40 тыс., которые выглядят как вид, к которому я стремился (пиковое значение находится так далеко от центра списка, что и "Лаг" указывает), но значения все странные - до 500, когда я ожидал чего-то от -1 до 1.
Я не могу просто разделить все на максимальное значение; Я знаю, что максимальная корреляция не 1.
Как я мог нормализовать "кросс-корреляцию" (корреляция в режиме "полный" ), поэтому возвращаемыми значениями были бы корреляция на каждом шаге задержки, а не те очень большие, странные значения?
Ответы
Ответ 1
Вы ищете нормализованную взаимную корреляцию. Этот параметр пока недоступен в Numpy, но патч ждет обзора, который делает именно то, что вы хотите. Это не должно быть слишком сложно применить, я бы подумал. Большая часть патча - это всего лишь материал в стиле doc. Единственными строками кода, которые он добавляет, являются
if normalize:
a = (a - mean(a)) / (std(a) * len(a))
v = (v - mean(v)) / std(v)
где a и v - введенные массивы numpy, из которых вы находите кросс-корреляцию. Не должно быть сложно добавить их в свой собственный дистрибутив Numpy или просто сделать копию функции корреляции и добавить туда строки. Я бы сделал последнее лично, если бы выбрал этот маршрут.
Другой, вполне возможно лучший вариант - просто выполнить нормализацию входных векторов, прежде чем отправлять его для корреляции. Это зависит от вас, как вы хотели бы это сделать.
Кстати, это выглядит как правильная нормализация на странице Wikipedia по кросс-корреляции, за исключением деления на len(a)
а не (len(a)-1)
. Я чувствую, что расхождение сродни стандартным отклонениям стандартного отклонения выборки и образца и действительно не будет иметь большого значения в моей мнение.
Ответ 2
В соответствии с этим слайдами, я предлагаю сделать это следующим образом:
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