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()
ds | y | |
---|---|---|
0 | 2017-01-01 | 0.000000 |
1 | 2017-01-02 | 0.103243 |
2 | 2017-01-03 | 0.205382 |
3 | 2017-01-04 | 0.305326 |
4 | 2017-01-05 | 0.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()
ds | hit | |
---|---|---|
0 | 2016-01-01 | 228 |
1 | 2016-01-02 | 304 |
2 | 2016-01-03 | 304 |
3 | 2016-01-04 | 659 |
4 | 2016-01-05 | 769 |
- 약 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는 학교 수업을 듣는 시간에는 잘 방문을 안하고 저녁을 먹고 개인공부 시간에 방문이 많은것으로 파악됨