深入剖析 Prophet 变点函数 changepoint_func:原理、用法与影响
changepoint_func:自定义你的变点检测引擎
数据输入格式
内部工作原理
与 changepoint_prior_scale 的交互
影响变点选择
实践案例:自定义 changepoint_func
案例 1:检测趋势的加速变化
案例 2:基于周期性成分的变点检测
案例3: 自定义分段常数变点
案例 4:结合多种变化检测
注意事项
总结
Facebook Prophet 是一个强大的时间序列预测工具,其灵活性的一大来源就是对变点(changepoint)的精细控制。changepoint_func
参数允许你自定义变点检测的底层模型,这为高级用户提供了更深层次的定制能力。今天咱们就来深入探讨一下 changepoint_func
,聊聊它的数据输入格式、内部工作原理、与 changepoint_prior_scale
的交互,以及它如何影响最终的变点选择。
changepoint_func:自定义你的变点检测引擎
在 Prophet 中,默认的变点检测方法是基于线性模型的斜率变化。但现实世界的时间序列数据往往更加复杂,可能需要更灵活的变点模型。changepoint_func
参数正是为此而生,它允许你传入一个自定义的函数,该函数将负责计算每个潜在变点的“变化幅度”。
数据输入格式
传给 changepoint_func
的函数需要接受两个主要参数:
t
: 一个 NumPy 数组,表示时间序列的时间点(通常是相对于序列起始时间的标准化时间)。y
: 一个 NumPy 数组,表示时间序列的观测值。
你的自定义函数需要返回一个与 t
长度相同的 NumPy 数组,其中每个元素代表对应时间点的“变化幅度”。这个“变化幅度”可以是任何你认为能反映变点可能性的指标。Prophet 会根据这个“变化幅度”来选择最终的变点。
内部工作原理
Prophet 的变点选择过程可以大致概括为以下几个步骤:
- 潜在变点生成:Prophet 首先会在时间序列上生成一系列潜在的变点。默认情况下,这些潜在变点会均匀地分布在时间序列的前 80% 范围内(可以通过
changepoints
参数手动指定)。 - 变化幅度计算:对于每个潜在变点,Prophet 会调用
changepoint_func
(如果你提供了的话,否则使用默认的线性模型)来计算该点的“变化幅度”。 - 变点选择:Prophet 会根据
changepoint_prior_scale
参数来调整“变化幅度”的先验分布。changepoint_prior_scale
越大,模型越倾向于选择更多的变点;反之,则倾向于选择更少的变点。最终,Prophet 会从潜在变点中选择一部分作为最终的变点,这些被选中的变点对应的“变化幅度”在调整后的先验分布下具有较高的后验概率。 - 模型拟合:在确定了变点之后,Prophet 会使用分段线性模型(或你指定的其他模型)来拟合整个时间序列。
与 changepoint_prior_scale 的交互
changepoint_prior_scale
是一个重要的超参数,它控制着模型对变点的敏感程度。它的值越大,模型就越容易将数据中的波动视为变点,从而选择更多的变点;反之,它的值越小,模型就越倾向于认为数据中的波动是噪声,从而选择更少的变点。
changepoint_func
和 changepoint_prior_scale
是协同工作的。changepoint_func
负责计算每个潜在变点的“原始”变化幅度,而 changepoint_prior_scale
则负责对这些“原始”变化幅度进行缩放,从而影响最终的变点选择。
影响变点选择
changepoint_func
的选择直接影响了模型对变点的定义。不同的 changepoint_func
会对数据的不同特征产生不同的敏感度。例如:
- 默认的线性模型:对趋势的线性变化敏感。
- 自定义的二次模型:可能对趋势的加速或减速更敏感。
- 基于傅里叶变换的模型:可能对周期性的变化更敏感。
通过精心设计 changepoint_func
,你可以让 Prophet 更好地捕捉到你所关心的变点类型。
实践案例:自定义 changepoint_func
下面,我们通过几个具体的例子来展示如何使用 changepoint_func
。
案例 1:检测趋势的加速变化
假设我们有一个时间序列,其趋势可能存在加速或减速的变化。我们可以定义一个 changepoint_func
来检测这种变化:
import numpy as np def quadratic_changepoint_func(t, y): """ 计算二次模型的斜率变化,用于检测趋势的加速或减速。 """ # 对时间进行标准化 t_scaled = (t - t.min()) / (t.max() - t.min()) # 拟合二次模型 z = np.polyfit(t_scaled, y, 2) p = np.poly1d(z) # 计算二阶导数(斜率的变化率) second_derivative = p.deriv(m=2)(t_scaled) return np.abs(second_derivative)
这个函数首先对时间进行标准化,然后拟合一个二次模型,最后计算二次模型的二阶导数(即斜率的变化率)的绝对值作为“变化幅度”。二阶导数的绝对值越大,表示趋势的加速或减速越明显。
案例 2:基于周期性成分的变点检测
如果我们的时间序列具有明显的周期性,我们可能希望基于周期性成分的变化来检测变点。我们可以使用傅里叶变换来实现这一点:
import numpy as np from scipy.fft import fft def periodic_changepoint_func(t, y): """ 基于傅里叶变换的周期性成分变化检测变点。 """ # 计算傅里叶变换 yf = fft(y) # 计算幅度谱 amplitude_spectrum = np.abs(yf) # 计算幅度谱的变化 amplitude_spectrum_change = np.diff(amplitude_spectrum) # 在两端填充以保持长度一致 amplitude_spectrum_change = np.concatenate(([0], amplitude_spectrum_change, [0])) return np.abs(amplitude_spectrum_change)
这个函数首先计算时间序列的傅里叶变换,然后计算幅度谱的变化作为“变化幅度”。幅度谱的变化越大,表示周期性成分的变化越明显。
案例3: 自定义分段常数变点
有时候,你可能需要对数据进行分段常数拟合。这种情况下,变点就代表了不同常数段之间的切换点。下面是一个自定义的changepoint_func
来实现这个功能:
import numpy as np def piecewise_constant_changepoint_func(t, y): """检测分段常数变化""" # 计算相邻数据点之间的差值 diffs = np.diff(y) # 在开头补0,使其与t的长度相同 diffs = np.concatenate(([0], diffs)) # 返回差值的绝对值,作为变化幅度 return np.abs(diffs)
这个函数计算了相邻数据点之间的差值。在分段常数模型中,变点位置的差值会显著大于非变点位置。通过返回差值的绝对值,我们让Prophet更容易识别这些切换点。
案例 4:结合多种变化检测
在许多实际应用中,单一类型的变点检测可能不足以捕捉到所有重要的变化。因此,将多种变化检测方法结合起来可能是一个好主意。下面是一个例子,展示如何结合线性和分段常数检测:
import numpy as np from prophet.make_seasonality_features import fourier_series def combined_changepoint_func(t, y): """结合线性趋势变化和分段常数变化""" # 线性趋势变化 (默认的Prophet方法) m = np.mean(np.diff(y)) linear_change = np.abs(np.diff(y) - m) linear_change = np.concatenate(([0], linear_change)) # 分段常数变化 piecewise_change = piecewise_constant_changepoint_func(t, y) # 结合两种变化幅度 (这里简单地取平均) combined_change = (linear_change + piecewise_change) / 2 return combined_change
在这个例子中,我们结合了默认的线性趋势变化检测和自定义的分段常数变化检测。通过简单地取两种变化幅度的平均值,我们创建了一个新的changepoint_func
,它对两种类型的变化都敏感。
注意事项
- 计算复杂度:自定义的
changepoint_func
可能会增加模型的计算复杂度,特别是当你的函数涉及到复杂的计算时。在设计changepoint_func
时,要注意平衡模型的准确性和计算效率。 - 数据预处理:在某些情况下,你可能需要对数据进行预处理,例如去除异常值、填补缺失值等,以提高
changepoint_func
的效果。 - 参数调优:
changepoint_prior_scale
和changepoint_func
需要结合起来进行调优。你可以通过交叉验证等方法来选择最佳的参数组合。 - 与其它Prophet组件的交互:
changepoint_func
主要影响变点检测,但Prophet还有其它组件,如季节性(seasonality
)和节假日(holidays
)。 当自定义changepoint_func
时,要考虑它是否与其它组件产生了意料之外的交互。例如,如果你的changepoint_func
过于敏感,可能会错误地将季节性波动识别为变点。
总结
changepoint_func
是 Prophet 中一个强大的工具,它允许你自定义变点检测的逻辑,从而更好地适应各种复杂的时间序列数据。通过深入理解 changepoint_func
的工作原理和使用方法,你可以充分发挥 Prophet 的潜力,构建更准确、更可靠的预测模型。希望这篇深入的讲解能帮助你更好地驾驭 Prophet,成为时间序列预测的高手!