Подтвердить что ты не робот

Оценка автокорреляции с использованием Python

Я хотел бы выполнить автокорреляцию по сигналу, показанному ниже. Время между двумя последовательными точками составляет 2,5 мс (или частота повторения 400 Гц).

enter image description here

Это уравнение для оценки автокорреляции, которое я бы хотел использовать (взято из http://en.wikipedia.org/wiki/Autocorrelation, оценка раздела):

enter image description here

Каков самый простой способ нахождения оцененной автокорреляции моих данных в python? Есть ли что-то похожее на numpy.correlate, которое я могу использовать?

Или нужно просто вычислить среднее значение и дисперсию?


Edit:

С помощью unutbu я написал:

from numpy import *
import numpy as N
import pylab as P

fn = 'data.txt'
x = loadtxt(fn,unpack=True,usecols=[1])
time = loadtxt(fn,unpack=True,usecols=[0]) 

def estimated_autocorrelation(x):
    n = len(x)
    variance = x.var()
    x = x-x.mean()
    r = N.correlate(x, x, mode = 'full')[-n:]
    #assert N.allclose(r, N.array([(x[:n-k]*x[-(n-k):]).sum() for k in range(n)]))
    result = r/(variance*(N.arange(n, 0, -1)))
    return result

P.plot(time,estimated_autocorrelation(x))
P.xlabel('time (s)')
P.ylabel('autocorrelation')
P.show()
4b9b3361

Ответ 1

Я не думаю, что для этого конкретного вычисления есть функция NumPy. Вот как я его написал:

def estimated_autocorrelation(x):
    """
    http://stackoverflow.com/q/14297012/190597
    http://en.wikipedia.org/wiki/Autocorrelation#Estimation
    """
    n = len(x)
    variance = x.var()
    x = x-x.mean()
    r = np.correlate(x, x, mode = 'full')[-n:]
    assert np.allclose(r, np.array([(x[:n-k]*x[-(n-k):]).sum() for k in range(n)]))
    result = r/(variance*(np.arange(n, 0, -1)))
    return result

Утверждающий оператор существует как для проверки расчета, так и для документирования его намерения.

Если вы уверены, что эта функция ведет себя как ожидалось, вы можете прокомментировать инструкцию assert или запустить script с помощью python -O. (Флаг -O указывает Python игнорировать утверждения assert.)

Ответ 2

Я взял часть кода из функции pandas autocorrelation_plot(). Я проверил ответы с помощью R, и значения точно совпадают.

import numpy
def acf(series):
    n = len(series)
    data = numpy.asarray(series)
    mean = numpy.mean(data)
    c0 = numpy.sum((data - mean) ** 2) / float(n)

    def r(h):
        acf_lag = ((data[:n - h] - mean) * (data[h:] - mean)).sum() / float(n) / c0
        return round(acf_lag, 3)
    x = numpy.arange(n) # Avoiding lag 0 calculation
    acf_coeffs = map(r, x)
    return acf_coeffs

Ответ 4

Метод, который я написал с моего последнего редактирования, теперь быстрее, чем даже scipy.statstools.acf с fft=True, пока размер выборки не станет очень большим.

Анализ ошибок. Если вы хотите настроить отклонения и получить очень точные оценки ошибок: посмотрите на мой код здесь который реализует эту статью Улли Вольфа (или оригинал UW в Matlab)

Проверенные функции

  • a = correlatedData(n=10000) происходит из найденной процедуры здесь
  • gamma() - это то же место, что и correlated_data()
  • acorr() - моя функция ниже
  • estimated_autocorrelation находится в другом ответе
  • acf() - от from statsmodels.tsa.stattools import acf

Задержки

%timeit a0, junk, junk = gamma(a, f=0)                            # puwr.py
%timeit a1 = [acorr(a, m, i) for i in range(l)]                   # my own
%timeit a2 = acf(a)                                               # statstools
%timeit a3 = estimated_autocorrelation(a)                         # numpy
%timeit a4 = acf(a, fft=True)                                     # stats FFT

## -- End pasted text --
100 loops, best of 3: 7.18 ms per loop
100 loops, best of 3: 2.15 ms per loop
10 loops, best of 3: 88.3 ms per loop
10 loops, best of 3: 87.6 ms per loop
100 loops, best of 3: 3.33 ms per loop

Изменить... Я снова проверил, сохраняя l=40 и меняя n=10000 на n=200000 образцы, методы FFT начинают получать немного тяги, а реализация statsmodels fft просто режет его... (заказ - это то же самое)

## -- End pasted text --
10 loops, best of 3: 86.2 ms per loop
10 loops, best of 3: 69.5 ms per loop
1 loops, best of 3: 16.2 s per loop
1 loops, best of 3: 16.3 s per loop
10 loops, best of 3: 52.3 ms per loop

Редактировать 2: я изменил свою процедуру и повторно протестировал против FFT для n=10000 и n=20000

a = correlatedData(n=200000); b=correlatedData(n=10000)
m = a.mean(); rng = np.arange(40); mb = b.mean()
%timeit a1 = map(lambda t:acorr(a, m, t), rng)
%timeit a1 = map(lambda t:acorr.acorr(b, mb, t), rng)
%timeit a4 = acf(a, fft=True)
%timeit a4 = acf(b, fft=True)

10 loops, best of 3: 73.3 ms per loop   # acorr below
100 loops, best of 3: 2.37 ms per loop  # acorr below
10 loops, best of 3: 79.2 ms per loop   # statstools with FFT
100 loops, best of 3: 2.69 ms per loop # statstools with FFT

Реализация

def acorr(op_samples, mean, separation, norm = 1):
    """autocorrelation of a measured operator with optional normalisation
    the autocorrelation is measured over the 0th axis

    Required Inputs
        op_samples  :: np.ndarray :: the operator samples
        mean        :: float :: the mean of the operator
        separation  :: int :: the separation between HMC steps
        norm        :: float :: the autocorrelation with separation=0
    """
    return ((op_samples[:op_samples.size-separation] - mean)*(op_samples[separation:]- mean)).ravel().mean() / norm

4x ускорение может быть достигнуто ниже. Вы должны быть осторожны, чтобы пройти только op_samples=a.copy(), так как он изменит массив a на a-=mean иначе:

op_samples -= mean
return (op_samples[:op_samples.size-separation]*op_samples[separation:]).ravel().mean() / norm

Проверка работоспособности

введите описание изображения здесь

Пример анализа ошибок

Это немного выходит за пределы области видимости, но я не могу потрудиться, чтобы переделать фигуру без встроенного расчета автокорреляции или расчета окна интеграции. Автокорреляции с ошибками ясны в нижнем графике введите описание изображения здесь

Ответ 5

Я нашел, что полученные ожидаемые результаты произошли с небольшим изменением:

def estimated_autocorrelation(x):
    n = len(x)
    variance = x.var()
    x = x-x.mean()
    r = N.correlate(x, x, mode = 'full')
    result = r/(variance*n)
    return result

Тестирование результатов автокорреляции Excel.