코딩하는 타코야끼

[스터디 노트] Week7_1일차 [Prophet] - EDA(시계열 분석) 본문

zero-base 데이터 취업 스쿨/스터디 노트

[스터디 노트] Week7_1일차 [Prophet] - EDA(시계열 분석)

가스오부시 2023. 8. 16. 02:15
728x90
반응형

1. 함수 기초 이론 및 실습


📍 전역변수, 지역변수

  • 전역 변수(global variable)는 함수 안에서나 클래스 안에서가 아닌, 프로그램의 최상위 레벨에서 정의된 변수를 의미합니다. 전역 변수는 프로그램 어디에서나 접근이 가능하며, 함수 내부에서 전역 변수를 수정하려면  global  키워드를 사용해야 합니다
# 전역변수(global)
a = 1

def edit_a(i):
    # 지역변수(local)
    global a
    a = i

edit_a(2)
print(a)
>>>
2

❗️주의

  • 가능하면 전역 변수의 사용을 최소화하는 것이 좋습니다. 전역 변수를 과도하게 사용하면 코드의 유지 보수가 어려워지고 버그의 원인이 될 수 있습니다.
  • 함수나 클래스 내에서 전역 변수를 수정할 필요가 있을 때만  global   키워드를 사용하면 됩니다. 단순히 전역 변수의 값을 읽어오는 경우에는  global  키워드가 필요 없습니다.

📍 함수 기능 확인

  • 함수 괄호안에 커서를 놓고 'shift + tab'을 누르면 그 함수에 대한 설명(Docstring)이 나온다
np.arange()
plotSinWave1()

📍 삼각함수의 표준형

📎 삼각함수 함수화

# sin 함수를 구성하기 위해 필요한 인자들을 def의 입력변수로 받는다.
def plotSinWave1(amp, freq, end_time, sample_time, start_time, bias):
    """
    plot sine wave
    y = a sin(2 pi f t + t_0) + b
    """
    time = np.arange(start_time, end_time, sample_time) + bias
    result = amp * np.sin(2 * np.pi * freq * time + start_time) + bias
    
    plt.figure(figsize = (12, 6))
    plt.plot(time, result)
    plt.grid(True)
    plt.xlabel("time")
    plt.ylabel("sin")
    plt.title(
    str(amp) + "*sin(2*pi*" + str(freq) + "*t+" + str(start_time) + ")+" + str(bias))
    plt.show()

⚡️ 출력

plotSinWave1(2, 1, 10, 0.01, 0.5, 0)

📎 삼각함수 함수화( **kwargs )

  • 사용자가 end_time 라는 변수명을 지정했다면 그것을 사용하고 아니면 1을 사용한다.
  • 변수명 지정이 없을 시 Default 값으로 1을 정의한다는 뜻.
def plotSinWave2(**kwargs):
    """
    plot sine wave
    y = a sin(2 pi f t + t_0) + b
    """
    end_time = kwargs.get("end_time", 1)
    sample_time = kwargs.get("sample_time", 0.01)
    amp = kwargs.get("amp", 1)
    freq = kwargs.get("freq", 1)
    start_time = kwargs.get("start_time", 0)
    bias = kwargs.get("bias", 0)
    figsize = kwargs.get("figsize", (12, 6))
    
    time = np.arange(start_time, end_time, sample_time) + bias
    result = amp * np.sin(2 * np.pi * freq * time + start_time) + bias
    
    plt.figure(figsize = (12, 6))
    plt.plot(time, result)
    plt.grid(True)
    plt.xlabel("time")
    plt.ylabel("sin")
    plt.title(
    str(amp) + "*sin(2*pi*" + str(freq) + "*t+" + str(start_time) + ")+" + str(bias))
    plt.show()

⚡️ 출력

plotSinWave2()


2. 함수 모듈 import

  • .py 파일 맨 아래에 실행문 코드를 작성해야 모듈을 불러왔을때 실행 가능.
  • 실행문

  • __ ” : 던던 → 예약문

📎 모듈 만들기

%%writefile ./drawSinWave.py

import numpy as np
import matplotlib.pyplot as plt

def plotSinWave2(**kwargs):
    """
    plot sine wave
    y = a sin(2 pi f t + t_0) + b
    """
		# 변수 정의
    end_time = kwargs.get("end_time", 1)
    sample_time = kwargs.get("sample_time", 0.01)
    amp = kwargs.get("amp", 1)
    freq = kwargs.get("freq", 1)
    start_time = kwargs.get("start_time", 0)
    bias = kwargs.get("bias", 0)
    figsize = kwargs.get("figsize", (12, 6))
    
		# 타임 및 함수 결과 정의
    time = np.arange(start_time, end_time, sample_time) + bias
    result = amp * np.sin(2 * np.pi * freq * time + start_time) + bias

    # 시각화
    plt.figure(figsize = (12, 6))
    plt.plot(time, result)
    plt.grid(True)
    plt.xlabel("time")
    plt.ylabel("sin")
    plt.title("한글테스트" +
    str(amp) + "*sin(2*pi*" + str(freq) + "*t+" + str(start_time) + ")+" + str(bias))
    plt.show()
    
# 실행문
if __name__ == "__main__":
    print("Hello world")
    print("This is test graph!!")
    plotSinWave2(emp = 1 , endTime = 2)

⚡️ item으로 실행 시

 

⚡️ 주피터 노트북으로 실행 시

import drawSinWave as ds

ds.plotSinWave2()

 

📎 한글 폰트 적용하는 모듈 만들기

%%writefile ./set_matplotlib_hangul.py

import platform
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc

path = "c:/Windows/Fonts/malgun.ttf"

if platform.system() == "Darwin":
    print("Hangil OK in your MAC!!!")
    rc("font", family="Arial Unicode MS")
elif platform.system() == "Windows":
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc("font", family=font_name)
else:
    print("Unknown system.. sorry~~~")
    
plt.rcParams["axes.unicode_minus"] = False

⚡️ 출력

import set_matplotlib_hangul

plt.title("한글")


3. Prophet

  • Prophet은 Facebook에서 개발한 시계열 예측을 위한 오픈 소스 도구입니다.
  • Prophet은 계절성, 휴일 및 특정 이벤트의 영향을 고려하여 시계열 데이터의 트렌드를 예측하는 데 특화되어 있습니다.
    • ds: 날짜 열
    • y: 예측하려는 값
  • Prophet은 많은 실제 시나리오에서 효과적인 결과를 보이며, 특히 큰 시계열 데이터나 누락된 데이터 포인트, 큰 계절성 변동성이 있는 데이터에 잘 작동합니다

📍 Prophet 설치

# 터미널 가상환경 활성화 이후 설치
pip install prophet

📍 import

  • 패키지를 성공적으로 설치한 후, Python 코드 내에서 다음과 같이 Prophet을 임포트할 수 있습니다.
from prophet import Prophet

📍 Prophet 기초

📎 DataFrame 만들기

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

time = np.linspace(0, 1, 365*2)
result = np.sin(2*np.pi*12*time)
ds = pd.date_range("2018-01-01", periods=365*2, freq="D")
df = pd.DataFrame({
    "ds": ds, 
    "y": result
})
df.head()

⚡️ 시각화

df["y"].plot(figsize=(10, 6))


📍 Prophet 학습 ( m.fit( ) )

# import 
from prophet import Prophet

# 객체 생성
m = Prophet(yearly_seasonality = True, daily_seasonality = True)

# 객체를 df 내용을 바탕으로 학습
m.fit(df)

# 30 간격으로 미래 예측
future = m.make_future_dataframe(periods = 30)

# 모델 예측
forecast = m.predict(future)

# 시각화 출력
m.plot(forecast)


📍 예측 응용

  • 기존 result에 time 과 평균이 0이고 표준 편차가 0.25인 정규 분포에서 730개의 샘플을 생성하는 값을 추가
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("2018-01-01", periods=365*2, freq="D")
df = pd.DataFrame({
    "ds": ds, 
    "y": result
})
df['y'].plot(figsize=(10, 6));

⚡️ 예측

from prophet import Prophet

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


4. 시계열 데이터 (웹 유입량)

import pandas as pd
import pandas_datareader as web
import numpy as np
import matplotlib.pyplot as plt

from prophet import Prophet
from datetime import datetime

%matplotlib inline

# csv 핑크웹 데이터 읽어오기
pinkwink_web = pd.read_csv("./05_PinkWink_Web_Traffic.csv",
                         encoding="utf-8",
                         thousands=",",
                         names=["data", "hit"],
                         index_col=0)

# 결측치 제거
pinkwink_web = pinkwink_web[pinkwink_web["hit"].notnull()]

# 전테 데이터 그려보기
pinkwink_web["hit"].plot(figsize=(12, 4), grid=True)


📍 trend 분석을 시각화하기 위한 x축 값을 만들기

time = np.arange(0, len(pinkwink_web))
traffic = pinkwink_web["hit"].values
fx = np.linspace(0, time[-1], 1000) # time[-1]은 364

📍 에러를 계산할 함수

def error(f, x, y):
    return np.sqrt(np.mean((f(x) - y) ** 2))

📍 np.polyfit, np.poly1d

f1p = np.polyfit(time, traffic, 1)
f1 = np.poly1d(f1p)
# poly1d([  2.94751137, 678.39950595])

f2p = np.polyfit(time, traffic, 2)
f2 = np.poly1d(f2p)

f3p = np.polyfit(time, traffic, 3)
f3 = np.poly1d(f3p)

f15p = np.polyfit(time, traffic, 15)
f15 = np.poly1d(f15p)

print(error(f1, time, traffic))
print(error(f2, time, traffic))
print(error(f3, time, traffic))
print(error(f15, time, traffic))
>>>
430.8597308110963
430.6284101894695
429.53280466762925
330.4777302323968

⚡️ 출력

plt.figure(figsize=(12, 4))
plt.scatter(time, traffic, s=10)
plt.plot(fx, f1(fx), lw=4, label="f1")
plt.plot(fx, f2(fx), lw=4, label="f2")
plt.plot(fx, f3(fx), lw=4, label="f3")
plt.plot(fx, f15(fx), lw=4, label="f15")

plt.grid(True, linestyle="-", color="0.75")
plt.legend(loc=2)
plt.show()


📍예측 응용

df = pd.DataFrame({
    "ds": pinkwink_web.index,
    "y": pinkwink_web["hit"]
})
df

# 인덱스 초기화
df.reset_index(inplace=True)

# ds 값 형태 변경
df["ds"] = pd.to_datetime(df["ds"], format="%y. %m. %d.")

# 인덱스 초기화로 인한 불필요한 열 제거
del df["data"]

df.head()

# 객체 정의 및 학습
m = Prophet(yearly_seasonality=True, daily_seasonality=True)
m.fit(df)

# 60일에 해당하는 데이터 예측
future = m.make_future_dataframe(periods=60)

# 예측 결과는 상한/하한의 범위를 포함해서 얻어진다
forecast = m.predict(future)
forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail()

m.plot(forecast)

📍m.plot_components( )

m.plot_components(forecast)

반응형