Posts 시계열 분석의 기초
Post
Cancel

시계열 분석의 기초

1. 시계열 분석


1.1 시계열 분석이란?

  • 주가, 환율 거래량 변동
  • 기온, 습도, 변화
  • 수요량, 판매량, 클릭율 변화
  • 인구, 출생률 변화
  • 시간의 흐름에 따라 규칙이 있는 데이터는 수학적 모델이 필요함


1.2 시간적 요소를 분석

  • 추세 파악 : 작위 적인 잡음을 제거하여 큰 흐름 파악
  • 원인 예측 및 대응 : 매출이 특정 요일에 하락하는 패턴이 보이면, 이를 극복하기 위한 방안을 마련
  • 향후 전망 : 판매량 추이 전망에 따라 생산량 조절


2. Fbprophet


2.1 테스트 준비

1
2
3
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt


2.2 데이터 준비

1
2
3
4
5
time = np.linspace(0, 1, 365 * 2)
result = np.sin(2 * np.pi * 12 * time)
ds = pd.date_range('2017-01-01', periods=365*2, freq='D')
df = pd.DataFrame({'ds': ds, 'y': result})
df.head()
dsy
02017-01-010.000000
12017-01-020.103243
22017-01-030.205382
32017-01-040.305326
42017-01-050.402007


2.3 데이터 생긴 모양

1
2
df['y'].plot(figsize=(10, 6))
plt.show()


2.4 예측 시도

1
2
3
4
from fbprophet import Prophet

m = Prophet(yearly_seasonality=True, daily_seasonality= True)
m.fit(df)
1
<fbprophet.forecaster.Prophet at 0x7f9290688f40>
1
2
future = m.make_future_dataframe(periods=30)
forecast = m.predict(future)
  • Fbprophet을 사용하여 생성한 데이터를 예측해봄


2.5 확인

1
2
m.plot(forecast)
plt.show()

  • 예측을 굉장히 잘하는 것을 알수 있다.(검은 점이 예측한 것)


2.6 어렵게

1
2
3
4
5
6
7
8
time = np.linspace(0, 1, 365 * 2)
result = np.sin(2 * np.pi * 12 * time) + time

ds = pd.date_range('2017-01-01', periods=365 * 2, freq='D')
df = pd.DataFrame({'ds': ds, 'y': result})

df['y'].plot(figsize=(10, 6))
plt.show()

  • 앞의 데이터가 너무 쉬워 보여서 약간의 수치를 변형 시켜봄


2.7 예측

1
2
m = Prophet(yearly_seasonality=True, daily_seasonality=True)
m.fit(df)
1
<fbprophet.forecaster.Prophet at 0x7f92b2b70e50>
1
2
3
4
future = m.make_future_dataframe(periods = 30)
forecast = m.predict(future)
m.plot(forecast)
plt.show()

  • 아까보단 좀 덜 예측 하지만, 그래도 생각보다 잘 예측함


2.8 노이즈를 섞어서 더 어렵게

1
2
3
4
5
6
7
8
time = np.linspace(0, 1, 365 * 2)
result = np.sin(2 * np.pi * 12 * time) + time + np.random.randn(365 * 2)/4

ds = pd.date_range('2017-01-01', periods=365 * 2, freq='D')
df = pd.DataFrame({'ds': ds, 'y': result})

df['y'].plot(figsize=(10, 8))
plt.show()

  • 이번엔 노이즈를 random으로 섞어서 더 어렵게 만들어보았음


2.9 예측

1
2
m = Prophet(yearly_seasonality=True, daily_seasonality=True)
m.fit(df)
1
<fbprophet.forecaster.Prophet at 0x7f92700bc160>
1
2
3
4
future = m.make_future_dataframe(periods = 30)
forecast = m.predict(future)
m.plot(forecast)
plt.show()

  • 간혹 아웃라이어가 눈에 띄긴 하지만, 잘 예측한다


3. 실전 예측 웹 데이터 분석


3.1 데이터 읽기

1
2
pinkwink_web = pd.read_excel('data/pinkwink_web.xlsx', names = ['ds', 'hit'])
pinkwink_web.head()
dshit
02016-01-01228
12016-01-02304
22016-01-03304
32016-01-04659
42016-01-05769
  • 약 3년치의 강사님의 블로그 방문자수 데이터로 시계열 데이터 분석진행해봄


3.2 예측시도

1
2
3
4
5
6
7
8
9
df = pd.DataFrame({'ds' : pd.to_datetime(pinkwink_web['ds'], format= '%y. %m. %d.'),
                  'y' : pinkwink_web['hit']})

m = Prophet(yearly_seasonality= True, daily_seasonality= True)
m.fit(df)
future = m.make_future_dataframe(periods = 31)
forecast = m.predict(future)
m.plot(forecast)
plt.show()

  • 블로그 방문자를 예측하였고, 생각보다 많이 맞는것을 볼수 있음


3.3 trend와 seasonal data 추출

1
2
3
4
5
6
7
8
9
10
11
12
import seaborn as sns
import matplotlib.pyplot as plt

sns.set_style('whitegrid')
sns.set_palette('husl')

plt.figure(figsize = (10, 6))
for each in ['trend', 'yhat', 'yhat_lower', 'yhat_upper']:
    plt.plot(forecast['ds'], forecast[each], label = each)
    
plt.legend(loc = 'best')
plt.show()

  • 데이터의 trend와 seasonal 데이어틀 보았음
  • trend는 늘어나는 것이 보임


3.4 trend를 중심으로

1
2
3
4
5
6
plt.figure(figsize=(10, 6))
for each in ['trend', 'yhat', 'yearly']:
    plt.plot(forecast['ds'], forecast[each], label = each)

plt.legend(loc = 'best')
plt.show()


3.5 시계열 분석에서는 components 분석이 중요함

1
2
m.plot_components(forecast)
plt.show()

  • trend는 방문자수가 꾸준히 증가하는 방향으로 보임
  • weekly는 평일에 방문자가 많다가 주말엔 없는것으로 보임, 교육블로그이다보니 평일 공부할때 많이들 방문하는것으로 보임
  • yearly는 방학 시즌 (12월 ~ 3월, 6월 ~ 8월)은 방문자가 적고, 확실히 시험 기간에 방문자가 많은것으로 확인됨, 이는 블로그 방문자가 대부분 대학생일것을 예상할수 있음
  • daily는 학교 수업을 듣는 시간에는 잘 방문을 안하고 저녁을 먹고 개인공부 시간에 방문이 많은것으로 파악됨
This post is licensed under CC BY 4.0 by the author.

문장 사이의 거리

정밀도(Precision)와 재현율(Recall)