정현파 항을 데이터에 적합


26

게시물을 읽었지만 여전히 내 데이터에 어떻게 적용하고 누군가 나를 도울 수 있기를 바랍니다.

다음과 같은 데이터가 있습니다.

y <- c(11.622967, 12.006081, 11.760928, 12.246830, 12.052126, 12.346154, 12.039262, 12.362163, 12.009269, 11.260743, 10.950483, 10.522091,  9.346292,  7.014578,  6.981853,  7.197708,  7.035624,  6.785289, 7.134426,  8.338514,  8.723832, 10.276473, 10.602792, 11.031908, 11.364901, 11.687638, 11.947783, 12.228909, 11.918379, 12.343574, 12.046851, 12.316508, 12.147746, 12.136446, 11.744371,  8.317413, 8.790837, 10.139807,  7.019035,  7.541484,  7.199672,  9.090377,  7.532161,  8.156842,  9.329572, 9.991522, 10.036448, 10.797905)
t <- 18:65

이제는 사인파를 맞추고 싶습니다

y(t)=Asin(ωt+ϕ)+C.

네 개의 미지수 , , 및 가 있습니다.Aϕ CωϕC

내 코드의 나머지 부분은 다음과 같습니다.

res <- nls(y ~ A*sin(omega*t+phi)+C, data=data.frame(t,y), start=list(A=1,omega=1,phi=1,C=1))
co <- coef(res)

fit <- function(x, a, b, c, d) {a*sin(b*x+c)+d}

# Plot result
plot(x=t, y=y)
curve(fit(x, a=co["A"], b=co["omega"], c=co["phi"], d=co["C"]), add=TRUE ,lwd=2, col="steelblue")

그러나 결과는 정말 좋지 않습니다.

사인 적합

도움을 주시면 대단히 감사하겠습니다.

건배.


사인파를 데이터에 맞추려고하거나 사인 및 코사인 성분으로 어떤 종류의 고조파 모델을 맞추려고합니까? R의 TSA 패키지에는 체크 아웃 할 수있는 고조파 기능이 있습니다. 그것을 사용하여 모델을 맞추고 어떤 종류의 결과를 얻는 지보십시오.
Eric Peterson

5
다른 시작 값을 사용해 보셨습니까? 손실 함수는 볼록하지 않으므로 시작 값이 다르면 솔루션이 다를 수 있습니다.
Stefan Wager 2016 년

1
데이터에 대해 자세히 알려주세요. 일반적으로 알려진 주기성이 있으므로 데이터에서 추정 할 필요가 없습니다. 이것은 시계열입니까 아니면 다른 것입니까? 선형 모형으로 사인 및 코사인 항을 분리 할 수 ​​있으면 훨씬 쉽습니다.
Nick Cox

2
알 수없는 기간이 있으면 모델이 비선형이됩니다 (이러한 이벤트는 연결된 게시물의 선택된 답변에서 언급됩니다). 주어진 다른 매개 변수는 조건부 선형입니다. 일부 비선형 LS 루틴의 경우 정보가 중요하며 동작을 개선 할 수 있습니다. 한 가지 옵션은 스펙트럼 방법을 사용하여 기간과 조건을 얻는 것입니다. 다른 하나는 반복적 인 방식으로 각각 비선형 및 선형 최적화를 통해주기 및 다른 파라미터를 업데이트하는 것이다.
Glen_b-복지 주 모니카

(방금 알려지지 않은 시대의 특정 사례를 비선형으로 만들 수있는 것에 대한 명확한 예를 만들기 위해 답을 편집했습니다.)
Glen_b -Reinstate Monica

답변:


18

의 좋은 추정치를 원 하고 표준 오류에별로 신경 쓰지 않는다면 :ω

ssp <- spectrum(y)  
per <- 1/ssp$freq[ssp$spec==max(ssp$spec)]
reslm <- lm(y ~ sin(2*pi/per*t)+cos(2*pi/per*t))
summary(reslm)

rg <- diff(range(y))
plot(y~t,ylim=c(min(y)-0.1*rg,max(y)+0.1*rg))
lines(fitted(reslm)~t,col=4,lty=2)   # dashed blue line is sin fit

# including 2nd harmonic really improves the fit
reslm2 <- lm(y ~ sin(2*pi/per*t)+cos(2*pi/per*t)+sin(4*pi/per*t)+cos(4*pi/per*t))
summary(reslm2)
lines(fitted(reslm2)~t,col=3)    # solid green line is periodic with second harmonic

사인 플롯

(더 나은 적합은 아마도 그 시리즈의 특이점을 어떤 식 으로든 설명하여 영향을 줄입니다.)

---

의 불확실성에 대한 아이디어를 원한다면 프로파일 가능성을 사용할 수 있습니다 ( pdf1 , pdf2- 프로파일 가능성에서 근사한 CI 또는 SE를 얻거나 그 변형을 찾기가 어렵습니다)ω

(또는,이 추정값을 nls에 공급하고 이미 수렴하기 시작할 수 있습니다.)


(+1) 좋은 답변입니다. 선형 모델에 맞추려고 lm(y~sin(2*pi*t)+cos(2*pi*t)했지만 작동하지 않았습니다 ( cos항은 항상 1이었습니다). 호기심에서 시작 : 처음 두 줄은 무엇을합니까 ( spectrum스펙트럼 밀도 를 추정 한다는 것을 알고 있습니다 )?
COOLSerdash

1
@COOLSerdash 그래, 작동하려면 의 단위가 (연관된 질문에서와 같이) 기간 이어야 합니다. 다시 돌아가서 다른 답변에서 강조해야합니다. (ctd)t2*pi*t
Glen_b-복지국 Monica

1
@COOLSerdash (ctd)-두 번째 라인은 스펙트럼에서 가장 큰 피크와 관련된 주파수를 찾고주기를 식별하기 위해 반전합니다. 적어도이 경우 (그러나 더 널리 의심되는 경우) 기본값은 기본적으로 가능성을 최대화하는 기간을 식별하므로 해당 기간 주변 지역의 프로필 가능성을 최대화하기 위해 수행 한 단계를 삭제했습니다. specTSA 의 기능 이 더 좋을 수도 있습니다 (더 많은 옵션이 있으며 그중 하나가 때로는 중요 할 수 있습니다).이 경우 주 피크는 정확히 같은 위치에 spectrum있었으므로 귀찮게하지 않았습니다.
Glen_b-복지 주 모니카

@Glen_b이 방법은 사용 사례에 놀라운 일입니다. 나는 변경 ... 나는 또한 COS (x)의 곡선에 맞게 필요하지만, 그것은뿐만 아니라 일을하지 않습니다 reslmreslm <- lm(y ~ cos(2*pi/per*t)+tan(2*pi/per*t))있지만 그 권리를 보지 않는다. 힌트가 있습니까?
Amit Kohli

왜 거기에 황갈색 용어가 있습니까?
Glen_b-복지 모니카

15

@Stefan이 제안했듯이 다른 시작 값은 적합을 크게 향상시키는 것으로 보입니다. 데이터가 눈에 띄었다. 오메가는 약 이어야한다고 제안했다 . 피크는 약 20 단위 떨어져있는 것처럼 보였기 때문이다.2π/20

나는에 그것을 넣어 때 nlsstart목록은 여전히 체계적인 편견을 가지고 있지만, 나는 훨씬 더 합리적이었다 곡선을 얻었다.

이 데이터 세트의 목표에 따라 용어를 추가하거나 주기적 커널을 사용하는 가우시안 프로세스와 같은 비모수 적 접근 방식을 사용하여 적합도를 향상시킬 수 있습니다.

사인 적합

시작 값을 자동으로 선택

지배적 인 주파수를 선택하려면 빠른 푸리에 변환 (FFT)을 사용할 수 있습니다. 이것은 내 전문 분야를 벗어난 방법이므로 다른 사람들이 원하는 경우 (특히 2 단계 및 3 단계) 세부 정보를 작성하도록하지만 R아래 코드는 작동합니다.

# Step 1: do the FFT
raw.fft = fft(y)

# Step 2: drop anything past the N/2 - 1th element.
# This has something to do with the Nyquist-shannon limit, I believe
# (https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem)
truncated.fft = raw.fft[seq(1, length(y)/2 - 1)]

# Step 3: drop the first element. It doesn't contain frequency information.
truncated.fft[1] = 0

# Step 4: the importance of each frequency corresponds to the absolute value of the FFT.
# The 2, pi, and length(y) ensure that omega is on the correct scale relative to t.
# Here, I set omega based on the largest value using which.max().
omega = which.max(abs(truncated.fft)) * 2 * pi / length(y)

abs(truncated.fft)다른 중요한 주파수가 있는지 확인하기 위해 플롯 할 수도 있지만 x 축의 스케일링을 약간 조정해야합니다.

또한 @Glen_b는 오메가를 알고 나면 문제가 볼록한 것이 맞습니다 (또는 아마도 파이도 알아야합니까? 확실하지 않습니다). 어쨌든, 다른 매개 변수의 시작 값을 아는 것이 올바른 야구장에 있다면 오메가만큼 중요하지 않아야합니다. FFT에서 다른 매개 변수에 대한 적절한 추정치를 얻을 수는 있지만 어떻게 작동하는지 잘 모르겠습니다.


1
그 힌트에 감사드립니다. 간단히 설명하자면, 데이터는 시간이 지남에 따라 유전자의 주기성이 측정 된 마이크로 어레이의 일부입니다. 즉, 표시된 데이터는 한 유전자의 발현 데이터입니다. 문제는 이제이 방법을주기와 진폭이 다른 약 40k 유전자에 적용하고 싶다는 것입니다. 따라서 초기 조건과 무관하게 올바른 맞춤을 찾는 것이 매우 중요합니다.
파스칼

1
@Pascal 오메가의 시작 값을 자동으로 선택하기위한 권장 사항은 위의 업데이트를 참조하십시오.
David J. Harris

2
@ DavidJ.Harris 선형 모델에서도 를 추정 할 수 있습니다 (선형 모델의 및 에서 직접 계산 ). OP가 연결된 게시물을 참조하십시오. B를ϕab
Glen_b-복지국 Monica

여기서 x 값이 어디에서 사용되는지 궁금합니다. 주어진 y 값이 1 또는 5 x 단계로 구분되는지 여부에 따라 오메가에 차이가 생기지 않습니까?
knub

1
질문과 관련이없는 프로그래밍 팁 : R 객체의 이름을로 지정할 때주의하십시오 foo.bar. 이것은 R이 클래스의 메소드를 지정하는 방식 때문입니다 .
Firebug

10

이미 말한 것에 대한 대안으로, ARIMA 모델 클래스의 AR (2) 모델을 사용하여 사인파 패턴으로 예측을 생성 할 수 있습니다.

AR (2) 모델은 다음과 같이 작성할 수 있습니다. 여기서 는 상수이고 , 는 추정 할 모수이고 는 임의의 충격 항입니다. C ϕ 1 ϕ 2 a t

yt=C+ϕ1yt1+ϕ2yt2+at
Cϕ1ϕ2at

이제 모든 AR (2) 모델 이 예측에서 사인파 패턴 ( 스토캐스틱 사이클 이라고도 함)을 생성 하는 것은 아니지만 다음 조건이 충족되면 발생합니다.

ϕ12+4ϕ2<0.

Panratz (1991)는 확률 론적 순환에 대해 다음과 같이 알려줍니다.

확률 론적 사이클 패턴은 예측 패턴에서 왜곡 된 사인파 패턴으로 생각할 수 있습니다. 확률 론적 (확률 적) 기간, 진폭 및 위상 각을 갖는 사인파입니다.

그러한 모델이 데이터에 적합 할 수 auto.arima()있는지 확인하기 위해 예측 패키지 의 함수를 사용하여 AR (2) 모델을 제안하는지 알아 냈습니다. 이 auto.arima()함수는 ARMA (2,2) 모델을 제안합니다. 순수한 AR (2) 모델은 아니지만 괜찮습니다. ARMA (2,2) 모델에 AR (2) 구성 요소가 포함되어있어 동일한 규칙 (확률 론적 사이클에 대한)이 적용되므로 문제가 없습니다. 즉, 사인파 예측이 생성되는지 확인하기 위해 위에서 언급 한 조건을 여전히 확인할 수 있습니다.

결과는 auto.arima(y)아래와 같습니다.

Series: y 
ARIMA(2,0,2) with non-zero mean 

Coefficients:
         ar1      ar2      ma1     ma2  intercept
      1.7347  -0.8324  -1.2474  0.6918    10.2727
s.e.  0.1078   0.0981   0.1167  0.1911     0.5324

sigma^2 estimated as 0.6756:  log likelihood=-60.14
AIC=132.27   AICc=134.32   BIC=143.5

이제 조건을 점검해 봅시다 : 그리고 조건이 실제로 만족 스럽다는 것을 알았습니다.

ϕ12+4ϕ2<01.73472+4(0.8324)<00.3202914<0

아래 그림은 원래 시리즈 y, ARMA (2,2) 모형의 적합도 및 14 개의 표본 외부 예측을 보여줍니다. 보다시피, 샘플 외부 예측은 사인파 패턴을 따릅니다.

여기에 이미지 설명을 입력하십시오

두 가지를 명심하십시오. 1) 이것은 자동화 된 도구를 사용하는 매우 빠른 분석이며 Box-Jenkins 방법론을 따르는 적절한 처리가 필요합니다. 2) ARIMA 예측은 단기 예측에 적합하므로 @David J. Harris 및 @Glen_b의 답변에서 모델의 장기 예측이 더 신뢰할 수 있음을 알 수 있습니다.

마지막으로, 이것은 이미 매우 유익한 답변에 좋은 추가 사항이되기를 바랍니다.

참조 : 동적 회귀 모형을 사용한 예측 : Alan Pankratz, 1991, (John Wiley and Sons, New York), ISBN 0-471-61528-5


1

sin 곡선을 주어진 데이터 세트에 맞추기위한 현재의 방법은 매개 변수의 첫 번째 추측이 필요하며 그 다음에 상호 적 과정이 필요합니다. 이것은 비선형 회귀 문제입니다. 편리한 적분 방정식 덕분에 비선형 회귀를 선형 회귀로 변환하는 다른 방법이 있습니다. 그런 다음, 초기 추측 및 반복 프로세스가 필요하지 않습니다. 피팅이 직접 확보됩니다. 기능 y = a + r * sin (w * x + phi) 또는 y = a + b * sin (w * x) + c * cos (w * x) 인 경우 용지 35-36 페이지를 참조하십시오. Scribd에 게시 된 "Régression sinusoidale": http://www.scribd.com/JJacquelin/documents 함수 y = a + p * x + r * sin (w * x + phi) 인 경우 : "혼합 선형 및 정현파 회귀"장의 49-51 페이지. 더 복잡한 함수의 경우 일반 프로세스는 54-61 페이지의 "일반화 된 정현파 회귀"장에 설명되어 있으며 숫자 예제는 y = r * sin (w * x + phi) + (b / x) + c입니다. * ln (x), 62-63 페이지


0

코사인 모양 데이터의 가장 낮은 점과 가장 높은 점을 알고있는 경우이 간단한 함수를 사용하여 모든 코사인 계수를 계산할 수 있습니다.

getMyCosine <- function(lowest_point=c(pi,-1), highest_point=c(0,1)){
  cosine <- list(
    T = pi / abs(highest_point[1] - lowest_point[1]),
    b = - highest_point[1],
    k = (highest_point[2] + lowest_point[2]) / 2,
    A = (highest_point[2] - lowest_point[2]) / 2
  )
  return(cosine)
}

아래는 가장 낮고 가장 따뜻한 시간에 대한 시간과 온도 값을 입력하여 코사인 함수로 하루 종일 온도 변화를 시뮬레이션하는 데 사용됩니다.

c <- getMyCosine(c(4,10),c(17,25)) 
# lowest temprature at 4:00 (10 degrees), highest at 17:00 (25 degrees)

x = seq(0,23,by=1);  y = c$A*cos(c$T*(x +c$b))+c$k ; 
library(ggplot2);   qplot(x,y,geom="step")

출력은 다음과 같습니다. 최저점과 최고점에서 계산 된 코사인


3
이 접근 방식은 순수한 정현파 동작에서 임의의 모양을 벗어나는 데 특히 민감한 것처럼 보이므로 질문에 설명 된 것과 같은 거의 모든 데이터 세트에는 적용 할 수 없습니다. 이 스레드에서 제안 된 다른 반복 접근 방식 중 일부에 시작 값을 제공하는 데 사용할 수 있습니다.
whuber

그것이 가장 단순하고, 특정 가정 하에서 간단한 근사에 적합 할 것이라는 데 동의합니다
IVIM

0

다른 옵션은 일반 함수 optim 또는 nls를 사용하는 것입니다. 나는 두 가지 모두를 시도했지만 완전히 견고하지는 않았다.

다음 함수는 y의 데이터를 가져 와서 매개 변수를 계산합니다.

calc.period <- function(y,t)
{     
   fs <- 1/(t[2]-t[1])
   ssp <- spectrum(y,plot=FALSE )  
   fN <- ssp$freq[which.max(ssp$spec)]
   per <- 1/(fN*fs)
   return(per)
 }

fit.sine<- function(y, t)
{ 
  data <- data.frame(x = as.vector(t), y=as.vector(y))
  min.RSS <- function (data, par){
    with(data, sum((par[1]*sin(2*pi*par[2]*x + par[3])+par[4]-y )^2))
  }  
  amp = sd(data$y)*2.**0.5
  offset = mean(data$y)
  fest <- 1/calc.period(y,t)
  guess = c( amp, fest,  0,   offset)
  #res <- optim(par=guess, fn = min.RSS, data=data ) 
  r<-nls(y~offset+A*sin(2*pi*f*t+phi), 
     start=list(A=amp, f=fest, phi=0, offset=offset))
  res <- list(par=as.vector(r$m$getPars()))
  return(res)
}

 genSine <- function(t, params)
     return( params[1]*sin(2*pi*params[2]*t+ params[3])+params[4])

사용은 다음과 같습니다.

t <- seq(0, 10, by = 0.01)
A <- 2 
f <- 1.5
phase <- 0.2432
offset <- -2

y <- A*sin(2*pi*f*t +phase)+offset + rnorm(length(t), mean=0, sd=0.2)

reslm1 <- fit.sine(y = y, t= t)

다음 코드는 데이터를 비교합니다

ysin <- genSine(as.vector(t), params=reslm1$par)
ysin.cor <- genSine(as.vector(t), params=c(A, f, phase, offset))

plot(t, y)
lines(t, ysin, col=2)
lines(t, ysin.cor, col=3)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.