پیشبینی سری های زمانی به وسیله کتابخانه پیشگوی فیسبوک (Prophet)

یکی از ابزارهایی که ما در مرکز تحقیقات هوش پارت از آن استفاده می کنیم کتابخانه Prophet یا به قولی کتابخانه «پیشگو» است. کتابخانه prophet یک کتابخانه برای پیشبینی سری های زمانی است که توسط تیم علم داده های فیسبوک توسعه داده شده است و از سال گذشته به صورت متن باز در دسترس عموم قرار گرفت. این کتابخانه با استفاده مدل های های جمعی (additive model) و بر اساس این مقاله می تواند سری های زمانی که دارای روندهای غیرخطی و الگوهای فصلی بودن روزانه، هفتگی و سالانه هستند را پیشبینی کند. علاوه بر این ها، پیشگو می تواند اثر روزهای تعطیل، داده های پرت و مقادیر گمشده را هم در پیشبینی که انجام می دهد در نظر بگیرد. کتابخانه پیشگو هم برای زبان پایتون و هم برای زبان R نوشته است که در این پست ما نحوه شروع به کار با کتابخانه پایتون آن را به شما توضیح می دهیم. در پست های بعدی الگوریتمی که این کتابخانه با آن سری های زمانی را پیشبینی می کند را به شما توضیح می گوییم.

تمام کدها و داده های مربوط به این پست درگیت هاب مرکز تحقیقات هوش پارت قرار داده شده است

نصب کتابخانه

اولین قدم برای شروع به کار با کتابخانه پیشگو نصب آن است که به وسیله دستور زیر به راحتی می توانیم آن را انجام دهیم.

pip install fbprophet

توجه: اگر بر روی ویندوز کار می کنیم برای نصب این کتابخانه به پیش نیازهایی مثل Visual C++ هم نیاز داریم.

شروع به کار

برای شروع به کار با پیشگو از یک دیتاست سری زمانی مصنوعی استفاده می کنیم که می توانید آن را در گیت هاب ما ببینید. استفاده از پیشگو بسیار آسان است تنها لازم است که کتابخانه آن را به برنامه اضافه کنیم، داده هایمان را به صورت یک دیتافریم پانداس بخوانیم و به فرمت مناسب در بیاوریم و سپس داده ها را برای مدل سازی به پیشگو بدهیم.

پیش از شروع باید تذکر بدهیم که داده ورودی به مدل ها در پیشگو باید به صورت یک دیتافریم باشد. برای همین باید داده های سری زمانی را از روی یک فایل بخوانیم و تبدیل به یک دیتافریم می کنیم. علاوه بر این، دیتافریمی که پیشگو به عنوان ورودی می گیرد باید دارای یک ستون به نام ds که شامل فیلدی از نوع تاریخ( تایپ datetime یا date در پانداس و پایتون) و یک ستون y شامل مقادیری که می خواهیم مدل سازی و پیشبینی کنیم باشد که در شکل زیر هم این مسئله مشخص است.

برای شروع ابتدا کتابخانه پیشگو و چندین کتابخانه ضروری دیگر مثل نامپای و پانداس را به برنامه اضافه می کنیم:

import matplotlib.pyplot as plt 
import numpy as np
import pandas as pd
import fbprophet

سپس با استفاده از پانداس دیتاست حاوی سری زمانی را به صورت یک دیتافریم به نام data می خوانیم و تنها ستون تاریخ و قیمت بسته شدن را نگه می داریم. علاوه بر این نام این دو ستون را به ترتیب به ds و y تغییر می دهیم تا مطابق با فرمت مدنظر پیشگو شود.

data = pd.read_csv('stock_data.csv', usecols=['Date', 'close_price'])
data.columns = ['ds', 'y']
data.head()


علاوه بر این، اغلب پیش از مدل سازی داده ها لازم است که داده ها را از حالت غیر ایستا به ایستا تبدیل و روندها را خطی تر کنیم. برای این کار لگاریتم مقادیر ستون y را به دست می آوریم و از آن به جای ستون اصلی y برای پیشبینی استفاده می کنیم.

data['y'] = np.log(data['y'])
data.head()

پیشگو از رویکرد و ساختاری مشابه با مدل های کتابخانه یادگیری ماشین sklearn پیروی می کند یعنی برای برازش مدل ابتدا باید یک نمونه از شی Prophet بسازیم و هر تنظیمات خاصی که برای فرآیند پیشبینی در نظر داریم را در آن مشخص کنیم. این نمونه ساخته شده دارای یک متد ()fit برای برازش مدل است که با فراخوانی آن بر روی داده های سری زمانی فرآیند برازش که معمولا در حدود 1 تا 5 ثانیه طول می کشد را انجام دهیم. این مدل یک متد ()predict هم دارد که برای پیشبینی مشاهدات جدید به کار می رود. این دو متد را به صورت مفصل تر در این مثال توضیح می دهیم.

برای مدل سازی لازم است که به صورت یک نمونه از کلاس Prophet بسازیم و آن را بر روی دیتافریم حاوی داده ها ()fit کنیم. برای شروع یک مدل ساده Prophet به نام p می سازیم و با استفاده از متد ()p.fit بر روی دیتافریم data برازش می کنیم.

from fbprophet import Prophet
p = Prophet()
p.fit(data)

حال که مدل را برازش کردیم برای پیشبینی مقدار سری زمانی در آینده باید ابتدا با استفاده از متد ()make_future_dataframe دیتافریمی از تاریخ های مشخصی در آینده که می خواهیم برای آن ها پیشبینی انجام دهیم بسازیم. به صورت پیشفرض این دیتافریم شامل مقادیر مربوط به داده های گذشته هم هست. در این متد تعداد دوره های آینده ای که می خواهیم پیشبینی شوند را با استفاده از پارامتر ورودی تعداد دوره ها (periods) مشخص می کنیم. به عنوان مثال در مثال زیر با استفاده از ورودی periods = 100 به پیشگو می گوییم که یک دیتافریم حاوی تاریخ های گذشته به همراه 100 روز آینده را ایجاد کن.

future = p.make_future_dataframe(periods=100)
future.tail()

اگر هم بخواهیم پیشبینی بر اساس frequency غیر روزانه ایجاد شوند از ورودی freq استفاده می کنیم. به طور مثال، می خواهیم 10 ماه آینده را پیشبینی کنیم در این حالت ورودی periods را برابر با 10 قرار می دهیم و ورودی freq که به صورت پیشفرض برابر با D (روزانه) است را برابر با M (ماهانه) قرار می دهیم.

future = p.make_future_dataframe(periods=10, freq = 'M')

حال که این دیتافریم را ساختیم می توانیم آن را به عنوان ورودی متد ()predict به صورت زیر بدهیم و پپیشبینی را بر روی داده های آینده انجام دهیم.

forecast = p.predict(future)

خروجی این متد به صورت یک دیتافریم با مجموعه ای مختلف از اطلاعات در خصوص پیشبینی انجام شده است که در شکل زیر هم می توان آن را دید. مهمترین این ستون ها ds (تاریخ) ، yhat (مقدار پیشبینی شده)، yhat_lower و yhat_upper (سطوح عدم قطعیت پیشبینی یا همان فواصل اطمینان) هستند.

حال می توانیم با استفاده از متد ()plot شی مدل ساخته شده و با استفاده از دیتافریم پیشبینی شده نمودار پیشبینی ها را هم رسم کنیم و آن را با مقدار واقعی مقایسه کنیم.

p.plot(forecast)

در نمودار ساخته شده که نمایی از آن در شکل زیر نیز پیداست مقدار واقعی با خط آبی رنگ نشان داده شده است. همچنین مقدار پیشبینی شده با نقاط مشکی رنگ مشخص شده اند. فواصل اطمینان نیز با هاله آبی رنگ نشان داده شده اند.

یک قابلیت دیگر این است که می توانیم مولفه های پیشبینی را هم رسم کنیم. برای این کار کافی است که از متد ()plot_components استفاده کنیم که به صورت پیشفرض اگر داده های ما به صورت روزانه باشند مولفه های روند، فصلی بودن سال، فصلی بودن هفتگی سری زمانی را رسم می کند

p.plot_components(forecast)