网络流量预测是运维和容量规划中非常常见的需求。服务器带宽、接口入流量、CDN 回源量这类数据天然是时间序列,既带有长期的增长或下降趋势,也有明显的日周期和周周期规律。neuralprophet 是在经典 Prophet 思路基础上融合了神经网络的可分解时间序列模型,它把序列拆成趋势、季节性、节假日和滞后项分别建模,对网络流量这种多周期叠加的数据特别友好。本文从模型原理讲到完整代码实战,最后给出分量拆解和预测评估的思路。

一、为什么网络流量适合用可分解模型
拿到一份交换机出口的流量采样数据,通常会看到三种成分混在一起:一是趋势成分,比如业务量逐月增长导致基线缓慢抬升;二是季节性成分,白天高峰、深夜低谷的日周期,以及工作日高、周末低的周周期;三是随机波动和突发尖峰,比如活动推广或攻击流量带来的瞬时峰值。如果直接用一个整体模型去拟合,模型很容易被周期性淹没,看不清趋势的真实走向。
neuralprophet 的做法是把观测值拆成加法形式:
y(t) = T(t) + S(t) + E(t) + L(t) + F(t) # T: 趋势项 S: 季节性项 E: 节假日/事件项 # L: 自回归滞后项 F: 未来已知的外部回归量
这种拆分带来的最大好处是可解释性。预测出来一个明天的峰值,你可以明确知道其中多少来自趋势抬升、多少来自周周期效应,而不是像黑盒模型那样只有一个数字。对运维场景来说,这一点非常关键,因为告警阈值往往需要区分正常周期性高峰和异常增长。
另外,neuralprophet 用 PyTorch 实现了自动梯度下降训练,支持配置自回归项 AR-Net 和外部变量,比如把历史流量、机房温度甚至营销活动标记一起喂进模型。相比经典 Prophet,它在多变量场景下扩展性更好,预测精度通常也有提升。
二、数据准备与模型训练完整流程
假设我们已经通过 SNMP 或者 zabbix 导出了一份每 5 分钟采集一次的出口流量数据,先安装依赖并整理数据格式。neuralprophet 要求输入是一个包含 ds(时间戳)和 y(观测值)两列的 DataFrame,注意列名必须严格一致:
pip install neuralprophet
import pandas as pd
from neuralprophet import NeuralProphet, set_log_level
set_log_level("ERROR")
# 读取流量数据,原始格式为 timestamp,megabits_per_sec
df = pd.read_csv("traffic.csv")
df["ds"] = pd.to_datetime(df["timestamp"])
df["y"] = df["megabits_per_sec"].astype(float)
df = df[["ds", "y"]].dropna()
建模之前有一个细节不能忽略:采集频率必须是稳定的。如果中间有大量缺失点,建议先用 resample 补齐再插值,否则周期项的拟合会失真。5 分钟粒度的数据一小时就有 12 个点,一天 288 个点,直接用日周期会导致傅里叶阶数开销很大,这时候更实用的做法是先重采样到小时级:
# 重采样到小时均值,减少计算量
df = df.set_index("ds").resample("H").mean().interpolate().reset_index()
m = NeuralProphet(
growth="linear", # 线性趋势,流量平稳增长场景够用
n_changepoints=15, # 自动检测趋势拐点数量
changepoints_range=0.9, # 允许后 10% 数据不设拐点,避免过拟合尾部
yearly_seasonality=True, # 年周期,适合有寒暑假效应的校园网
weekly_seasonality=8, # 周周期傅里叶阶数
daily_seasonality=12, # 日周期傅里叶阶数,阶数越高越能拟合尖峰
learning_rate=0.05,
)
metrics = m.fit(df, freq="H", valid_p=0.1)
这里解释一下两个容易踩坑的参数。changepoints_range 默认是 0.9,意思是趋势拐点只会在前 90% 的时间范围内寻找,留出最后一段数据验证趋势的稳定性;如果把它设成 1.0,模型往往会在序列尾部强行拟合一个虚假的趋势突变。daily_seasonality 的傅里叶阶数也不是越大越好,流量曲线的日形态通常是一峰一谷,阶数取 10 到 15 就足够,调到 30 以上反而会把噪声当成周期信号学进去。
三、预测未来流量并拆解各分量
模型训练好之后,用 make_future_dataframe 生成未来时间戳,然后预测接下来 7 天的小时级流量:
future = m.make_future_dataframe(df, periods=7 * 24, freq="H")
forecast = m.predict(future)
# 查看关键列
print(forecast[["ds", "yhat1", "trend",
"season_daily", "season_weekly"]].tail())
# 绘制预测结果与分量拆解
fig1 = m.plot(forecast) # 整体预测与置信区间
fig2 = m.plot_components(forecast) # 趋势、日周期、周周期分开画
plot_components 输出的分量图是这套方案最有价值的部分。日周期图上你会看到流量大约从上午 9 点爬升、晚间 21 点到 22 点见顶、凌晨 4 点触底,这个形态一旦和历史监测吻合,说明模型确实学到了业务规律;周周期图则通常呈现周一到周五偏高、周六周日回落的形态。如果分量图和实际业务直觉明显不符,多半是训练数据里混入了异常段,需要回到清洗环节排查。
拿到预测值后,实际落地一般是两个用途。一是容量规划:取预测的上界分位数作为扩容依据,提前评估带宽余量;二是动态告警阈值:用 yhat 加上历史残差的标准差乘一个系数,生成随时间变化的阈值带,替代过去拍脑袋定的固定阈值,能显著减少深夜低谷期的误报。评估精度时建议看 MAE 和 MAPE 而不是只看 RMSE,因为流量突发尖峰会主导 RMSE,掩盖常态预测的真实水平。
四、加入自回归和事件效应提升精度
纯趋势加季节性的模型对短期波动的响应偏慢,因为当前时刻的流量和过去几小时的相关性很强,这部分信息可以通过自回归项利用起来:
m2 = NeuralProphet(
n_lags=24, # 使用过去 24 小时作为自回归输入
n_forecasts=6, # 每次向前预测 6 小时
ar_layers=[32, 32], # AR-Net 的隐藏层结构
daily_seasonality=10,
weekly_seasonality=8,
)
m2.highlight_dt = 48
metrics = m2.fit(df, freq="H", valid_p=0.1)
自回归模式下的预测是滚动式的,一次只输出未来 6 小时的值,想要预测更远就要用递归方式不断把预测值回填。短期预测(比如 1 到 6 小时)加了 AR 项之后误差通常能下降两到三成,但长期预测反而可能更差,因为误差会累积。所以实践中常见做法是两套模型并行:带 AR 的负责短时精细预测用于实时告警,纯趋势季节性模型负责一周以上的容量预估。
如果流量受已知事件影响,比如每周三晚上的定时备份任务会推高出口流量,可以定义自定义事件或直接把节假日数据传入。neuralprophet 支持通过 add_country_holidays 接入法定节假日,对有明显节假日回落特征的政企网络尤其有效:
m2.add_country_holidays("CN") # 接入中国法定节假日
# 或者自定义事件窗口
events = pd.DataFrame({
"ds": pd.to_datetime(["2024-05-01", "2024-05-02"]),
"event": "holiday_peak",
})
最后提醒一点,网络流量数据里的攻击尖峰和故障掉零对模型干扰很大,训练前最好用滑动窗口的中位数或分位数做一次异常平滑,只对训练集做,验证集保持原样,这样评估出的精度才可信。把趋势、多周期季节性、事件效应和自回归这四块组合好,neuralprophet 完全可以作为网络流量预测场景的常态化基线方案。
neuralprophet时间序列预测网络流量修改时间:2026-09-10 19:42:44