🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Facebook Prophet 완벽 가이드 - 슬라이드 1/11
A

AI Generated

2025. 12. 3. · 15 Views

Facebook Prophet 완벽 가이드

Facebook에서 개발한 시계열 예측 라이브러리 Prophet의 핵심 개념부터 실무 활용까지 다룹니다. 초급 개발자도 쉽게 따라할 수 있도록 단계별로 설명합니다.


목차

  1. Prophet_소개와_설치
  2. 기본_예측_수행하기
  3. 예측_결과_시각화
  4. 계절성_상세_설정
  5. 휴일_효과_반영하기
  6. 외부_변수_추가하기
  7. 트렌드_변화점_감지
  8. 모델_성능_평가하기
  9. 하이퍼파라미터_튜닝
  10. 예측_결과_저장과_활용

1. Prophet 소개와 설치

데이터 분석팀에 새로 합류한 김개발 씨는 첫 번째 업무로 다음 분기 매출 예측을 맡게 되었습니다. 엑셀로 추세선을 그려봤지만, 정확도가 너무 낮아 고민이 깊어졌습니다.

이때 선배 박시니어 씨가 다가와 한마디 건넸습니다. "Prophet 써봤어요?

Facebook에서 만든 시계열 예측 라이브러리인데, 초보자도 쉽게 쓸 수 있어요."

Prophet은 Facebook에서 2017년에 공개한 오픈소스 시계열 예측 라이브러리입니다. 마치 자동차의 자동 변속기처럼, 복잡한 시계열 분석을 자동으로 처리해줍니다.

트렌드, 계절성, 휴일 효과를 자동으로 감지하여 비전문가도 정확한 예측 모델을 만들 수 있습니다.

다음 코드를 살펴봅시다.

# Prophet 설치 및 기본 임포트
# pip install prophet 으로 설치합니다

from prophet import Prophet
import pandas as pd

# 데이터 준비 - Prophet은 ds(날짜)와 y(값) 컬럼이 필요합니다
df = pd.DataFrame({
    'ds': pd.date_range('2023-01-01', periods=365, freq='D'),
    'y': [100 + i * 0.5 + (i % 7) * 10 for i in range(365)]
})

# 모델 생성 및 학습
model = Prophet()
model.fit(df)

print("Prophet 모델 학습 완료!")

김개발 씨는 입사한 지 한 달이 채 안 된 주니어 데이터 분석가입니다. 상사로부터 "다음 분기 매출을 예측해달라"는 요청을 받았을 때, 머릿속이 하얘졌습니다.

대학에서 통계학을 조금 배우긴 했지만, 실무에서 시계열 예측을 해본 적은 없었기 때문입니다. 처음에는 ARIMA라는 전통적인 시계열 모델을 찾아봤습니다.

그런데 p, d, q 파라미터가 뭔지, 정상성이 뭔지, 차분이 뭔지... 용어 하나하나가 외계어처럼 느껴졌습니다.

바로 그때, 데이터팀의 베테랑 박시니어 씨가 구원의 손길을 내밀었습니다. "Prophet 써봐요.

Facebook에서 만든 건데, 우리 팀에서도 많이 써요." 그렇다면 Prophet이란 정확히 무엇일까요? 쉽게 비유하자면, Prophet은 마치 자동 변속기가 장착된 자동차와 같습니다.

수동 변속기 자동차를 운전하려면 클러치 타이밍, 기어 변속 시점 등 많은 것을 알아야 합니다. 하지만 자동 변속기 차량은 그냥 악셀만 밟으면 됩니다.

Prophet도 마찬가지입니다. 복잡한 시계열 이론을 몰라도, 데이터만 넣으면 알아서 예측해줍니다.

Prophet이 등장하기 전에는 어땠을까요? 시계열 예측을 하려면 ARIMA, 지수평활법 같은 통계 모델을 직접 구현해야 했습니다.

파라미터 튜닝에만 며칠이 걸리기도 했고, 잘못된 가정을 하면 예측이 완전히 빗나가기도 했습니다. Prophet은 이런 복잡함을 획기적으로 줄여줬습니다.

날짜가 담긴 ds 컬럼과 예측하고 싶은 값이 담긴 y 컬럼, 이 두 가지만 있으면 됩니다. 나머지는 Prophet이 알아서 처리합니다.

위의 코드를 한 줄씩 살펴보겠습니다. 먼저 from prophet import Prophet으로 라이브러리를 임포트합니다.

그 다음 데이터프레임을 만드는데, 여기서 중요한 것은 컬럼 이름이 반드시 ds와 y여야 한다는 점입니다. 그리고 Prophet()으로 모델 객체를 생성하고, fit() 메서드로 학습시킵니다.

실제 현업에서는 매출 예측, 트래픽 예측, 재고 수요 예측 등 다양한 분야에 Prophet이 활용됩니다. 특히 데이터 과학 전문가가 없는 중소기업에서 Prophet의 진가가 발휘됩니다.

복잡한 수학적 배경 없이도 합리적인 예측을 할 수 있기 때문입니다. 주의할 점도 있습니다.

Prophet은 일별 데이터 이상에서 가장 잘 작동합니다. 시간별 데이터도 가능하지만, 분 단위나 초 단위 데이터에는 적합하지 않습니다.

또한 최소 1년 이상의 데이터가 있어야 계절성을 제대로 감지합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

박시니어 씨의 조언대로 Prophet을 설치하고 첫 번째 모델을 만들어본 김개발 씨는 감탄했습니다. "이렇게 간단한데 이렇게 정확하다고요?" 그의 시계열 예측 여정이 이제 막 시작되었습니다.

실전 팁

💡 - Prophet 설치 시 오류가 나면 conda install -c conda-forge prophet을 시도해보세요

  • 컬럼 이름은 반드시 소문자 ds와 y를 사용해야 합니다

2. 기본 예측 수행하기

Prophet 설치를 마친 김개발 씨는 이제 본격적으로 예측을 해보고 싶어졌습니다. 하지만 모델을 학습시킨 후 어떻게 미래를 예측하는지 막막했습니다.

"학습은 했는데, 이제 어떻게 3개월 후를 예측하죠?" 박시니어 씨가 웃으며 대답했습니다. "make_future_dataframe이라는 마법의 메서드가 있어요."

Prophet에서 미래를 예측하려면 make_future_dataframe 메서드로 미래 날짜가 담긴 데이터프레임을 먼저 만들어야 합니다. 마치 빈 달력을 펼쳐놓고 그 위에 예측값을 채워넣는 것과 같습니다.

predict 메서드를 호출하면 예측값과 함께 상한선, 하한선도 함께 계산됩니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
import pandas as pd

# 샘플 데이터 준비
df = pd.read_csv('sales_data.csv')  # ds, y 컬럼 포함

# 모델 학습
model = Prophet()
model.fit(df)

# 미래 90일을 예측할 데이터프레임 생성
future = model.make_future_dataframe(periods=90)

# 예측 수행
forecast = model.predict(future)

# 주요 예측 결과 확인
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())

김개발 씨는 Prophet 모델을 학습시키는 데 성공했습니다. 그런데 문제가 생겼습니다.

학습은 했는데, 정작 미래 예측은 어떻게 하는 걸까요? fit() 메서드를 호출한 뒤에 그 다음 단계가 보이지 않았습니다.

박시니어 씨가 친절하게 설명을 시작했습니다. "Prophet의 예측 과정은 두 단계로 나뉘어요.

먼저 미래 날짜가 담긴 빈 데이터프레임을 만들고, 그 다음에 그 날짜들에 대한 예측값을 채워넣는 거예요." 이것을 비유하자면 빈 달력에 일정을 채워넣는 것과 같습니다. 먼저 12월 달력을 펼쳐놓고, 그 위에 하나하나 일정을 적어나가는 것처럼요.

Prophet도 마찬가지로, 먼저 예측하고 싶은 날짜들이 담긴 빈 데이터프레임을 만들고, 그 위에 예측값을 채워넣습니다. make_future_dataframe 메서드가 바로 이 빈 달력을 만드는 역할을 합니다.

periods=90이라고 지정하면, 학습 데이터의 마지막 날짜로부터 90일 후까지의 날짜가 담긴 데이터프레임이 생성됩니다. 여기서 한 가지 중요한 점이 있습니다.

make_future_dataframe은 과거 데이터도 포함합니다. 왜 그럴까요?

과거 데이터에 대한 예측값과 실제값을 비교해야 모델의 성능을 평가할 수 있기 때문입니다. 이것을 백테스팅이라고 부릅니다.

이제 predict 메서드를 호출하면 본격적인 예측이 시작됩니다. 이 메서드는 Prophet이 학습한 패턴을 바탕으로 미래 값을 예측합니다.

반환되는 데이터프레임에는 여러 컬럼이 있는데, 가장 중요한 것은 세 가지입니다. yhat은 예측값 자체입니다.

모델이 생각하는 가장 가능성 높은 값입니다. yhat_loweryhat_upper는 신뢰 구간의 하한과 상한입니다.

기본적으로 80% 신뢰 구간이 사용됩니다. 실무에서 이 신뢰 구간은 매우 중요합니다.

예를 들어 재고 관리를 한다면, yhat_upper를 기준으로 넉넉하게 재고를 확보할 수도 있고, 비용을 줄이기 위해 yhat을 기준으로 최소한만 확보할 수도 있습니다. 김개발 씨는 코드를 실행하고 결과를 확인했습니다.

forecast 데이터프레임의 마지막 5개 행을 출력해보니, 앞으로 90일간의 예측값이 깔끔하게 나와있었습니다. "오, 생각보다 간단하네요!" 김개발 씨가 감탄했습니다.

박시니어 씨가 덧붙였습니다. "이제 이 예측 결과를 시각화해보면 더 직관적으로 이해할 수 있을 거예요."

실전 팁

💡 - periods 값을 너무 크게 설정하면 예측 불확실성이 급격히 커집니다

  • 신뢰 구간 너비는 interval_width 파라미터로 조절할 수 있습니다 (기본값 0.8)

3. 예측 결과 시각화

김개발 씨는 예측 결과를 담당 임원에게 보고해야 했습니다. 하지만 숫자만 나열된 엑셀 파일로는 설득력이 부족했습니다.

"이걸 그래프로 만들 수 있을까요?" 박시니어 씨가 말했습니다. "Prophet에는 시각화 메서드가 내장되어 있어요.

한 줄이면 됩니다."

Prophet은 plotplot_components라는 두 가지 내장 시각화 메서드를 제공합니다. plot은 전체 예측 결과를 보여주고, plot_components는 트렌드와 계절성을 분리해서 보여줍니다.

마치 요리의 맛을 전체적으로 보는 것과 각 재료의 맛을 따로 보는 것과 같습니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
from prophet.plot import plot_plotly, plot_components_plotly
import pandas as pd
import matplotlib.pyplot as plt

# 모델 학습 및 예측 (이전 단계 가정)
model = Prophet()
model.fit(df)
future = model.make_future_dataframe(periods=90)
forecast = model.predict(future)

# 기본 시각화 - 예측 결과 전체
fig1 = model.plot(forecast)
plt.title('매출 예측 결과')
plt.savefig('forecast.png')

# 컴포넌트 시각화 - 트렌드, 계절성 분리
fig2 = model.plot_components(forecast)
plt.savefig('components.png')

데이터 분석의 세계에서는 오래된 격언이 있습니다. "숫자는 거짓말을 하지 않지만, 그래프는 진실을 말한다." 아무리 정확한 예측을 했더라도, 그것을 시각적으로 전달하지 못하면 의사결정자를 설득하기 어렵습니다.

김개발 씨도 이 문제에 직면했습니다. 예측 결과를 담은 CSV 파일을 임원에게 보냈더니, "이게 뭐야?

그래프로 보여줘"라는 답장이 돌아왔습니다. 다행히 Prophet에는 강력한 시각화 기능이 내장되어 있습니다.

별도의 matplotlib 코드를 작성할 필요 없이, 단 한 줄로 전문적인 그래프를 그릴 수 있습니다. plot 메서드를 호출하면 전체 예측 결과가 그래프로 표시됩니다.

이 그래프에는 세 가지 요소가 포함됩니다. 첫째, 검은 점은 실제 관측값입니다.

둘째, 파란 선은 모델의 예측값입니다. 셋째, 연한 파란색 영역은 신뢰 구간입니다.

이 그래프만 봐도 모델이 과거 데이터를 얼마나 잘 설명하는지, 미래 예측이 어떤 방향으로 가고 있는지 한눈에 파악할 수 있습니다. 하지만 더 깊은 인사이트를 원한다면 plot_components 메서드를 사용해야 합니다.

이 메서드는 예측을 구성하는 각 요소를 분리해서 보여줍니다. 비유하자면, 맛있는 비빔밥을 먹을 때 전체 맛도 중요하지만, 각 재료가 어떤 역할을 하는지 알면 더 깊이 이해할 수 있는 것과 같습니다.

고추장이 매운맛을, 참기름이 고소한 맛을, 나물이 아삭한 식감을 담당하듯이, 예측에서도 각 컴포넌트가 서로 다른 역할을 합니다. plot_components 그래프는 보통 세 개의 패널로 구성됩니다.

첫 번째는 트렌드로, 장기적인 상승 또는 하락 추세를 보여줍니다. 두 번째는 주간 계절성으로, 요일별 패턴을 보여줍니다.

세 번째는 연간 계절성으로, 월별 패턴을 보여줍니다. 김개발 씨는 이 그래프를 보고 중요한 인사이트를 발견했습니다.

주간 계절성을 보니, 월요일에 매출이 가장 낮고 금요일에 가장 높았습니다. 연간 계절성을 보니, 12월에 매출이 급증하는 패턴이 있었습니다.

이런 정보를 임원에게 보고하자, 반응이 완전히 달라졌습니다. "오, 금요일에 프로모션을 집중하면 되겠네!

그리고 12월 대비 재고도 미리 확보해야겠어." 숫자가 아닌 그래프로 보여주니, 액션으로 이어지는 인사이트가 된 것입니다. 더 인터랙티브한 시각화를 원한다면 plotly 기반 함수도 사용할 수 있습니다.

plot_plotly와 plot_components_plotly 함수를 사용하면 줌인, 줌아웃, 마우스 오버 등이 가능한 동적 그래프를 만들 수 있습니다.

실전 팁

💡 - 보고서용으로는 matplotlib 기반 plot이, 대시보드용으로는 plotly 기반이 적합합니다

  • figsize 파라미터로 그래프 크기를 조절할 수 있습니다

4. 계절성 상세 설정

김개발 씨의 예측 모델이 점점 정교해지고 있었습니다. 그런데 어느 날, 이상한 점을 발견했습니다.

매출 데이터에 월말마다 급증하는 패턴이 있는데, Prophet이 이것을 제대로 잡아내지 못하고 있었습니다. "주간 계절성, 연간 계절성 말고 월간 계절성은 어떻게 추가하죠?" 박시니어 씨가 대답했습니다.

"add_seasonality 메서드를 쓰면 돼요."

Prophet은 기본적으로 주간 계절성연간 계절성을 자동으로 감지합니다. 하지만 비즈니스에 따라 월간 계절성, 분기별 계절성 등 다른 주기가 필요할 수 있습니다.

add_seasonality 메서드를 사용하면 원하는 주기의 계절성을 직접 추가할 수 있습니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
import pandas as pd

# 데이터 로드
df = pd.read_csv('monthly_sales.csv')

# 커스텀 계절성을 가진 모델 생성
model = Prophet(
    yearly_seasonality=True,   # 연간 계절성 활성화
    weekly_seasonality=True,   # 주간 계절성 활성화
    daily_seasonality=False    # 일간 계절성 비활성화
)

# 월간 계절성 추가 (30.5일 주기)
model.add_seasonality(
    name='monthly',
    period=30.5,
    fourier_order=5
)

# 모델 학습
model.fit(df)

# 예측 수행
future = model.make_future_dataframe(periods=90)
forecast = model.predict(future)

세상의 모든 비즈니스가 같은 리듬으로 움직이지는 않습니다. 어떤 회사는 주말에 바쁘고, 어떤 회사는 월초에 바쁩니다.

어떤 서비스는 여름에 피크를 치고, 어떤 서비스는 겨울에 피크를 칩니다. 김개발 씨가 분석하던 B2B 소프트웨어 회사의 매출 데이터에는 독특한 패턴이 있었습니다.

매월 말에 매출이 급증하는 것이었습니다. 이유는 간단했습니다.

기업 고객들이 월말에 예산을 소진하기 위해 구매를 몰아서 하기 때문입니다. 하지만 Prophet의 기본 설정으로는 이 패턴을 제대로 잡아내지 못했습니다.

Prophet은 기본적으로 주간 계절성(7일 주기)과 연간 계절성(365.25일 주기)만 자동으로 감지하기 때문입니다. 이럴 때 add_seasonality 메서드가 등장합니다.

이 메서드를 사용하면 원하는 주기의 계절성을 직접 추가할 수 있습니다. add_seasonality 메서드에는 세 가지 핵심 파라미터가 있습니다.

첫째, name은 계절성의 이름입니다. 나중에 plot_components에서 이 이름으로 표시됩니다.

둘째, period는 주기의 길이를 일수로 나타냅니다. 월간 계절성이라면 30.5일(한 달의 평균 일수)을 사용합니다.

셋째, fourier_order는 패턴의 복잡도를 결정합니다. fourier_order를 조금 더 설명하자면, 이것은 마치 음악에서 화음의 풍부함과 같습니다.

단순한 "도" 음만 있는 것과 "도미솔" 화음이 있는 것의 차이입니다. fourier_order가 높을수록 더 복잡한 패턴을 표현할 수 있지만, 너무 높으면 과적합의 위험이 있습니다.

일반적인 가이드라인으로, 주간 계절성에는 fourier_order=3, 연간 계절성에는 fourier_order=10, 월간 계절성에는 fourier_order=5 정도가 적당합니다. Prophet 생성자에서 계절성을 켜고 끄는 것도 가능합니다.

예를 들어 시간별 데이터를 다루지 않는다면 daily_seasonality=False로 설정하여 불필요한 계산을 줄일 수 있습니다. 김개발 씨는 월간 계절성을 추가한 후 다시 예측을 수행했습니다.

plot_components 그래프를 확인하니, 새로 추가한 "monthly" 패널이 나타났습니다. 예상대로 월말에 급등하는 패턴이 명확하게 보였습니다.

"이제 월말 매출 급증도 예측에 반영됐네요!" 김개발 씨가 기뻐했습니다. 박시니어 씨가 덧붙였습니다.

"좋아요, 근데 과적합 조심해요. 계절성을 너무 많이 추가하면 오히려 예측 성능이 떨어질 수 있어요."

실전 팁

💡 - fourier_order는 낮게 시작해서 점진적으로 높여가며 성능을 확인하세요

  • 데이터가 최소 2주기 이상 있어야 해당 계절성을 신뢰할 수 있습니다

5. 휴일 효과 반영하기

추석 연휴가 다가오고 있었습니다. 김개발 씨는 고민에 빠졌습니다.

작년 추석에는 매출이 평소보다 50%나 떨어졌는데, 현재 모델은 이것을 전혀 반영하지 못하고 있었습니다. "휴일을 어떻게 모델에 알려주죠?" 박시니어 씨가 답했습니다.

"Prophet에 휴일 데이터프레임을 전달하면 돼요."

휴일 효과는 시계열 예측에서 매우 중요한 요소입니다. 크리스마스, 설날, 블랙프라이데이 같은 특별한 날들은 일반적인 패턴과 다르게 행동합니다.

Prophet에서는 holidays 파라미터로 휴일 정보를 전달하면, 이 효과를 자동으로 학습하고 반영합니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
import pandas as pd

# 휴일 데이터프레임 생성
holidays = pd.DataFrame({
    'holiday': 'chuseok',  # 휴일 이름
    'ds': pd.to_datetime([
        '2023-09-28', '2023-09-29', '2023-09-30',  # 2023년 추석
        '2024-09-16', '2024-09-17', '2024-09-18'   # 2024년 추석
    ]),
    'lower_window': -1,  # 휴일 1일 전부터 효과 시작
    'upper_window': 1    # 휴일 1일 후까지 효과 지속
})

# 설날도 추가
seollal = pd.DataFrame({
    'holiday': 'seollal',
    'ds': pd.to_datetime(['2024-02-09', '2024-02-10', '2024-02-11']),
    'lower_window': -1,
    'upper_window': 1
})

# 휴일 합치기
all_holidays = pd.concat([holidays, seollal])

# 모델에 휴일 적용
model = Prophet(holidays=all_holidays)
model.fit(df)

모든 날이 같지는 않습니다. 크리스마스에 선물 판매가 급증하고, 설날에 여행 예약이 폭발하고, 시험 기간에 카페 매출이 치솟습니다.

이런 특별한 날들의 효과를 무시하면 예측 정확도가 크게 떨어집니다. 김개발 씨가 분석하던 회사의 서비스는 B2B 솔루션이었습니다.

명절에는 대부분의 기업이 쉬기 때문에 매출이 급감했습니다. 하지만 Prophet의 기본 모델은 이 점을 알지 못했고, 추석 연휴에도 평소와 비슷한 매출을 예측하고 있었습니다.

휴일 효과를 반영하는 방법은 간단합니다. holidays라는 데이터프레임을 만들어서 Prophet에 전달하면 됩니다.

휴일 데이터프레임에는 최소 두 개의 컬럼이 필요합니다. holiday는 휴일의 이름이고, ds는 휴일 날짜입니다.

같은 이름의 휴일이 여러 날짜에 걸쳐 있을 수 있습니다. 예를 들어 추석은 보통 3일 연휴이므로, 같은 'chuseok'이라는 이름으로 3개의 날짜를 등록합니다.

여기서 중요한 것이 lower_windowupper_window입니다. 휴일 효과는 정확히 그 날에만 나타나는 것이 아니라, 전후로 영향을 미칩니다.

예를 들어 추석 당일뿐만 아니라, 추석 전날에도 사람들은 이미 귀성길에 올라 일을 하지 않습니다. 추석 다음날에도 아직 복귀하지 않은 사람들이 많습니다.

lower_window=-1은 "휴일 하루 전부터 효과가 시작된다"는 의미이고, upper_window=1은 "휴일 하루 후까지 효과가 지속된다"는 의미입니다. 한국의 비즈니스를 분석한다면, 추석과 설날은 반드시 포함해야 합니다.

이 외에도 어린이날, 광복절, 한글날 같은 공휴일도 영향을 미칠 수 있습니다. 재미있는 점은, 휴일이 꼭 공휴일일 필요는 없다는 것입니다.

비즈니스에 영향을 미치는 모든 특별한 날을 휴일로 등록할 수 있습니다. 예를 들어 쇼핑몰이라면 "블랙프라이데이", "광군제", "회사 창립기념일 할인행사" 같은 것도 휴일로 등록할 수 있습니다.

김개발 씨는 추석과 설날 데이터를 정리해서 모델에 추가했습니다. 다시 예측을 수행하니, 명절 기간의 예측값이 확 낮아졌습니다.

plot_components를 확인하니, 새로운 "holidays" 패널이 추가되어 각 휴일의 효과를 보여주고 있었습니다. "추석에는 -45% 효과가 있네요.

작년 실제 데이터와 거의 일치해요!" 김개발 씨가 놀라며 말했습니다.

실전 팁

💡 - 한국 공휴일은 holidays 패키지(pip install holidays)를 사용하면 자동으로 가져올 수 있습니다

  • 휴일 효과가 매년 달라진다면, 각 연도별로 다른 휴일 이름을 사용하세요

6. 외부 변수 추가하기

김개발 씨의 예측 모델이 점점 정교해지고 있었습니다. 그런데 마케팅팀에서 요청이 들어왔습니다.

"다음 달에 TV 광고를 집행하는데, 그 효과를 예측에 반영할 수 있을까요?" 김개발 씨는 막막해졌습니다. 광고비 같은 외부 요인은 어떻게 모델에 넣을 수 있을까요?

Prophet에서는 add_regressor 메서드를 통해 외부 변수를 추가할 수 있습니다. 이를 회귀 변수라고 부릅니다.

광고비, 가격, 날씨, 경쟁사 프로모션 등 예측하려는 값에 영향을 미치는 모든 변수를 추가할 수 있습니다. 단, 미래 기간에 대해서도 이 변수의 값을 알고 있어야 합니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
import pandas as pd

# 데이터 준비 - 광고비 컬럼 포함
df = pd.DataFrame({
    'ds': pd.date_range('2023-01-01', periods=365, freq='D'),
    'y': [100 + i * 0.5 for i in range(365)],
    'ad_spend': [1000 + (i % 30) * 100 for i in range(365)]  # 광고비
})

# 회귀 변수 추가
model = Prophet()
model.add_regressor('ad_spend', standardize=True)

# 모델 학습
model.fit(df)

# 미래 데이터프레임에도 회귀 변수 포함 필요
future = model.make_future_dataframe(periods=30)
# 미래 광고비 계획 입력
future['ad_spend'] = [1500] * len(future)  # 다음 달 광고비 증액 계획

forecast = model.predict(future)

시계열 예측에서 가장 어려운 부분 중 하나는 외부 요인의 영향을 반영하는 것입니다. 매출은 시간의 흐름에 따른 자연스러운 트렌드뿐만 아니라, 광고, 가격 변동, 경쟁사의 움직임, 심지어 날씨에도 영향을 받습니다.

김개발 씨가 만든 예측 모델은 이제 꽤 정확해졌습니다. 하지만 마케팅팀의 질문에는 답할 수 없었습니다.

"다음 달에 광고비를 두 배로 늘리면 매출이 얼마나 올라갈까요?" 이때 사용하는 것이 add_regressor 메서드입니다. regressor는 "회귀 변수"라는 의미로, 예측하려는 값에 영향을 미치는 독립 변수를 말합니다.

add_regressor를 사용하려면 두 가지 조건이 필요합니다. 첫째, 학습 데이터에 해당 변수의 과거 값이 포함되어 있어야 합니다.

둘째, 예측하려는 미래 기간에 대해서도 해당 변수의 값을 알고 있어야 합니다. 두 번째 조건이 중요합니다.

예를 들어 광고비는 회사가 계획하는 것이므로 미래 값을 알 수 있습니다. 하지만 경쟁사의 가격은 알 수 없으므로 회귀 변수로 사용하기 어렵습니다.

코드를 살펴보면, 먼저 학습 데이터프레임에 'ad_spend' 컬럼이 포함되어 있습니다. 그리고 Prophet 모델을 생성한 후 add_regressor('ad_spend')를 호출합니다.

standardize=True는 변수를 표준화하여 스케일 차이로 인한 문제를 방지합니다. 중요한 부분은 미래 데이터프레임을 만들 때입니다.

make_future_dataframe으로 만든 future 데이터프레임에는 ds 컬럼만 있습니다. 여기에 미래 광고비 계획을 직접 입력해야 합니다.

이것이 바로 시나리오 분석이 가능해지는 순간입니다. "광고비를 1500으로 유지하면 매출이 이렇고, 2000으로 올리면 매출이 저렇습니다"라는 식의 분석이 가능해집니다.

김개발 씨는 두 가지 시나리오를 비교해봤습니다. 광고비를 현재 수준으로 유지하는 경우와, 두 배로 늘리는 경우.

예측 결과를 비교하니, 광고비 증액 시 매출이 약 15% 상승하는 것으로 나타났습니다. 마케팅팀에 이 분석 결과를 전달하자, 팀장이 감탄했습니다.

"오, 이제 광고 효과를 미리 예측할 수 있겠네요! ROI 계산도 가능하겠어요." 박시니어 씨가 마지막으로 조언했습니다.

"회귀 변수를 너무 많이 추가하면 과적합 위험이 있어요. 정말 중요한 변수만 선별해서 넣으세요."

실전 팁

💡 - 회귀 변수의 미래 값을 모른다면 사용할 수 없습니다. 계획 가능한 변수만 추가하세요

  • 여러 시나리오를 비교하여 민감도 분석을 수행할 수 있습니다

7. 트렌드 변화점 감지

김개발 씨의 회사에 큰 사건이 있었습니다. 2년 전에 경쟁사가 시장에서 철수했고, 그 이후로 성장률이 급격히 높아졌습니다.

하지만 Prophet 모델은 이 변화를 제대로 반영하지 못하고 있었습니다. "갑자기 트렌드가 바뀌는 시점은 어떻게 처리하죠?"

Prophet은 **변화점(changepoint)**을 자동으로 감지합니다. 변화점이란 트렌드의 기울기가 급격히 바뀌는 시점을 말합니다.

신제품 출시, 경쟁사 진입/철수, 팬데믹 같은 큰 사건이 발생하면 트렌드가 변합니다. Prophet에서는 이 변화점의 개수와 유연성을 조절할 수 있습니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
import pandas as pd

# 데이터 로드
df = pd.read_csv('sales_with_changepoint.csv')

# 변화점 설정을 조정한 모델
model = Prophet(
    changepoint_prior_scale=0.05,  # 트렌드 유연성 (기본값: 0.05)
    changepoints=['2022-06-01'],   # 수동으로 변화점 지정
    n_changepoints=25              # 자동 감지할 변화점 개수
)

model.fit(df)

# 예측 수행
future = model.make_future_dataframe(periods=90)
forecast = model.predict(future)

# 변화점 위치 확인
from prophet.plot import add_changepoints_to_plot
fig = model.plot(forecast)
add_changepoints_to_plot(fig.gca(), model, forecast)

세상 모든 것에는 변곡점이 있습니다. 스타트업이 시리즈 A 투자를 받고 급성장하는 순간, 코로나 팬데믹이 시작되어 오프라인 매출이 급감하는 순간, 경쟁사가 시장에서 철수하여 점유율이 급등하는 순간.

이런 **변화점(changepoint)**을 제대로 감지하지 못하면 예측이 완전히 틀어질 수 있습니다. 김개발 씨의 회사도 마찬가지였습니다.

2022년 6월에 주요 경쟁사가 시장에서 철수했고, 그 이후 성장률이 두 배로 뛰었습니다. 하지만 Prophet의 기본 설정으로는 이 급격한 변화를 충분히 반영하지 못하고 있었습니다.

Prophet은 기본적으로 변화점을 자동으로 감지합니다. 데이터의 처음 80% 구간에서 25개의 잠재적 변화점을 설정하고, 그중에서 실제로 의미 있는 변화가 있는 지점을 찾아냅니다.

하지만 세 가지 방법으로 이 동작을 조절할 수 있습니다. 첫째, changepoint_prior_scale입니다.

이 값은 트렌드가 얼마나 유연하게 변할 수 있는지를 결정합니다. 값이 클수록 트렌드가 더 유연해지고, 값이 작을수록 더 부드러워집니다.

기본값은 0.05입니다. 만약 모델이 트렌드 변화를 과소평가한다면 이 값을 높이고, 과대평가한다면 낮추면 됩니다.

둘째, n_changepoints입니다. 자동으로 감지할 변화점의 최대 개수입니다.

기본값은 25개입니다. 데이터가 길고 변화가 많다면 이 값을 높일 수 있습니다.

셋째, changepoints입니다. 가장 강력한 옵션으로, 변화점을 직접 지정할 수 있습니다.

비즈니스에서 중요한 사건이 발생한 날짜를 알고 있다면, 그 날짜를 직접 변화점으로 지정하는 것이 가장 정확합니다. 김개발 씨는 경쟁사가 철수한 2022년 6월 1일을 변화점으로 직접 지정했습니다.

그리고 add_changepoints_to_plot 함수를 사용해 그래프에 변화점을 표시해봤습니다. 결과 그래프에는 빨간 점선이 2022년 6월 1일에 표시되었고, 그 시점을 기준으로 트렌드의 기울기가 확연히 달라지는 것이 보였습니다.

"이제야 모델이 현실을 제대로 반영하네요!" 김개발 씨가 만족스럽게 말했습니다. 박시니어 씨가 덧붙였습니다.

"변화점을 너무 많이 넣으면 과적합이 될 수 있어요. 정말 중요한 사건만 수동으로 지정하고, 나머지는 자동 감지에 맡기세요."

실전 팁

💡 - 중요한 비즈니스 이벤트 날짜는 수동으로 변화점에 추가하세요

  • changepoint_prior_scale은 0.001부터 0.5 사이에서 실험해보세요

8. 모델 성능 평가하기

김개발 씨의 예측 모델이 점점 복잡해지고 있었습니다. 계절성도 추가하고, 휴일도 추가하고, 외부 변수도 추가했습니다.

그런데 문득 의문이 들었습니다. "이 모델이 정말 잘 작동하는 걸까?

어떻게 확인하지?" 박시니어 씨가 대답했습니다. "교차 검증을 해봐야죠."

시계열 예측에서는 일반적인 랜덤 교차 검증을 사용할 수 없습니다. 시간 순서가 중요하기 때문입니다.

Prophet에서는 시뮬레이션 기반 교차 검증을 제공합니다. 과거의 특정 시점으로 돌아가서 그때의 데이터만으로 예측을 수행하고, 실제값과 비교합니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
from prophet.diagnostics import cross_validation, performance_metrics
import pandas as pd

# 모델 학습
model = Prophet()
model.fit(df)

# 교차 검증 수행
# initial: 최소 학습 기간
# period: 검증 간격
# horizon: 예측 기간
df_cv = cross_validation(
    model,
    initial='730 days',   # 처음 2년은 학습에 사용
    period='90 days',     # 90일마다 검증 수행
    horizon='30 days'     # 30일 후까지 예측
)

# 성능 지표 계산
df_metrics = performance_metrics(df_cv)
print(df_metrics[['horizon', 'mape', 'rmse', 'mae']])

# 예측 성능 시각화
from prophet.plot import plot_cross_validation_metric
fig = plot_cross_validation_metric(df_cv, metric='mape')

모델을 만들었다면 반드시 물어야 할 질문이 있습니다. "이 모델이 정말 좋은 모델인가?" 아무리 복잡한 모델을 만들어도, 실제로 예측을 잘 못하면 쓸모가 없습니다.

일반적인 머신러닝에서는 데이터를 랜덤하게 섞어서 일부는 학습에, 일부는 검증에 사용합니다. 하지만 시계열 데이터에서는 이 방법을 사용할 수 없습니다.

왜냐하면 시간 순서가 중요하기 때문입니다. 예를 들어 2024년 데이터로 학습하고 2023년 데이터를 예측하면, 그것은 미래를 알고 과거를 맞추는 것이니 반칙입니다.

시계열에서는 항상 과거로 학습하고 미래를 예측해야 합니다. Prophet에서는 이 문제를 시뮬레이션 기반 교차 검증으로 해결합니다.

작동 방식은 이렇습니다. "만약 우리가 2022년 6월에 있다고 가정하고, 그때까지의 데이터로 2022년 7월을 예측했다면 얼마나 정확했을까?" 이런 시뮬레이션을 여러 시점에서 반복합니다.

2022년 9월, 2022년 12월, 2023년 3월... 각 시점에서 예측을 수행하고 실제값과 비교합니다.

cross_validation 함수의 파라미터를 살펴보겠습니다. initial은 최초 학습 기간입니다.

이 기간의 데이터로 첫 번째 모델을 학습합니다. period는 각 시뮬레이션 사이의 간격입니다.

90일로 설정하면 90일마다 새로운 시점에서 검증을 수행합니다. horizon은 얼마나 먼 미래를 예측할 것인지입니다.

교차 검증 결과로 나오는 데이터프레임에는 각 예측 시점의 실제값(y)과 예측값(yhat)이 담겨 있습니다. 이것을 performance_metrics 함수에 전달하면 다양한 성능 지표를 계산해줍니다.

가장 자주 사용하는 지표는 **MAPE(Mean Absolute Percentage Error)**입니다. 예를 들어 MAPE가 5%라면, 평균적으로 실제값의 5% 정도 오차가 있다는 뜻입니다.

일반적으로 MAPE 10% 이하면 꽤 좋은 모델로 봅니다. **RMSE(Root Mean Squared Error)**는 큰 오차에 더 민감한 지표이고, **MAE(Mean Absolute Error)**는 평균 절대 오차입니다.

김개발 씨는 교차 검증을 수행하고 결과를 확인했습니다. MAPE가 7.2%였습니다.

"오, 생각보다 괜찮네요!" 박시니어 씨가 말했습니다. "horizon별로 MAPE를 확인해봐요.

보통 예측 기간이 길어질수록 오차가 커집니다." plot_cross_validation_metric 그래프를 확인하니, 1일 후 예측은 MAPE 3%였지만, 30일 후 예측은 MAPE 12%까지 올라갔습니다. 이것이 현실입니다.

먼 미래일수록 예측이 어려워집니다.

실전 팁

💡 - MAPE 10% 이하면 일반적으로 좋은 모델입니다

  • horizon별 성능을 확인하여 신뢰할 수 있는 예측 기간을 파악하세요

9. 하이퍼파라미터 튜닝

김개발 씨의 모델이 MAPE 7%를 기록했습니다. 하지만 욕심이 생겼습니다.

"더 정확하게 만들 수는 없을까?" 박시니어 씨가 말했습니다. "하이퍼파라미터 튜닝을 해보세요.

계절성 강도나 변화점 유연성을 조절하면 성능이 달라질 수 있어요."

Prophet에는 여러 하이퍼파라미터가 있습니다. 계절성의 강도, 트렌드의 유연성, 휴일 효과의 범위 등을 조절할 수 있습니다.

최적의 파라미터를 찾으면 예측 성능이 크게 향상될 수 있습니다. 단, 과적합에 주의해야 합니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
from prophet.diagnostics import cross_validation, performance_metrics
import itertools
import pandas as pd

# 튜닝할 파라미터 조합 정의
param_grid = {
    'changepoint_prior_scale': [0.01, 0.1, 0.5],
    'seasonality_prior_scale': [0.1, 1.0, 10.0],
    'seasonality_mode': ['additive', 'multiplicative']
}

# 모든 조합 생성
all_params = [dict(zip(param_grid.keys(), v))
              for v in itertools.product(*param_grid.values())]

# 각 조합별 성능 측정
results = []
for params in all_params:
    model = Prophet(**params)
    model.fit(df)
    df_cv = cross_validation(model, initial='730 days',
                            period='90 days', horizon='30 days')
    df_metrics = performance_metrics(df_cv)
    results.append({'params': params, 'mape': df_metrics['mape'].mean()})

# 최적 파라미터 찾기
best = min(results, key=lambda x: x['mape'])
print(f"최적 파라미터: {best['params']}")
print(f"MAPE: {best['mape']:.2%}")

세상에 완벽한 기본값은 없습니다. Prophet의 기본 설정이 대부분의 경우에 잘 작동하지만, 데이터의 특성에 따라 조정이 필요할 수 있습니다.

하이퍼파라미터 튜닝이란, 이런 설정값들을 조정하여 최적의 성능을 찾는 과정입니다. 마치 오디오 장비의 이퀄라이저를 조정하여 최적의 음질을 찾는 것과 같습니다.

Prophet에서 가장 중요한 하이퍼파라미터 세 가지를 살펴보겠습니다. 첫째, changepoint_prior_scale입니다.

앞서 배웠듯이 트렌드의 유연성을 결정합니다. 값이 크면 트렌드가 급격히 변할 수 있고, 값이 작으면 부드럽게 변합니다.

기본값은 0.05입니다. 둘째, seasonality_prior_scale입니다.

계절성 패턴의 강도를 결정합니다. 값이 크면 계절성 패턴이 더 뚜렷하게 나타나고, 값이 작으면 더 약하게 나타납니다.

기본값은 10입니다. 셋째, seasonality_mode입니다.

'additive'와 'multiplicative' 중 선택합니다. additive는 계절성이 고정된 양만큼 더해지는 것이고, multiplicative는 비율로 곱해지는 것입니다.

예를 들어 "12월에 항상 100만원 더 번다"면 additive, "12월에 항상 20% 더 번다"면 multiplicative입니다. 위의 코드는 그리드 서치를 수행합니다.

모든 파라미터 조합을 시도해보고, 각 조합에서 교차 검증을 수행하여 가장 좋은 성능을 내는 조합을 찾습니다. 주의할 점이 있습니다.

그리드 서치는 시간이 오래 걸립니다. 위의 예에서는 3 x 3 x 2 = 18개의 조합이 있고, 각 조합마다 교차 검증을 수행해야 합니다.

데이터가 크면 몇 시간이 걸릴 수도 있습니다. 더 효율적인 방법으로는 베이지안 최적화랜덤 서치가 있습니다.

하지만 처음 시작할 때는 그리드 서치로 전체적인 감을 잡는 것이 좋습니다. 김개발 씨는 그리드 서치를 돌려놨고, 점심을 먹고 돌아왔습니다.

결과를 확인하니, 최적 조합은 changepoint_prior_scale=0.1, seasonality_prior_scale=1.0, seasonality_mode='multiplicative'였습니다. MAPE가 7.2%에서 5.8%로 개선되었습니다.

"와, 거의 20%나 개선됐네요!" 김개발 씨가 기뻐했습니다. 박시니어 씨가 경고했습니다.

"조심해요. 과적합이 아닌지 확인해야 해요.

테스트 데이터에서도 성능이 유지되는지 검증하세요."

실전 팁

💡 - seasonality_mode는 데이터 스케일이 커질수록 계절 효과도 커지면 multiplicative, 그렇지 않으면 additive를 사용하세요

  • 그리드 서치는 시간이 오래 걸리므로, 처음에는 적은 조합으로 시작하세요

10. 예측 결과 저장과 활용

김개발 씨의 예측 모델이 완성되었습니다. 이제 마지막 관문이 남았습니다.

"이 예측 결과를 어떻게 다른 시스템에 연동하죠? 그리고 모델을 매번 다시 학습시켜야 하나요?" 박시니어 씨가 미소 지었습니다.

"모델을 저장하고 불러오는 방법이 있어요."

Prophet 모델과 예측 결과를 저장하면 재사용할 수 있습니다. 예측 결과는 CSV나 데이터베이스에 저장하고, 모델 자체는 JSON 형태로 직렬화할 수 있습니다.

프로덕션 환경에서는 정기적으로 모델을 재학습하고 예측을 업데이트하는 파이프라인을 구축합니다.

다음 코드를 살펴봅시다.

from prophet import Prophet
from prophet.serialize import model_to_json, model_from_json
import pandas as pd
import json

# 모델 학습
model = Prophet()
model.fit(df)

# 모델을 JSON으로 저장
with open('prophet_model.json', 'w') as f:
    f.write(model_to_json(model))

# 저장된 모델 불러오기
with open('prophet_model.json', 'r') as f:
    loaded_model = model_from_json(f.read())

# 불러온 모델로 예측
future = loaded_model.make_future_dataframe(periods=30)
forecast = loaded_model.predict(future)

# 예측 결과를 CSV로 저장
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].to_csv(
    'forecast_results.csv', index=False
)

print("모델과 예측 결과가 저장되었습니다!")

모델을 만들고 예측을 수행했다면, 다음 단계는 실제 업무에 적용하는 것입니다. 그런데 여기서 현실적인 문제들이 발생합니다.

첫째, 매번 모델을 새로 학습시키면 시간이 오래 걸립니다. 데이터가 크면 학습에 몇 분에서 몇 시간이 걸릴 수 있습니다.

실시간으로 예측이 필요한 상황에서는 이것이 문제가 됩니다. 둘째, 예측 결과를 다른 시스템과 공유해야 합니다.

마케팅팀은 이 예측을 바탕으로 광고 예산을 세우고, 재무팀은 매출 계획을 수립하고, 물류팀은 재고를 준비합니다. 이런 문제들을 해결하기 위해 Prophet은 모델 직렬화 기능을 제공합니다.

model_to_json 함수는 학습된 모델을 JSON 문자열로 변환합니다. 이 JSON을 파일로 저장하면, 나중에 model_from_json으로 다시 불러올 수 있습니다.

불러온 모델은 처음부터 다시 학습할 필요 없이 바로 예측에 사용할 수 있습니다. 예전에는 pickle을 사용했지만, 현재 Prophet 공식 문서에서는 JSON 방식을 권장합니다.

JSON이 더 안전하고 버전 호환성도 좋기 때문입니다. 예측 결과는 상황에 따라 다양한 형태로 저장할 수 있습니다.

간단한 경우라면 CSV 파일로 저장하여 엑셀에서 열어볼 수 있습니다. 자동화된 시스템이라면 데이터베이스에 저장하여 다른 애플리케이션에서 조회할 수 있습니다.

API 형태로 제공한다면 JSON 응답으로 반환할 수도 있습니다. 프로덕션 환경에서는 보통 다음과 같은 파이프라인을 구축합니다.

매일 밤 새로운 데이터가 들어오면, 모델을 재학습합니다. 학습된 모델은 저장소에 저장됩니다.

그리고 향후 N일간의 예측을 수행하여 데이터베이스에 저장합니다. 다음 날 아침, 비즈니스 팀은 대시보드에서 최신 예측을 확인합니다.

김개발 씨는 이 모든 과정을 자동화하는 스크립트를 작성했습니다. 매일 새벽 3시에 크론잡이 실행되어 모델을 재학습하고, 예측 결과를 사내 데이터베이스에 저장합니다.

아침에 출근하면 대시보드에 최신 예측이 표시되어 있습니다. "이제 완전히 자동화됐네요!" 김개발 씨가 뿌듯하게 말했습니다.

박시니어 씨가 마무리했습니다. "잘했어요.

하지만 여기서 끝이 아니에요. 예측 모델은 계속 모니터링하고 개선해야 해요.

실제 값이 예측과 크게 다르면 경고를 보내는 시스템도 만들어보세요." 김개발 씨의 Prophet 여정은 이렇게 완성되었습니다. 처음에는 시계열 예측이 막막했지만, 이제는 자신 있게 미래를 예측할 수 있는 데이터 분석가로 성장했습니다.

실전 팁

💡 - 모델 재학습 주기는 데이터 특성에 따라 다릅니다. 빠르게 변하는 데이터는 매일, 안정적인 데이터는 매주나 매월 재학습하세요

  • 예측과 실제의 차이가 임계값을 넘으면 알림을 보내는 모니터링 시스템을 구축하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#Prophet#TimeSeries#Forecasting#DataScience#Data Science

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.