最近在写时间序列的预测模型,用到了Prophet 模型,总结一下。
了解什么是Prophet模型
自行百度,我参考别人的
https://blog.csdn.net/beiye_/article/details/123353123
Prophet适用于各种具有潜在特殊特征的预测问题包括广泛的业务时间序列问题,并且其对时间序列趋势变化点的检测、季节性、节假日以及突发事件具有更好的拟合效果。
https://blog.csdn.net/weixin_46969441/article/details/121146137
重点:Prophet模型的输入必须只包含两列数据
Python实现Prophet模型
以鸢尾花-sepal length的数据为例,导入基本的库
import pandas as pd
from prophet.plot import plot_plotly,plot_components_plotly
from sklearn.metrics import mean_squared_error
import numpy as np
from prophet import Prophet
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
import warnings
warnings.filterwarnings("ignore")
from sklearn.datasets import load_iris
# 加载鸢尾花数据集
iris = load_iris()
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
iris_df.tail()
构造一列日期
#构造日期函数
from datetime import datetime, timedelta
def generate_dates(start_date_str, end_date_str, date_format="%Y-%m-%d"):
# 将字符串日期转换为datetime对象
start_date = datetime.strptime(start_date_str, date_format)
end_date = datetime.strptime(end_date_str, date_format)
# 生成日期列表
dates = []
current_date = start_date
while current_date <= end_date:
dates.append(current_date.strftime(date_format)) # 将日期对象转换回字符串并添加到列表中
current_date += timedelta(days=1) # 移动到下一天
return dates
dates = generate_dates("2024-01-01", "2024-05-29")
date = pd.DataFrame(dates,columns = ['日期'])
date['日期'] = pd.to_datetime(date['日期'])
构造数据完成
data = pd.concat([date,iris_df['sepal length (cm)']],axis = 1)
data.tail()
# 初始化模型 :Prophet模型的输入必须包含两列数据
data.columns = ['ds','y']
model = Prophet()
# 训练模型
train_num = 30 #数据后30行不参与模型训练
fut_num = 50 #往后预测多少天
train_data = data[:-train_num]
model.add_country_holidays(country_name="CN")
model.fit(train_data)
future = model.make_future_dataframe(periods=fut_num,freq='D')
forecast = model.predict(future)
# 绘制预测结果
fig1 = model.plot(forecast)
fig2 = model.plot_components(forecast)
#误差计算
days = generate_dates("2024-01-01", "2024-06-18") #结束日期需要手动改
forecast[['日期']] = pd.DataFrame(days)
data = data.reset_index()
data[['日期']]= pd.DataFrame(days)
rmse = np.sqrt(mean_squared_error(data[['y']], forecast[['yhat']][:len(data)]))
mse = mean_squared_error(data[['y']], forecast[['yhat']][:len(data)])
true_result = data[['y','日期']].tail()
print('预测结果\n',forecast[['日期', 'yhat', 'yhat_lower', 'yhat_upper']].tail(30))
print(f'\n 真实结果:\n{true_result}\n \n预测与真实值之间的RMSE :{rmse}')
#结果可视化
plt.figure(figsize=(18,6))
plt.scatter(forecast['日期'][:len(data)],data['y'],ls=':',c='red',lw=1)
plt.fill_between(forecast['日期'],forecast['yhat_lower'],forecast['yhat_upper'],alpha = 0.15)
plt.plot(forecast['日期'],forecast['yhat'],c='blue')
plt.xlabel('日期', size= 15)
plt.xticks([days[i] for i in range(len(days)) if i % 3 == 0],rotation = 90)
plt.ylabel('鸢尾花sepal length', size= 15)
plt.title('Prophet模型鸢尾花sepal length预测与真实值比较', size= 18)
plt.legend(['真实值','预测值上下限','预测值'])
plt.show()
fig1 = model.plot(forecast)
fig2 = model.plot_components(forecast)
季节性、节假日等趋势变化
后面自己补充画的图
计算误差
foredata = forecast[['日期', 'yhat', 'yhat_lower', 'yhat_upper']]
all_data = pd.merge(foredata,data,on ='日期')
all_data = all_data[['日期', 'yhat', 'yhat_lower', 'yhat_upper','y']]
all_data.columns =['日期', '鸢尾花sepal length的预测值', 'yhat_lower', 'yhat_upper','鸢尾花sepal length的真实值']
all_data['误差'] = all_data['鸢尾花sepal length的真实值'] - all_data['鸢尾花sepal length的预测值']
all_data['误差百分比'] = all_data['误差']/all_data['鸢尾花sepal length的真实值']*100
all_data.tail(20)