Prophet İle Zaman Serisi Tahmini
Sayfa Görüntüleme Verilerinin Tahmin İçin Kullanılması
Veri analizi ve görselleştirme çalışmalarının kapsamını biraz daha genişletebilmek adına zaman serileri ve bu işlemlerin ardından yatan matematiksel ve istatiksel işlemleri anlamaya çalışıyorum. scikit-learn bu aşamada en çok karşılaştığım kütüphanelerden biri1. Ancak, bu süreci kolaylaştırmak ve hataları minimize edebilmek adına sunulan Prophet2, Darts3 ve Auto_TimeSeries gibi çeşitli yardımcı kütüphaneler de mevcut. Bu yazıda temel bir düzeyde de olsa Prophet ile ilgili notlarımı paylaşmaya çalışacağım.
Zaman serisi tahmini belirli bir duruma ilişkin zamana bağlı olarak sıralanmış veriler baz alınarak gelecekteki durumlara ilişkin tahminler (forecast) yürütülebilmesini sağlayan kavramsal bir model olarak ifade edilebilir4 5. Hisse senetlerinin açılış fiyatı, bir işletmenin aylık veya yıllık ürün satış miktarı, kullanıcılar tarafından bir arama motoru aracılığı ile belirli konulara yönelik olarak yapılan aramalar, 2 nokta arasındaki uçak seferleri ve yolcuların sayısı, konut satışları, belirli bir zaman dilimi içerisindeki elektrik tüketimi, belirli bir bölgeye ait aylık ve yıllık yağış miktarları, bir süre boyunca her gün atılan adım miktarı gibi pek çok durum örnek olarak verilebilir6.
Prophet
Prophet, R ve Python programlama dilleri için hazırlanmış, Facebook Open Source tarafından geliştirilen, sklearn
model API'i izleyen bir tahmin prosedürüdür. Prophet, ayrıştırılabilir (trend, mevsimsellik/sezonsallık, tatiller) bir zaman serisi modeli kullanmakta7.
Doğrusal olmayan zaman serisi verileri kullanılarak yıllık, dönemlik, haftalık ve günlük tahminlerde bulunulmasını mümkün kılan Prophet veri kayıpları ve uç değerleri de başarılı bir şekilde ele almakta.
Yönergeler bu 2 dil için oldukça anlaşılır ve güncel bir şekilde paylaşılmakta. Prosedür ile ilgili açıklama bölümünde ilgili işlemlerin olabildiğince doğru ve hızlı sonuçlar üretmesinin yanı sıra veri bilimcileri ve analistler tarafından kolay bir şekilde ayarlamalarının yapılabileceği bir yapı oluşturmaya çalışıldığı belirtilmekte8.
Aşağıdaki örnek işlemde bir web sitesine ait günlük syafa görüntüleme sayılarını zaman serisi tahmini için kullanacağım. Bu veriyi daha önce yayınladığım Python İle Google Analytics ve Search Console API İşlemleri başlıklı yazıdaki örnek kod parçacığı ile edindim. Ek olarak, tatil verileri ile ilgili olarak da Python İle PDF İçerisinden Metin Kazımak başlıklı yazımı inceleyebilirsiniz.
01-01-2018 ile 31-07-2021 tarihleri arasına ait 1307 gözlemden ve 2 sütundan ((1307, 2)) oluşan sayfa görüntüleme kayıtlarına ait özet:
1.01.2018;13053
2.01.2018;17263
3.01.2018;14330
4.01.2018;12155
5.01.2018;15418
...
27.07.2021;28519
28.07.2021;29134
29.07.2021;30600
30.07.2021;27762
31.07.2021;26816
Tatil verilerine ait özet;
2017-01-01
2017-04-23
2017-05-01
2017-05-19
2017-06-24
...
2021-07-19
2021-07-20
2021-07-21
2021-07-22
2021-07-23
İşlemler için sıklıkla kullanacağım pandas
paketi ve bu pakete ait read_csv
metodu ilgili CSV dosyalarının yüklenerek DataFrame haline getirilmesi ile başlayabiliriz.
Prophet için veri girişi ds
ve y
sütunlarını kullanılır. Sütun adlarındaki ds
tarihsel değeri (Datetime) ve y
ise sayısal olarak tahmin etmek istediğiniz değeri (target veya label) ifade eder.
import pandas as pd
df = pd.read_csv('/pageviews.csv', header=0, names=['ds','y'], delimiter=';')
holidays = pd.read_csv('/holidays.csv', header=0, names=['ds'], delimiter=',')
Python Datetime Modülü İle Tarih - Zaman İşlemleri başlıklı yazımda Python programlama dilinin ön tanımlı olarak tarih veri tipine sahip olmadığından ancak datetime
ve pandas
gibi paketler aracılığı ile tarihsel işlemler yapılabileceğinden, pandas'ın ayrıca tarih ve zaman veri tiplerini barındırdığından bahsetmiştim. Şimdi, bu bilgi doğrultusunda pandas'a ait to_datetime
metodunu kullanalım.
df['ds'] = pd.to_datetime(df['ds'], format='%d.%m.%Y', errors='ignore')
df.head()
ds | y | |
---|---|---|
1302 | 2021-07-27 | 28519 |
1303 | 2021-07-28 | 29134 |
1304 | 2021-07-29 | 30600 |
1305 | 2021-07-30 | 27762 |
1306 | 2021-07-31 | 26816 |
Eksik bir veri olup olmadığını df.isna().any()
ile kontrol edebiliriz. True
değeri dönmesi belirtilen tarih(ler) için Google Analytics tarafında bir kayıt gerçekleştirilmediği ve/ya ilgili kaydın işlemler esnasında silindiği anlamına gelebilir. Buna bağlı olarak eksik veri için yakın ya da ortalama değer kullanılabilir.
Aynı şekilde, date_range
metodu ile tarihleri de gözden geçirmemiz uygun olacaktır.
missing_dates = pd.date_range(start=df['ds'].min(), end=df['ds'].max()).difference(df['ds'])
missing_dates
'''
DatetimeIndex([], dtype='datetime64[ns]', freq='D')
'''
Veri ile ilgili istatistikleri son bir defa daha gözden geçirelim.
df.info()
'''
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1307 entries, 0 to 1306
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ds 1307 non-null datetime64[ns]
1 y 1307 non-null int64
dtypes: datetime64[ns](1), int64(1)
memory usage: 30.6 KB
'''
df.describe()
'''
y
count 1307.000000
mean 27200.494262
std 17122.890352
min 993.000000
25% 11824.000000
50% 24451.000000
75% 44630.500000
max 65125.000000
'''
Bu aşamaya kadar aslında elimizdeki veriyi kontrol edip Prophet için uygun hale getirmiş olduk.
Bu aşamadan sonrası verinin görselleştirilmesi ve Prophet aracılığı ile işlemden geçirilmesi ile ilgili olacak. İlk olarak gerekli paketleri yükleyelim ve ardından verimize çizgi grafiği aracılığı ile bakalım.
from prophet import Prophet
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 8), dpi=200)
plt.plot(df['ds'], df['y'])
plt.title('Pageview')
plt.xlabel('Date')
plt.ylabel('Views')
plt.show()

Birkaç noktada ani düşüşler görünüyor. Pandas query
metodu ile bu alanlara yakından bakalım.
df.query("ds > '10-10.2020' and ds < '30-11-2020'").plot(x='ds', y='y')

Eldeki veri ile ilgili her şey yolunda ise Prophet ile ilgili düzenlemelere geçebiliriz. Prophet()
ile tahmin modelini tanımlıyoruz. Bu aşamada kullanılabilecek bazı parametrelerden de faydalanabilmekteyiz.
m = Prophet()
Prophet nesnesi ile ilişkili parametreleri dir
metodu ile listeleyebiliriz; dir(Prophet)
. Bu parametrelerden bazılarına aşağıda yer verdim.
Trend Parametreleri
Parametre | Açıklama |
---|---|
growth | linear ya da logistic değerlerini alır |
changepoints | Potansiyel dönüm noktalarını tanımlar. Eğer boş bırakılırsa otomatik olarak oluşturulur |
n_changepoints | Dönüm noktaları için dahil edilecek nokta sayısını belirtir |
changepoint_prior_scale | Değişim noktasının belirlenme esnekliğini tanımlar |
Sezonsallık ve Tatil Parametreleri
Parametre | Açıklama |
---|---|
daily_seasonality | Günlük sezonsallığı tanımlar. True veya False değeri alır |
weekly_seasonality | Haftanın günlerine bağlı sezonsallığı tanımlar. True veya False değeri alır |
yearly_seasonality | Yıllık sezonsallığı tanımlar. True veya False değeri alır |
holidays | Tatil günlerini tanımlar; ad ve tarih içeren bir DataFrame olarak iletilir |
holiday_prior_scale | Tatillerin veri değişimdeki etkisini/gücünü belirlemek için kullanılır |
seasonality_prior_scale | Sezonsal değişimin veri değişimdeki etkisini/gücünü belirlemek için kullanılır |
Maçlar ve benzeri dönemsel (aylık, haftalık) olarak söz konusu olan durumlarda weekly_seasonality
için False
değeri verilip ilgili sezonsallık ayrıca modele eklenebilir.
m = Prophet(weekly_seasonality=False)
m.add_seasonality(name='weekly_on_season', period=7, fourier_order=3, condition_name='on_season')
m.add_seasonality(name='weekly_off_season', period=7, fourier_order=3, condition_name='off_season')
Artık sahip olduğumuz veriler için fit
metodu ile öğrenme işlemini başlatabiliriz.
m.fit(df)
Bu aşamadan sonra artık tahmin oluşturma işlemlerine geçebiliriz.
future = m.make_future_dataframe(periods=6, freq='M')
make_future_dataframe
içerisinde periods
ile tahminin genişliğini, freq
ile periods
ile belirtilen sayısal değerin gün (day), hafta (week), ay (month), çeyreklik (quarter) ve yıl (year) olarak birimini ifade eder. Örneğin, periods=6
ve freq='M'
ile 6 aylık bir dönem belirtilmiş olacaktır. Tahminler için geçmiş tarihleri de kullanacaksak include_history
için True
değeri verilebilir.
Tahmin edilen veriye ait son 5 satırı görüntüleyelim.
forecast = m.predict(future)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
yhat
tahmin edilen değeri, yhat_lower
tahmin edilen alt sınır değerini ve yhat_upper
tahmin edilen üst sınır değerini ifade eder.
ds yhat yhat_lower yhat_upper
1308 2021-09-30 64361.761223 47748.397929 81143.462649
1309 2021-10-31 70216.208049 38084.941807 104641.692041
1310 2021-11-30 79226.657448 32424.925871 131655.565849
1311 2021-12-31 83051.808601 14001.976910 156144.670404
1312 2022-01-31 83874.889960 -10767.884182 179685.090374
Grafik aracılığı ile bakalım.
fig1 = m.plot(forecast, figsize=(12, 6))

Yukarıda örneklendirilen veri kullanarak ve model için herhangi bir parametre tanımında bulunmadan 6 aylık bir tahmin oluşturmak istediğimizde aşağıdaki grafiğe ulaşılmakta.
Sezonsallık, tatiller ve değişim noktalarının veri üzerindeki etkileri oldukça düşük bir etki yaratmış gibi görünüyor. O halde, parametreler için değerler tanımlayarak bizim için en uygun (noktaların tamamına yakınını kapsayan) bir model oluşturmaya çalışalım9.
İlk olarak daha önce PDF içeriğinden kazıdığımız tatil verisini uygun gale getirelim.
holiday = pd.DataFrame({
'ds': holidays['ds'],
'holiday': 'start',
'lower_window': 0,
'upper_window': 2,
})
Bu arada, add_country_holidays
metodu ile çeşitli ülkelere ait ön tanımlı tatil verilerine de ulaşmak mümkün. Örnek olarak Türkiye için tanımlı verileri listeleyelim10.
m.add_country_holidays(country_name='TR')
m.train_holiday_names
'''
0 start
1 New Year's Day
2 National Sovereignty and Children's Day
3 Labour Day
4 Commemoration of Ataturk
5 Youth and Sports Day
6 Democracy and National Unity Day
7 Victory Day
8 Republic Day
9 Ramadan Feast
10 Ramadan Feast Holiday
11 Sacrifice Feast
12 Sacrifice Feast Holiday
dtype: object
'''
Bu verileri tekrar eğitim için kullanalım.
m = Prophet(yearly_seasonality=True,
seasonality_prior_scale=5,
holidays=holiday,
holidays_prior_scale=1,
changepoint_prior_scale=5)
m.fit(df)
future = m.make_future_dataframe(periods=6, freq='M')
forecast = m.predict(future)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
Elde edilen tahmin değerlerine bakıldığında, tahminin alt ve üst değerler açıklığının zamana bağlı olarak oldukça arttığı görülebilir.
ds yhat yhat_lower yhat_upper
1308 2021-09-30 64361.761223 46687.508813 78074.890175
1309 2021-10-31 70216.208049 38979.528898 97530.617444
1310 2021-11-30 79226.657448 30762.968989 126897.075345
1311 2021-12-31 83051.808601 13955.979289 152157.477989
1312 2022-01-31 83874.889960 -14840.257424 178205.721309
Grafik aracılığı ile bakalım.

Parametreler için verilen değerlerde bir süre sonra yakın sonuçlara ulaşılmaya başlandığı için bir sonraki aşamaya geçip tatillerin, sezonsallık ve haftalık değişimlerin etkileri ayrı grafikler halinde görüntülemeye geçelim.
fig2 = m.plot_components(forecast, weekly_start=1, figsize=(12, 8))

Grafiklerde de görüldüğü üzere hafta başından sonuna doğru ve yıllar bazında yaz aylarında sayfa görüntülemelerde belirgin bir düşüş görülmekte.
Son olarak değişim noktalarına bakalım.
from prophet.plot import add_changepoints_to_plot
fig = m.plot(forecast)
a = add_changepoints_to_plot(fig.gca(), m, forecast)

Prophet ile ilgili farklı veriler üzerinden mümkün olduğunca çalışmaya devam edeceğim11 12 13 14 15. Bu süreçte hem Prophet ve benzeri çözümler hem de ML ile ilgili edindiğim bilgileri paylaşmaya devam edeceğim.
Son olarak, Python veya R ile uğraşmadan, bir UI aracılığı ile temel bir şekilde Prophet yeteneklerinden faydalanamak için forecastr'i kullanabilirsiniz14.
- scikit-learn. Machine Learning in Python ↩
- Prophet. Forecasting at scale ↩
- Darts: Time Series Made Easy in Python ↩
- Zaman serisi. Wikipedia ↩
- Kardelen Erdem. (2020). Time Series Analysis (Zaman Serileri Analizi) ↩
- Murat Ova. (2019). Zaman Serisi Nedir? R ile Zaman Serisi Analizine Giriş ↩
- Ankit Choudharyç (2018). Generate Quick and Accurate Time Series Forecasts using Facebook’s Prophet (with Python & R codes) ↩
- Onur Sevli, Vesile Gül Başer. (2020). Covid-19 Salgınına Yönelik Zaman Serisi Verileri ile Prophet Model Kullanarak Makine Öğrenmesi Temelli Vaka Tahminlemesi. PDF ↩
- Hakkı Kaan Simsek. (2018). Python ile Zaman Serisi Analizi-2 ↩
- Generate and work with holidays in Python ↩
- Eric D. Brown, D.Sc. (2019). Forecasting Time Series Data With Prophet I & II ↩
- Rob Mulla. (2019). Hourly Time Series Forecasting using Facebook's Prophet. Kaggle ↩
- Martin Stingl. (2021). Anomaly Detection with Prophet ↩
- forecastr. Let's build a time series forecast, garethcull/forecastr. GitHub ↩ ↩
- Christopher Lewis. (2021). Forecasting Using Facebook’s Prophet Library ↩