Pythhon의 일반 고스 상태 공간 모델을 사용한 시간 서열 분석[외인성과 계절성을 고려한 실시례]

이 보도가 해야 할 일

  • 파이톤을 사용하여 일반 고스 상태 공간 모델의 시차 분석을 기술하는 실현 방법
  • statsmodels로 구현
  • 계절성과 외인성을 고려할 때 실시
  • 이론 부분은 참고 문장 소개만 제공
  • 자세한 논의 불가(...)
  • "시간 서열 분석과 상태 공간 모델의 기초 R과 Stan에서 학습한 이론과 실현"
    읽었지만 몰라서 곤란해요!python으로 쓰기!!이런 사람
  • 개시하다


    '시간 서열 분석과 상태 공간 모델의 기초 R과 Stan에서 배운 이론과 실현'(이른바 매본)을 사용해 시간 서열 분석을 배우고 있다.
    그러나 나는 파이토존에 익숙해져서 R의 실현은 건너뛰었고 작가의 블로그에 있는 아래의 글을 참고하여 실시했다.
    -Python 기반 상태 공간 모델: https://logics-of-blue.com/python-state-space-models/
    이 글에서 파이썬 일반 고스 상태 공간 모델의 설치 방법을 파악했지만 외인성이 있을 때 설치 방법과 효과가 없었다.
    따라서 우리는 다른 데이터를 사용하여 외인성 데이터의 설치와 효과를 총괄할 것이다.
    *상태 공간 모델에 대해서는 이 작성자의 다음 기사를 참조하십시오.
    상태 공간 모델의 평가 방법 분류: https://logics-of-blue.com/python-state-space-models/
    칼만 필터의 생각: https://logics-of-blue.com/kalman-filter-concept/
    사용하는 라이브러리는 이쪽부터 시작합니다.구글 colab에 설치합니다.
    import pandas as pd
    import numpy as np
    import os
    import matplotlib.pyplot as plt
    import seaborn as sns
    from matplotlib.pylab import rcParams
    import statsmodels.api as sm
    

    데이터 준비

  • 도쿄전력을 사용한 2019년 전력 수요 데이터: http://www.tepco.co.jp/forecast/index-j.html
  • df = pd.read_csv("data/juyo-2019.csv",encoding="shift-jis")
    df.head()
    
    데이터는 시간마다 한 번씩 나오기 때문에 매일의 데이터로 다시 정리한다.
    groupby 함수를 사용하면 바로 완성할 수 있습니다.그리고 데이터 인덱스를 날짜로 수정합니다.
    df["date"] = pd.to_datetime(df["date"],format="%Y/%m/%d")
    df["power"] = df["power"].values.astype(int)
    daily_data = df.groupby("date")["power"].sum().reset_index()
    daily_data = daily_data.set_index(["date"])
    rcParams["figure.figsize"] = [12,5]
    daily_data.plot()
    

    데이터로 보면 주기적인 톱날을 볼 수 있다.
    이는 7일마다 변동하기 때문에 주치와 관련된 주기로 추정된다.
    휴일인지 아닌지에 따라 전력 수요가 달라지는 것이다.
    또 요일뿐만 아니라 공휴일에도 전력 수요에 영향을 미칠 것으로 보인다.
    명절이 주기적으로 발생하지 않기 때문에 외인성으로 모델링을 할 수 있다.
    위에서 말한 바와 같이 우리는 아래의 모델링을 통해 더욱 높은 정밀도의 모델화를 실현할 것이다.
    - 주기성: 7일마다 발생
    - 외인성: 명절에 무작위로 발생

    계절성과 외인성을 고려하지 않는 상황


    우선 계절성을 고려하지 않고 요일에 모형을 만들어 보자.
    계절성과 외인성을 고려하지 않는 현지 선형 모델을 사용하여 모델링을 한다.이 모델링 상황에서
    #ローカル線形トレンドモデル
    mod_trend = sm.tsa.UnobservedComponents(daily_data,"local linear trend")
    res_trend = mod_trend.fit(method="bfgs")
    
    rcParams["figure.figsize"] = 15,15
    fig = res_trend.plot_components()
    

    그림의 맨 위에는 실제 데이터, 두 번째는 상태, 세 번째는 트렌드 데이터이다.
    주기성을 고려하지 않으면 추세가 엉망진창으로 변했다는 것을 알 수 있다.

    계절적 상황을 고려하다


    이어서 주기적인 상황을 고려한다.Unobserved Components에 seasonal의 매개 변수를 추가하면 완성됩니다.
    여기는 무슨 요일을 고려합니까? 매개 변수는 7입니다.
    그림의 네 번째는 계절성을 나타내는 도표를 추가했다.주기적으로 변동하고 있다는 것을 안다.
    #季節性を入れた,ローカル線形トレンドモデル
    mod_season_trend = sm.tsa.UnobservedComponents(daily_data.power,
                                                  "local linear trend",
                                                  seasonal = 7)
    
    res_season_trend = mod_season_trend.fit(
        method='bfgs', 
        maxiter=1000, 
    )
    
    rcParams["figure.figsize"] = 15,20
    fig = res_season_trend.plot_components()
    

    아까와 가장 큰 차이점은 트렌드 데이터의 톱날이 없어졌다는 것이다.
    주기성을 제거하면 아까보다 추세가 더 좋다는 것을 알 수 있다.
    (주기성 차트에서 매달 첫 번째 데이터 값이 높다는 점에 신경을 많이 썼지만...)
    또 5월 초 level의 그래프가 크게 줄었다.
    컨디션 변화라기보다는 GW의 영향이다.
    따라서 공휴일을 외인성으로 포함하는 모델을 고려해 보자.

    계절성, 외인성을 고려할 때


    마지막으로 외부 요인을 고려할 때의 모델이다.
    공휴일을 외인성으로 고려하다.명절 로고에 가입하기 위해서 저는 jpholiday를 import으로 삼을 것입니다.
    (Google colab을 사용할 때의 코드입니다)
    홀리데이 1의 홀리데이 열을 추가합니다.
    토요일, 일요일은 원래 휴일이기 때문에 휴일 표지를 달지 않는다.
    #祝日フラグを入れる,google colabの場合
    !pip install jpholiday
    import jpholiday
    
    #祝日フラグ
    daily_data["holiday"] = 0
    for i in range(len(daily_data)):
      if daily_data.index[i].dayofweek != 6: #日曜日でない場合のみ
        date_i = daily_data.index[i] #日付
        if jpholiday.is_holiday(date_i): #祝日の場合
          daily_data.loc[date_i,"holiday"] = 1
    daily_data.head()
    
    공휴일이라면 연휴를 생각할 수 없다.
    12~1월의 겨울방학, 5월의 황금주, 8월의 우란분절 휴가를 수동으로 1로 변경한다.
    list1 = daily_data.query("20190101 <= index <= 20190104").index
    list2 = daily_data.query("20190429 <= index <= 20190503").index
    list3 = daily_data.query("20190812 <= index <= 20190816").index
    list4 = daily_data.query("20191230 <= index <= 20191231").index
    
    for i in list1:
      daily_data.loc[i,"holiday"]=1
    for i in list2:
      daily_data.loc[i,"holiday"]=1
    for i in list3:
      daily_data.loc[i,"holiday"]=1
    for i in list4:
      daily_data.loc[i,"holiday"]=1
    
    마지막으로 외원적인 로컬 선형 트렌드 모델을 만들고 그립니다.
    매개 변수에 exog를 넣고 방금 만든 명절 표시를 지정합니다.
    #季節性,外因性を入れたローカル線形トレンドモデル
    mod_season_exog_trend = sm.tsa.UnobservedComponents(
        daily_data.power,
        "local linear trend",
        seasonal=7,
        exog=daily_data.holiday
    )
    
    res_season_exog_trend = mod_season_exog_trend.fit(
        method="bfgs",
        maxiter=1000, 
    )
    
    # 推定された状態・トレンド・季節の影響の描画
    rcParams['figure.figsize'] = 15, 20
    fig = res_season_exog_trend.plot_components()
    

    5월 초순에 눈을 돌리면 주기적인 경우보다 훨씬 낮아질 뿐이다.
    그러나 명절 로고만 더하면 이런 하락은 완전히 억제할 수 없을 것 같다.
    더 개선할 필요는 있지만 지금 내 실력으로는 한계야...

    총결산

  • statsmodel을 사용하여 계절성과 외인성 모델을 실현
  • 전력 수요를 대상으로 계절성을 요일, 외인성을 명절로 실시
  • 주기성 모델이 높은 효과를 실현했다
  • 외인성 모델은 명절에만 부족하고 개선이 필요하다
  • 끝까지 읽어주셔서 감사합니다.

    참고 문장

  • 파이톤 상태 공간 모델: https://logics-of-blue.com/python-state-space-models/
  • 빠른 추세 추출: 파이톤의statsmodels를 통해 시간 서열 분석 입문: https://data.gunosy.io/entry/statsmodel_trend
  • 좋은 웹페이지 즐겨찾기