본문 바로가기
시계열모델링

시계열 자료의 평활법 - 회귀평활 part 1

by 다빈치스탁 2020. 10. 15.
728x90
반응형

지난 포스트에 이어서 우리는 불필요한 잡음을 없애는데 계속해서 주력할 것이다. 왜냐? 대부분의 주식투자자들이 추세를 판가름하고자 할때 이동평균을 많이 활용한다. 즉 어제 오늘의 변동성에 휘둘리기 싫다는 의미가 된다. 하물며 일반적인 투자도 그러할진데 모델링을 이용한 AI 혹은 EA(Expert Adviser)로 구현하고자 한다면 더 더욱 이러한 문제에 직면하게 된다.

 

추후 다루겠지만 강화학습을 수행함에 있어서 일반적인 Policy Gradient 에서도 이러한 문제가 발생을 한다. 간단히 부연설명을 하자면 환경에서 주어지는 데이터가 조금만 변하더라도 정책 신경망의 최적화된 파라메터는 급격히 변동을 한다. 이러한 문제를 해결하고 강화학습의 학습이 잘 되도록 하기 위해서 Actor-Critic, A3C 등의 모델이 등장하게 된다. 즉 환경에서 주어지는 데이터를 예측을 통해서 학습하면 이러한 자잘한 변동이 줄어들기 때문에 학습을 효율적으로 진행(정책 신경망의 파라메터의 변동성 안정화)할 수 있게 되는 것과 마찬가지로 시계열 분석에서도 비슷한 효과를 기대할 수 있다.

 

회귀 평활의 종류와 방법론

회귀평활의 방법론으로는 위의 그림과 같이 분류가 가능하다. 그러나 우리의 목적은 잡음의 제거이지 너무 일반화된 자료를 원하는 것이 아니다. 물론 경우에 따라서는 일반화된 모델이 더 유용할 수 있다. 그러나 아래의 코드를 수행한 결과 3차 다항회귀의 피팅그래프는 코스피 지수를 너무 단순화했다. 또한 이렇게 단순화한 모델이 일반화 될 수 없기 때문에 그닥 유용하지 못하다고 할 수 있다. 즉 시계열 자료와 같이 다양하고 복잡한 변화를 나타내는 방법으로 단순한 선형(혹은 일반적인 비선형 다항)구조로 해석하는 것은 무리가 있다. 

 

이럴 때 유용하게 써 먹을 수 있는 방법 중 하나로 kernel 법이 있다. 이 커널법은 조사자료를 고차원 벡터공간에 투영하여 시계열 자료의 비선형적 자료변환을 하는 방법인데 이러한 커널법에 의해 추정된 y 값과 실제 데이터 사이의 잔차의 제곱합을 최소화 하는 alpha를 산정한 뒤 이것을 토대로 정규화 과정을 거쳐 자료를 스무딩하는 기법이다. 자세한 수리적 유도과정은 관련서적을 참고하자. 

 

R프로그램에 기반한 시계열 자료 분석
국내도서
저자 : 이재길
출판 : 황소걸음 아카데미 2017.05.22
상세보기

 

아래의 코드에서 밴드위드의 값이 커질수록 자료의 스무딩이 완만해지는데 얼마를 줘야할지 고민하지 말고 국지적 선형 가우시안 커널 회귀 추정치를 제공하는 kersmooth 패키지의 dpill 함수를 사용하면 추정치를 제공해준다. 자 분석한 결과(아래의 그림2)를 보면 커널법으로 추정한 자료가 훨씬 실제와 근사하게 스무딩 되어 있음을 알 수 있다. 

 

우리의 목적은 뭐다? 실제와 가장 근사하고 불필요한 휩소(변동성)에 속지 않는 추세를 표현해보는 것이다. 따라서 어떤 하나의 최적화된 방법 하나를 찾는 것이 아니라 각각의 스무딩 방법들이 가지는 장.단점과 그리고 어떠한 자료에 어떠한 기법이 적합한지를 판단하는 것이 중요하다. 이외에도 다양한 방법들이 있지만 그건 다음 포스트에서 다루어보자.

#작업경로를 지정하는 명령어
setwd("")

mydatat<-read.csv("jisu.csv",
                  header=TRUE, na.strings = "")

o=mydatat$코스피지수
plot(o)

#-----------------단순이동평균.-------------------
#5일 이동평균
f5=filter(mydatat$코스피지수, filter=rep(1/5,5), side=1)
plot(f5)

#이중이동평균
df5=filter(f5, filter=rep(1/5,5), side=1)
plot(df5)

#독립성 검증(자기상관은 없는 것으로 관측)
res = o[10:100] - f5[10:100]
Box.test((res))

#독립성 검증(자기상관이 있는 것으로 관측)
res = o[10:100] - df5[10:100]
Box.test((res))

#-----------------가중이동평균.-------------------
w=c(0.5,0.4,0.3,0.2,0.1)
fw=filter(mydatat$코스피지수, filter=w)

#독립성 검증(자기상관이 있는 것으로 관측)
res = o[10:100] - fw[10:100]
Box.test((res))

#-----------------예측.-------------------
library(forecast)
fore1=forecast(o[10:100],h=1)
fore2=forecast(f5[10:100],h=1) 
fore3=forecast(df5[10:100],h=1)
fore4=forecast(fw[10:100],h=1)


#-----------------검증.-------------------
#ME : 예측오차의 산술평균
#RMSE : ME의 제곱의 평균
#MAE : 예측오차의 절대값의 평균
#MPE : 예측오차의 상대적인 크기를 반영(비율)한 평균
#MAPE : 예측오차의 절대값의 상대적 크기를 반영한 평균
#MASE : 예측오차의 절대값에 대한 평균으로 크기를 나타내는 지표
accuracy(fore1)
accuracy(fore2) 
accuracy(fore3) #이중이동평균의 성능이 가장 우수(오차들이 작다)
accuracy(fore4)


#-----------------HoltWinters Method.-------------------
#단순히 가중치를 0.1로 지정할 경우.
h=HoltWinters(o,alpha = 0.1, beta=F,gamma=F)
plot(h$fitted)
fh=forecast(h,h=1)
#테스트 결과 자기상관이 존재하는 것으로 나타남.
Box.test(fh$residuals)

#가중치를 추론하고자 할 경우
hi=HoltWinters(o,beta=F,gamma=F)
plot(hi$fitted)
fi=forecast(hi,h=1)
#테스트 결과 자기상관이 없는 것으로 나타남.<-그렇게 되도록 추정했으므로
Box.test(fi$residuals)

accuracy(fore3) #이중이동평균의 성능이 가장 우수(오차들이 작다)
accuracy(fi) #홀트-윈터 방법으로 추정한 결과 일부 지표에서는 이중이동평균보다 낫지만 드라마틱하지는 않다.

#추세가 있는 시계열의 가중치를 추론하고자 할 경우
#추세가 있다고 가정할 경우 alpha 값이 1이 되어 가중평균은 성립되지 않는 것으로 나타남.
#gamma도 무시하지 않고 고려하면 계절성이 있는 자료일 때 사용하는 방법이지만 코스피 지수는 계절을 타지 않음.
#굳이 계절성이 있다고 고려해본다면 산타랠리?? 정도 이지만 그것도 결산실적이 좋을 것으로 예측될 경우 가능한 이야기라 불규칙적임
hit=HoltWinters(o,gamma=F) 

#-----------------단수 지수평활법.-------------------
s=ses(o)
#simple exponential smooth 기법으로 추정한 alpha=0.99 로 1에 매우 근사한 값으로 나왔다.
summary(s)
sf=forecast(s,h=1)
accuracy(sf) #홀트-윈터 방법으로 추정한 결과와 별다른 차이점을 발견할 수 없다.

#-----------------ets-------------------
e=ets(o)
plot(e$fitted)
summary(e)
ef=forecast(e,h=1)
#테스트 결과 자기상관이 없는 것으로 나타남.
Box.test(ef$residuals)

accuracy(ef) #홀트-윈터 방법보다는 다소 개선된 성능지표를 관측할 수 있다.


#-----------------회귀 평활법.-------------------
#1차 회귀.
lt = seq(1:length(o))
sl=lm(o~poly(lt,1))
plot(fitted(sl))

#3차 다항 회귀.
sl3=lm(o~poly(lt,3))
plot(fitted(sl3))

#-----------------일반화 회귀 평활법.-------------------
#1차 회귀.
nlt=nls(o~a+b*lt,start = c(a=1,b=1))
plot(fitted(nlt))

#2차 다항 회귀.
nlt2=nls(o~a+b*lt+c*lt^2,start = c(a=1,b=1,c=1))
plot(fitted(nlt2))

#-----------------kernel 평활법.-------------------
#install.packages("KernSmooth")
library(KernSmooth)
dks=dpill(lt,o)
ks=locpoly(lt,o, bandwidth = dks)
plot(ks$y)

 

3차 다항 회귀 평활 그래프
kernel 평활 그래프

 

728x90
반응형

댓글