다음을 통해 공유


시계열 예측 모델 학습 및 평가

이 Notebook에서는 계절 주기가 있는 시계열 데이터를 예측하는 프로그램을 빌드합니다. 뉴욕 재무부가 뉴욕 오픈 데이터 포털에 게시한 2003년부터 2015년까지의 뉴욕 부동산 매매 데이터 세트를 사용합니다.

필수 조건

  • Microsoft Fabric 구독을 구매합니다. 또는 무료 Microsoft Fabric 평가판에 등록합니다.

  • Microsoft Fabric에 로그인합니다.

  • 홈페이지 왼쪽의 환경 전환기를 사용하여 Synapse 데이터 과학 환경으로 전환합니다.

    데이터 과학을 선택할 위치를 보여 주는 환경 전환기 메뉴의 스크린샷.

Notebook에서 따라 하기

다음 두 가지 방법 중 하나로 Notebook에서 따라 할 수 있습니다.

  • Synapse 데이터 과학 환경에서 기본 제공 Notebook을 열고 실행합니다.
  • GitHub에서 Synapse 데이터 과학 환경으로 Notebook을 업로드합니다.

기본 제공 Notebook 열기

이 자습서에는 샘플 시계열 Notebook이 함께 제공됩니다.

Synapse 데이터 과학 환경에서 자습서의 기본 제공 샘플 Notebook을 열려면 다음을 수행합니다.

  1. Synapse 데이터 과학 홈페이지로 이동합니다.

  2. 샘플 사용을 선택합니다.

  3. 해당 샘플을 선택합니다.

    • 샘플이 Python 자습서용인 경우, 기본 엔드 투 엔드 워크플로(Python) 탭에서.
    • 샘플이 R 자습서용인 경우, 엔드 투 엔드 워크플로(R) 탭에서.
    • 샘플이 빠른 자습서용인 경우, 빠른 자습서 탭에서.
  4. 코드 실행을 시작하기 전에 레이크하우스를 Notebook에 연결합니다.

GitHub에서 Notebook 가져오기

이 자습서에는 AIsample - Time Series Forecasting.ipynb Notebook이 함께 제공됩니다.

이 자습서에 함께 제공되는 Notebook을 열려면 데이터 과학 자습서를 위한 시스템 준비의 지침에 따라 Notebook을 작업 영역으로 가져옵니다.

이 페이지에서 코드를 복사하여 붙여 넣으면 새 Notebook을 만들 수 있습니다.

코드 실행을 시작하기 전에 레이크하우스를 Notebook에 연결해야 합니다.

1단계: 사용자 지정 라이브러리 설치

기계 학습 모델을 개발하거나 임시 데이터 분석을 처리할 때 Apache Spark 세션에 대한 사용자 지정 라이브러리(예: 이 Notebook의 prophet)를 신속하게 설치해야 할 수 있습니다. 이렇게 하려면 두 가지 선택 사항이 있습니다.

  1. 인라인 설치 기능(예: %pip, %conda 등)을 사용하여 새 라이브러리를 빠르게 시작할 수 있습니다. 이렇게 하면 현재 Notebook에만 사용자 지정 라이브러리가 설치되고, 작업 영역에는 설치되지 않습니다.
# Use pip to install libraries
%pip install <library name>

# Use conda to install libraries
%conda install <library name>
  1. 또는 Fabric 환경을 만들거나, 공개 소스에서 라이브러리를 설치하거나, 사용자 지정 라이브러리를 업로드한 다음, 작업 영역 관리자가 해당 환경을 작업 영역의 기본값으로 연결할 수 있습니다. 그러면 환경의 모든 라이브러리를 작업 영역의 모든 Notebook 및 Spark 작업 정의에서 사용할 수 있게 됩니다. 환경에 대한 자세한 내용은 Microsoft Fabric에서 환경 생성, 구성 및 사용을 참조하세요.

이 Notebook의 경우 %pip install을 사용하여 prophet 라이브러리를 설치합니다. PySpark 커널은 %pip install 이후에 다시 시작됩니다. 즉, 다른 셀을 실행하기 전에 라이브러리를 설치해야 합니다.

# Use pip to install Prophet
%pip install prophet

2단계: 데이터 로드

데이터 세트

이 Notebook은 뉴욕 부동산 매매 데이터 데이터 세트를 사용합니다. 뉴욕 재무부가 뉴욕 오픈 데이터 포털에 게시한 2003년부터 2015년까지의 데이터를 다룹니다.

데이터 세트에는 13년 동안 뉴욕 부동산 시장에서 이루어진 모든 건물 매매 기록이 포함되어 있습니다. 데이터 세트의 열에 대한 정의는 부동산 매매 파일 용어집을 참조하세요.

자치 구역 동네 building_class_category tax_class block lot eastment building_class_at_present address apartment_number zip_code residential_units commercial_units total_units land_square_feet gross_square_feet year_built tax_class_at_time_of_sale building_class_at_time_of_sale sale_price sale_date
Manhattan 알파벳 도시 07 임대 - 엘리베이터 없는 아파트 0.0 384.0 17.0 C4 225 EAST 2ND STREET 10009.0 10.0 0.0 10.0 2145.0 6670.0 1900.0 2.0 C4 275000.0 2007-06-19
Manhattan 알파벳 도시 07 임대 - 엘리베이터 없는 아파트 2.0 405.0 12.0 C7 508 EAST 12TH STREET 10009.0 28.0 2.0 30.0 3872.0 15428.0 1930.0 2.0 C7 7794005.0 2007-05-21

목표는 기록 데이터를 기반으로 월별 총 매매를 예측하는 모델을 빌드하는 것입니다. 이를 위해 Facebook에서 개발한 오픈 소스 예측 라이브러리인 Prophet을 사용합니다. Prophet은 비선형 추세가 일간, 주간, 연간 계절성 및 휴일 효과에 적합한 가산 모델을 기반으로 합니다. Prophet은 계절적 효과이 강한 시계열 데이터 세트와 여러 계절의 기록 데이터에 가장 적합합니다. 또한 Prophet은 누락된 데이터 및 데이터 이상값을 강력하게 처리합니다.

Prophet은 다음 세 가지 구성 요소로 구성된 분해 가능한 시계열 모델을 사용합니다.

  • 추세: Prophet은 자동 변경 지점 선택을 통해 조각별로 일정한 증가율을 가정합니다.
  • 계절성: 기본적으로 Prophet은 푸리에 급수를 사용하여 주간 및 연간 계절성을 맞춥니다.
  • 휴일: Prophet은 과거와 미래의 모든 휴일을 필요로 합니다. 미래에 휴일이 반복되지 않는 경우, Prophet은 해당 휴일을 예측에 포함하지 않습니다.

이 Notebook은 월간으로 데이터를 집계하므로 휴일을 무시합니다.

Prophet 모델링 기술에 대한 자세한 내용은 공식 문서를 참조하세요.

데이터 세트를 다운로드하고 레이크하우스에 업로드합니다.

데이터 원본은 15개의 .csv 파일로 구성되어 있습니다. 이 파일에는 2003년부터 2015년까지 뉴욕의 5개 자치구의 부동산 매매 기록이 포함되어 있습니다. 편의를 위해, nyc_property_sales.tar 파일은 이러한 모든 .csv 파일을 하나의 파일로 압축하여 보관합니다. 공개적으로 사용 가능한 Blob Storage는 이 .tar 파일을 호스트합니다.

이 코드 셀에 표시된 매개 변수를 사용하면 이 Notebook을 다른 데이터 세트에 쉽게 적용할 수 있습니다.

URL = "https://synapseaisolutionsa.blob.core.windows.net/public/NYC_Property_Sales_Dataset/"
TAR_FILE_NAME = "nyc_property_sales.tar"
DATA_FOLDER = "Files/NYC_Property_Sales_Dataset"
TAR_FILE_PATH = f"/lakehouse/default/{DATA_FOLDER}/tar/"
CSV_FILE_PATH = f"/lakehouse/default/{DATA_FOLDER}/csv/"

EXPERIMENT_NAME = "aisample-timeseries" # MLflow experiment name

이 코드는 공개적으로 사용 가능한 버전의 데이터 세트를 다운로드한 다음 해당 데이터 세트를 Fabric 레이크하우스에 저장합니다.

중요 사항

실행하기 전에 Notebook에 레이크하우스를 추가해야 합니다. 그렇게 하지 않으면 오류가 발생합니다.

import os

if not os.path.exists("/lakehouse/default"):
    # Add a lakehouse if the notebook has no default lakehouse
    # A new notebook will not link to any lakehouse by default
    raise FileNotFoundError(
        "Default lakehouse not found, please add a lakehouse for the notebook."
    )
else:
    # Verify whether or not the required files are already in the lakehouse, and if not, download and unzip
    if not os.path.exists(f"{TAR_FILE_PATH}{TAR_FILE_NAME}"):
        os.makedirs(TAR_FILE_PATH, exist_ok=True)
        os.system(f"wget {URL}{TAR_FILE_NAME} -O {TAR_FILE_PATH}{TAR_FILE_NAME}")

    os.makedirs(CSV_FILE_PATH, exist_ok=True)
    os.system(f"tar -zxvf {TAR_FILE_PATH}{TAR_FILE_NAME} -C {CSV_FILE_PATH}")

이 Notebook의 런타임 기록을 시작합니다.

# Record the notebook running time
import time

ts = time.time()

MLflow 실험 추적 설정

MLflow 로깅 기능을 확장하기 위해, 자동 로깅은 학습 중에 기계 학습 모델의 입력 매개 변수 및 출력 메트릭 값을 자동으로 캡처합니다. 그런 다음 이 정보는 작업 영역에 기록되며, MLflow API 또는 작업 영역의 해당 실험에서 액세스하여 시각화할 수 있습니다. 자동 로깅에 대한 자세한 내용을 보려면 이 리소스를 방문하세요.

# Set up the MLflow experiment
import mlflow

mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True)  # Disable MLflow autologging

참고 항목

Notebook 세션에서 Microsoft Fabric 자동 로깅을 사용하지 않도록 설정하려면 mlflow.autolog()을 호출하고 disable=True를 설정합니다.

레이크하우스에서 원시 날짜 데이터 읽기

df = (
    spark.read.format("csv")
    .option("header", "true")
    .load("Files/NYC_Property_Sales_Dataset/csv")
)

3단계: 탐색적 데이터 분석 시작

데이터 세트를 검토하려면 데이터 하위 집합을 수동으로 검사하여 해당 데이터 세트를 더 잘 이해할 수 있습니다. display 함수를 사용하여 DataFrame을 인쇄할 수 있습니다. 또한 차트 보기를 표시하여 데이터 세트의 하위 집합을 쉽게 시각화할 수 있습니다.

display(df)

데이터 세트를 수동으로 검토하면 다음과 같은 몇 가지 초기 관찰 결과가 나옵니다.

  • 판매 가격이 $0.00인 경우. 용어집에 따르면 이는 현금 대가 없이 소유권을 이전하는 것을 의미합니다. 즉, 거래에 현금이 유입되지 않았습니다. 데이터 세트에서 $0.00 sales_price 값을 가진 매매를 제거해야 합니다.

  • 데이터 세트는 다양한 건물 유형을 포괄합니다. 그러나 이 Notebook은 용어집에 따르면 유형 ‘A’로 표시된 주거용 건물에 초점을 맞춥니다. 주거용 건물만 포함하도록 데이터 세트를 필터링해야 합니다. 이렇게 하려면 building_class_at_time_of_sale 열 또는 building_class_at_present 열을 포함합니다. building_class_at_time_of_sale 데이터만 포함해야 합니다.

  • 데이터 세트에는 total_units 값이 0이거나 gross_square_feet 값이 0인 인스턴스가 포함되어 있습니다. total_units 또는 gross_square_units 값이 0인 모든 인스턴스를 제거해야 합니다.

  • 일부 열(예: apartment_number, tax_class, build_class_at_present 등)에는 누락된 값이나 NULL 값이 있습니다. 누락된 데이터에 사무적 오류나 존재하지 않는 데이터와 관련이 있다고 가정합니다. 분석은 이러한 누락된 값에 의존하지 않으므로 무시해도 됩니다.

  • sale_price 열은 문자열로 저장되며, 앞에 ‘$’ 문자가 붙습니다. 분석을 계속하려면 이 열을 숫자로 표시합니다. sale_price 열을 정수로 캐스팅해야 합니다.

유형 전환 및 필터링

식별된 문제 중 일부를 해결하려면 필요한 라이브러리를 가져옵니다.

# Import libraries
import pyspark.sql.functions as F
from pyspark.sql.types import *

매매 데이터를 문자열에서 정수로 캐스트

정규식을 사용하여 문자열의 숫자 부분을 달러 기호(예: 문자열 $300,000, 분할 $300,000)에서 구분한 다음 숫자 부분을 정수로 캐스팅합니다.

다음으로, 이러한 모든 조건을 충족하는 인스턴스만 포함하도록 데이터를 필터링합니다.

  1. sales_price가 0보다 큰 경우
  2. total_units가 0보다 큰 경우
  3. gross_square_feet가 0보다 큰 경우
  4. building_class_at_time_of_sale는 유형 A입니다.
df = df.withColumn(
    "sale_price", F.regexp_replace("sale_price", "[$,]", "").cast(IntegerType())
)
df = df.select("*").where(
    'sale_price > 0 and total_units > 0 and gross_square_feet > 0 and building_class_at_time_of_sale like "A%"'
)

월별 집계

데이터 리소스는 매일 부동산 매매를 추적하지만 이 접근 방식은 이 Notebook에 비해 너무 세분화되어 있습니다. 대신 월 단위로 데이터를 집계합니다.

먼저, 날짜 값을 변경하여 월간 및 연간 데이터만 표시합니다. 날짜 값에는 여전히 연간 데이터가 포함됩니다. 예를 들어 2005년 12월과 2006년 12월을 구분할 수 있습니다.

또한 분석과 관련된 열만 유지합니다. 여기에는 sales_price, total_units, gross_square_feet, sales_date가 포함됩니다. 또한 sales_date의 이름을 month로 바꿔야 합니다.

monthly_sale_df = df.select(
    "sale_price",
    "total_units",
    "gross_square_feet",
    F.date_format("sale_date", "yyyy-MM").alias("month"),
)
display(monthly_sale_df)

월별로 sale_price, total_units, gross_square_feet 값을 집계합니다. 그런 다음 month로 데이터를 그룹화하고 각 그룹 내의 모든 값을 합산합니다.

summary_df = (
    monthly_sale_df.groupBy("month")
    .agg(
        F.sum("sale_price").alias("total_sales"),
        F.sum("total_units").alias("units"),
        F.sum("gross_square_feet").alias("square_feet"),
    )
    .orderBy("month")
)

display(summary_df)

Pyspark에서 Pandas로 전환

Pyspark DataFrames는 대규모 데이터 세트를 잘 처리합니다. 그러나 데이터 집계로 인해 DataFrame 크기는 더 작습니다. 이는 이제 Pandas DataFrames를 사용할 수 있음을 시사합니다.

이 코드는 Pyspark DataFrame에서 Pandas DataFrame으로 데이터 세트를 캐스팅합니다.

import pandas as pd

df_pandas = summary_df.toPandas()
display(df_pandas)

시각화

뉴욕의 부동산 거래 추세를 조사하면 데이터를 더 잘 이해할 수 있습니다. 이를 통해 잠재적인 패턴과 계절성 추세에 대한 인사이트를 얻을 수 있습니다. 리소스에서 Microsoft Fabric 데이터 시각화에 대해 자세히 알아봅니다.

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

f, (ax1, ax2) = plt.subplots(2, 1, figsize=(35, 10))
plt.sca(ax1)
plt.xticks(np.arange(0, 15 * 12, step=12))
plt.ticklabel_format(style="plain", axis="y")
sns.lineplot(x="month", y="total_sales", data=df_pandas)
plt.ylabel("Total Sales")
plt.xlabel("Time")
plt.title("Total Property Sales by Month")

plt.sca(ax2)
plt.xticks(np.arange(0, 15 * 12, step=12))
plt.ticklabel_format(style="plain", axis="y")
sns.lineplot(x="month", y="square_feet", data=df_pandas)
plt.ylabel("Total Square Feet")
plt.xlabel("Time")
plt.title("Total Property Square Feet Sold by Month")
plt.show()

탐색적 데이터 분석에서 얻은 관찰 결과 요약

  • 데이터는 연간 주기에 따라 명확한 정기 패턴을 보여 줍니다. 즉, 데이터에 연간 계절성이 있습니다.
  • 여름철은 겨울철에 비해 매매량이 더 많은 것으로 나타납니다.
  • 매매가 많았던 연도와 매매가 적었던 연도를 비교했을 때, 매매가 많았던 연도의 매매가 많았던 월과 매매가 적었던 월의 매매 차이는 매매가 적었던 연도의 매매가 많았던 월과 매매가 적었던 월의 매매 차이보다 절대적으로 더 큽니다.

예를 들어 2004년에 매매가 가장 많았던 월과 매매가 가장 적었던 월 간의 매출 차이는 약 다음과 같습니다.

$900,000,000 - $500,000,000 = $400,000,000

2011년의 경우 수익 차이 계산은 다음과 같습니다.

$400,000,000 - $300,000,000 = $100,000,000

이것은 나중에 배수가산 계절성 효과 중에서 하나를 결정해야 할 때 중요해집니다.

4단계: 모델 학습 및 추적

모델 맞춤

Prophet 입력은 항상 2열로 구성된 데이터 프레임입니다. 하나의 입력 열은 ds라는 이름의 시간 열이고, 하나의 입력 열은 y라는 이름의 값 열입니다. 시간 열에는 날짜, 시간 또는 날짜/시간 데이터 형식(예: YYYY_MM)이 있어야 합니다. 여기에 있는 데이터 세트는 해당 조건을 충족합니다. 값 열은 숫자 데이터 형식이어야 합니다.

모델 맞춤의 경우 시간 열의 이름을 ds로, 값 열의 이름을 y로 변경하고 데이터를 Prophet에 전달해야 합니다. 자세한 내용은 Prophet Python API 설명서를 참조하세요.

df_pandas["ds"] = pd.to_datetime(df_pandas["month"])
df_pandas["y"] = df_pandas["total_sales"]

Prophet은 Scikit-learn 규칙을 따릅니다. 먼저, Prophet의 새 인스턴스를 만들고 특정 매개 변수(예: seasonality_mode)를 설정한 다음, 해당 인스턴스를 데이터 세트에 맞춥니다.

  • 상수 가산 요소는 Prophet의 기본 계절성 효과이지만 계절성 효과 매개 변수에는 '배수' 계절성을 사용해야 합니다. 이전 섹션의 분석에 따르면 계절성 진폭의 변화로 인해 단순 가산 계절성은 데이터에 전혀 맞지 않는 것으로 나타났습니다.

  • 데이터가 월별로 집계되었으므로 weekly_seasonality 매개 변수를 off로 설정합니다. 따라서 주간 데이터를 사용할 수 없습니다.

  • MCMC(마르코프 연쇄 몬테카를로) 방법을 사용하여 계절성 불확실성 추정치를 파악합니다. 기본적으로, Prophet은 추세와 관찰 노이즈에 대한 불확실성 추정치를 제공할 수 있지만 계절성에 대한 추정치는 제공할 수 없습니다. MCMC는 더 많은 처리 시간이 필요하지만 알고리즘이 계절성, 추세 및 관찰 노이즈에 대한 불확실성 추정치를 제공할 수 있습니다. 자세한 내용은 Prophet 불확실성 간격 설명서를 참조하세요.

  • changepoint_prior_scale 매개 변수를 통해 자동 변경 지점 검색 민감도를 조정합니다. Prophet 알고리즘은 데이터에서 궤적이 갑자기 변경되는 인스턴스를 자동으로 찾으려고 시도합니다. 올바른 값을 찾기가 어려울 수 있습니다. 이 문제를 해결하려면 다양한 값을 시도한 다음 최상의 성능을 가진 모델을 선택하면 됩니다. 자세한 내용은 Prophet 추세 변경 지점 설명서를 참조하세요.

from prophet import Prophet

def fit_model(dataframe, seasonality_mode, weekly_seasonality, chpt_prior, mcmc_samples):
    m = Prophet(
        seasonality_mode=seasonality_mode,
        weekly_seasonality=weekly_seasonality,
        changepoint_prior_scale=chpt_prior,
        mcmc_samples=mcmc_samples,
    )
    m.fit(dataframe)
    return m

교차 유효성 검사

Prophet에는 기본 제공 교차 유효성 검사 도구가 있습니다. 이 도구는 예측 오류를 추정하고 최상의 성능을 가진 모델을 찾을 수 있습니다.

교차 유효성 검사 기술은 모델 효율성의 유효성을 검사할 수 있습니다. 이 기술은 데이터 세트의 하위 집합에서 모델을 학습시키고, 이전에 보이지 않았던 데이터 세트의 하위 집합에서 테스트를 실행합니다. 이 기술은 통계 모델이 독립적인 데이터 세트로 얼마나 잘 일반화되는지 확인할 수 있습니다.

교차 유효성 검사를 위해, 학습 데이터 세트의 일부가 아닌 특정 데이터 세트 샘플을 예약합니다. 그런 다음, 배포 전에 해당 샘플에서 학습된 모델을 테스트합니다. 그러나 이 접근 방식은 시계열 데이터에는 효과가 없습니다. 모델이 2005년 1월과 2005년 3월의 데이터를 보았고 사용자가 2005년 2월을 예측하려고 시도하면, 모델은 데이터 추세가 어디로 이어지는지 볼 수 있으므로 모델이 본질적으로 속임수를 사용할 수 있기 때문입니다. 실제 응용에서는 보이지 않는 영역처럼 미래를 예측하는 것이 목표입니다.

이를 처리하고 테스트를 안정적으로 만들려면 날짜를 기준으로 데이터 세트를 분할합니다. 학습에 특정 날짜(예: 처음 11년 데이터)까지 데이터 세트를 사용한 다음, 보이지 않는 나머지 데이터를 예측에 사용합니다.

이 시나리오에서는 11년간의 학습 데이터로 시작한 다음, 1년 기간을 사용하여 월별 예측을 수행합니다. 특히 학습 데이터에는 2003년부터 2013년까지의 모든 항목이 포함되어 있습니다. 그런 다음, 첫 번째 실행에서는 2014년 1월부터 2015년 1월까지의 예측을 처리합니다. 다음 실행에서는 2014년 2월부터 2015년 2월까지의 예측을 처리합니다.

학습된 세 모델 각각에 대해 이 프로세스를 반복하여 어떤 모델이 가장 성능이 좋은지 확인합니다. 그런 다음 이러한 예측을 실제 값과 비교하여 가장 좋은 모델의 예측 품질을 설정합니다.

from prophet.diagnostics import cross_validation
from prophet.diagnostics import performance_metrics

def evaluation(m):
    df_cv = cross_validation(m, initial="4017 days", period="30 days", horizon="365 days")
    df_p = performance_metrics(df_cv, monthly=True)
    future = m.make_future_dataframe(periods=12, freq="M")
    forecast = m.predict(future)
    return df_p, future, forecast

MLflow를 통해 모델 로그

모델을 기록하여 해당 매개 변수를 추적하고 나중에 사용할 수 있도록 모델을 저장합니다. 모든 관련 모델 정보는 실험 이름 아래 작업 영역에 기록됩니다. 모델, 매개 변수, 메트릭은 MLflow 자동 로깅 항목과 함께 하나의 MLflow 실행에 저장됩니다.

# Setup MLflow
from mlflow.models.signature import infer_signature

실험 수행

기계 학습 실험은 관련된 모든 기계 학습 실행에 대한 조직 및 제어의 기본 단위 역할을 합니다. 실행은 모델 코드의 단일 실행에 해당합니다. 기계 학습 실험 추적은 다양한 실험과 해당 구성 요소를 관리하는 것을 의미합니다. 여기에는 매개 변수, 메트릭, 모델 및 기타 아티팩트가 포함되며 특정 기계 학습 실험의 필수 구성 요소를 구성하는 데 도움이 됩니다. 또한 기계 학습 실험 추적을 사용하면 저장된 실험으로 과거 결과를 쉽게 복제할 수 있습니다. Microsoft Fabric의 기계 학습 실험에 대해 자세히 알아봅니다. 포함하려는 단계(예: 이 Notebook에서 Prophet 모델 맞춤 및 평가)를 결정하면 실험을 실행할 수 있습니다.

model_name = f"{EXPERIMENT_NAME}-prophet"

models = []
df_metrics = []
forecasts = []
seasonality_mode = "multiplicative"
weekly_seasonality = False
changepoint_priors = [0.01, 0.05, 0.1]
mcmc_samples = 100

for chpt_prior in changepoint_priors:
    with mlflow.start_run(run_name=f"prophet_changepoint_{chpt_prior}"):
        # init model and fit
        m = fit_model(df_pandas, seasonality_mode, weekly_seasonality, chpt_prior, mcmc_samples)
        models.append(m)
        # Validation
        df_p, future, forecast = evaluation(m)
        df_metrics.append(df_p)
        forecasts.append(forecast)
        # Log model and parameters with MLflow
        mlflow.prophet.log_model(
            m,
            model_name,
            registered_model_name=model_name,
            signature=infer_signature(future, forecast),
        )
        mlflow.log_params(
            {
                "seasonality_mode": seasonality_mode,
                "mcmc_samples": mcmc_samples,
                "weekly_seasonality": weekly_seasonality,
                "changepoint_prior": chpt_prior,
            }
        )
        metrics = df_p.mean().to_dict()
        metrics.pop("horizon")
        mlflow.log_metrics(metrics)

속성 패널의 스크린샷.

Prophet을 통해 모델 시각화

Prophet에는 모델 맞춤 결과를 표시할 수 있는 기본 제공 시각화 함수가 있습니다.

검은색 점은 모델을 학습시키는 데 사용되는 데이터 요소를 나타냅니다. 파란색 선은 예측이며 연한 파란색 영역은 불확실성 간격을 나타냅니다. changepoint_prior_scale 값이 서로 다른 세 가지 모델을 빌드했습니다. 이러한 세 가지 모델의 예측은 이 코드 블록의 결과에 표시됩니다.

for idx, pack in enumerate(zip(models, forecasts)):
    m, forecast = pack
    fig = m.plot(forecast)
    fig.suptitle(f"changepoint = {changepoint_priors[idx]}")

첫 번째 그래프에서 가장 작은 changepoint_prior_scale 값은 추세 변화의 과소 적합으로 이어집니다. 세 번째 그래프에서 가장 큰 changepoint_prior_scale의 경우 과대 적합으로 이어질 수 있습니다. 따라서 두 번째 그래프가 최적의 선택인 것 같습니다. 이는 두 번째 모델이 가장 적합하다는 것을 의미합니다.

또한 Prophet은 기본 추세와 계절성을 쉽게 시각화할 수 있습니다. 두 번째 모델의 시각화는 이 코드 블록의 결과에 표시됩니다.

BEST_MODEL_INDEX = 1  # Set the best model index according to the previous results
fig2 = models[BEST_MODEL_INDEX].plot_components(forecast)

가격 책정 데이터의 연간 추세 그래프 스크린샷.

이러한 그래프에서 연한 파란색 음영은 불확실성을 반영합니다. 위쪽 그래프는 강력한 장기 진동 추세를 보여줍니다. 몇 년에 걸쳐 매매량이 증가하고 감소합니다. 아래쪽 그래프는 매매가 2월과 9월에 정점을 찍으며 해당 월에 연간 최대값에 도달하는 경향이 있음을 보여줍니다. 해당 월 직후인 3월과 10월에는 해당 연도의 최저치로 떨어집니다.

다음과 같은 다양한 메트릭을 사용하여 모델의 성능을 평가합니다.

  • MSE(평균 제곱 오차)
  • RMSE(제곱 평균 오차)
  • MAE(평균 절대 오차)
  • MAPE(평균 절대 백분율 오차)
  • MDAPE(중간 절대 백분율 오차)
  • SMAPE(대칭 평균 절대 백분율 오차)

yhat_loweryhat_upper 추정치를 사용하여 적용 범위를 평가합니다. 향후 1년을 12번 예측하는 다양한 기간에 주목합니다.

display(df_metrics[BEST_MODEL_INDEX])

MAPE 메트릭을 사용하면 이 예측 모델의 경우 한 달을 미래로 확장하는 예측에는 일반적으로 약 8%의 오류가 수반됩니다. 그러나 미래로 1년 후 예측의 경우 오류가 약 10%로 증가합니다.

5단계: 모델 점수 매기기 및 예측 결과 저장

이제 모델의 점수를 매기고 예측 결과를 저장합니다.

예측 변환기를 통해 예측하기

이제 모델을 사용하여 예측을 수행할 수 있습니다. 사용자는 모든 컴퓨팅 엔진에서 일괄 처리 채점을 지원하는 확장 가능한 Microsoft Fabric 함수인 PREDICT를 사용하여 기계 학습 모델을 운영할 수 있습니다. 이 리소스에서 PREDICT에 대한 자세한 내용과 Microsoft Fabric 내에서 사용하는 방법을 알아볼 수 있습니다.

from synapse.ml.predict import MLFlowTransformer

spark.conf.set("spark.synapse.ml.predict.enabled", "true")

model = MLFlowTransformer(
    inputCols=future.columns.values,
    outputCol="prediction",
    modelName=f"{EXPERIMENT_NAME}-prophet",
    modelVersion=BEST_MODEL_INDEX,
)

test_spark = spark.createDataFrame(data=future, schema=future.columns.to_list())

batch_predictions = model.transform(test_spark)

display(batch_predictions)
# Code for saving predictions into lakehouse
batch_predictions.write.format("delta").mode("overwrite").save(
    f"{DATA_FOLDER}/predictions/batch_predictions"
)
# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")