티스토리 뷰

Machine Learning 입문

11. 시계열 분석

DWD85 2024. 12. 28. 09:07

> 피쳐가 여러 개, 타깃 데이터가 있으면 행 간 상관이 없는 데이터가 있고 상관이 있는 데이터가 있다.

> 시계열은 후자이다, 앞의 행의 데이터가 없으면 밑의 행 데이터가 영향을 받는다. : 종속 변수 y의 오차들은 독립이다 

 

 

> 시계열 분석으로 회귀 분석을 하고 남은 오차를 예측하는 것이다. 

> ARIMA, GARCH를 붙여서 더 복잡한 모델로 발전시킨다. 

 

> t 까지의 데이터를 가지고 있고 한 시점은 데이터마다의 정의가 다르다. 

> 시계열 기준 보통 최대 3 시점까지만 예측 가능하다. (상황마다 달라질 수 있다)

> 단위가 다르면 예측하지 못한다. 단위 시간이 1년이면 7개월 후는 예측 못함.

 

 

> Bold B는 한 시점 뒤로, Bold F는 한 시점 뒤로

> Bold 대문자 표현을 하는데 행렬은 아니다. 

 

> k 시점 기준으로 동일한 값을 갖는다 

 

> 어느 시점에서나 평균과 분산은 같다. (시간이 지나도 기댓값과 변동성이 같다)

> variance보다 volatility 라고 더 많이 쓴다. 

> autocovariance, autocorrelation은 넘어감 (내용이 길어져서) 

 

 

> 현 시점의 값을 과거의 값으로 나눈다.

> 피처가 내 옛날 자시의 값이 되는 것이다. 

> AR(1) 과거 시점 하나를 본 값. 

 

 

> 파이들을 구하는 게 목적이 된다. 

> 피처들이 자기 자신 

 

> 과거 오차들의 합이다. 

> MA(1) 는 현재의 오차와 과거 시점의 오차를 더한다 

> 통상전 MA는 기간을 잡고 rolling 시켜서 평균을 잡는 개념이랑 조금 다르다. 

 

> 과거와 오차를 함께 보는 걸 ARMA 모형이라고 한다. 

> ARMA(1,1) 순서대로 과거 시점 1 나와 과거 시점 1의 오차.

 

> ARMA 까지는 타깃만 활용했는데 여기에 피처를 더해주는걸 ARMAX라고 한다.

 

 

> ARMA를 사용하려면 정상성 만족해야 하여 일반적인 데이터 형태엔 적합하지 않을 수 있다. 

> 시간에 따라 추세를 가지면 ARIMA를 사용한다.

> Auto Regressive Integrated Moving Average (ARMA에 I 추가) 

 

> ARIMA에 회귀 모델 추가하면 ARIMAX가 된다. 

 

 

> 계절성이면 새로운 첨자가 들어간다. 

> 예) 여름의 데이터를 예측하기 위해선 전년도 전전 연도의 봄이 아닌 여름 데이터를 봐야 한다. 

> 그 전 시즌에 대한 데이터와의 차이를 나타낸다. 

 

> (p, d, q)는 계절성 데이터 빼고 모델링, (P, D, Q)는 계절성 데이터 모아서 모델링, s는 계절 주기

> 다 hyper parameter이다. 

> ARIMA(p,d,g) :  AR(p) I(d) MA(g)

> ARIMA(1,1,0) → ARI(1,1) 모형

> ARIMA(0,1,1) → IMA(1,1) 모형

> 식이나 식변경은 참고용

 

X_train = X_tn.asfreq('H') #데이터 주기 변환, D는 day, W는 week 
y_train = y_tn.asfreq('H')
X_test = X_te.asfreq('H')
y_test = y_te.asfreq('H') 

sarimax = ARIMA(endog=y_train, exog=X_train, order=(1,1,0), seasonal_order=(0,1,1,24))
sarimax_fit = sarimax.fit()

sarimax_fit.predict()

 

sarimax_fit.forecast(steps=len(X_test), exog=X_test)

 

> p,d,q 값 정하는 방법은 autocorrelation을 활용해서 그림 그려서 구하면 되는데 실무에서 구할 여유가 없다.

> 보통 기본 값 정해서 for 문 돌려서 mse 가장 낮은 값을 구하면 된다. (정석대로 하기 어려운 경우) 

 

#정리

> AR : 과거의 나

> MA : 과거의 오차

> ARMA : AR + MA

> ARMA 쓰려면 데이터가 정상성을 따라야 한다. (약정상성)

> 정상성 : 시간의 흐름에 따라 평균과 분산이 일정

> 평균이 정상성을 안 따르면 (분산은 따름) ARIMA 모형 사용

> I : 차분 

> 평균이 정상성 안 따르고 분산은 따르고 근데 계절성 데이터가 있으면 SARIMA(pdq)(PDQ) s 적용한다 

> 여기에 회귀까지 보고 싶으면 X가 붙는다. 

> 평균을 추정하는것이 보통 중요하기 때문에 (추세선 예측) 관심사가 평균이다. 

 

> 특히 선물 시장에서 volatility 변화가 중요함 

 

> 현재의 분산을 과거의 오차들로 나타낸다. 

> et 평균 0이고 분산이 1인 값

 

> 현재의 분산을 오차랑 과거의 분산으로 나타냄.

> ARCH를 일반화한 모델.

 

> ARIMA 다음에 남는 오차를 GARCH로 적용한다. 

 

#시계열 분석
import statsmodels
from statsmodels.regression import linear_model 
from statsmodels.tsa.arima.model import ARIMA
from arch import arch_model

df = pd.read_csv('./data/air_quality_uci.csv')
df['DateTime'] = df['Date'] + ' ' + df['Time']

df['Date_Index'] = pd.to_datetime(df['DateTime'])
df = df.set_index(keys = ['Date_Index'])

train_ratio = 0.9
n = len(df)
n_tn = int(n*train_ratio)
df_tn = df[:n_tn]
df_te = df[n_tn:]

features = ['T', 'AH']
target = 'PT08_S5'

X_tn = df_tn[features]
y_tn = df_tn[target]

X_te = df_te[features]
y_te = df_te[target]

ols_reg = linear_model.OLS(endog = y_tn, exog=X_tn)
ols_model = ols_reg.fit()
ols_model.predict(X_te)
#ARIMA

X_train = X_tn.asfreq('H')
y_train = y_tn.asfreq('H')

X_test = X_te.asfreq('H')
y_test = y_te.asfreq('H')
sarimax = ARIMA(endog = y_train, exog = X_train, order=(0, 0, 0), seasonal_order=(0, 0, 0, 24))
sarimax_fit = sarimax.fit()
sarimax_fit.predict()
sarimax_fit.forecast(steps = len(X_test), exog = X_test)

 

> 시계열 분석은 X_train, X_test는 가지고 있는 데이터를 쪼갠 거다 

> 앞으로 일어날 데이터의 예측 값은 X 통째로 넣으면 된다.

 

 

 

ols_model.predict(X_te)

 

 

> 시계열 데이터는 shuffle 하면 안 됨, 데이터 행의 순서도 정보이기 때문이다. 

> 시계열 처리에서 시간 data를 index로 만들어야 statsmodel 라이브러리 활용할 수 있다.

> ols : Ordinary Least Squares  최소 제곱 추정량

> Dep. Variable : 종속 변수 (피처) 

> Coef : 피쳐마다의 w 값, 회귀식에 넣으면 된다. 

> p > t의 p는 p-value이다. (가설이 있다)

> 가설  H0 : w=0, H1 : w!= 0

> w= 0이라는 뜻은 피쳐가 의미가 없다. 

> mse로 검증이 가능하다, mse 값이 매우 크게 나오는 경우는 데이터의 단위가 크면 크게 나올 수 있다. 

> 시계열 데이터가 Index이기 때문에 중복되면 안 된다.
> 만약 동일한 시간의 데이터들이 많다면 시간 데이터 기준을 Pivot 해줘야 한다. 

> 만약 시간 데이터가 일정하지 않으면 비어있는 시간에 대해서 데이터를 채워줘야 한다.

> 숫자 예측만 가능하다, 문자 예측은 Deep Learning (신경망)

#ARCH
arch = arch_model(y_train, vol='ARCH', p=1)
arch_fit = arch.fit()
pred_var = arch_fit.forecast(horizon=len(y_test))
pred_arch = np.sqrt(pred_var.variance.values[0])
pred_arch

>  vol : volaitility, p는 사용되는 계수

> np.sqrt 하는 이유는 표준 편차를 구하기 위해 

 

#SARIMAX + GARCH
from statsmodels.tsa.statespace.sarimax import SARIMAX
sarimax = ARIMA(endog =y_train, exog=X_train, order=(1,1,0),seasonal_order=(0,1,1,12))
sarimax_fit = sarimax.fit()

sarimax_residual = sarimax_fit.resid

adj_sarimax_residual = sarimax_residual*0.1 #data가 많서서

garch = arch_model(adj_sarimax_residual, vol='GARCH', p=20, q=20)
garch_fit = garch.fit()

pred_mu = sarimax_fit.forecast(steps=len(X_test), exog=X_test)

adj_forecast_residual = garch_fit.forecast(horizon=len(y_test))
adj_forecast_residual.variance.values

 

 

forecast_residual = np.sqrt(adj_forecast_residual.variance.values)/0.1
pred_residual = pd.Series(forecast_residual[-1, :], index=y_test.index)

e_t = np.random.randn(len(X_test))
y_hat = pred_mu + pred_residual*e_t
y_hat

 

 

Final 버전

> 추세를 추정하고 분산을 추정한다 

> 평균은 ARIMA, 분산은 GARCH로 추정한다

> ARIMAX를 하고나면 에러가 남는다 이 에러를 추정하는 게 GARCH다.

> 숫자가 커서 scaling 했음(0.1)
> scaling한 값을 GARCH에 넣는다.

> ARIMA forecast 하면 평균이 추정되고 

> Garch로 forecast하면 분산이 추정된다. 

> root 해주고 scaling값을 다시 나눠줘서 원복 시킨다.

> ARIMAX에 더해주면 된다. 

 

 

Ref : https://losskatsu.github.io/categories/#

반응형

'Machine Learning 입문' 카테고리의 다른 글

12. Deep Learning 기초  (3) 2024.12.28
10. 비지도 학습  (0) 2024.12.28
9. 앙상블 학습  (2) 2024.12.28
8. 지도 학습  (0) 2024.12.26
7. 최적화 & 모형 평가  (1) 2024.12.26
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함