我们的时间序列数据集可能包含趋势。
趋势是指序列随时间持续的增长或减少。识别、建模甚至移除时间序列数据集中的趋势信息可能是有益的。
在本教程中,您将学习如何在 Python 中对时间序列数据进行建模和移除趋势信息。
完成本教程后,您将了解:
- 时间序列中可能存在的趋势的重要性、类型以及如何识别它们。
- 如何使用简单的差分方法移除趋势。
- 如何为销售时间序列数据集建模线性趋势并将其移除。
开启您的项目,阅读我的新书《Python 时间序列预测入门》,其中包括分步教程和所有示例的Python源代码文件。
让我们开始吧。
- 2019 年 4 月更新:更新了数据集链接。

如何在 Python 中使用和移除时间序列数据中的趋势信息
照片由 john78727 提供,部分权利保留。
时间序列中的趋势
趋势是时间序列水平的长期增长或下降。
总的来说,时间序列中不呈现周期性的系统性变化被称为趋势。
— 第 5 页, 《R 语言时间序列入门》
识别和理解趋势信息有助于提高模型性能;以下是几个原因:
- 更快的建模:趋势的存在或缺失可能会提示方法,并使模型选择和评估更有效率。
- 更简单的问题:通过修正或移除趋势,可以简化建模并提高模型性能。
- 更多数据:趋势信息可以直接或以摘要的形式提供给模型,作为额外信息,以提高模型性能。
趋势的类型
趋势有很多种。
我们可以考虑两个一般类别:
- 确定性趋势:这些趋势是持续增长或减少的。
- 随机趋势:这些趋势是不规律地增长和减少的。
总的来说,确定性趋势更容易识别和移除,但本教程中讨论的方法对于随机趋势仍然有用。
我们可以根据观察范围来考虑趋势。
- 全局趋势:这些趋势适用于整个时间序列。
- 局部趋势:这些趋势适用于时间序列的某些部分或子序列。
通常,全局趋势更容易识别和处理。
识别趋势
您可以绘制时间序列数据来查看趋势是否明显。
然而,在实践中,识别时间序列中的趋势可能是一个主观的过程。因此,从中提取或移除趋势也可能同样主观。
创建数据的折线图,并检查图表是否存在明显的趋势。
在图表中添加线性和非线性趋势线,并查看趋势是否明显。
移除趋势
具有趋势的时间序列称为非平稳序列。
已识别的趋势可以被建模。一旦建模完成,就可以从时间序列数据集中移除。这称为对时间序列进行去趋势处理。
如果数据集没有趋势,或者我们成功地移除了趋势,那么该数据集就被称为趋势平稳数据集。
在机器学习中使用时间序列趋势
从机器学习的角度来看,数据中的趋势代表了两个机会:
- 移除信息:移除扭曲输入和输出变量之间关系的系统信息。
- 添加信息:添加系统信息以改善输入和输出变量之间的关系。
具体来说,趋势可以从您当前和未来的时间序列数据中移除,作为数据准备和清理练习。当使用统计方法进行时间序列预测时,这很常见,但对于机器学习模型,并不总能改善结果。
或者,趋势可以被添加,无论是直接添加还是以摘要的形式,作为监督学习问题的一个新输入变量来预测输出变量。
这两种方法中的一种或两种都可能与您的时间序列预测问题相关,并且值得进行研究。
接下来,让我们看看一个具有趋势的数据集。
停止以**慢速**学习时间序列预测!
参加我的免费7天电子邮件课程,了解如何入门(附带示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
洗发水销售数据集
此数据集描述了三年期间每月洗发水销售数量。
单位是销售计数,共有 36 个观测值。原始数据集归功于 Makridakis、Wheelwright 和 Hyndman (1998)。
以下是数据的前 5 行样本,包括标题行。
|
1 2 3 4 5 6 |
"Month","Sales" "1-01",266.0 "1-02",145.9 "1-03",183.1 "1-04",119.3 "1-05",180.3 |
下面是整个数据集的图表,您可以在此处了解更多信息并下载数据集。
数据集显示出增长趋势。

洗发水销售数据集
加载洗发水销售数据集
下载数据集并将其放在当前工作目录中,文件名为“shampoo-sales.csv”。
可以使用自定义日期解析例程加载数据集,如下所示:
|
1 2 3 4 5 6 7 8 9 10 |
from pandas import read_csv from pandas import datetime from matplotlib import pyplot def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) series.plot() pyplot.show() |
运行该示例将加载数据集并生成图表。

洗发水销售数据集图
通过差分去趋势
可能是最简单的去趋势时间序列的方法是差分。
具体来说,构建一个新的序列,其中当前时间步的值计算为原始观测值与前一个时间步的观测值之间的差值。
|
1 |
value(t) = observation(t) - observation(t-1) |
这具有从时间序列数据集中移除趋势的效果。
我们可以在 Python 中通过直接实现来创建新的差分数据集。可以创建一个新的观测值列表。
下面是一个创建洗发水销售数据集差分去趋势版本的示例。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from pandas import read_csv from pandas import datetime from matplotlib import pyplot def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) X = series.values diff = list() for i in range(1, len(X)): value = X[i] - X[i - 1] diff.append(value) pyplot.plot(diff) pyplot.show() |
运行该示例将创建新的去趋势数据集,然后绘制时间序列。
由于无法为第一个观测值创建差分值(没有可以减去的值),因此新数据集比原始数据集少一条记录。我们可以看到趋势确实已经被移除了。

洗发水销售数据集差分去趋势
这种方法对于具有线性趋势的数据效果很好。如果趋势是二次的(趋势的变化也增加或减少),那么可以对已经差分过的数据进行差分,即二次差分。如果需要,可以进一步重复此过程。
由于差分只需要前一个时间步的观测值,因此它可以轻松地应用于未见的样本外数据,以进行预处理或为监督学习提供额外的输入。
接下来,我们将研究拟合一个模型来描述趋势。
通过拟合模型去趋势
趋势通常可以很容易地可视化为穿过观测值的一条直线。
线性趋势可以用线性模型来概括,而非线性趋势可能最好用多项式或其他曲线拟合方法来概括。
由于识别趋势的主观性和特定于领域性,这种方法可以帮助确定趋势是否存在。即使将线性模型拟合到明显超线性或指数级增长的趋势上也有帮助。
除了作为趋势识别工具外,这些拟合模型还可以用于对时间序列进行去趋势处理。
例如,可以在时间索引上拟合一个线性模型来预测观测值。该数据集将如下所示:
|
1 2 3 4 5 6 |
X, y 1, obs1 2, obs2 3, obs3 4, obs4 5, obs5 |
此模型的预测将形成一条直线,可作为数据集的趋势线。这些预测值也可以从原始时间序列中减去,从而得到数据集的去趋势版本。
|
1 |
value(t) = observation(t) - prediction(t) |
模型拟合的残差是数据集的去趋势形式。也可以使用多项式曲线拟合和其他非线性模型。
我们可以在 Python 中通过在数据上训练 scikit-learn 的 LinearRegression 模型来实现这一点。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
from pandas import read_csv from pandas import datetime 来自 sklearn.linear_model 导入 LinearRegression from matplotlib import pyplot import numpy def parser(x): return datetime.strptime('190'+x, '%Y-%m') series = read_csv('shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser) # 拟合线性模型 X = [i for i in range(0, len(series))] X = numpy.reshape(X, (len(X), 1)) y = series.values 模型 = LinearRegression() model.fit(X, y) # 计算趋势 trend = model.predict(X) # 绘制趋势 pyplot.plot(y) pyplot.plot(trend) pyplot.show() # 去趋势 detrended = [y[i]-trend[i] for i in range(0, len(series))] # 绘制去趋势数据 pyplot.plot(detrended) pyplot.show() |
运行该示例,首先将线性模型拟合到整数索引的观测值上,并绘制原始数据集(蓝色)上方的趋势线(绿色)。

洗发水销售数据集带趋势的图
接下来,将趋势从原始数据集中减去,并绘制由此产生的去趋势数据集。

洗发水销售数据集模型去趋势
同样,我们可以看到这种方法有效地去除了趋势。残差中可能存在一个抛物线,这表明多项式拟合可能效果更好。
由于趋势模型仅将观测值的整数索引作为输入,因此可以将其用于新数据,以进行去趋势处理或为模型提供新的输入变量。
进一步阅读
以下是一些关于时间序列中趋势估计和去趋势的额外资源:
- Wikipedia 上的线性趋势估计
- 去趋势注意事项,GEOS 585A,应用时间序列分析 [PDF]
- 更新:从此页面下载。
总结
在本教程中,您了解了时间序列数据中的趋势以及如何使用 Python 移除它们。
具体来说,你学到了:
- 关于时间序列趋势信息的重要性以及如何在机器学习中使用它们。
- 如何使用差分从时间序列数据中移除趋势。
- 如何为时间序列数据建模线性趋势并将其移除。
您对去趋势或本教程有任何疑问吗?
在下面的评论中提出你的问题,我会尽力回答。







非常有用的信息 Jason。有一个问题。去趋势后的值是作为附加特征使用,还是代替原始特征?另外,通常也会去趋势目标变量吗?如果会,那么去趋势后的值会成为新的目标变量吗?如果是这样,那么如何从 ML 模型(至少是 sklearn)中获得完整的预测(我猜一个自定义转换器需要存储移除的趋势并使用 inverse_transform 加回去)?
谢谢!
你好 Carmen,
这篇帖子讨论的是对单变量时间序列进行去趋势处理。如果您想对单变量时间序列进行去趋势处理,您应该将其视为一组单变量时间序列,一次去趋势一个。
整个序列可以被去趋势,并用作 ARIMA 等学习算法的输入。请看这篇帖子:
https://machinelearning.org.cn/arima-for-time-series-forecasting-with-python/
或者,去趋势后的序列可以用作机器学习算法的附加输入。
非常有用,谢谢!我想知道是否有可能将原始趋势加回到去趋势的时间序列中……您知道我该怎么做吗?谢谢!
是的,如果趋势是通过减法移除的,那么可以通过加法加回来。
我想你可以从原始时间序列的初始值开始,然后通过加上通过差分获得的每个增量来重新创建原始时间序列。
去趋势技术会改善 ARIMA 预测吗?
可能会。试试看。ARIMA 有内置的 q 参数。
您是指 d 参数吗?
你好 Aman…请澄清您的问题,以便我们能更好地帮助您。
很棒的教程!非常感谢您提供如此有用的信息。我的问题是,是否可以将线性和非线性趋势同时添加到同一个数据集中?如果是,我应该先移除线性部分,然后移除非线性部分(即拟合到数据的直线,然后减去它),然后再移除非线性部分(拟合一个低阶多项式到信号然后减去它)?还是仅移除非线性部分就足够了?
有趣的问题。总的来说,我建议您尝试这两种方法,看看哪种模型能带来更好的预测。
假设时间序列大部分时间显示下降趋势,那么从前一个时间戳减去可能会得到负值。在这种情况下,简单的移动平均是否可以使用?
也许可以。但负值有什么问题——您在变换后的空间中操作。您总可以在预测时反转变换,回到原始尺度。
感谢您的回复。此技术可能不适用于泊松自回归模型。您对事件计数模型中的去趋势有什么建议吗?
暂时没有,抱歉 Weber。
亲爱的 Jason,
我按照您的方法对训练集上的时间序列数据进行去趋势处理,然后再拟合神经网络模型。
我需要预测第二天的每小时值。
当我需要使用我训练的模型来预测新数据时,我该如何处理趋势?
我是否需要像通常的观测值一样一起预测趋势,因为我的模型是在去趋势数据上训练的?是否应该将此预测的趋势加到训练模型的预测输出中?
谢谢
Mamta
您可以通过差分来移除趋势。在做出预测后,您可以对差分进行反向操作。
请看这里
https://machinelearning.org.cn/remove-trends-seasonality-difference-transform-python/
和这里
https://machinelearning.org.cn/difference-time-series-dataset-python/
尊敬的 Jason
先生,我有一个通过积分获得的时间序列数据。数据的性质是振幅随时间呈指数衰减。您能否建议我一种方法来获得(识别)派生时间序列数据(即通过积分获得的数据)中存在的线性或非线性趋势(多项式方程)?
谢谢
我没有现成的例子。也许您可以在观测值上使用幂变换来稳定变化的方差,然后尝试移除周期?
或者也许您可以使用 scipy 函数调用来对指数趋势进行建模并手动移除它?
或许可以探索几种方法,看看哪种效果好。
亲爱的Jason
先生,请给我一个例子,我有一个为期 4 个季度的时间序列数据。我该如何解决这个问题:“假设乘法模型并使用移动平均法,得到去趋势时间序列”?????
抱歉,我不能为您编写代码。也许可以聘请承包商?
嗨,Jason,
非常棒的教程。只想告知您,在“进一步阅读”部分中的“去趋势注意事项,GEOS 585A,应用时间序列分析 [PDF]”链接已失效。如果可能,能否请您修复它?
此致,
Rahul Sathyajit
谢谢,我已添加了一个链接到该页面以了解更多信息。
Jason,
感谢您这篇精彩的文章。
在您的一篇 LSTM 文章中,您使用了多变量天气输入特征(x1、x2、x3、x4)来预测另一个天气参数(Y)。我是否也应该对具有趋势的输入特征(例如,假设 x1 和 x4 有趋势)使用去趋势技术?如果是,我对我所获得的结果不太有信心,因为我已经更改了输入数据。如果不是,也许我的模型无法很好地预测。我遗漏了什么?
理想情况下是的。LSTM 对趋势和季节性敏感。
你好,Jason
选择最佳子集(行)进行 LSTM 训练的最佳方法是什么?
致敬
Salah
谨慎和系统的实验。
你好,Jason。
非常感谢您的精彩教程。我尝试通过 pandas 的 diff 来应用差分到数据,但模型未能收敛。我尝试了不同的拓扑结构、层中的神经元数量等,但结果几乎相同。但是,当我不对数据进行修改时,拟合效果非常好。您遇到过这种情况吗,或者您是否知道有关此主题的任何好资料?
此致,Jakub。
是的,MLP 和 CNN 在非平稳数据上表现良好,甚至更好,至少在我进行的一些测试中是这样。
你好,Jason,
是否有任何著名的方法可以识别时间序列趋势?例如,给定一个时间序列,该方法应该能够给出一个值,说明序列是增长、下降还是稳定(该值应该完美地代表趋势。可能是一个 0-100 的量表,0 表示下降,100 表示高速增长,50 表示稳定等)。
从您的示例中,我可以看到拟合的直线可以用来得出一些关于趋势的值(也许使用梯度)。是否有更复杂的方法可以做到这一点?
谢谢你。
很棒的教程。非常喜欢这个网站……
是的,梯度,即上升/运行。
感谢教程!
问题——一旦趋势被移除(如您最后一张图所示),就可以使用去趋势数据来对 ARIMA 进行预测。如何解释预测值?假设它在下一个周期上升 2 个“单位”= 预计会增加 2 倍于原始数据集使用的尺度?
趋势可以加回到任何预测值上,其解释将特定于领域。
嗨,Jason,
感谢您的本教程!
所以,我正在处理一个需要结合独立于时间特征来预测时间依赖的目标变量的问题。
我对目标(时间依赖)进行去趋势处理,并使用时间独立特征构建监督 ML 模型。然后,我将趋势加回到此模型的预测值中。
这是正确的做法吗?
您的其他教程中是否有讨论过这个问题?我搜了一下但没找到。
非常感谢您的帮助!
也许可以将新变量作为时间步的 exog 变量添加。
否则,也许可以使用一个集成模型,该模型结合了时间序列模型和静态数据模型的预测?
你好 Jason,
非常感谢这个很棒的教程!
我想问一下,如果我们进行去趋势和去季节性处理,我们是不是可以直接使用seasonal_decompose()函数,并从中提取趋势和季节性分量,只留下残差?残差是否可以被认为是去趋势和去季节性处理后的数据?
例如
result = seasonal_decompose(self.series, model=’additive’, freq=frequency)
residual = result.resid # 这是我指的是什么。
提前感谢
也许吧。它可能对你的数据不可靠。最好有更多的控制,并理解每个部分的结构。
那么哪种方法更可靠?是进行去趋势和去季节性处理,还是仅仅从seasonal_decompose()中提取残差?
这取决于你的项目,总的来说,我建议在建模之前进行去趋势和季节性调整,或者在SARIMA等方法中将其作为建模的一部分。
感谢 Jason 的这篇帖子!
我想知道,如果我正在进行一个多变量的LSTM模型,并且我只观察到5个变量中的2个有趋势,
1. 我是否应该通过差分来对所有5个变量进行去趋势?
2. 如果其中一个变量是分类变量,并且我已经将其编码为(1,-1),这是否也需要进行差分?
非常感谢!
尝试直接对数据进行建模,然后对有趋势的序列进行差分处理,看看是否有影响。
对于分类变量,可以尝试整数编码、独热编码以及嵌入。
嗨,Jason,
好文章!
关于模型拟合方法,可以向您请教一下吗?
当您提到从原始数据中减去趋势时,这与获得线性/二次/多项式模型的残差相同吗?
谢谢!
相似。
嗨,Jason,
如果目标是预测显示随机趋势的时间序列的未来N个时间步长,那么我们应该拟合一个模型来近似趋势,从原始数据中移除这个近似趋势,并使用ARIMA等模型来预测其残差。然而,最终的预测将是ARIMA预测+趋势预测。
我处理的时间序列数据不能很好地用线性回归来近似,它包含随机模式,趋势以不同的幅度上下波动(就像随机游走一样)。我还没有找到一个模型能很好地近似它。您推荐使用什么模型来近似这种随机趋势?
谢谢!
通常ARIMA可以通过d参数来为您去除趋势。
我建议测试一系列线性和非线性模型,以发现最适合您特定数据集的模型。
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
您好,我在Python上运行了代码,但不知道为什么这个函数一直显示datetime.strptime错误。可以换一种写法吗?
很抱歉听到这个消息,也许这个会有帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
亲爱的Jason
如何使用非线性回归进行时间序列数据去趋势?
什么是局部回归用于数据去趋势?
如何使用二次多项式趋势进行去趋势?
请向我澄清一下。
可以使用什么软件来完成所有这些?
您可以使用scipy来实现每一个,也许上面的例子可以为您提供一个有用的实验起点。
嗨,Jason,
这似乎是个愚蠢的问题,但我按照您的指示对数据集进行了去趋势,并且运行得很好。然而,我很难解释去趋势后的版本,主要是因为y值现在是负值并且围绕零。在我的数据集中,我绘制了随时间变化的CO2浓度。
CO2浓度怎么可能出现负值?我明白数据已经被转换了,但我不知道它对我的测量值意味着什么。
如果能得到您的回复,我将非常高兴。
此致
Laila
是的,您必须对任何预测进行反向转换,以便能够解释结果。
我相信本教程中的示例将有助于反转该过程。
https://machinelearning.org.cn/machine-learning-data-transforms-for-time-series-forecasting/
我认为我错误地使用了“转换”这个词。在我应用线性模型之前,我没有对我的数据进行任何幂转换或类似的转换。我使用了原始数据,拟合了线性模型,然后查看了残差图,数据部分是负数且围绕0。例如,在2010年,我的原始数据中有22.000吨CO2,而我去趋势数据(线性模型残差)中同一年的值约为-500。我的问题是,现在的去趋势数据是否可以用于计算2010-2040十年间的预期值?
非常感谢您的时间和快速回复!
也许可以尝试一下。
嗨,Jason,
我有一个关于LSTM模型去趋势的问题。我使用seasonal_decompose函数移除了输入数据的趋势和季节性。然而,当我将这个去趋势数据输入到LSTM编解码模型时,训练没有发生。训练损失和验证损失从第一个epoch开始就没有降低。另一方面,当我提供正常数据(即未去趋势的数据)时,模型可以正常训练。
我想知道是否需要进行其他调整才能在LSTM上使用去趋势数据进行训练。任何想法/建议都将不胜感激。
此致,
Aji
您可能需要调整模型架构和学习超参数以适应您的准备数据。
您好,我的问题是,我们如何使用去趋势数据/图来构建模型和进行预测?看起来我们在这里改变了数据集,所以模型的预测将是一些未定义的值。我们如何从预测值回到数据集值(销售/注册/土地/点击次数等)?
您可以使用差分转换来去除趋势 – 如上文教程所述。
您好,这是一篇非常有启发性的文章,请问如何添加趋势呢?比如您要模拟周期性数据,并想在有趋势的数据上测试频谱分析方法,您如何添加一个线性趋势来使您的模拟数据看起来像这篇文章中的数据。提前感谢。
你好 M. Mossad… 以下内容可能对您有所帮助
https://towardsdatascience.com/time-series-analysis-creating-synthetic-datasets-cf008208e014
嗨,Jason,
我们能否只从时间序列数据中移除趋势,而不影响季节性模式?
我尝试使用差分以及从季节性分解技术中移除趋势部分,但它们仍然会移除图中的季节性波动。
如何才能移除趋势?
提前感谢,
非常感谢您的工作。
嗨 Jason,
非常有帮助的文章。我正在处理一个多元问题,我正在预测某件商品的销售额。我想将趋势作为输入包含在这个监督问题中。我该如何做到?如何为销售额捕捉趋势并将其作为输入添加到我的模型中?
提前感谢,
嗨 Jason,
非常有帮助的文章。我正在处理一个多元问题,我正在预测某件商品的销售额。我想将趋势作为输入包含在这个监督问题中。我该如何做到?如何为销售额捕捉趋势并将其作为输入添加到我的模型中?
提前感谢,
你好 nehapawar…为此目的,您可以保留原始时间序列数据中的趋势信息。也就是说…根本不要移除它。