두 신호를 정렬 / 동기화하려면 어떻게해야합니까?


21

나는 약간의 연구를하고 있지만 분석 단계에 갇혀 있습니다 (통계 강의에 더 많은 관심을 기울여야 함).

볼륨과 흉부 확장의 변화를 위해 통합 된 유량 두 가지 동시 신호를 수집했습니다. 나는 신호를 비교하고 궁극적으로 가슴 확장 신호에서 볼륨을 도출하기를 희망합니다. 그러나 먼저 데이터를 정렬 / 동기화해야합니다.

기록이 정확히 동시에 시작되지 않고 가슴 확장이 더 오랜 기간 동안 캡처되므로 가슴 확장 데이터 세트 내에서 볼륨 데이터에 해당하는 데이터를 찾아서 얼마나 잘 정렬되었는지 측정해야합니다. 두 신호가 정확히 동시에 시작되지 않거나 다른 스케일과 다른 해상도의 데이터 사이에서 시작되지 않으면 어떻게 해야할지 잘 모르겠습니다.

두 가지 신호의 예를 첨부했습니다 ( https://docs.google.com/spreadsheet/ccc?key=0As4oZTKp4RZ3dFRKaktYWEhZLXlFbFVKNmllbGVXNHc ), 더 제공 할 수있는 것이 있으면 알려주십시오.


나는 이것에 대한 답을 충분히 알지 못하며 이것이 문제를 해결하지는 못하지만 신호를 동기화하는 한 가지 접근 방식은 기능적 데이터 분석의 하위 집합 인 "등록"이라고합니다. 이 주제는 Ramsey와 Silverman의 FDA 책에서 논의됩니다. 기본 개념은 관측 된 신호가 "뒤 틀릴"수 있다는 것입니다 (예 : 사람들이 씹는 방식의 역학에 관심이 있지만 다른 속도로 씹는 사람들에 대한 데이터가있는 경우-이 경우 시간 축이 "뒤틀린"). 등록은 일반적인 "뒤 틀리지 않은"스케일에서 기본 신호를 정의하려고합니다.
매크로

1
이미 모든 데이터를 수집 했습니까? 이 파일럿 주제입니까? 방금 시작한 경우 벨트에서 신호를 분리하여 플로우 기록을 트리거로 사용하거나 타임 스탬프로 표시하는 방법을 살펴 보겠습니다. 일반적으로 수집 시스템은 보조 또는 트리거 포트를 통해이 기능을 제공합니다. 매크로가 제안한 것처럼 데이터를 사용하여 구별하는 방법이 있다고 확신하지만이 추가 단계를 추가하면 많은 추측이 필요합니다.
jonsca

1
나는 당신이 고정 지연 만 추정하고 싶다고 생각합니다. stats.stackexchange.com/questions/16121/…에
thias

1
신호 동기화에 대해 생각하는 dsp.SE에서이 질문을 할 수 있습니다.
Dilip Sarwate

1
@Thias는 정확하지만 첫 번째 시리즈는 공통 간격을 갖도록 다시 샘플링해야합니다.
whuber

답변:


24

이 질문은 시리즈가 규칙적이지만 다른 간격으로 샘플링 될 때 한 시계열 ( "확장")이 다른 시계열 ( "볼륨")보다 지연되는 양을 찾는 방법을 묻습니다 .

이 경우 두 시리즈 모두 그림과 같이 합리적으로 연속적인 동작을 나타냅니다. 이는 (1) 초기 스무딩이 거의 또는 전혀 필요하지 않으며 (2) 리샘플링은 선형 또는 2 차 보간만큼 간단 할 수 있음을 의미합니다. 매끄러움으로 인해 이차가 약간 더 나을 수 있습니다. 리샘플링 후 스레드에 표시된 것처럼 상호 상관을 최대화하여 지연을 찾습니다. 두 오프셋 샘플 데이터 계열의 경우 오프셋 간의 최적 추정치는 무엇입니까? .


설명하기R 위해, 의사 코드를 사용하여 질문에 제공된 데이터를 사용할 수 있습니다 . 기본 기능, 상호 상관 및 리샘플링으로 시작하겠습니다.

cor.cross <- function(x0, y0, i=0) {
  #
  # Sample autocorrelation at (integral) lag `i`:
  # Positive `i` compares future values of `x` to present values of `y`';
  # negative `i` compares past values of `x` to present values of `y`.
  #
  if (i < 0) {x<-y0; y<-x0; i<- -i}
  else {x<-x0; y<-y0}
  n <- length(x)
  cor(x[(i+1):n], y[1:(n-i)], use="complete.obs")
}

이것은 조잡한 알고리즘입니다. FFT 기반 계산이 더 빠릅니다. 그러나 이러한 데이터 (약 4000 개의 값 포함)는 충분합니다.

resample <- function(x,t) {
  #
  # Resample time series `x`, assumed to have unit time intervals, at time `t`.
  # Uses quadratic interpolation.
  #
  n <- length(x)
  if (n < 3) stop("First argument to resample is too short; need 3 elements.")
  i <- median(c(2, floor(t+1/2), n-1)) # Clamp `i` to the range 2..n-1
  u <- t-i
  x[i-1]*u*(u-1)/2 - x[i]*(u+1)*(u-1) + x[i+1]*u*(u+1)/2
}

데이터를 쉼표로 구분 된 CSV 파일로 다운로드하고 헤더를 제거했습니다. (헤더는 진단에 신경 쓰지 않은 R에 문제를 일으켰습니다.)

data <- read.table("f:/temp/a.csv", header=FALSE, sep=",", 
                    col.names=c("Sample","Time32Hz","Expansion","Time100Hz","Volume"))

NB 이 솔루션은 각 일련의 데이터가 시간 순서대로되어 있고 어느 한 쪽에도 간격이 없다고 가정합니다. 이를 통해 인덱스를 시간에 대한 프록시로 값으로 사용하고 시간으로 변환하기 위해 시간 샘플링 주파수에 따라 인덱스를 스케일링 할 수 있습니다.

이 악기 중 하나 또는 둘 다 시간이 지남에 따라 약간 표류하는 것으로 나타났습니다. 계속하기 전에 이러한 추세를 제거하는 것이 좋습니다. 또한 끝에 볼륨 신호가 좁아 지므로 클립을 잘라 내야합니다.

n.clip <- 350      # Number of terminal volume values to eliminate
n <- length(data$Volume) - n.clip
indexes <- 1:n
v <- residuals(lm(data$Volume[indexes] ~ indexes))
expansion <- residuals(lm(data$Expansion[indexes] ~ indexes)

결과를 최대한 정확하게 얻기 위해 빈번한 시리즈를 다시 샘플링합니다 .

e.frequency <- 32  # Herz
v.frequency <- 100 # Herz
e <- sapply(1:length(v), function(t) resample(expansion, e.frequency*t/v.frequency))

이제 상호 상관을 계산할 수 있습니다. 효율성을 위해 합리적인 지연 창만 검색하고 최대 값이 발견 된 지연을 식별 할 수 있습니다.

lag.max <- 5       # Seconds
lag.min <- -2      # Seconds (use 0 if expansion must lag volume)
time.range <- (lag.min*v.frequency):(lag.max*v.frequency)
data.cor <- sapply(time.range, function(i) cor.cross(e, v, i))
i <- time.range[which.max(data.cor)]
print(paste("Expansion lags volume by", i / v.frequency, "seconds."))

출력은 확장이 1.85 초만큼 볼륨보다 느리다는 것을 알려줍니다. (최근 3.5 초의 데이터가 클리핑되지 않은 경우 출력은 1.84 초입니다.)

가급적 시각적으로 여러 가지 방법으로 모든 것을 확인하는 것이 좋습니다. 먼저 상호 상관 함수 :

plot(time.range * (1/v.frequency), data.cor, type="l", lwd=2,
     xlab="Lag (seconds)", ylab="Correlation")
points(i * (1/v.frequency), max(data.cor), col="Red", cex=2.5)

상호 상관도

다음으로 두 시리즈를 시간에 등록 하고 동일한 좌표축에 함께 그려 봅시다 .

normalize <- function(x) {
  #
  # Normalize vector `x` to the range 0..1.
  #
  x.max <- max(x); x.min <- min(x); dx <- x.max - x.min
  if (dx==0) dx <- 1
  (x-x.min) / dx
}
times <- (1:(n-i))* (1/v.frequency)
plot(times, normalize(e)[(i+1):n], type="l", lwd=2, 
     xlab="Time of volume measurement, seconds", ylab="Normalized values (volume is red)")
lines(times, normalize(v)[1:(n-i)], col="Red", lwd=2)

등록 된 플롯

꽤 좋아 보인다! 그러나 scatterplot을 사용하면 등록 품질을 더 잘 이해할 수 있습니다 . 진행 상황을 보여주기 위해 시간에 따라 색상이 다릅니다.

colors <- hsv(1:(n-i)/(n-i+1), .8, .8)
plot(e[(i+1):n], v[1:(n-i)], col=colors, cex = 0.7,
     xlab="Expansion (lagged)", ylab="Volume")

산포도

우리는 선을 따라 앞뒤로 추적 할 요점을 찾고 있습니다. 그 변화는 볼륨 확장에 대한 시간 지연 반응의 비선형 성을 반영합니다. 약간의 변형이 있지만 상당히 작습니다. 그러나 시간이 지남에 따라 이러한 변화가 어떻게 변화 하는지 는 생리적으로 관심이있을 수 있습니다. 통계, 특히 탐색 및 시각적 측면에서 훌륭한 점은 유용한 질문 과 함께 좋은 질문아이디어 를 만드는 경향이 있다는 것입니다.


1
이런 지옥, 당신은 훌륭합니다. 상호 상관은 정확히 내가 상상했던 것입니다. 매우 감사합니다!
person157

나는 지금 완전한 설명을 할 시간이 없지만 "Numerical Recipes"책에 큰 설명이 나온다. 예를 들어 C의 수치 레시피에서 13.2 장, "FFT를 사용한 상관 및 자기 상관"을 참조하십시오 . R의 acf기능을 살펴볼 수도 있습니다 .
whuber

'r'을 처음 사용하십시오. 친절하십시오. 결합 된 플롯 (두 번째 플롯)에 사용 된 '정규화'기능이 작동하지 않습니다.이 답변이 게시 된 이후이 기능이 업데이트됩니까?
CmKndy

1
@CmKndy R이 답변을 게시하고 해당 기능에 대한 정의를 제공하는 것을 잊었을 때도을 처음 사용했습니다 . 여기에 원래의 :normalize <- function(x) { x.max <- max(x); x.min <- min(x); dx <- x.max - x.min; if (dx==0) dx <- 1; (x-x.min) / dx }
whuber

완벽합니다, @whuber 감사합니다. R을 처음
접했을
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.