Facebook Prophet
Prognozowanie Szeregów Czasowych w Pythonie
Przewodnik oparty na oficjalnej dokumentacji Facebook Prophet
Historia Facebook Prophet
2017 - Facebook opublikował Prophet jako projekt open-source
Autorzy: Sean J. Taylor i Benjamin Letham z zespołu Core Data Science w Facebooku
Cel stworzenia:
- Demokratyzacja prognozowania - narzędzie dla analityków bez głębokiej wiedzy statystycznej
- Obsługa tysięcy prognoz dziennie w Facebooku
- Automatyzacja rutynowych zadań prognostycznych
Publikacja naukowa:
"Forecasting at Scale" (2017) - opisuje architekturę i zastosowania Prophet w środowisku produkcyjnym
Dlaczego Facebook Stworzył Prophet?
Problemy tradycyjnych metod prognozowania:
- ARIMA - wymaga dużej wiedzy statystycznej, trudne w dostrajaniu
- Eksponencjalne wygładzanie - słabo radzi sobie z wieloma sezonowościami
- Machine Learning - potrzebuje dużo danych, trudne w interpretacji
Wyzwania w Facebooku:
- Tysiące różnych szeregów czasowych do prognozowania
- Analitycy biznesowi (nie-statystycy) potrzebują szybkich prognoz
- Dane z outliers, brakującymi wartościami, świętami
- Potrzeba szybkich iteracji i dostrajania
Rozwiązanie Prophet: Intuicyjna biblioteka z sensownymi domyślnymi ustawieniami, łatwa w użyciu i interpretacji
Założenia Modelu Prophet
Prophet opiera się na modelu addytywnym:
y(t) = g(t) + s(t) + h(t) + εₜ
Gdzie:
- g(t) - funkcja trendu (wzrost w czasie)
- s(t) - sezonowość (periodyczne wzorce)
- h(t) - efekty świąt i wydarzeń
- εₜ - składnik błędu (szum)
Kluczowe założenia:
- Szereg czasowy ma wyraźny trend (liniowy lub logistyczny)
- Występuje sezonowość (dzienna, tygodniowa, roczna)
- Święta i wydarzenia mają przewidywalny wpływ
- Zmiany trendu (changepoints) występują regularnie
Komponenty Modelu - Trend g(t)
Trend opisuje długoterminowy wzrost lub spadek wartości.
Dwa typy trendu:
-
Liniowy (domyślny): g(t) = (k + a(t)ᵀδ)t + (m + a(t)ᵀγ)
- k - tempo wzrostu
- δ - zmiany tempa wzrostu w changepoints
- m - offset (wartość początkowa)
-
Logistyczny (saturating): g(t) = C / (1 + exp(-(k + a(t)ᵀδ)(t - (m + a(t)ᵀγ))))
- C - maksymalna wartość (capacity)
- Używany gdy wzrost ma górny lub dolny limit
Changepoints: Punkty, w których trend może się zmieniać automatycznie wykrywane przez model
Komponenty Modelu - Sezonowość s(t)
Sezonowość to periodyczne wzorce powtarzające się w czasie.
Prophet używa szeregów Fouriera:
s(t) = Σ [aₙ·cos(2πnt/P) + bₙ·sin(2πnt/P)]
Gdzie:
- P - okres sezonowości (365.25 dla rocznej, 7 dla tygodniowej)
- n - order Fouriera (kontroluje złożoność wzorca)
Domyślne sezonowości:
- Yearly (roczna) - period=365.25 dni, fourier_order=10
- Weekly (tygodniowa) - period=7 dni, fourier_order=3
- Daily (dzienna) - period=24 godz, fourier_order=4 (tylko dla danych godzinowych)
Możliwość dodania niestandardowych sezonowości (miesięczna, kwartalna, etc.)
Komponenty Modelu - Święta h(t)
Święta i wydarzenia to nieregularne zdarzenia wpływające na szereg czasowy.
Model świąt:
h(t) = Σ κᵢ · 1{t ∈ Dᵢ}
Gdzie:
- κᵢ - wpływ i-tego święta (estymowany przez model)
- Dᵢ - zbiór dat dla i-tego święta (włącznie z oknem przed/po)
- 1{·} - funkcja wskaźnikowa (1 jeśli prawda, 0 jeśli fałsz)
Elastyczność:
- Możliwość definiowania niestandardowych świąt
- Okna czasowe (np. 2 dni przed i po Black Friday)
- Wbudowane święta dla 95+ krajów
- Różne święta mogą mieć różny wpływ
Zalety Facebook Prophet
1. Łatwość użycia:
- Intuicyjne API - fit() i predict()
- Minimalna konfiguracja - sensowne wartości domyślne
- Nie wymaga wiedzy o ARIMA, stacjonarności, etc.
2. Elastyczność:
- Łatwe dodawanie niestandardowych sezonowości
- Wbudowane święta dla wielu krajów
- Obsługa dodatkowych regressorów
3. Odporność:
- Radzi sobie z brakującymi danymi
- Automatycznie wykrywa outliers
- Obsługuje zmiany trendu (changepoints)
4. Interpretowalność:
- Wizualizacja komponentów (trend, sezonowość, święta)
- Łatwo zrozumieć wpływ każdego komponentu
- Przedziały ufności dla prognoz
Wady i Ograniczenia Prophet
1. Nie dla wszystkich szeregów czasowych:
- Wymaga minimum kilku miesięcy danych historycznych
- Słabo radzi sobie z nieregularnymi wzorcami
- Nie dla szeregów bez wyraźnego trendu lub sezonowości
2. Ograniczenia modelu:
- Zakłada addytywność komponentów (chyba że multiplicative)
- Nie uwzględnia auto-korelacji w residuach
- Nie modeluje zależności między szeregami (VAR, VECM)
3. Wydajność:
- Wolniejszy niż ARIMA dla krótkich szeregów
- Wymaga Stan (może sprawiać problemy przy instalacji)
4. Prognozy długoterminowe:
- Niepewność rośnie szybko dla długich horyzontów
- Zakłada kontynuację obecnych wzorców
Plan Prezentacji
- Historia i założenia modelu ✓
- Instalacja i konfiguracja
- Quick Start - pierwszy model
- Python API - podstawowe funkcje
- Saturating Forecasts - prognozy z ograniczeniami
- Trend Changepoints - punkty zmiany trendu
- Seasonality - sezonowość
- Holiday Effects - efekty świąt
- Country Holidays - wbudowane święta krajowe
- Regressors - dodatkowe zmienne
- Cross-Validation i Performance Metrics
- Parallelizing Cross Validation
- Hyperparameter Tuning (Grid Search, Random Search)
- Outliers - wykrywanie i obsługa
- Handling Shocks - modelowanie wstrząsów
Czym jest Facebook Prophet?
Prophet to biblioteka open-source stworzona przez Facebook (Meta) do prognozowania szeregów czasowych.
Kluczowe cechy:
- Intuicyjny - łatwy w użyciu, minimalny kod
- Automatyczny - wykrywa sezonowość i trendy
- Odporny na braki - radzi sobie z brakującymi danymi
- Efekty świąt - wbudowane święta dla wielu krajów
- Interpretowalny - wizualizacja komponentów
- Szybki - działa na CPU, nie wymaga GPU
Kiedy Używać Prophet?
Prophet sprawdza się najlepiej gdy:
- Masz dane historyczne (minimum kilka miesięcy)
- Dane mają silną sezonowość (dzienną, tygodniową, roczną)
- Występują święta i wydarzenia specjalne
- Występują trendy zmieniające się w czasie
- Dane mają wartości odstające (outliers)
- Potrzebujesz szybkich prognoz bez głębokiej wiedzy o time series
Typowe zastosowania:
- Prognozowanie sprzedaży i przychodów
- Przewidywanie ruchu na stronie internetowej
- Analiza zapotrzebowania na produkty
- Prognozowanie zużycia energii
- Planowanie zasobów
Instalacja
Instalacja Prophet w Pythonie
# Metoda 1: pip (zalecana)
pip install prophet
# Metoda 2: conda (jeśli używasz Anacondy)
conda install -c conda-forge prophet
# Prophet wymaga dodatkowych zależności:
# - pystan (silnik Stan dla modelowania bayesowskiego)
# - numpy, pandas, matplotlib
# Sprawdź instalację
python -c "import prophet; print(prophet.__version__)"
# Jeśli występują problemy z instalacją:
# Windows: zainstaluj Microsoft C++ Build Tools
# Linux: sudo apt-get install python3-dev
# macOS: brew install gcc
# Opcjonalnie: plotly dla interaktywnych wykresów
pip install plotlyImport Podstawowych Bibliotek
# Podstawowe importy
import pandas as pd
import numpy as np
from prophet import Prophet
import matplotlib.pyplot as plt
# Dla interaktywnych wykresów (opcjonalnie)
from prophet.plot import plot_plotly, plot_components_plotly
import plotly.offline as py
# Wyłącz ostrzeżenia (opcjonalnie)
import warnings
warnings.filterwarnings('ignore')
# Ustawienia pandas
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', 100)
print("Prophet zainstalowany pomyślnie!")Quick Start
Przygotowanie Danych
Prophet wymaga DataFrame z dwoma kolumnami:
-
ds- data (datetime) -
y- wartość do prognozowania
import pandas as pd
# Przykładowe dane - dzienne sprzedaże
data = {
'ds': pd.date_range(start='2020-01-01', periods=365, freq='D'),
'y': np.random.randn(365).cumsum() + 100
}
df = pd.DataFrame(data)
print(df.head())
# ds y
# 0 2020-01-01 100.496714
# 1 2020-01-02 99.358760
# 2 2020-01-03 100.758990
# WAŻNE: kolumny MUSZĄ nazywać się 'ds' i 'y'!Pierwszy Model Prophet
from prophet import Prophet
# 1. Utwórz model
model = Prophet()
# 2. Dopasuj model do danych (trening)
model.fit(df)
# 3. Utwórz DataFrame z przyszłymi datami
# periods=365 - przewiduj 365 dni w przyszłość
future = model.make_future_dataframe(periods=365)
print(f"Rozmiar future: {len(future)} dni")
# 4. Wykonaj prognozę
forecast = model.predict(future)Wyniki Prognozy
# 5. Zobacz wyniki
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
# ds yhat yhat_lower yhat_upper
# 725 2021-12-27 102.456789 95.123456 109.789012
# 726 2021-12-28 103.234567 95.901234 110.567890
# yhat - prognoza (wartość przewidywana)
# yhat_lower - dolna granica (95% CI)
# yhat_upper - górna granica (95% CI)Wizualizacja Prognozy
# Wykres główny - prognoza z przedziałem ufności
fig1 = model.plot(forecast)
plt.title('Prognoza Prophet')
plt.xlabel('Data')
plt.ylabel('Wartość')
plt.show()
# Wykres komponentów - trend, sezonowość
fig2 = model.plot_components(forecast)
plt.show()
# Komponenty pokazują:
# - trend: ogólny kierunek zmian
# - weekly: sezonowość tygodniowa
# - yearly: sezonowość rocznaInteraktywna Wizualizacja (Plotly)
# Interaktywny wykres (wymaga plotly)
from prophet.plot import plot_plotly
fig = plot_plotly(model, forecast)
fig.show()
# Interaktywne komponenty
from prophet.plot import plot_components_plotly
fig = plot_components_plotly(model, forecast)
fig.show()
# Zalety plotly:
# - Możliwość przybliżania (zoom)
# - Podgląd wartości po najechaniu myszką
# - Eksport do PNGPython API
Podstawowe Parametry Prophet
from prophet import Prophet
model = Prophet(
# Typ wzrostu: 'linear' (domyślny) lub 'logistic'
growth='linear',
# Punkty zmiany trendu
changepoints=None, # Auto-detekcja
n_changepoints=25, # Liczba punktów zmiany
changepoint_range=0.8, # Tylko pierwsze 80% danych
# Sezonowość
yearly_seasonality='auto', # True, False, lub 'auto'
weekly_seasonality='auto',
daily_seasonality='auto',
# Święta
holidays=None, # DataFrame ze świętami
# Regularyzacja (elastyczność)
seasonality_prior_scale=10.0, # Im wyższy, tym bardziej elastyczna sezonowość
holidays_prior_scale=10.0,
changepoint_prior_scale=0.05, # Im wyższy, tym więcej punktów zmiany
# Interwał ufności
interval_width=0.95, # 95% przedział ufności
# Inne
uncertainty_samples=1000,
stan_backend=None
)Główne Metody Prophet - Część 1
# fit() - trenuj model
model.fit(df)
# make_future_dataframe() - utwórz daty dla prognozy
future = model.make_future_dataframe(
periods=365, # Liczba okresów do przewidzenia
freq='D', # Częstotliwość: 'D'=dzień, 'M'=miesiąc, 'H'=godzina
include_history=True # Czy dołączyć dane historyczne
)
# predict() - wykonaj prognozę
forecast = model.predict(future)
# plot() - wizualizuj prognozę
model.plot(forecast)
# plot_components() - wizualizuj komponenty
model.plot_components(forecast)Główne Metody Prophet - Część 2
# add_seasonality() - dodaj niestandardową sezonowość
model.add_seasonality(
name='monthly',
period=30.5,
fourier_order=5
)
# add_country_holidays() - dodaj święta krajowe
model.add_country_holidays(country_name='PL')
# add_regressor() - dodaj dodatkową zmienną
model.add_regressor('temperature')
# Zobacz wykryte święta
print(model.train_holiday_names)Saturating Forecasts
Prognozy z Ograniczeniami
Problem: Wzrost liniowy nie zawsze jest realistyczny. Wiele procesów ma górny limit (cap) lub dolny limit (floor).
Przykłady:
- Liczba użytkowników (max = populacja rynku)
- Penetracja rynku (max = 100%)
- Zajętość hotelu (max = liczba pokoi)
- Temperatura (floor = 0 Kelvin)
Rozwiązanie: Wzrost logistyczny (growth='logistic')
Forecasting Growth - Wzrost Logistyczny
Określ maksymalną wartość, do której może dążyć prognoza:
import pandas as pd
from prophet import Prophet
# Dane z górnym limitem
df = pd.read_csv('example_data.csv')
# WAŻNE: Dodaj kolumnę 'cap' - maksymalna wartość
df['cap'] = 1000000 # Np. 1 milion użytkowników
# Możesz też mieć różne limity w czasie
# df.loc[df['ds'] < '2021-01-01', 'cap'] = 800000
# df.loc[df['ds'] >= '2021-01-01', 'cap'] = 1000000
# Model z wzrostem logistycznym
model = Prophet(growth='logistic')
model.fit(df)
# WAŻNE: future też musi mieć 'cap'!
future = model.make_future_dataframe(periods=365)
future['cap'] = 1000000
# Prognoza
forecast = model.predict(future)
# Wykres
model.plot(forecast)Saturating Minimum - Dolny Limit
Oprócz górnego limitu (cap), możesz określić dolny limit (floor):
# Dane z górnym i dolnym limitem
df['cap'] = 1000000 # Maksimum
df['floor'] = 10000 # Minimum (np. minimalna liczba użytkowników)
# Model logistyczny
model = Prophet(growth='logistic')
model.fit(df)
# Future z oboma limitami
future = model.make_future_dataframe(periods=365)
future['cap'] = 1000000
future['floor'] = 10000
# Prognoza
forecast = model.predict(future)
# Prognoza będzie oscylować między floor a cap
print(f"Min prognoza: {forecast['yhat'].min():.0f}")
print(f"Max prognoza: {forecast['yhat'].max():.0f}")
model.plot(forecast)Trend Changepoints
Punkty Zmiany Trendu
Changepoints to momenty, w których tempo wzrostu/spadku zmienia się.
Przykłady:
- Wprowadzenie nowego produktu
- Zmiana strategii marketingowej
- Kryzys gospodarczy
- Pandemie, święta
Prophet automatycznie wykrywa changepoints:
- Domyślnie: 25 potencjalnych punktów zmiany
- Tylko w pierwszych 80% danych (changepoint_range=0.8)
- Używa modelu bayesowskiego do regularyzacji
Automatic Changepoint Detection
from prophet import Prophet
# Model z domyślnymi ustawieniami
model = Prophet()
model.fit(df)
forecast = model.predict(future)
# Wizualizacja z zaznaczonymi changepoints
fig = model.plot(forecast)
# Czerwone linie pionowe = wykryte changepoints
from prophet.plot import add_changepoints_to_plot
add_changepoints_to_plot(fig.gca(), model, forecast)
plt.show()Analiza Wykrytych Changepoints
# Wyświetl wykryte changepoints
print("Wykryte changepoints:")
print(model.changepoints)
# 0 2020-01-15
# 1 2020-02-04
# 2 2020-02-24
# ...
# Sprawdź siłę zmiany trendu w każdym punkcie
print("\nDelta (zmiana trendu):")
print(model.params['delta'])
# Delta pokazuje jak mocno trend się zmienia w każdym punkcieAdjusting Trend Flexibility
Parametr changepoint_prior_scale kontroluje elastyczność trendu:
# Domyślnie: changepoint_prior_scale = 0.05
# MNIEJ elastyczny trend (mniej zmian, gładszy)
# Użyj gdy dane są zaszumione
model_smooth = Prophet(changepoint_prior_scale=0.01)
model_smooth.fit(df)
# BARDZIEJ elastyczny trend (więcej zmian)
# Użyj gdy masz pewność co do punktów zmiany
model_flexible = Prophet(changepoint_prior_scale=0.5)
model_flexible.fit(df)
# Porównanie
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
model1 = Prophet(changepoint_prior_scale=0.001)
model1.fit(df)
model1.plot(model1.predict(future), ax=axes[0])
axes[0].set_title('Prior Scale = 0.001 (bardzo gładki)')
model2 = Prophet(changepoint_prior_scale=0.05)
model2.fit(df)
model2.plot(model2.predict(future), ax=axes[1])
axes[1].set_title('Prior Scale = 0.05 (domyślny)')
model3 = Prophet(changepoint_prior_scale=0.5)
model3.fit(df)
model3.plot(model3.predict(future), ax=axes[2])
axes[2].set_title('Prior Scale = 0.5 (bardzo elastyczny)')
plt.show()Specifying the Locations of Changepoints
Jeśli znasz dokładne daty zmian, możesz je ręcznie określić:
from prophet import Prophet
# Określ konkretne daty changepoints
changepoints = [
'2020-03-15', # Lockdown COVID
'2020-06-01', # Zniesienie ograniczeń
'2021-01-01', # Nowy rok, nowa strategia
]
model = Prophet(changepoints=changepoints)
model.fit(df)
forecast = model.predict(future)
# Wizualizacja
fig = model.plot(forecast)
add_changepoints_to_plot(fig.gca(), model, forecast)
plt.show()
# Możesz też kontrolować liczbę auto-wykrywanych punktów
model = Prophet(
n_changepoints=50, # Zwiększ z 25 do 50
changepoint_range=0.9 # Rozważ 90% danych (zamiast 80%)
)
model.fit(df)
# Wyłącz auto-detekcję (użyj tylko ręcznych)
model = Prophet(
changepoints=changepoints,
n_changepoints=0 # Wyłącz auto-detekcję
)Seasonality
Sezonowość w Prophet
Prophet automatycznie wykrywa 3 typy sezonowości:
- Yearly (roczna) - period=365.25 dni
- Weekly (tygodniowa) - period=7 dni
- Daily (dzienna) - period=24 godziny (tylko dla danych godzinowych)
Fourier Order:
Prophet używa szeregów Fouriera do modelowania sezonowości. Wyższy order = bardziej złożone wzorce.
- Yearly: domyślnie fourier_order=10
- Weekly: domyślnie fourier_order=3
- Daily: domyślnie fourier_order=4
Kontrola Sezonowości - Część 1
# Wyłącz konkretne sezonowości
model = Prophet(
yearly_seasonality=False, # Wyłącz sezonowość roczną
weekly_seasonality=True, # Włącz sezonowość tygodniową
daily_seasonality=False # Wyłącz sezonowość dzienną
)
# Auto-detekcja (domyślne)
model = Prophet(
yearly_seasonality='auto', # Włącz jeśli dane > 2 lata
weekly_seasonality='auto', # Włącz jeśli dane > 2 tygodnie
daily_seasonality='auto' # Włącz jeśli dane godzinowe > 2 dni
)Kontrola Sezonowości - Część 2
# Dostosuj fourier_order (elastyczność sezonowości)
model = Prophet()
model.add_seasonality(
name='yearly',
period=365.25,
fourier_order=20, # Domyślnie 10, wyższy = bardziej elastyczny
prior_scale=10.0
)
# Kontrola elastyczności sezonowości
model = Prophet(
seasonality_prior_scale=15.0 # Domyślnie 10.0
# Wyższy = bardziej elastyczna sezonowość
# Niższy = bardziej gładka sezonowość
)Niestandardowa Sezonowość - Część 1
# Dodaj miesięczną sezonowość
model = Prophet(weekly_seasonality=False)
model.add_seasonality(
name='monthly',
period=30.5, # ~30.5 dni w miesiącu
fourier_order=5
)
# Dodaj kwartalną sezonowość
model.add_seasonality(
name='quarterly',
period=365.25/4, # ~91.3 dni
fourier_order=8,
prior_scale=15.0
)
model.fit(df)Niestandardowa Sezonowość - Część 2 (Warunkowa)
# Sezonowość warunkowa - tylko w określonych warunkach
# Przykład: sezonowość działa inaczej w weekendy
df['on_weekend'] = df['ds'].dt.weekday >= 5 # Sobota=5, Niedziela=6
model = Prophet()
model.add_seasonality(
name='weekend_seasonality',
period=7,
fourier_order=3,
condition_name='on_weekend' # Tylko gdy on_weekend=True
)
# Future też musi mieć tę kolumnę!
future['on_weekend'] = future['ds'].dt.weekday >= 5
model.fit(df)
forecast = model.predict(future)Holiday Effects
Modelowanie Świąt i Wydarzeń Specjalnych
Prophet pozwala modelować wpływ świąt i wydarzeń specjalnych.
Przykłady:
- Święta państwowe (Boże Narodzenie, Wielkanoc)
- Black Friday, Cyber Monday
- Super Bowl, Mistrzostwa świata
- Kampanie marketingowe
- Konferencje firmowe
Format DataFrame ze świętami:
-
holiday- nazwa święta -
ds- data -
lower_window- dni przed (opcjonalne) -
upper_window- dni po (opcjonalne)
Tworzenie Niestandardowych Świąt - Część 1
import pandas as pd
# Stwórz DataFrame z świętami
holidays = pd.DataFrame({
'holiday': 'christmas',
'ds': pd.to_datetime([
'2020-12-25', '2021-12-25', '2022-12-25'
]),
'lower_window': 0, # Dzień święta
'upper_window': 1, # + 1 dzień po
})
# Dodaj więcej świąt
black_friday = pd.DataFrame({
'holiday': 'black_friday',
'ds': pd.to_datetime(['2020-11-27', '2021-11-26', '2022-11-25']),
'lower_window': -1, # 1 dzień przed
'upper_window': 1, # 1 dzień po
})
# Połącz wszystkie święta
holidays = pd.concat([holidays, black_friday])Tworzenie Niestandardowych Świąt - Część 2
# Użyj świąt w modelu
model = Prophet(holidays=holidays)
model.fit(df)
forecast = model.predict(future)
# Zobacz wpływ świąt w prognozie
print(forecast[['ds', 'yhat', 'christmas', 'black_friday']].tail())
# Każde święto ma swoją kolumnę pokazującą jego wpływBuilt-in Country Holidays
Wbudowane Święta Krajowe
Prophet ma wbudowane święta dla wielu krajów!
Używa biblioteki holidays (Python).
from prophet import Prophet
# Dodaj święta polskie
model = Prophet()
model.add_country_holidays(country_name='PL')
model.fit(df)
# Dostępne kody krajów (wybrane):
# 'US' - USA
# 'UK' - Wielka Brytania
# 'DE' - Niemcy
# 'FR' - Francja
# 'PL' - Polska
# 'IT' - Włochy
# 'ES' - Hiszpania
# 'BR' - Brazylia
# 'CN' - Chiny
# 'JP' - Japonia
# ... i wiele więcej
# Zobacz jakie święta zostały dodane
print(model.train_holiday_names)
# ['New Year', 'Easter Monday', 'Corpus Christi', ...]
forecast = model.predict(future)
# Komponenty zawierają teraz wpływ świąt
model.plot_components(forecast)Holidays for Subdivisions (Python)
Możesz dodać święta dla konkretnych regionów/stanów:
# Święta dla konkretnego stanu USA
model = Prophet()
model.add_country_holidays(
country_name='US',
subdiv='CA' # Kalifornia
)
model.fit(df)
# Inne przykłady subdivisions:
# US: 'CA', 'NY', 'TX', 'FL', ...
# UK: 'England', 'Scotland', 'Wales', 'Northern Ireland'
# DE: 'BY' (Bawaria), 'BE' (Berlin), ...
# CA: 'ON' (Ontario), 'QC' (Quebec), ...
# Sprawdź dostępne subdivisions
import holidays
print(holidays.country_holidays('US').subdivisions)
# Połączenie kraju z custom holidays
custom_holidays = pd.DataFrame({
'holiday': 'company_event',
'ds': pd.to_datetime(['2021-03-15', '2022-03-15']),
})
model = Prophet(holidays=custom_holidays)
model.add_country_holidays(country_name='PL')
model.fit(df)Regressors
Dodatkowe Zmienne (Additional Regressors)
Regressors to dodatkowe zmienne, które mogą wpływać na prognozę.
Przykłady:
- Temperatura, pogoda
- Wydatki na reklamę
- Ceny konkurencji
- Ruch na stronie internetowej
- Wskaźniki ekonomiczne (inflacja, bezrobocie)
Wymagania:
- Musisz mieć wartości regressora dla WSZYSTKICH dat (historycznych i przyszłych)
- Jeśli nie masz wartości przyszłych, musisz je przewidzieć osobno
Dodawanie Regressors do Modelu - Część 1
import pandas as pd
import numpy as np
# Dane z dodatkową zmienną (temperatura)
df = pd.DataFrame({
'ds': pd.date_range('2020-01-01', periods=365),
'y': np.random.randn(365).cumsum() + 100,
'temperature': np.random.uniform(0, 30, 365) # Temperatura 0-30°C
})
# PRZED fit(): dodaj regressor do modelu
model = Prophet()
model.add_regressor(
name='temperature',
prior_scale=0.5, # Regularyzacja (domyślnie 10.0)
standardize='auto', # Automatyczna standaryzacja
mode='additive' # 'additive' (domyślne) lub 'multiplicative'
)
model.fit(df)Dodawanie Regressors do Modelu - Część 2
# Future MUSI mieć kolumnę 'temperature'!
future = model.make_future_dataframe(periods=30)
# Musisz przewidzieć przyszłe wartości temperatury
# Opcja 1: Prosta prognoza (średnia)
future['temperature'] = df['temperature'].mean()
# Opcja 2: Sezonowa prognoza
# future['temperature'] = forecast_temperature_model.predict(future)
forecast = model.predict(future)
# Zobacz wpływ temperatury
print(forecast[['ds', 'yhat', 'temperature']].tail())Wiele Regressors - Część 1
# Dane z wieloma zmiennymi dodatkowymi
df = pd.DataFrame({
'ds': pd.date_range('2020-01-01', periods=365),
'y': np.random.randn(365).cumsum() + 1000,
'ad_spend': np.random.uniform(1000, 5000, 365), # Wydatki na reklamę
'temperature': np.random.uniform(0, 30, 365),
'competitor_price': np.random.uniform(50, 150, 365)
})
# Dodaj wszystkie regressors
model = Prophet()
model.add_regressor('ad_spend', prior_scale=0.5)
model.add_regressor('temperature', prior_scale=0.3)
model.add_regressor('competitor_price', prior_scale=0.7)
model.fit(df)Wiele Regressors - Część 2
# Future z wszystkimi regressors
future = model.make_future_dataframe(periods=30)
future['ad_spend'] = 3000 # Planowany budżet reklamowy
future['temperature'] = 15 # Średnia temperatura
future['competitor_price'] = 100 # Przewidywana cena konkurencji
forecast = model.predict(future)
# Zobacz wkład każdego regressora
model.plot_components(forecast)
# Wykres pokaże osobne linie dla każdego regressoraMultiplicative Regressors
Additive vs Multiplicative:
- Additive (domyślny): efekt dodawany do prognozy
- Multiplicative: efekt mnożony przez prognozę
# Przykład: promocja zwiększa sprzedaż o % (multiplicative)
df['promotion'] = 0 # 0 = brak promocji, 1 = promocja aktywna
# Dodaj dni promocyjne
df.loc[df['ds'].isin(promo_dates), 'promotion'] = 1
model = Prophet()
# Multiplicative regressor
model.add_regressor(
name='promotion',
mode='multiplicative', # Efekt procentowy
prior_scale=0.5
)
model.fit(df)
# Future z informacją o planowanych promocjach
future = model.make_future_dataframe(periods=60)
future['promotion'] = 0
future.loc[future['ds'].isin(future_promo_dates), 'promotion'] = 1
forecast = model.predict(future)
# Multiplicative: yhat = baseline * (1 + promotion_effect)
# Additive: yhat = baseline + promotion_effectCross-Validation dla Szeregów Czasowych
Prophet używa Time Series Cross-Validation:
- Szacuje błąd out-of-sample
- Zachowuje kolejność chronologiczną
- Używa expanding window (rozszerzające się okno)
Parametry cross_validation():
-
initial- początkowy okres treningowy (np. '730 days') -
period- jak często tworzyć cutoff (np. '180 days') -
horizon- jak daleko prognozować (np. '365 days')
from prophet.diagnostics import cross_validation
# Cross-validation
df_cv = cross_validation(
model,
initial='730 days', # Minimum 2 lata danych treningowych
period='180 days', # Nowy cutoff co 180 dni
horizon='365 days' # Prognozuj 365 dni w przód
)
# df_cv zawiera:
# - ds: data prognozy
# - yhat: prognozowana wartość
# - yhat_lower, yhat_upper: przedziały ufności
# - y: rzeczywista wartość
# - cutoff: data końca okresu treningowego
print(f"Liczba prognoz: {len(df_cv)}")
print(df_cv.head())Performance Metrics - Metryki Wydajności
from prophet.diagnostics import performance_metrics
from prophet.plot import plot_cross_validation_metric
import matplotlib.pyplot as plt
# Oblicz metryki dla różnych horyzontów
df_metrics = performance_metrics(df_cv)
print(df_metrics)
# horizon mse rmse mae mape mdape coverage
# 0 37 days 12.34 3.51234 2.67890 0.02567 0.02134 0.923
# 1 74 days 15.67 3.95234 3.12345 0.03012 0.02567 0.912
# 2 111 days 18.90 4.34567 3.45678 0.03456 0.02890 0.901Performance Metrics - Opis Metryk
Metryki:
- mse: Mean Squared Error
- rmse: Root Mean Squared Error
- mae: Mean Absolute Error
- mape: Mean Absolute Percentage Error
- mdape: Median Absolute Percentage Error
- coverage: % wartości w przedziale ufności
# Wizualizacja MAPE vs horizon
fig = plot_cross_validation_metric(df_cv, metric='mape')
plt.title('MAPE w zależności od horyzontu prognozy')
plt.show()
# Wizualizacja RMSE
fig = plot_cross_validation_metric(df_cv, metric='rmse')
plt.show()Parallelizing Cross Validation - Część 1
Cross-validation może być wolny dla dużych zbiorów danych. Prophet wspiera równoległe przetwarzanie!
from prophet.diagnostics import cross_validation
import multiprocessing
# Sprawdź liczbę rdzeni CPU
n_cores = multiprocessing.cpu_count()
print(f"Dostępne rdzenie: {n_cores}")
# Metoda 1: Użyj parallel z cross_validation (Python)
# Prophet automatycznie używa wszystkich dostępnych rdzeni
df_cv = cross_validation(
model,
initial='730 days',
period='180 days',
horizon='365 days',
parallel='processes' # 'processes', 'threads' lub None
)Parallelizing Cross Validation - Część 2
# Metoda 2: Równoległe testowanie wielu modeli z joblib
from joblib import Parallel, delayed
def evaluate_model(params):
model = Prophet(**params)
model.fit(df)
df_cv = cross_validation(model, initial='365 days',
period='90 days', horizon='180 days')
df_metrics = performance_metrics(df_cv)
return df_metrics['mape'].mean()
# Równoległe testowanie wielu modeli
results = Parallel(n_jobs=-1)( # -1 = użyj wszystkich rdzeni
delayed(evaluate_model)(params) for params in param_list
)
print(f"Przyspieszenie: ~{n_cores}x")Hyperparameter Tuning - Grid Search
Najważniejsze hiperparametry do dostrojenia:
-
changepoint_prior_scale- elastyczność trendu (0.001-0.5) -
seasonality_prior_scale- elastyczność sezonowości (0.01-10) -
holidays_prior_scale- wpływ świąt (0.01-10) -
seasonality_mode- 'additive' vs 'multiplicative'
import itertools
from prophet.diagnostics import cross_validation, performance_metrics
# Parametry do przetestowania
param_grid = {
'changepoint_prior_scale': [0.001, 0.01, 0.1, 0.5],
'seasonality_prior_scale': [0.01, 0.1, 1.0, 10.0],
'holidays_prior_scale': [0.01, 0.1, 1.0, 10.0],
'seasonality_mode': ['additive', 'multiplicative']
}
# Wygeneruj wszystkie kombinacje
all_params = [dict(zip(param_grid.keys(), v))
for v in itertools.product(*param_grid.values())]
print(f"Liczba kombinacji: {len(all_params)}")
# Lista na wyniki
results = []
# Testuj każdą kombinację
for params in all_params:
model = Prophet(**params)
model.fit(df)
df_cv = cross_validation(model, initial='730 days',
period='180 days', horizon='365 days')
df_metrics = performance_metrics(df_cv)
results.append({
**params,
'mape': df_metrics['mape'].mean(),
'rmse': df_metrics['rmse'].mean()
})Analiza Wyników Tuningu - Część 1
# Utwórz DataFrame z wynikami
results_df = pd.DataFrame(results)
# Sortuj po MAPE
results_df = results_df.sort_values('mape')
print("Top 5 najlepszych modeli:")
print(results_df.head())
# Najlepsze parametry
best_params = results_df.iloc[0].to_dict()
print("\nNajlepsze parametry:")
for key, value in best_params.items():
if key not in ['mape', 'rmse']:
print(f" {key}: {value}")
print(f"\nNajlepszy MAPE: {best_params['mape']:.4f}")
print(f"Najlepszy RMSE: {best_params['rmse']:.4f}")Analiza Wyników Tuningu - Część 2
# Wizualizacja wpływu parametrów
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# Wpływ changepoint_prior_scale
results_df.groupby('changepoint_prior_scale')['mape'].mean().plot(
ax=axes[0, 0], marker='o'
)
axes[0, 0].set_title('Changepoint Prior Scale vs MAPE')
# Wpływ seasonality_prior_scale
results_df.groupby('seasonality_prior_scale')['mape'].mean().plot(
ax=axes[0, 1], marker='o'
)
axes[0, 1].set_title('Seasonality Prior Scale vs MAPE')
plt.tight_layout()
plt.show()Random Search i Bayesian Optimization
Dla dużych przestrzeni parametrów Grid Search jest wolny. Użyj alternatywnych metod:
import numpy as np
from sklearn.model_selection import RandomizedSearchCV
# Random Search - losowo próbkuj przestrzeń parametrów
param_distributions = {
'changepoint_prior_scale': np.logspace(-3, 0, 20), # 0.001 do 1
'seasonality_prior_scale': np.logspace(-2, 1, 20), # 0.01 do 10
'holidays_prior_scale': np.logspace(-2, 1, 20)
}
# Losuj 50 kombinacji zamiast testować wszystkie
n_iter = 50
results = []
for i in range(n_iter):
params = {
'changepoint_prior_scale': np.random.choice(
param_distributions['changepoint_prior_scale']
),
'seasonality_prior_scale': np.random.choice(
param_distributions['seasonality_prior_scale']
),
'holidays_prior_scale': np.random.choice(
param_distributions['holidays_prior_scale']
)
}
model = Prophet(**params)
model.fit(df)
df_cv = cross_validation(model, initial='365 days',
period='90 days', horizon='180 days')
df_metrics = performance_metrics(df_cv)
results.append({**params, 'mape': df_metrics['mape'].mean()})
# Najlepszy wynik
best = min(results, key=lambda x: x['mape'])
print("Najlepsze parametry (Random Search):", best)Uncertainty Intervals - Przedziały Ufności
# Domyślnie Prophet daje 95% przedział ufności
# Zmień szerokość przedziału
model = Prophet(
interval_width=0.80 # 80% przedział ufności
)
model.fit(df)
forecast = model.predict(future)
# forecast zawiera:
# - yhat: prognoza (median)
# - yhat_lower: dolna granica (10% percentyl dla interval_width=0.80)
# - yhat_upper: górna granica (90% percentyl)
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())Uncertainty Intervals - Kontrola Przedziałów
# Szerszy przedział (99%)
model_wide = Prophet(interval_width=0.99)
model_wide.fit(df)
forecast_wide = model_wide.predict(future)
# Węższy przedział (50%)
model_narrow = Prophet(interval_width=0.50)
model_narrow.fit(df)
forecast_narrow = model_narrow.predict(future)
# Kontroluj liczbę próbek (dokładność przedziałów)
model = Prophet(
uncertainty_samples=2000 # Domyślnie 1000
)Outliers - Wykrywanie i Obsługa
Outliers to wartości znacząco odstające od reszty danych. Prophet jest odporny, ale ekstrema mogą wpływać na prognozę.
Rodzaje outliers:
- Błędy pomiarowe
- Jednorazowe wydarzenia (awarie, promocje)
- Anomalie w danych
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Wczytaj dane
df = pd.read_csv('data.csv')
# Metoda 1: IQR (Interquartile Range)
def detect_outliers_iqr(df, column='y', threshold=1.5):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - threshold * IQR
upper_bound = Q3 + threshold * IQR
outliers = (df[column] < lower_bound) | (df[column] > upper_bound)
print(f"Znaleziono {outliers.sum()} outliers")
return outliers
# Metoda 2: Z-score (odległość od średniej w odchyleniach std)
def detect_outliers_zscore(df, column='y', threshold=3):
mean = df[column].mean()
std = df[column].std()
z_scores = np.abs((df[column] - mean) / std)
outliers = z_scores > threshold
print(f"Znaleziono {outliers.sum()} outliers (Z-score)")
return outliers
# Wizualizacja
outliers_iqr = detect_outliers_iqr(df)
plt.figure(figsize=(14, 5))
plt.plot(df['ds'], df['y'], label='Dane')
plt.scatter(df.loc[outliers_iqr, 'ds'],
df.loc[outliers_iqr, 'y'],
color='red', s=100, label='Outliers')
plt.legend()
plt.show()import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Wczytaj dane
df = pd.read_csv('data.csv')
# Metoda 1: IQR (Interquartile Range)
def detect_outliers_iqr(df, column='y', threshold=1.5):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - threshold * IQR
upper_bound = Q3 + threshold * IQR
outliers = (df[column] < lower_bound) | (df[column] > upper_bound)
print(f"Znaleziono {outliers.sum()} outliers")
return outliers
# Metoda 2: Z-score (odległość od średniej w odchyleniach std)
def detect_outliers_zscore(df, column='y', threshold=3):
mean = df[column].mean()
std = df[column].std()
z_scores = np.abs((df[column] - mean) / std)
outliers = z_scores > threshold
print(f"Znaleziono {outliers.sum()} outliers (Z-score)")
return outliers
# Wizualizacja
outliers_iqr = detect_outliers_iqr(df)
plt.figure(figsize=(14, 5))
plt.plot(df['ds'], df['y'], label='Dane')
plt.scatter(df.loc[outliers_iqr, 'ds'],
df.loc[outliers_iqr, 'y'],
color='red', s=100, label='Outliers')
plt.legend()
plt.show()Outliers - Usuwanie
# Opcja 1: Usuń outliers całkowicie
def remove_outliers(df, column='y', threshold=1.5):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - threshold * IQR
upper = Q3 + threshold * IQR
df_clean = df[(df[column] >= lower) & (df[column] <= upper)]
print(f"Usunięto {len(df) - len(df_clean)} wierszy")
return df_clean
df_no_outliers = remove_outliers(df)
# Opcja 2: Zastąp outliers NaN (Prophet interpoluje)
def replace_outliers_with_nan(df, column='y', threshold=3):
mean = df[column].mean()
std = df[column].std()
df_copy = df.copy()
mask = np.abs((df_copy[column] - mean) / std) > threshold
df_copy.loc[mask, column] = np.nan
print(f"Zastąpiono {mask.sum()} wartości na NaN")
return df_copy
df_with_nans = replace_outliers_with_nan(df)Outliers - Winsoryzacja i Porównanie
# Opcja 3: Winsoryzacja - obetnij do percentyli
def winsorize(df, column='y', lower=0.01, upper=0.99):
lower_val = df[column].quantile(lower)
upper_val = df[column].quantile(upper)
df_copy = df.copy()
df_copy[column] = df_copy[column].clip(lower_val, upper_val)
return df_copy
df_winsorized = winsorize(df)
# Trenuj modele i porównaj
model1 = Prophet().fit(df_no_outliers)
model2 = Prophet().fit(df_with_nans)
model3 = Prophet().fit(df_winsorized)
# Porównaj prognozy
future = model1.make_future_dataframe(periods=30)
forecast1 = model1.predict(future)
forecast2 = model2.predict(future)
forecast3 = model3.predict(future)Handling Shocks - Obsługa Wstrząsów
Shocks (wstrząsy) to nagłe, nieoczekiwane zmiany w danych, które trwają przez pewien czas.
Przykłady:
- COVID-19 lockdown
- Kryzys finansowy
- Zmiana regulacji prawnych
- Awaria systemów
- Viralowa kampania marketingowa
Różnica: Outlier vs Shock
- Outlier: pojedyncza wartość odstająca
- Shock: trwała zmiana poziomu lub trendu
Modelowanie Shocks przez Regressor
Użyj binary regressor (0/1) do oznaczenia okresu wstrząsu:
import pandas as pd
from prophet import Prophet
# Dane z wstrząsem (np. COVID-19)
df = pd.read_csv('sales_data.csv')
# Dodaj kolumnę oznaczającą okres lockdown
df['lockdown'] = 0
df.loc[(df['ds'] >= '2020-03-15') &
(df['ds'] <= '2020-06-01'), 'lockdown'] = 1
# Model z regressorem
model = Prophet()
model.add_regressor('lockdown', mode='additive')
model.fit(df)
# Future musi zawierać wartości regressora
future = model.make_future_dataframe(periods=90)
future['lockdown'] = 0 # Zakładamy brak lockdown w przyszłości
# Lub modeluj stopniowy powrót do normalności
# future['lockdown'] = np.linspace(0.5, 0, len(future))
forecast = model.predict(future)
# Zobacz wpływ lockdown
print(forecast[['ds', 'lockdown', 'yhat']].head(20))
# Komponenty pokażą wpływ lockdown
model.plot_components(forecast)Modelowanie Shocks przez Changepoints
Jeśli shock zmienił trend na stałe, użyj ręcznych changepoints:
# Określ daty kluczowych wstrząsów
changepoints = [
'2020-03-15', # Początek lockdown
'2020-06-01', # Koniec lockdown
'2021-01-01', # Nowa strategia
]
model = Prophet(
changepoints=changepoints,
changepoint_prior_scale=0.5 # Większa elastyczność w tych punktach
)
model.fit(df)
# Opcja: Usuń dane z okresu shock dla czystej prognozy
# Jeśli shock był tymczasowy i nie powtórzy się
df_before_shock = df[df['ds'] < '2020-03-15']
df_after_shock = df[df['ds'] > '2020-06-01']
df_no_shock = pd.concat([df_before_shock, df_after_shock])
model_clean = Prophet()
model_clean.fit(df_no_shock)
# Porównaj prognozy
fig, axes = plt.subplots(1, 2, figsize=(16, 5))
model.plot(forecast, ax=axes[0])
axes[0].set_title('Z uwzględnieniem shock')
forecast_clean = model_clean.predict(
model_clean.make_future_dataframe(periods=90)
)
model_clean.plot(forecast_clean, ax=axes[1])
axes[1].set_title('Bez shock (dane usunięte)')
plt.show()Strategie Obsługi Shocks
Wybierz strategię w zależności od typu shock:
1. Shock tymczasowy (powrót do normalności):
- Użyj binary regressor (0/1)
- Lub oznacz jako outliers i zastąp NaN
- Lub dodaj jako holiday z window
2. Shock trwały (nowa rzeczywistość):
- Dodaj manual changepoint w momencie shock
- Zwiększ changepoint_prior_scale
- Trenuj model tylko na danych po shock
Strategie Obsługi Shocks
Wybierz strategię w zależności od typu shock:
3. Shock nieznany (nie wiesz czy trwały):
- Trenuj 2 modele: z shock i bez
- Monitoruj nowe dane
- Dostosuj model gdy sytuacja się wyjaśni
4. Multiple shocks:
- Dodaj regressor dla każdego shock
- Lub użyj wielu changepoints
Dane Nie-dzienne - Godzinowe
# Dane godzinowe
df_hourly = pd.DataFrame({
'ds': pd.date_range('2020-01-01', periods=24*365, freq='H'),
'y': np.random.randn(24*365).cumsum() + 100
})
model = Prophet(
daily_seasonality=True # Włącz sezonowość dzienną
)
model.fit(df_hourly)
# Prognoza na 7 dni (168 godzin)
future = model.make_future_dataframe(periods=168, freq='H')
forecast = model.predict(future)Dane Nie-dzienne - Miesięczne
# Dane miesięczne
df_monthly = pd.DataFrame({
'ds': pd.date_range('2010-01-01', periods=120, freq='MS'), # MS = month start
'y': np.random.randn(120).cumsum() + 1000
})
model = Prophet(
yearly_seasonality=True,
weekly_seasonality=False,
daily_seasonality=False
)
model.fit(df_monthly)
# Prognoza na 12 miesięcy
future = model.make_future_dataframe(periods=12, freq='MS')
forecast = model.predict(future)Zapisywanie i Ładowanie Modelu - Pickle
import pickle
# Metoda 1: Pickle (Python standard)
with open('prophet_model.pkl', 'wb') as f:
pickle.dump(model, f)
# Ładowanie
with open('prophet_model.pkl', 'rb') as f:
loaded_model = pickle.load(f)
# Użyj załadowanego modelu
future = loaded_model.make_future_dataframe(periods=30)
forecast = loaded_model.predict(future)Zapisywanie i Ładowanie Modelu - JSON
from prophet.serialize import model_to_json, model_from_json
# Metoda 2: JSON (zalecana, bardziej portable)
# Zapisz
with open('prophet_model.json', 'w') as f:
f.write(model_to_json(model))
# Załaduj
with open('prophet_model.json', 'r') as f:
loaded_model = model_from_json(f.read())
# Użyj załadowanego modelu
future = loaded_model.make_future_dataframe(periods=30)
forecast = loaded_model.predict(future)
# Zapisz też DataFrame z danymi
df.to_csv('training_data.csv', index=False)Praktyczny Przykład - Prognoza Sprzedaży (1)
import pandas as pd
from prophet import Prophet
# 1. Wczytaj dane sprzedażowe
df = pd.read_csv('sales_data.csv')
df['ds'] = pd.to_datetime(df['date'])
df['y'] = df['sales']
df = df[['ds', 'y']]
# 2. Dodaj informacje o promocjach i pogodzie
df['promotion'] = 0
df.loc[df['ds'].isin(promo_dates), 'promotion'] = 1
df['temperature'] = temperature_data
# 3. Święta
holidays = pd.DataFrame({
'holiday': 'black_friday',
'ds': pd.to_datetime(['2020-11-27', '2021-11-26', '2022-11-25']),
'lower_window': -2,
'upper_window': 2
})Praktyczny Przykład - Prognoza Sprzedaży (2)
# 4. Model
model = Prophet(
holidays=holidays,
seasonality_mode='multiplicative', # Sezonowość procentowa
changepoint_prior_scale=0.05
)
model.add_country_holidays(country_name='PL')
model.add_regressor('promotion', mode='multiplicative')
model.add_regressor('temperature')
# 5. Trenuj model
model.fit(df)
print("Model wytrenowany pomyślnie!")Praktyczny Przykład - Prognoza (3)
# 6. Future z regressors
future = model.make_future_dataframe(periods=90)
# Dodaj wartości regressors dla przyszłości
future['promotion'] = 0
future.loc[future['ds'].isin(future_promos), 'promotion'] = 1
future['temperature'] = future_temperature_forecast
# 7. Prognoza
forecast = model.predict(future)
# 8. Analiza wyników
print("Prognoza na najbliższe 7 dni:")
print(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(7))Praktyczny Przykład - Wizualizacja (4)
# 9. Wizualizacja
import matplotlib.pyplot as plt
fig1 = model.plot(forecast)
plt.title('Prognoza sprzedaży na 90 dni')
plt.show()
fig2 = model.plot_components(forecast)
plt.show()
# 10. Zapisz wyniki
forecast.to_csv('sales_forecast.csv', index=False)
print("Prognoza zapisana do pliku sales_forecast.csv")Best Practices - Dobre Praktyki
1. Przygotowanie danych:
- Minimum kilka miesięcy danych historycznych
- Kolumny MUSZĄ nazywać się 'ds' i 'y'
- Usuń lub oznacz outliers
- Prophet radzi sobie z brakami danych (NaN)
2. Modelowanie:
- Zacznij od prostego modelu, potem dodawaj złożoność
- Użyj cross-validation do tuningu
- Dodaj święta i wydarzenia specjalne
- Użyj regressors jeśli masz dodatkowe dane
3. Ewaluacja:
- Zawsze sprawdź komponenty (plot_components)
- Użyj cross_validation dla rzetelnej ewaluacji
- Wizualizuj prognozy
- Porównaj z prostymi baseline'ami
Częste Problemy i Rozwiązania
❌ Problem 1: Kolumny nie nazywają się 'ds' i 'y'
✅ Rozwiązanie: df = df.rename(columns={'date': 'ds', 'value': 'y'})
❌ Problem 2: Overfitting (za dużo changepoints)
✅ Rozwiązanie: Zmniejsz changepoint_prior_scale (np. 0.01)
❌ Problem 3: Underfitting (za gładki trend)
✅ Rozwiązanie: Zwiększ changepoint_prior_scale (np. 0.5)
❌ Problem 4: Brak wartości regressora w future
✅ Rozwiązanie: Dodaj kolumnę do future DataFrame
❌ Problem 5: Wolny trening
✅ Rozwiązanie: Zmniejsz uncertainty_samples, użyj mniej regressors
❌ Problem 6: Instalacja pystan nie działa
✅ Rozwiązanie: Użyj conda install -c conda-forge prophet
Podsumowanie
Czego się nauczyliśmy:
- Czym jest Facebook Prophet i kiedy go używać
- Instalacja i podstawowe użycie (Quick Start)
- Python API - parametry i metody
- Saturating Forecasts - prognozy z ograniczeniami (cap, floor)
- Trend Changepoints - automatyczna detekcja i ręczne określanie
- Seasonality - sezonowość roczna, tygodniowa, niestandardowa
- Holiday Effects - modelowanie świąt i wydarzeń
- Country Holidays - wbudowane święta dla wielu krajów
- Regressors - dodawanie zmiennych zewnętrznych
- Cross-validation i performance metrics
- Parallelizing cross validation - przyspieszenie obliczeń
- Hyperparameter tuning - Grid Search i Random Search
- Outliers - wykrywanie i różne metody obsługi (IQR, Z-score, winsoryzacja)
- Handling Shocks - strategie modelowania wstrząsów (regressors, changepoints)
- Best practices i rozwiązywanie problemów
Zasoby i Dalsze Kroki
Oficjalna dokumentacja:
- https://facebook.github.io/prophet/
- Quick Start: https://facebook.github.io/prophet/docs/quick_start.html
- GitHub: https://github.com/facebook/prophet
Dalsze tematy do nauki:
- Seasonality modes - additive vs multiplicative
- Sub-daily data - dane minutowe
- Prophet w R - alternatywna implementacja
- Ensemble methods - łączenie z innymi modelami
- Real-time forecasting - aktualizacje na bieżąco
Alternatywne biblioteki:
- ARIMA/SARIMA (statsmodels)
- LSTM (TensorFlow/Keras)
- XGBoost dla szeregów czasowych
- NeuralProphet - następca Prophet z neural networks
Dziękuję za Uwagę!
Pytania?
"The best time to plant a tree was 20 years ago. The second best time is now." - Najlepszy czas na prognozowanie to teraz!
Powodzenia z prognozowaniem! 📈🔮
Facebook Prophet - Prognozowanie Szeregów Czasowych w Pythonie
By noinputsignal