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

이 Notebook에서는 계절 주기가 있는 시계열 데이터를 예측하는 프로그램을 빌드합니다. NYC 속성 판매 데이터 세트는 NYC Open Data Portal에서 NYC 재무부에서 게시한 2003년부터 2015년까지의 날짜와 함께 사용합니다.

필수 조건

전자 필기장에서 팔로우

다음 두 가지 방법 중 하나를 전자 필기장에서 따를 수 있습니다.

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

기본 제공 Notebook 열기

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

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

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

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

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

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

GitHub에서 Notebook 가져오기

AIsample - Time Series Forecasting.ipynb 는 이 자습서와 함께 제공되는 Notebook입니다.

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

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

코드 실행을 시작하기 전에 Lakehouse를 Notebook에 연결해야 합니다.

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

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

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

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

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

# Use pip to install Prophet
%pip install prophet

2단계: 데이터 로드

데이터 세트

이 Notebook은 NYC Property Sales 데이터 데이터 세트를 사용합니다. NYC Open Data Portal에서 NYC 재무부 에서 게시한 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 이스트 12번가 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는 다음 세 가지 구성 요소로 구성된 분해 가능한 시계열 모델을 사용합니다.

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

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

예언자 모델링 기술에 대한 자세한 내용은 공식 논문을 참조하세요.

데이터 세트를 다운로드하고 Lakehouse에 업로드합니다.

데이터 원본은 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 Lakehouse에 저장합니다.

Important

레이크하우스를 실행하기 전에 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

참고 항목

전자 필기장 세션에서 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 값이 있는 판매를 제거해야 합니다.

  • 데이터 세트는 다양한 건물 클래스를 다룹니다. 그러나 이 전자 필기장은 용어집에 따라 "A" 형식으로 표시된 주거용 건물에 초점을 맞춥니다. 주거용 건물만 포함하도록 데이터 세트를 필터링해야 합니다. 이렇게 하려면 열 또는 building_class_at_present 열을 포함합니다building_class_at_time_of_sale. 데이터만 포함 building_class_at_time_of_sale 해야 합니다.

  • 데이터 세트에는 값이 0이거나 gross_square_feet 값이 total_units 0인 인스턴스가 포함됩니다. 값이 0인 모든 인스턴스를 total_unitsgross_square_units 제거해야 합니다.

  • 일부 열(예: apartment_number, tax_classbuild_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 형식의 is
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_unitsgross_square_feetsales_date. 또한 이름을 으로 바꿔 sales_datemonth야 합니다.

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_pricetotal_unitsgross_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는 큰 데이터 세트를 잘 처리합니다. 그러나 데이터 집계로 인해 데이터 프레임 크기는 더 작습니다. 이는 이제 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단계: 모델 학습 및 추적

모델 맞춤

예언자 입력은 항상 2열 데이터 프레임입니다. 하나의 입력 열은 명명 ds된 시간 열이고, 하나의 입력 열은 값 열입니다 y. 시간 열에는 날짜, 시간 또는 datetime 데이터 형식(예: 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 인스턴스를 만들고 특정 매개 변수(예seasonality_mode: )를 설정한 다음 해당 인스턴스를 데이터 세트에 맞습니다.

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

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

  • MCMC(Markov Chain Monte Carlo) 메서드를 사용하여 계절성 불확실성 추정치를 캡처합니다. 기본적으로, 예언자는 추세와 관찰 소음에 대한 불확실성 추정을 제공 할 수 있지만 계절성에 대한 것은 아닙니다. MCMC는 더 많은 처리 시간이 필요하지만 알고리즘이 계절성 및 추세 및 관찰 노이즈에 대한 불확실성 추정치를 제공할 수 있도록 합니다. 자세한 내용은 예언자 불확실성 간격 설명서를 참조하세요.

  • changepoint_prior_scale 매개 변수를 통해 자동 변경 지점 검색 민감도를 조정합니다. 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의 기계 학습 실험에 대해 자세히 알아봅니다. 포함하려는 단계(예: 이 전자 필기장에서 예언자 모델 맞춤 및 평가)를 결정하면 실험을 실행할 수 있습니다.

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 큰 경우 과잉 맞춤이 발생할 수 있습니다. 따라서 두 번째 그래프가 최적의 선택인 것 같습니다. 이는 두 번째 모델이 가장 적합하다는 것을 의미합니다.

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

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)
  • MEAN 절대 오차(MAE)
  • 평균 절대 백분율 오차(MAPE)
  • 중간 절대 백분율 오차(MDAPE)
  • 대칭 평균 절대 백분율 오차(SMAPE)

yhat_upper 추정을 yhat_lower 사용하여 적용 범위를 평가합니다. 향후 1년을 12번 예측하는 다양한 지평선을 확인합니다.

display(df_metrics[BEST_MODEL_INDEX])

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

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

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

예측 변환기를 사용하여 예측

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

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.")