Как соотнести два временных ряда с пробелами и разными временными базами? - PullRequest
14 голосов
/ 27 февраля 2011

У меня есть два временных ряда данных трехмерного акселерометра, которые имеют разные временные базы (часы запускались в разное время, с небольшим ползучестью в течение времени выборки), а также содержат много пробелов различного размера (из-за задержек, связанных с запись на отдельные флэш-устройства).

Используемые мной акселерометры - недорогие GCDC X250-2 . Я использую акселерометры с максимальным усилением, поэтому данные имеют значительный уровень шума.

Каждый временной ряд имеет около 2 миллионов точек данных (более часа при 512 выборках в секунду) и содержит около 500 интересных событий, где типичное событие охватывает 100–150 выборок (по 200–300 мс каждая). На многие из этих событий влияют сбои данных во время флэш-записи.

Итак, данные не чистые и даже не очень красивые. Но мой осмотр глазного яблока показывает, что он явно содержит информацию, которая мне интересна. (При необходимости я могу публиковать графики).

Акселерометры находятся в схожих средах, но они только умеренно связаны, что означает, что я могу наглядно определить, какие события совпадают с каждым акселерометром, но до сих пор мне не удалось это сделать в программном обеспечении. Из-за физических ограничений устройства также монтируются в разных ориентациях, где оси не совпадают, но они настолько близки к ортогональным, насколько я мог сделать их. Так, например, для 3-осевых акселерометров A & B, + Ax отображается на -By (вверх-вниз), + Az отображается на -Bx (слева-справа), а + Ay отображается на -Bz (спереди назад) .

Моя первоначальная цель состоит в том, чтобы сопоставить шоковые события на вертикальной оси, хотя я бы в конечном итоге хотел бы: а) автоматически обнаружить отображение оси, б) сопоставить активность на сопоставленных тузах и в) извлечь различия в поведении между двумя акселерометрами ( такие как скручивание или изгиб).

Характер данных временного ряда делает Python numpy.correlate () непригодным для использования. Я также посмотрел на пакет R's Zoo, но не добился успеха. Я обращался за помощью в различные области анализа сигналов, но я не добился прогресса.

У кого-нибудь есть какие-либо подсказки для того, что я могу сделать, или подходы, которые я должен исследовать?

Обновление 28 февраля 2011: добавлено несколько графиков здесь с примерами данных.

Ответы [ 5 ]

4 голосов
/ 28 февраля 2011

Моя интерпретация вашего вопроса: учитывая два очень длинных, шумных временных ряда, найдите сдвиг, который соответствует большим «ударам» в одном сигнале и большим ударам в другом сигнале.

Мое предложение: интерполироватьданные таким образом, чтобы они были равномерно распределены, выпрямляли и сглаживали данные (предполагая, что фаза быстрых колебаний неинтересна), и выполняли взаимную взаимную корреляцию по одной точке (предполагая, что небольшой сдвиг выровняет данные).

import numpy
from scipy.ndimage import gaussian_filter
"""
sig1 and sig 2 are assumed to be large, 1D numpy arrays
sig1 is sampled at times t1, sig2 is sampled at times t2
t_start, t_end, is your desired sampling interval
t_len is your desired number of measurements
"""

t = numpy.linspace(t_start, t_end, t_len)
sig1 = numpy.interp(t, t1, sig1)
sig2 = numpy.interp(t, t2, sig2)
#Now sig1 and sig2 are sampled at the same points.

"""
Rectify and smooth, so 'peaks' will stand out.
This makes big assumptions about your data;
these assumptions seem true-ish based on your plots.
"""
sigma = 10 #Tune this parameter to get the right smoothing
sig1, sig2 = abs(sig1), abs(sig2)
sig1, sig2 = gaussian_filter(sig1, sigma), gaussian_filter(sig2, sigma)

"""
Now sig1 and sig2 should look smoothly varying, with humps at each 'event'.
Hopefully we can search a small range of shifts to find the maximum of the 
cross-correlation. This assumes your data are *nearly* lined up already.
"""
max_xc = 0
best_shift = 0
for shift in range(-10, 10): #Tune this search range
    xc = (numpy.roll(sig1, shift) * sig2).sum()
    if xc > max_xc:
        max_xc = xc
        best_shift = shift
print 'Best shift:', best_shift
"""
If best_shift is at the edges of your search range,
you should expand the search range.
"""
1 голос
/ 27 февраля 2011

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

Оттуда у вас есть небольшие проблемы, которые легче анализировать.

0 голосов
/ 27 февраля 2011

Полагаю, вам нужно будет вручную построить таблицу смещений, которая выровняет «совпадения» между рядами.Ниже приведен пример способа получения этих совпадений.Идея состоит в том, чтобы сдвигать данные влево-вправо, пока они не выстроятся в линию, а затем отрегулировать масштаб, пока он не «совпадет».Попробуйте.

library(rpanel)

#Generate the x1 and x2 data
n1 <- rnorm(500)
n2 <- rnorm(200)
x1 <- c(n1, rep(0,100), n2, rep(0,150))
x2 <- c(rep(0,50), 2*n1, rep(0,150), 3*n2, rep(0,50))

#Build the panel function that will draw/update the graph
lvm.draw <- function(panel) {
       plot(x=(1:length(panel$dat3))+panel$off, y=panel$dat3, ylim=panel$dat1, xlab="", ylab="y", main=paste("Alignment Graph   Offset = ", panel$off, "   Scale = ", panel$sca, sep=""), typ="l")
       lines(x=1:length(panel$dat3), y=panel$sca*panel$dat4, col="red")
       grid()
       panel
}

#Build the panel
xlimdat <- c(1, length(x1))
ylimdat <- c(-5, 5)
panel <- rp.control(title = "Eye-Ball-It", dat1=ylimdat, dat2=xlimdat, dat3=x1, dat4=x2, off=100, sca=1.0, size=c(300, 160))
rp.slider(panel, var=off, from=-500, to=500, action=lvm.draw, title="Offset", pos=c(5, 5, 290, 70), showvalue=TRUE)
rp.slider(panel, var=sca, from=0, to=2, action=lvm.draw, title="Scale", pos=c(5, 70, 290, 90), showvalue=TRUE)
0 голосов
/ 27 февраля 2011

Это не технический ответ, но он может помочь вам найти один:

  • Преобразование сюжета в изображение и вставка его в приличную графическую программу, например gimp или photoshop
  • разбивать графики на отдельные изображения, когда есть разрыв
  • положите первую серию графиков в горизонтальную линию
  • поместите второй ряд в горизонтальную линию прямо под ним
  • визуально идентифицирует первое коррелированное событие
  • если два события не выстроены вертикально:
    • выберите любой экземпляр слева и все справа от него в этой строке
    • перетащите эти вещи вправо, пока они не выстроятся в линию

Это почти то же самое, как работает аудиоредактор, поэтому, если вы конвертируете его в простой аудиоформат, такой как несжатый WAV-файл, вы можете манипулировать им напрямую, например, в Audacity. (Конечно, это будет звучать ужасно, но вы сможете перемещать графики данных довольно легко.)

На самом деле, Audacity также имеет язык сценариев, называемый nyquist, поэтому, если вам не нужна программа для обнаружения корреляций (или вы по крайней мере готовы отложить этот шаг на время ) вы, вероятно, могли бы использовать некоторую комбинацию маркеров audacity и nyquist для автоматизации выравнивания и экспорта чистых данных в выбранный вами формат, как только вы пометите точки корреляции.

0 голосов
/ 27 февраля 2011

Звучит так, как будто вы хотите минимизировать функцию (Ax '+ By) + (Az' + Bx) + (Ay '+ Bz) для пары значений: А именно, смещение по времени: t 0 и масштабный коэффициент времени: t r .где Ax '= t r * (Ax + t 0 ) и т. д.

Я бы посмотрел на двумерный SciPy , оптимизирующий функции .И я бы использовал mask или временно обнулил бы данные (например, Ax 'и By) над "пробелами" (предполагая, что пробелы могут быть определены программно).

Чтобы сделатьпроцесс более эффективен, начните с грубой выборки A и B, но установите точность в fmin (или любом другом оптимизаторе, который вы выбрали), которая соизмерима с вашей выборкой.Затем продолжайте работу с более тонкими окнами полного набора данных до тех пор, пока ваши окна не станут узкими и не будут уменьшены.

Правка - соответствующие оси

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

...