原文:
annas-archive.org/md5/92b806e0bfe2149821d7ca72450c0f00
译者:飞龙
前言
时间序列无处不在,时刻在增长。借助可以扩展的正确工具,您可以轻松释放其时间维度的洞察,赋予您在时间的赛道上的优势。
时间序列分析——从时间序列中提取洞见——对于企业和组织做出明智决策至关重要。这通过分析在时间间隔中收集的数据中的模式、趋势和异常来实现。Apache Spark 是一个强大的大数据处理框架,能够高效处理大规模时间序列数据,是处理此类数据的理想工具。
对于任何涉及 Apache Spark 的时间序列分析任务,有三个主要支柱:
-
数据准备与处理:包括收集、清洗和转换时间序列数据,使其适合进行分析。
-
建模与预测:包括应用统计模型或机器学习算法来揭示模式并预测未来趋势。
-
部署与维护:包括将模型集成到运营系统中,并持续监控和更新,以确保准确性和相关性。
本书《使用 Spark 进行时间序列分析》旨在涵盖所有这些支柱。它将提供处理、建模和预测时间序列数据的实际技术,帮助读者使用 Apache Spark 进行时间序列分析。本书基于两个主要信息来源:
-
实践经验:借鉴实际项目和经验,处理大规模时间序列数据时的 Apache Spark 运用。
-
行业洞察:融入时间序列分析和大数据处理领域专家和从业者的见解。
随着 Apache Spark 在时间序列分析中的应用不断增长,对掌握此领域技能的专业人才需求也在快速增加。本书将引导您了解使用 Apache Spark 有效进行时间序列分析所需的最佳实践和技巧,帮助您在这个快速发展的领域中保持领先。
本书适用对象
数据和 AI 专业人员,尤其是处理时间相关数据集的人员,将会发现《使用 Spark 进行时间序列分析》有助于提升他们在时间序列分析中运用 Apache Spark 和 Databricks 的技能。本书面向广泛的受众,从初学者到有经验的从业者,都可以从中学习如何利用 Spark 进行时序数据分析。
更具体地说,数据工程师将提升他们在使用 Spark 和 Databricks 进行大规模时间序列数据准备方面的能力。机器学习(ML)工程师将更容易扩展他们的机器学习项目范围。数据科学家和分析师将掌握新的时间序列分析技能,拓宽工具使用的范围。
本书涵盖的内容
第一章,什么是时间序列?,介绍了时间序列数据的概念及其分析中的独特挑战。这个基础对于有效分析和预测时间相关数据至关重要。
第二章,为什么进行时间序列分析?,详细阐述了分析时间相关数据在预测建模、趋势识别和异常检测中的重要性。通过各行业的实际应用来说明这一点。
第三章,Apache Spark 简介,深入探讨了 Apache Spark 及其在处理大规模时间序列数据时的分布式计算能力。
第四章,时间序列分析项目的端到端视角,引导我们了解时间序列分析项目的整个过程。从用例开始,涵盖了数据处理、特征工程、模型选择和评估等关键阶段。
第五章,数据准备,深入探讨了组织、清理和转换时间序列数据的关键步骤。内容包括处理缺失值、处理异常值和数据结构化等技术,从而提升后续分析过程的可靠性。
第六章,探索性数据分析,介绍了如何通过探索性数据分析揭示时间序列数据中的模式和洞察。此过程对于识别趋势和季节性等特征至关重要,为后续建模决策提供指导。
第七章,构建与测试模型,专注于为时间序列数据构建预测模型,涵盖了各种类型的模型、选择模型的方法以及如何训练、调优和评估模型。
第八章,扩展分析,讨论了在大规模和分布式计算环境中扩展时间序列分析时需要考虑的因素。内容涵盖了如何利用 Apache Spark 扩展特征工程、超参数调优以及单模型和多模型训练的不同方式。
第九章,投入生产,探讨了将时间序列模型部署到生产环境中的实际考虑因素和步骤,同时确保时间序列模型在操作环境中的可靠性和有效性。
第十章,深入探索 Apache Spark,提供了通过使用 Databricks 作为云端托管的 PaaS 平台,解决设置和管理 Apache Spark 平台的挑战。
第十一章,时间序列分析的最新发展,探讨了时间序列分析领域的最新发展,包括将生成性 AI 应用于时间序列预测的激动人心的研究方向,以及使时间序列分析结果对非技术人员易于理解的新方法。
为了最大限度地发挥本书的作用
本书要求你具备基本的 Python 编程语言知识,并且对数据科学和机器学习概念有基本了解。
-
第一章、第二章、第五章、第六章 和 第七章 使用 Databricks Community Edition。
-
第三章、第四章 和 第九章 使用本地容器化环境。本书中的示例在 macOS 上使用 Docker 进行测试。如果你在 Windows 或 Linux 上使用 Docker 或 Podman,适当调整后也应能够运行。如果你不打算在本地构建环境,而是更倾向于使用 Databricks 等托管平台,可以跳过这些章节的实践部分。
-
第八章、第十章 和 第十一章 使用 Databricks 平台。
获取安装和设置的附加说明及信息已在各个章节中记录。
本书中涉及的软件/硬件 | 操作系统要求 |
---|---|
Databricks Community Edition | |
在 Amazon Web Services (AWS) 或 Microsoft Azure 上的 Databricks | |
Docker v4.48 或 Podman v1.16 | Windows、macOS 或 Linux |
示例代码所需的附加软件包会在代码执行时自动安装。由于软件包和用户界面可能会发生变化,请参考相应的软件包或产品文档,以了解更改信息。
如果你使用的是本书的数字版本,我们建议你自己输入代码或从本书的 GitHub 仓库访问代码(链接在下一节提供)。这样可以帮助你避免与复制粘贴代码相关的潜在错误。
如果有说明更新,它将尽可能地添加到 GitHub 仓库中各个章节的 README.md 文件中。
下载示例代码文件
你可以从 GitHub 下载本书的示例代码文件,链接为 github.com/PacktPublishing/Time-Series-Analysis-with-Spark
。如果代码有更新,GitHub 仓库中的内容将会进行相应更新。
我们还在 https://github.com/PacktPublishing/ 提供了其他丰富书籍和视频的代码包。快去看看吧!
使用的约定
本书中使用了许多文本约定。
文本中的代码
:表示文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账号。例如:“将下载的 WebStorm-10*.dmg
磁盘映像文件挂载为系统中的另一个磁盘。”
代码块设置如下:
#### Summary Statistics
# Code in cell 10
df.summary().display()
当我们希望引起你对代码块中特定部分的注意时,相关的行或项目会以粗体显示:
sns.boxplot(x='dayOfWeek', y='Global_active_power', data=pdf)
任何命令行输入或输出都按如下方式显示:
Test SMAPE: 41.193985580947896
Test WAPE: 0.35355667972102317
粗体:表示一个新术语、一个重要的词,或者你在屏幕上看到的词。例如,菜单或对话框中的词会以粗体显示。以下是一个示例:“报告的其他部分涉及警报,如图 6.8所示,包括在数据集上运行的测试结果,包括特定于时间序列的测试,以及一个重现部分,详细描述了分析运行的情况。”
提示或重要说明
显示效果如下。
与我们联系
我们始终欢迎读者的反馈。
一般反馈:如果你对本书的任何内容有疑问,请通过电子邮件 customercare@packtpub.com 联系我们,并在邮件主题中注明书名。
勘误表:尽管我们已经尽力确保内容的准确性,但错误难免。如果你在本书中发现任何错误,恳请报告给我们。请访问www.packtpub.com/support/errata并填写表格。
盗版:如果你在互联网上发现任何非法复制的作品,恳请提供相关的网址或网站名称。请通过 copyright@packtpub.com 与我们联系,并附上链接。
如果你有兴趣成为作者:如果你在某个领域拥有专业知识,并有意撰写或贡献书籍,请访问authors.packtpub.com。
分享你的想法
一旦你阅读了*《使用 Spark 进行时间序列分析》*,我们很希望听到你的想法!请点击这里直接访问亚马逊评价页面并分享你的反馈。
你的评价对我们和技术社区都非常重要,它将帮助我们确保提供高质量的内容。
下载本书的免费 PDF 副本
感谢购买本书!
你喜欢随时随地阅读,但又无法随身携带纸质书籍吗?
你的电子书购买是否与选定的设备不兼容?
别担心,现在每本 Packt 书籍你都能免费获得该书的 DRM-free PDF 版本。
在任何地方、任何设备上阅读。直接从你最喜爱的技术书籍中搜索、复制并粘贴代码到你的应用程序中。
福利不仅仅到此为止,你还可以独享折扣、新闻通讯和每天通过电子邮件收到的精彩免费内容。
按照这些简单步骤来获取福利:
- 扫描二维码或访问以下链接
packt.link/free-ebook/978-1-80323-225-6
-
提交你的购买凭证
-
就这样!我们将直接通过电子邮件发送你的免费 PDF 及其他福利。
第一部分:时间序列和 Apache Spark 简介
在本部分中,您将了解时间序列分析和 Apache Spark。从时间序列数据的基础概念开始,我们将深入探讨时间序列分析的实际意义及其在各行业的应用,并结合一些实践示例。接着,您将了解 Apache Spark,理解它的使用方式、架构以及工作原理,最后在您的环境中安装它。
本部分包括以下章节:
-
第一章,什么是时间序列?
-
第二章,为什么进行时间序列分析?
-
第三章,Apache Spark 简介
第一章:什么是时间序列?
“时间是最智慧的顾问。” – 伯里克勒斯
历史是迷人的。它提供了我们起源的深刻叙述,展现了我们所走的路和我们奋斗的目标。历史赋予我们从过去汲取的教训,使我们更好地面对未来。
让我们以气象数据对历史的影响为例。天气模式的变化,从中世纪开始,直到 1783 年拉基火山爆发后加剧,给法国带来了广泛的困苦。这场气候动荡加剧了社会的不安,最终导致了 1789 年的法国大革命。(关于这一点,详细内容请参考进一步 阅读部分。)
时间序列体现了这一叙事,数字回响着我们的过去。它们是历史的量化,是我们集体过去的数值化叙事,为未来提供了宝贵的经验。
本书将带你进行一段全面的时间序列之旅,从基础概念开始,指导你进行实践中的数据准备和模型构建技巧,最终涵盖诸如扩展性和部署到生产等高级主题,同时跟进跨行业的尖端应用最新进展。通过本书的学习,你将能够结合 Apache Spark 构建强大的时间序列模型,以满足你所在行业应用场景的需求。
本章作为本书旅程的起点,介绍了时间序列数据的基本概念,探讨了其顺序性质和所面临的独特挑战。内容涵盖了趋势和季节性等关键组成部分,为使用 Spark 框架进行大规模时间序列分析奠定了基础。对于数据科学家和分析师来说,这些知识至关重要,它为有效利用 Spark 的分布式计算能力来分析和预测时间相关数据,并在金融、医疗保健、营销等多个领域做出明智决策提供了基础。
本章将涵盖以下主题:
-
时间序列简介
-
将时间序列分解成其组成部分
-
时间序列分析中的额外考虑
技术要求
在本书的第一部分,奠定了基础,你可以不参与实际操作示例而跟随阅读(尽管推荐参与)。本书后半部分将更加侧重于实践。如果你希望从一开始就进行实际操作,本章的代码可以在本书的 GitHub 仓库中找到,地址为:
github.com/PacktPublishing/Time-Series-Analysis-with-Spark/tree/main/
ch1
注意
请参考此 GitHub 仓库,以获取最新版本的代码,若在出版后有更新,将会进行注释说明。更新后的代码(如果有)可能与书中展示的代码部分有所不同。
以下动手实践部分将提供更多细节,帮助你开始进行时间序列分析。
时间序列简介
在这一部分,我们将了解什么是时间序列以及一些相关术语。通过动手实践的示例来可视化时间序列。我们将查看不同类型的时间序列及其特点。了解时间序列的性质对于我们在接下来的章节中选择合适的时间序列分析方法是必要的。
让我们从一个例子开始,这个时间序列表示的是自 1950 年以来毛里求斯每年的平均气温。数据的一个简短示例如表 1.1所示。
年份 | 平均气温 |
---|---|
1950 | 22.66 |
1951 | 22.35 |
1952 | 22.50 |
1953 | 22.71 |
1954 | 22.61 |
1955 | 22.40 |
1956 | 22.22 |
1957 | 22.53 |
1958 | 22.71 |
1959 | 22.49 |
表 1.1:样本时间序列数据——平均气温
在可视化并解释这个例子时,我们将接触到一些与时间序列相关的术语。用于可视化这个数据集的代码将在本章的动手部分讲解。
在下图中,我们可以看到自 1950 年以来气温的变化。如果我们将注意力集中在 1980 年后的这段时间,我们可以更仔细地观察到温度的变化,呈现出类似的逐年升高的趋势(趋势——在两图中用虚线表示),直到当前的温度。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_01.jpg
图 1.1:自 1950 年以来毛里求斯的平均气温
如果气温继续以相同的方式上升,我们正走向一个更温暖的未来,这也正是当前广泛接受的全球变暖的表现。与气温逐年上升的同时,每年夏季气温也会上升,冬季则会下降(季节性)。我们将在本章的动手部分可视化这一现象及温度时间序列的其他组成部分。
随着多年来气温逐渐升高(趋势),全球变暖对我们星球及其居民产生了影响(因果关系)。这一影响也可以通过时间序列来表示——例如海平面或降水量的测量。全球变暖的后果可能是剧烈的和不可逆的,这进一步突显了理解这一趋势的重要性。
这些时间序列的温度读数构成了我们所称的时间序列。对这种时间序列的分析和理解对我们的未来至关重要。
那么,更一般地说,什么是时间序列呢?它仅仅是一个按时间顺序排列的测量序列,以及每个测量值由源系统生成的特定时间。在温度的例子中,源系统是位于特定地理位置的温度计。
时间序列也可以以聚合形式表示,例如每年的平均气温,如表 1.1所示。
通过这个定义,并结合一个示例,我们将进一步探讨时间序列的性质。我们还将在本书的其余部分详细介绍这里提到的术语,如趋势、季节性和因果关系。
时间顺序
在本章开头,我们在定义时间序列时提到时间顺序,这是因为它是处理时间序列数据时与其他数据集的主要区别之一。顺序重要的一个主要原因是时间序列中的潜在自相关性,其中在时间t
的测量值与n
个时间步之前的测量值相关(滞后)。忽视这一顺序会使我们的分析不完整,甚至不正确。稍后我们将研究识别自相关性的方法,在第六章的探索性数据分析中详细讨论。
值得注意的是,在许多时间序列的情况下,自相关往往使得时间上较近的测量值之间的值更加接近,而与时间上较远的测量值相比,值的差异较大。
尊重时间顺序的另一个原因是避免在模型训练过程中发生数据泄露。在一些分析和预测方法中,我们会使用过去的数据训练模型,以预测未来目标日期的值。我们需要确保所有使用的数据点都在目标日期之前。时间序列数据中的数据泄露往往难以发现,这会破坏方法的完整性,并在开发阶段让模型表现得过于理想,而在面对新的未见数据时表现不佳。
本书的其余部分将进一步解释在这里提到的术语,如自相关、滞后和数据泄露。
本节讨论的时间顺序是时间序列的一个定义特征。在下一节中,我们将重点讨论规律性或其缺乏,这是另一个特征。
定期和不定期
时间序列可以是定期的或不定期的,这取决于它们的测量间隔。
定期时间序列在时间上的值是按规律的时间间隔预期的,比如每分钟、每小时、每月等等。这通常是源系统生成连续值的情况,这些值随后在规律的时间间隔内进行测量。这种规律性是预期的,但并不保证,因为这些时间序列可能会有间隔或值为零的情况,这可能是由于缺失的数据点或测量值本身为零造成的。在这种情况下,它们仍然会被视为定期的。
非规则时间序列是指在源头上测量的时间间隔不规则的情况。这通常发生在事件在不规则的时间点发生,并且会测量某种类型的值。这些不规则时间间隔的值可以通过降频重采样转换为规则间隔,从而变成规则时间序列。例如,一个不按每分钟发生的事件,可能每小时发生一次,按小时来看的话,它是规则的。
本书将主要关注规则时间序列。在时间序列的规则性之后,我们将在下一节考虑的另一个特征是平稳性。
平稳与非平稳
考虑到时间序列的统计性质随时间的变化,它们可以进一步分为平稳和非平稳。
平稳时间序列是指那些统计性质(如均值和方差)随时间变化不大的时间序列。
非平稳时间序列具有变化的统计性质。这些时间序列可以通过多种方法转换为平稳序列,例如,通过对差分进行一阶或多阶差分来稳定均值,使用对数值来稳定方差。这个区分非常重要,因为它决定了可以使用哪种分析方法。例如,如果某种分析方法假设时间序列是平稳的,那么可以先对非平稳数据进行上述转换。你将在第六章中学习如何识别平稳性。
注意
将非平稳时间序列转换为平稳时间序列可以去除趋势和季节性成分,但如果我们想分析这些成分,可能就不符合我们的需求。
本节内容对于理解时间序列的基本特性非常重要,这是在本书后半部分选择合适的分析方法的前提。图 1.2总结了可以使用的时间序列类型和转换操作。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_02.jpg
图 1.2:时间序列类型
这部分结束了本章的理论内容。在接下来的部分,我们将进行第一次动手实践,同时设置编码环境。本章将从可视化和分解时间序列开始。我们将在下一章深入探讨不同类型的时间序列分析及其使用场景。
动手实践:加载和可视化时间序列
让我们通过动手练习加载一个时间序列数据集并进行可视化。我们将尝试创建之前在图 1.1中看到的可视化表示。
开发环境
为了运行代码,你需要一个 Python 开发环境,在其中安装 Apache Spark 和其他所需的库。具体的库和安装说明将在相关章节中详细介绍。
PaaS
一个简单的方法是使用免费的 Databricks Community Edition,它包含一个基于笔记本的开发界面,并且预安装了 Spark 和其他一些库。
注册 Databricks Community Edition 的说明可以在这里找到:
docs.databricks.com/en/getting-started/community-edition.html
Community Edition 的计算能力是有限的,因为它是一个免费的基于云的 PaaS。你还可以注册 Databricks 的 14 天免费试用版,具体取决于你选择的注册选项,可能需要你首先拥有云服务提供商的账户。一些云服务提供商可能会有一些免费积分的促销活动,供你在开始时使用。这将为你提供比 Community Edition 更多的资源,时间有限。
你可以通过以下网址注册 Databricks 的免费试用版:www.databricks.com/try-databricks
Databricks 的开发团队是 Apache Spark 的原创作者,因此在这里工作会是一个不错的选择。
早期章节中的示例将使用 Community Edition 和 Apache Spark 的开源版本。我们将在 第八章 和 第十章 中使用完整的 Databricks 平台。
自定义
或者,你可以搭建自己的环境,设置完整的技术栈,例如在 Docker 容器中。这将在 第三章 中介绍,Apache Spark 简介。
代码
本节的代码位于本书 GitHub 仓库的 ch1
文件夹中的名为 ts-spark_ch1_1.dbc
的笔记本文件中,具体参考 技术要求 部分。
数据集的下载链接如下:github.com/PacktPublishing/Time-Series-Analysis-with-Spark/raw/main/ch1/ts-spark_ch1_1.dbc
数据集
一旦选择了开发和运行时环境,另一个需要考虑的因素是数据集。我们将使用的是毛里求斯年均地表空气温度数据,可以在气候变化知识门户网站上找到,网址为 climateknowledgeportal.worldbank.org/country/mauritius
。
数据集的副本(文件名为 ts-spark_ch1_ds1.csv
)可以在 GitHub 上的 ch1
文件夹中找到。可以使用前面提到的代码进行下载。
接下来,你将在 Databricks Community Edition 工作区中工作,这将是你自己的独立环境。
步骤:加载和可视化时间序列
现在我们已经完成了所有设置,让我们开始第一个编程练习。首先,登录 Databricks Community Edition 导入代码,创建一个集群,并最终运行代码:
-
使用你在注册过程中指定的凭证登录到 Databricks Community Edition,如图 1.3所示。访问登录页面的 URL 为:
community.cloud.databricks.com/
如果你还没有注册,请参考开发环境部分,了解如何进行注册。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_03.jpg
图 1.3:登录 Databricks Community Edition
- 进入工作区后,点击创建笔记本。见图 1.4。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_04.jpg
图 1.4:创建笔记本
- 从这里开始,我们将进入代码部分,首先导入提供的
ts-spark_ch1_1.dbc
笔记本,该笔记本可以在 GitHub 上找到,链接为第一章,如图 1.5所示。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_05.jpg
图 1.5:导入笔记本
- 请注意,你可以从技术要求部分提供的 GitHub URL 下载第一章的文件到本地计算机,然后从那里导入,或者可以按图 1.6所示,指定以下原始文件 URL 进行导入:
github.com/PacktPublishing/Time-Series-Analysis-with-Spark/raw/main/ch1/ts-spark_ch1_1.dbc
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_06.jpg
图 1.6:从文件或 URL 导入笔记本
- 到现在为止,我们已经进入了实际的代码部分。你应该现在已经有了一个带有代码的笔记本,如图 1.7所示。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_07.jpg
图 1.7:带代码的笔记本
- 最后,让我们运行代码。点击全部运行,如图 1.8所示。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_08.jpg
图 1.8:运行笔记本中的所有代码
- 如果你还没有启动集群,你需要创建并启动一个新的集群。请注意,在 Databricks Community Edition 中,当集群未使用时会自动终止,在这种情况下,你将看到附加集群已终止的消息,如图 1.9所示,你需要选择另一个资源。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_09.jpg
图 1.9:附加集群已终止
- 从此时起,你可以选择连接到另一个活动集群(非终止状态的集群),或者选择创建一个新的资源,如图 1.10所示。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_10.jpg
图 1.10:计算 – 创建新资源
- 接下来,你需要为集群指定一个名称,并选择你想要使用的 Spark 版本,如图 1.11所示。这里的推荐做法是使用最新版本,除非由于需要在其他环境中运行的兼容性原因,你需要让代码在旧版本上工作。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_11.jpg
图 1.11:计算 – 创建、附加并运行
-
一旦集群创建并启动(在这个免费环境中可能需要几分钟时间),代码就会运行,你将看到章节开头的图 1.1所示的图表作为输出。用于创建和显示图表的图形库提供了交互式界面,使你可以进行例如放大特定时间段的操作。
-
由于这是第一次动手实践,我们已经详细介绍了逐步操作。在未来的实践部分,我们将专注于特定的数据集和代码,因为其他部分将非常相似。只要有差异,会提供额外的说明。
现在我们已经执行了代码,接下来我们将回顾主要部分。在本介绍性部分,我们将保持高层次的讨论,待介绍完 Apache Spark 概念后,后续章节将进一步深入细节:
-
import
语句添加了日期格式转换和绘制图表的库:import pyspark.pandas as ps import Plotly, a graphing library that enables interactive visualization, converts data points into graphs.
-
然后我们使用
spark.read
将 CSV 数据文件读取到表中:df1 = spark.read.format("csv") \ .option("header", "true") \ .load("file:///" + SparkFiles.get(DATASET_FILE)) df1.createOrReplaceTempView("temperatures")
-
spark.sql
语句基于源数据集中的年份列(命名为Category
)选择数据集的一个子集:df2 = spark.sql("select to_date(Category) as year, float(`Annual Mean`) as annual_mean from temperatures where Category > '1950'")
-
最后,我们根据普通最小二乘法(OLS)回归绘制时间序列以及趋势线,如图 1.1所示:
fig = px.scatter( df2_pd, x="year", y="annual_mean", trendline="ols", title='Average Temperature - Mauritius (from 1950)' )
-
使用的绘图库
plotly
允许在用户界面上实现互动,例如鼠标悬停时显示数据点信息以及缩放。
从这一点开始,随时可以在代码和 Databricks 社区版环境中进行实验,我们将在本书的大部分初始章节中使用该环境。
在这一部分,你首次接触了时间序列和编码环境,从一个简单的练习开始。在下一节中,我们将详细讲解到目前为止介绍的一些概念,并将时间序列分解为其组成部分。
将时间序列分解为其组成部分
本节旨在通过分析时间序列的组成部分,进一步加深对时间序列的理解,并详细说明迄今为止介绍的几个术语。这将为接下来的章节奠定基础,使你能够根据分析的时间序列特性使用正确的方法。
时间序列模型可以分解为三个主要组成部分:趋势、季节性和残差:
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/1.png
注意
本书中的数学表示将采用简化的英文符号,以便于广泛的受众。关于时间序列的数学公式,请参考以下优秀资源:《预测:原理与实践》:otexts.com/fpp3/
。
正如您将在接下来的实践部分看到的那样,这种成分的划分是基于拟合到时间序列数据的模型得出的。对于大多数实际数据集来说,这种分解仅仅是模型对现实的近似。因此,每个模型都会有自己对这些成分的识别和近似。整个目标是找到最适合时间序列的模型。这就是我们在第七章中将要构建和测试的内容。
让我们逐一分析这些成分,定义它们的含义,并根据一个示例数据集进行可视化,如图 1.12所示。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_12.jpg
图 1.12:时间序列分解
系统性和非系统性成分
水平、趋势、季节性和周期性被称为系统性成分。它们代表了时间序列的基础结构,可以进行建模,因此可以预测。
除了系统成分外,还有一个非系统性部分无法建模,这部分被称为残差、噪声或误差。时间序列建模的目标是找到最适合系统成分的模型,同时最小化残差。
现在我们将详细介绍每个系统性和非系统性部分。
水平
水平,也称为基准水平,是序列的均值,作为基线,其他成分的效应会在其上叠加。有时,它会作为额外成分明确加入到前面的公式中。然而,水平并不总是出现在公式中,因为它可能不是分析的主要焦点,或者分解方法可能已经将其隐含在其他成分中。
趋势
趋势是指时间序列中值在一段时间内的总体变化方向:上升、下降或平稳。这种变化可以是线性的,如图 1.1和图 1.12所示,也可以是非线性的。趋势本身可以在不同的时间点发生变化,我们可以将其称为趋势变化点。更广泛地说,变化点是指时间序列的统计特性发生变化的时间点。这可能对模型参数,甚至我们用来分析时间序列的模型产生显著影响。
季节性和周期性
季节性表示时间序列在固定时间间隔内的变化。这通常是由季节性日历事件引起的。以我们的温度例子为例,每年夏季的温度都会相对于其他季节升高,冬季则下降,如图 1.12所示。类似地,礼品销售的时间序列可能会在每个圣诞节期间显示出销售的增加,形成其季节性模式。
多重季节性(间隔和振幅)可以在同一时间序列中产生组合效应,如图 1.13所示。例如,在温度的例子中,除了夏冬季的起伏变化外,白天温度升高,夜间温度下降。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_13.jpg
图 1.13:多重重叠的季节性(合成数据)
周期性是指类似季节性在不规则间隔发生的变化。时间序列中的周期性反映了外部周期对序列的影响。例如,经济衰退每隔若干年发生一次,并对经济指标产生影响。我们无法提前预测其发生时间,这与圣诞节的季节性不同,后者每年 12 月 25 日都能预测发生。
残差或剩余项
残差或剩余项是指在模型已考虑了趋势、季节性和周期性之后所剩下的部分。残差可以使用自回归(AR)或移动平均(MA)方法进行建模。此时剩余的部分,也被称为噪声或误差,具有随机性,无法被建模。在图 1.12的最上方图表中,你可以将残差可视化为数据点与拟合线之间的距离。我们将在第六章中介绍如何测试残差,内容涉及探索性数据分析。
注意
当残差只是时间序列中的一部分随机时,整个序列可能完全是随机的,或者是一个随机游走。完全随机的序列将不依赖于先前的时间值,而对于随机游走,时间t
的值依赖于t-1
时的值(加上一些漂移和随机成分)。
加法型或乘法型
时间序列可以是加法型(前述公式)或乘法型。在加法型的情况下,季节性和残差成分不依赖于趋势。而在乘法型的情况下,它们随趋势变化,可以视为季节性成分的振幅变化——例如,较高的峰值和较低的谷值。
现在我们已经了解了时间序列的各个组成部分,接下来我们通过代码来实践一下。
实践操作:分解时间序列
以演示ts-spark_ch1_2fp.dbc
为例。
位置 URL 如下:github.com/PacktPublishing/Time-Series-Analysis-with-Spark/raw/main/ch1/ts-spark_ch1_2fp.dbc
我们将使用的数据集是 1981 到 1990 年间澳大利亚墨尔本的每日最低温度,原始数据来自澳大利亚气象局,并可在 Kaggle 上通过以下链接获取:www.kaggle.com/datasets/samfaraday/daily-minimum-temperatures-in-me
数据集的副本已提供在 GitHub 文件夹中,文件名为ts-spark_ch1_ds2.csv
。
在本章中,我们将保持高层次的讨论,选取笔记本中的一些内容进行讲解,之后会在接下来的章节中详细介绍预测模型的其他概念:
-
import
语句添加了用于预测模型和绘制图表的库:from prophet import Prophet from prophet.plot import plot_plotly, plot_components_plotly
使用的预测库是
Prophet
,它是 Facebook 开源的库。无论是专家还是非专家,都可以使用它进行时间序列数据的自动预测。 -
然后,我们使用
spark.read
将 CSV 数据文件读入表格中:df1 = spark.read.format("csv") \ .option("header", "true") \ .load("file:///" + SparkFiles.get(DATASET_FILE)) df1.createOrReplaceTempView("temperatures")
-
spark.sql
语句将date
和daily_min_temperature
列转换为正确的格式和列名,这是Prophet
所要求的:df2 = spark.sql("select to_date(date) as ds, float(daily_min_temperature) as y from temperatures sort by ds asc")
-
接下来,我们使用
Prophet
库根据 12 个月的季节性创建一个预测模型,并将其拟合到数据上:model = Prophet( n_changepoints=20, yearly_seasonality=True, changepoint_prior_scale=0.001) model.fit(df2_pd)
-
该模型随后用于预测未来日期的温度:
future_dates = model.make_future_dataframe( periods=365, freq='D') forecast = model.predict(future_dates)
-
最后,我们绘制了模型识别出的时间序列成分,如图 1.12所示:
plot_components_plotly(model, forecast)
现在我们已经对成分和预测做了基本讨论,让我们来探讨一下重叠季节性案例。
多重重叠季节性
我们将通过代码来创建图 1.13中的数据可视化。此部分代码位于名为 ts-spark_ch1_3.dbc
的笔记本文件中。
位置 URL 如下:github.com/PacktPublishing/Time-Series-Analysis-with-Spark/raw/main/ch1/ts-spark_ch1_3.dbc
该数据集是合成的,生成了三条不同的正弦曲线,代表三种重叠的季节性。
以下代码摘自笔记本。让我们从高层次进行查看:
-
import
语句添加了用于数值计算和绘图的库:import numpy as np from plotly.subplots import make_subplots
NumPy 是一个开源的 Python 科学计算库,相比标准 Python,它在计算和内存使用上显著更高效。我们将在此使用它的数学函数。
-
接下来,我们生成多个正弦曲线,使用
np.sin
来表示不同的季节性,并将它们叠加在一起:(amp, freq) = (3, 0.33) seasonality1 = amp * np.sin(2 * np.pi * freq * time_period) (amp, freq) = (2, 1) seasonality2 = amp * np.sin(2 * np.pi * freq * time_period) (amp, freq) = (1, 4) seasonality3 = amp * np.sin(2 * np.pi * freq * time_period) combined = seasonality1 + seasonality2 + seasonality3
-
最后,我们绘制了各个季节性以及它们的合成季节性,如图 1.13所示:
fig = make_subplots(rows=4, cols=1, shared_xaxes=True) fig.add_scatter( x=time_period, y=seasonality1, row=1, col=1, name=f"seasonality 1") fig.add_scatter( x=time_period, y=seasonality2, row=2, col=1, name=f"seasonality 2") fig.add_scatter( x=time_period, y=seasonality3, row=3, col=1, name=f"seasonality 3") fig.add_scatter( x=time_period, y=combined, row=4, col=1, name=f"combined")fig.show()
从现在开始,尽管在笔记本中自由地尝试完整的代码。
在本节中,我们开始了分析时间序列的旅程,探讨了其潜在结构,并根据数据的性质铺平了进一步分析的道路。在下一节中,我们将涵盖一些关键的考虑因素和挑战,帮助你在整个过程中做好准备。
时间序列分析的额外考虑因素
本节可能是本书早期部分中最重要的一节。在导言部分,我们提到了一些时间序列的关键考虑因素,例如保持时间顺序、规律性和稳定性。在这里,我们列出了在实际项目中分析时间序列时遇到的关键挑战和额外的考虑因素。通过这样做,你可以根据本书中相关部分的指导以及进一步阅读来规划自己的学习和实践。
根据 2015 年发表的著名论文《机器学习系统中的隐性技术债务》,在高级分析项目中,只有一小部分工作与代码相关。剩余的时间大多数用于其他考虑因素,如数据准备和基础设施建设。
这些挑战的解决方案是非常具体的,依赖于你的具体背景。本章的目的是让你意识到这些考虑因素,如图 1.14所总结的。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_01_14.jpg
图 1.14:时间序列分析中的考虑因素和挑战
尽管这些考虑因素大多数与非时间序列分析(如机器学习)共享,但时间序列分析通常是高级分析方法中最具挑战性的。我们将在本书的其余部分详细讨论一些应对这些挑战的解决方案。
面对数据挑战
与所有数据科学和机器学习项目一样,数据是关键。你运行的分析和构建的模型的效果将取决于数据的质量。数据挑战各式各样,且非常依赖于你的具体环境和数据集。
我们将在这里列出一些常见的问题:
-
数据访问 可能是所有问题的起点。对于本书而言,我们将使用几个免费访问的数据集,因此这不是问题。在实际项目中,所需数据集的所有权可能属于你所在组织的其他部门,甚至可能完全属于另一家组织。在这种情况下,你将不得不经历获取数据集的过程,可能会涉及财务成本,并确保数据能够以可靠的方式进行传输,同时保证传输速度和数据的新鲜度。传输管道的构建将有其自身的成本,以及传输本身的成本。传输机制必须具备生产级别的能力,以支持操作需求:稳健、可恢复、可监控等。
最初,你的数据访问需求将用于探索性数据分析和模型训练。批量导出可能足够。进入生产阶段后,你可能需要实时或近实时的数据访问。那时,考虑因素将完全不同。
一旦数据被摄取,接下来的要求是以安全且可用的方式存储它。使用专门的时间序列数据库是一个优化性能的选择,尽管对于大多数情况,通用存储已足够:
-
敏感性是另一个关键方面。在这里,开发和生产中可能会有不同的要求。然而,在许多情况下,开发和测试中使用的是生产数据的子集。某些包含个人身份信息(PII)的列需要进行遮蔽或加密,以遵守如欧洲 GDPR 等法规。在高度敏感的情况下,整个数据集可能需要加密。这对大规模处理来说是一个挑战,因为每次访问数据都可能需要解密和重新加密。这会带来处理开销。
总结来说,端到端的安全性和数据治理将成为你的高优先级需求,这从第一天就开始了。你希望在每个阶段都避免安全性和合规性风险,包括开发阶段,尤其是当你处理敏感数据时。
-
数据量和频率在实时或近实时的大流量数据源中,将需要合适的平台来实现快速处理而不丢失数据。在预生产环境中,这一点可能不太明显,因为规模较小。性能和可靠性问题通常会在生产环境扩展时才显现出来。我们将在介绍 Apache Spark 时讨论扩展和流处理,这将帮助你避免此类问题。
-
数据质量是我们早期将面临的挑战,一旦数据访问问题解决,我们开始在探索阶段和开发中处理数据。挑战包括数据缺失、数据损坏、数据噪声,甚至对于时间序列数据来说,更为相关的是数据延迟和乱序。如前所述,对于时间序列数据,保持时间顺序非常重要。在我们讨论数据准备时,我们将进一步探讨解决数据质量问题的方法。
在数据挑战之后,下一步的重点是为需要解决的问题选择正确的方法和模型。
使用正确的模型
这对于那些刚接触时间序列的人来说可能是一个更大的挑战。正如我们到目前为止所看到的,时间序列具有不同的统计特性。一些分析和建模方法是基于对时间序列统计特性的假设而创建的,其中平稳性是常见的假设。如果使用不正确类型的时间序列,这些方法将无法按预期工作,甚至可能导致误导性结果。如果你已经识别出多个重叠的季节性,某些方法处理这些季节性也可能会是一个挑战。图 1.14 回顾了时间序列和分析模型的类型。模型的选择将在第七章,构建和 测试模型 中进一步讨论。
选择正确的模型也在很大程度上取决于我们希望实现的结果,无论是预测未来一个或多个时间步长,还是同时分析一个(单变量)或多个(多变量)序列。对于一些领域,如受监管行业,通常还需要可解释性,而某些模型(如黑箱模型)可能难以满足这一要求。我们将在下一章《为什么时间序列重要》中进一步讨论时间序列分析的结果及如何选择合适的模型,包括用于异常和模式检测以及预测建模的模型。
维持空间和时间层次结构
请注意,另一个关键考虑因素是数据收集和分析的层次结构。这需要在不同层级之间保持一致性。为了说明这一点,让我们以一个多店零售商销售不同产品的时间序列预测为例。这里的空间层次结构可能位于产品和产品类别层级,以及特定商店和区域层级。时间层次结构将对应于每小时、每日、每季度等的销售情况。在这种情况下的挑战是确保单个产品和产品类别的预测一致性,以及例如,日度预测与季度预测的一致性。
最终,选择正确的模型取决于数据量,正如我们将在后续章节中讨论的构建模型的内容。
解决可扩展性问题
主要有两个因素影响可扩展性:数据量和处理复杂性。之前,我们讨论了数据量作为数据挑战。这里我们来考虑处理复杂性。复杂性可能来自于准备数据所需的数据转换的程度,以及需要管理的模型的数量、层次结构和大小:
-
大量和复杂的模型层次结构:在实际项目中工作时,您可能需要在相对较短的时间内并行运行数十甚至数千个模型 - 比如,如果您在商店工作并需要为商店中销售的成千上万种商品预测第二天的销售和库存水平。这种并行性的需求是使用 Apache Spark 的主要原因之一,我们将在本书中进一步了解。
-
模型的大小:可扩展性的另一个要求来自模型本身的大小,如果我们使用具有许多层和节点的深度学习技术,模型可能会非常庞大,并且具有高计算要求。
我们将在本书后面专门讨论扩展。
接近实时
早些时候,我们确定高频数据是一个重要的数据挑战。接近实时不仅需要数据级别的调整,还需要一个设计用于处理这种需求的处理管道。通常,模型是在一段时间内收集的数据批次上进行训练,然后部署到诸如预测或异常检测等任务中,其中实时处理变得至关重要。例如,在检测欺诈交易时,尽可能接近事件发生时识别异常是至关重要的。近乎即时数据处理的可行解决方案是 Apache Spark 结构化流,这是我们在本书后面讨论 Apache Spark 时将探讨的一个主题。
生产管理
前述考虑也适用于生产环境。此外,将开发的解决方案移入生产环境还有一些特定要求。如果管理不当,这些要求可能会带来挑战。
一旦正确的模型已经训练好并准备好使用,下一步是将其与任何必需的 API 包装器一起打包,以及数据管道和消耗模型的应用程序代码。这意味着一个涉及 DataOps、ModelOps 和 DevOps 的端到端过程。在我们讨论生产时,我们将在第九章更详细地讨论这些内容。
监控和解决漂移
一旦模型投入使用,随着时间的推移会发生变化,导致模型不再适合使用。这些变化大致分为以下几类:
-
数据集性质的变化(数据漂移)
-
输入和输出之间关系的变化(概念漂移)
-
意外事件,如 COVID,或在建模过程中遗漏的重要事件(突发漂移,一种概念漂移)
这些漂移将影响模型的性能,因此需要进行监控。在这种情况下的解决方案通常是根据新数据重新训练模型或找到在更新的数据集上性能更好的新模型。
本节概述了处理时间序列时的考虑因素和挑战。与处理其他数据集的通用性有很多共同之处,因此这里的指导在更广泛的背景下也将非常有用。然而,正如我们在介绍部分看到的那样,时间序列也有其特定的考虑因素。
总结
时间序列随处可见,本章介绍了它们的基本概念、组成部分以及处理中的挑战。我们从一些简单的代码开始探索时间序列,为后续章节的进一步实践奠定基础。本书的第一章讨论的概念将逐步加深,最终使我们能够扩展到大规模分析时间序列的程度。
现在您已经理解了时间序列的“是什么”,在下一章中,我们将探讨“为什么”,这将为在各个领域中应用打下基础。
进一步阅读
本节作为资源库,可帮助您进一步了解该主题:
-
气候混乱助长了法国 大革命:
time.com/6107671/french-revolution-history-climate/
-
Databricks 社区版:
docs.databricks.com/en/getting-started/community-edition.html
-
气候变化知识门户:
climateknowledgeportal.worldbank.org/country/mauritius
-
预测: 原理与实践 由 Rob J Hyndman 和 George Athanasopoulos:
otexts.com/fpp3/
-
机器学习系统中的隐藏技术债务 (Sculley et al., 2015):
papers.neurips.cc/paper/5656-hidden-technical-debt-in-machine-learning-systems.pdf
加入我们的 Discord 社区
加入我们社区的 Discord 空间,与作者和其他读者讨论:
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/ds_(1.jpg)
第二章:为什么需要时间序列分析?
本章深入探讨了分析时间序列数据的实际意义。它阐明了时间序列分析如何支持预测建模、趋势识别和异常检测。通过展示各行业的实际应用,本章强调了时间洞察在决策中的关键作用。掌握时间序列分析的重要性对专业人士至关重要,因为它凸显了对预测准确性、资源优化和战略规划的影响,促进了对面向时间的数据分析的全面理解。
本章将涵盖以下内容:
-
时间序列分析的需求
-
行业特定的应用案例
-
选择应用案例的动手实践
技术要求
在第一章之后,我们将在这里进一步提高代码的难度,目标是展示时间序列在选定应用案例中的使用。本章的代码可以在本书 GitHub 仓库的 ch2
文件夹中找到: https://github.com/PacktPublishing/Time-Series-Analysis-with-Spark/tree/main/ch2。
请参考这个 GitHub 仓库,获取代码的最新修订版本,若更新内容与本书中代码部分不同,更新将会在仓库中注释说明。
本章的动手实践部分将进一步详细介绍。
理解时间序列分析的需求
正如我们在上一章讨论的,时间序列在生活的各个方面以及所有行业中都存在。因此,分析时间序列的需求无处不在。本章将探讨不同行业的不同应用案例。在此之前,我们将在本节中研究其基本方法。这些方法大致可以分为预测、模式检测与分类,以及异常检测。图 2.1展示了本章将讨论的几个关键时间序列分析概念。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_02_1.jpg
图 2.1:时间序列分析中的概念
现在,让我们更详细地讨论每一个部分。
预测
时间序列预测是基于先前观察到的数值来预测未来的值。这是通过建模时间序列数据中的基本模式——例如趋势、季节性和周期——来预测未来的数据点。例如,在我们在第一章中可视化的温度时间序列的例子中,我们可以使用预测模型根据从前几个月学习到的模式来预测下个月的温度。预测是时间序列分析中最常见的方法,本书将重点讨论这一方法。这可以是单步预测、多步预测、单变量预测或多变量预测。
单步预测
在单步预测中,我们根据对历史数据点的分析以及由此构建的模型,预测时间序列中的下一次发生事件。预测步骤的粒度通常与我们学习历史模式的数据集中的粒度相同。例如,如果我们的历史时间序列中包含的是每日温度,那么下一步将是第二天。如果我们将数据点汇总为例如月度平均值,并且对月度变化模式进行了建模,那么下一步将是下个月的平均温度。
虽然单步预测通常是我们能获得的最可靠的预测,但不幸的是,它对于许多需求来说是不够的,因为在现实生活中,我们往往需要比仅仅预测一个(时间)步骤更长远的计划。如果我们在做每日预测,我们不仅仅想预测明天的天气。我们希望能够预测未来几天、几周甚至几个月的情况。单步预测对于规划来说显然不足够。
多步预测
在多步预测中,我们使用从历史数据点构建的模型,预测时间序列中的多个下一步。我们还将预测的前一步作为输入。以我们的每日温度为例,这可能意味着对接下来一周的每天进行逐日预测。
挑战
多步预测的挑战在于,后续的预测是基于先前的预测,这与单步预测不同,单步预测是基于实际数据点的。实际上,这意味着递归地逐步应用预测算法,每一步都将预测结果添加到数据集中,并使用历史和预测数据点来预测下一步。因此,预测中的不准确性随着每一步向未来推进而逐渐累积。
注意事项
这种多步预测中的预测误差累积是你希望与业务或任何为你构建预测的人提前沟通的限制。你需要确保在长期预测方面设定清晰的预期。
解决方案
除了将预测限制在非常短的时间范围内外,还有几种方法可以应对多步预测的挑战:
-
首先,构建一个尽可能准确的模型,使得初步预测的结果接近现实。
-
另一种方法是使用模型组合,旨在平均化预测误差。
-
最后,限制预测间隔或步数,并在有新的测量数据时重新计算预测。
单变量预测
到目前为止,在第一章中,我们只考虑了单一变量(单变量)的时间序列,也就是特定位置的温度。另一个单变量时间序列的例子,在经济领域,是特定地区或国家的失业率。根据定义,单个时间序列是单变量的,无论是温度还是失业率。在现实世界中,需求往往是同时预测多个时间序列,这样我们能比单一时间序列提供的视角获得更全面的未来预测。以温度为例,这可能意味着需要考虑多个地点,或者额外预测空气中的污染物水平。对于经济预测,这可能意味着需要预测国内生产总值(GDP)以及失业率。这引出了多变量预测。
多变量预测
单变量是指单一的时间序列,而多变量预测有几种方式可以进行描述:
-
多重输入维度是指我们将多个变量(包括时间序列和非时间序列)作为输入提供给预测模型——例如,使用过去的温度和污染物水平来预测未来的温度。
-
多重输出预测使用预测模型来预测多个变量。以之前的温度示例为例,这意味着要同时预测温度和污染物水平。
正如我们从前面的例子中看到的,可能会有多个时间序列的不同场景。这些序列可以是相关的,如果它们有相同的潜在原因(这个原因本身也可以通过另一个时间序列来表示),它们就可能有共动关系。它们也可以有因果依赖性,即一个时间序列与另一个时间序列之间存在因果关系。它们还可能是独立的,我们只是同时进行预测。在第六章的探索性数据分析中,我们将讨论一些这些考虑因素。
总结来说,预测很少是单独进行的,我们需要同时分析的时间序列数量可能达到数百甚至数千。这个对多个时间序列的需求是使用并行执行工具(如 Apache Spark)的一个很好的理由,正如我们将在后续章节中看到的那样。
既然我们已经讨论了预测,现在让我们看看另一种分析方法,这将使我们能够对时间序列进行分类。
模式检测与分类
模式检测与分类是基于某些模式识别和分类时间序列。通常,时间序列遵循某种模式,我们可以识别并标记这些模式。这些标签允许我们通过将标记的模式与新的时间序列发生情况进行匹配,从而对时间序列进行分类。我们可以采取不同的方法来实现这一点,广义上可分为基于距离、基于区间、基于频率、基于字典、形状模式、集成方法和深度学习。接下来将详细介绍这些方法。
基于距离
基于距离的时间序列分类方法,使用k-最近邻(kNN)和动态时间规整(DTW),将在这里进行解释,这是分析时间序列数据的成熟方法。由于时间序列数据的偏移和扭曲,标准的欧几里得距离并不是衡量相似性的良好度量。DTW 通过将序列在时间上对齐提供了一种替代方案。它计算两条时间序列之间的最小距离,考虑所有可能的对齐方式,这使得其计算量较大。然后使用 kNN 根据时间序列的形状相似性来进行分类。
以下图表展示了使用动态时间规整(DTW)计算谷歌股票(下方,黑线)与亚马逊股票,以及谷歌股票与 Meta 股票之间的距离。我们将在本章的动手操作部分执行这个示例。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_02_2.jpg
图 2.2:DTW 距离(GOOG – 黑线)
基于区间
使用这种方法,时间序列首先被划分为多个区间,并计算每个区间的描述性统计量。这些区间随后与分类器如随机森林或支持向量机一起作为特征向量使用。该方法的优势在于它能够捕捉时间序列在不同阶段的特性,这对于那些在时间上具有不均匀模式的时间序列非常有效。将时间序列汇总成带有统计特征的区间也是降低复杂性并提高可解释性的好方法。
基于频率
这种分类方法,例如随机区间谱集成(RISE),首先通过例如傅里叶变换将时间序列转换到频域。RISE 是一种基于分类器的集成方法,分类器如决策树,是通过随机区间和为这些区间提取的谱特征构建的。该方法的优势在于能够识别与频率相关或周期性特征,并且作为一种集成方法,它在提供准确性的同时具有鲁棒性。
基于字典
基于字典的时间序列分类方法将时间序列转换为符号表示,从而可以使用基于文本的技术进行分类。遵循这一方法的突出方法有:
-
模式包(BoP):BoP 通过应用滑动窗口捕获局部模式,从而创建一个“模式包”。然后将其哈希为频率直方图,用作分类的特征向量。
-
SFA 符号包(BOSS):BOSS 是一种更能抵御噪声并有效捕获关键模式的变体。它使用符号傅里叶近似(SFA)在不同分辨率下捕获时间序列。
-
随机卷积核变换(ROCKET):ROCKET 为大数据集提供了更高的速度和效率。它生成并使用随机卷积核将时间序列转换为特征向量。
Shapelets
这些是时间序列中的子序列,代表了特定类别模式。通过找到在时间序列或其他相关时间序列中匹配的形状,可以相应地对时间序列进行分类。当定义类别的特征在时间上是局部化的时候,例如交易金额突然增加,可能对应信用卡盗窃。Shapelets 还可以帮助解释性——一旦形状被充分理解,可以用于解释在时间上匹配的时间序列点。
集成
迄今为止提到的集成分类方法将相似类型的分类器分组。另一种方法,如基于层次化投票的转换集成(HIVE-COTE),则采用不同类型的分类器。其思想是基于不同分类器捕获的时间序列的不同方面构建集成。这些分类器是独立训练的,其预测结果根据层次化投票方法进行组合。与其他集成方法一样,这可以提高鲁棒性和准确性。此外,由于使用了各种技术,HIVE-COTE 是复杂多模式时间序列的一个良好选择。然而,这也带来了较高的计算成本。
深度学习
诸如TimeNet的方法利用深度神经网络自动提取时间序列中的特征、模式和关系。TimeNet 是预训练的,这使得它能够快速应用。它结合了卷积神经网络(CNNs)用于局部特征和循环神经网络(RNNs)用于顺序模式。这使得 TimeNet 能够有效地捕获低级和高级模式,从而学习层次化表示。其优点在于适应各种时间序列分类问题,同时减少了手动特征工程的需求。与其他深度学习方法类似,缺点在于需要大量数据进行预训练、需要的计算资源较多,以及缺乏可解释性。尽管如此,在多种复杂情况下,它们仍然是性能最先进的方法之一。
虽然本书不会像预测那样详细讨论时间序列的分类,但这仍是一个值得进一步研究的有前景领域,并且面临一系列操作性挑战。
这带我们进入最后一种分析类型,即从时间序列数据中检测异常。
异常检测
时间序列分析的第三类使用场景是异常检测,旨在标记意外的模式或事件。虽然这与模式识别和预测有关,但其目的是不同的:识别源系统行为的意外偏差。异常检测在多个领域至关重要,如金融、医疗保健和工业系统。这些异常可能表明严重事件的发生,例如系统故障、金融欺诈或网络入侵。
除了单变量或多变量外,异常还可以表现为以下几种形式:
-
点:这是指一个单一的数据点被识别为异常的情况。
-
集合:当多个数据点作为一组近似的测量值被标记为异常时,就属于此类情况。
-
上下文:某个数据点或集合在周围测量值的上下文中可能是异常的,而在另一个上下文中, 同一个数据点或集合可能不是问题。
异常也可以分为离群值和新颖性,离群值可能表示错误或故障,而新颖性则是之前未见过的模式,可能不是问题。
注意
为了使异常检测有效,数据准备阶段必须保留数据集中的异常值,这与通常在数据整理过程中所做的相反。
除了传统的统计和基于规则的方法,还有更新的机器学习技术。时间序列数据中的异常检测方法可以分为无监督、监督和半监督方法,每种方法都有其独特的技术和算法。异常分数通常是通过设置阈值来计算,用于标记异常。
无监督异常检测
无监督异常检测不需要标记数据。这假设异常与正常数据的差异足够大,可以在没有先验知识的情况下检测到。常见的方法包括:
-
统计方法,如z-score和箱线图分析,用于根据统计特性识别异常值。
-
基于聚类的方法,如DBSCAN或k-means,将相似的数据点聚集在一起,而异常点则是那些不属于任何聚类的点。
-
基于密度的方法,如 kNN 和局部异常因子(LOF),利用局部邻域的密度来识别异常。
-
隔离森林是一种基于树的模型,适用于高维数据,能够有效地将异常值隔离出来。
图 2.3中的图表显示了隔离森林模型的结果,用于检测家庭能源消费中的异常。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_02_3.jpg
图 2.3:能耗异常检测
该模型是根据到 11 月 9 日为止的消费数据拟合的,然后用于之前未见过的数据。异常数据以红色/较浅的颜色显示。我们将在本章的实践部分运行此示例。
有监督异常检测
有监督异常检测适用于包含正常和异常情况的标注数据集。虽然能更好地检测异常,但它需要标注数据,这些数据可能比较难获得。相关技术包括以下几种:
-
分类模型,如传统的分类器(如逻辑回归)、支持向量机(SVM)或更复杂的模型,如 CNN 和 RNN,这些模型经过训练用来区分正常与异常实例。
-
集成方法,如随机森林或梯度提升,可以通过组合多个模型来提高检测精度。
半监督异常检测
半监督异常检测需要较少的标注数据,并结合大量未标注的数据。例如,在工业监控中,当我们从传感器读取的数据显示数据点有限时,这些测量值大多数对应设备的正常运行,可以标注为正常。然后,超出正常标签的新读数可以被标记为异常。
当标注一个大规模数据集昂贵时,半监督技术包括以下几种:
-
修改无监督技术以包含有限的可用标签——例如,修改基于密度的或聚类方法,以增强对标注异常的敏感性。
-
新颖性检测通过在正常数据上训练模型以找到其分布,类似于无监督统计方法,然后偏离该分布的值会被标记出来。一类 SVM 和自编码器就是这种技术的示例。
高级深度学习方法
使用深度学习技术的方法包括以下几种:
-
自编码器是神经网络,通过压缩然后重建输入数据。其原理是,这些模型能很好地重建正常数据,而对异常数据的重建误差较高。
-
序列类型的模型,如长短期记忆(LSTM)、RNN和Transformers,能够识别时间序列数据中的时间依赖性,因此在序列异常检测中非常有用。
注
从操作角度来看,异常检测系统是全面监控和告警架构的一部分。需要注意的是,在低延迟或实时检测和告警要求的情况下,卡尔曼滤波器常常被使用。
这总结了各种异常检测方法。选择异常检测方法取决于时间序列和异常的特征、可用的标记数据、计算资源以及实时检测的要求。混合方法和高级方法,特别是基于深度学习的方法,由于能够建模时间序列数据中的复杂模式和依赖关系,已在各种应用中取得了令人鼓舞的结果。
从时间序列分析的整体概述出发,我们现在来看看它们在各个行业中的使用及其影响。
行业特定的应用案例
我们在前一部分讨论了不同类型的时间序列分析。接下来我们将探讨它们在不同行业中的适用性。 在此之前,图 2.4中的图表能帮助你了解跨行业应用的多样性。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_02_4.jpg
图 2.4:时间序列分析在各行业中的应用
让我们详细了解时间序列分析在各个行业中的应用。
金融服务
金融服务中的时间序列分析对于理解趋势、模式和未来行为至关重要。其应用广泛,能为决策、战略规划、风险管理和合规提供宝贵的见解。以下是时间序列分析在金融服务各个职能中的应用:
-
市场分析:通过分析资产的历史价格,包括趋势和季节性,预测未来资产价格。这有助于交易员和投资者决定交易哪些资产以及何时交易。
-
风险管理:除了前述内容,金融工具价格的另一个重要方面是它们的波动性,这需要进行分析,以更好地管理风险并制定减缓策略。这包括风险价值(VaR)建模,通过基于历史波动性和相关性来估算某个投资在一段时间内的潜在损失。风险管理的另一个领域是信用风险,包括偿还历史、违约和经济状况的时间序列数据。这有助于评估未来违约和损失的可能性。为此,预备金估算确保足够的资金被预留以应对潜在的贷款损失,而流动性管理确保保持足够的流动性。最后,在宏观经济层面,压力测试涉及分析历史上的最坏情况。
-
投资组合管理:这里的两个主要方面是优化资产配置和相关的投资组合表现评估。通过分析历史回报和资产之间的相关性,投资组合经理可以确定资产配置,以满足预期的风险回报特征。回顾其随时间的表现后,投资组合可以根据需要进行调整。
-
算法交易:从本质上讲,这涉及利用微秒或毫秒级的时间序列数据来做出高频交易决策。完整的周期包括开发策略、进行回测,然后一旦策略投入实际使用,就生成正确的交易信号。
-
欺诈检测:这里的核心思想是分析交易,识别并标记可能表明欺诈活动的模式,包括市场操纵或内幕交易。
-
经济预测:这用于预测例如利率和其他对中央银行、政府和金融机构政策制定有影响的经济指标。
从本质上讲,金融服务中的时间序列分析是支撑广泛活动的基础,从交易决策到投资组合管理和合规监管。它利用历史数据预测未来事件、管理风险并揭示有价值的洞察力。因此,时间序列分析推动了金融生态系统中的明智决策。
零售
零售行业中的时间序列分析使用按时间顺序排列的数据来进行决策、优化运营和提升客户体验。零售商可以洞察影响其业务的趋势、季节性变化和周期性行为。以下是一些关键的应用场景:
-
销售预测和收入预测:根据历史数据预测未来的销售情况,考虑季节性变化、趋势和外部因素(如假期和经济条件),有助于规划库存、员工和营销活动。这对于财务规划和投资决策至关重要。
-
库存管理和供应链优化:零售商可以通过分析购买模式和交货时间来优化库存水平。更好的需求规划和补货调度可以最大限度地减少缺货现象并减少过剩库存。在每个产品层级进行预测,有助于高效的库存补充。这也对供应链管理产生积极影响。零售行业中一个正在增加应用的相关案例是食品浪费预测和减少。
-
价格优化与营销规划:通过分析价格变动对销量的影响,可以确定最佳定价策略,从而最大化销售和利润。这包括对季节性价格敏感性、促销和营销活动的影响以及竞争定价的洞察。同时,这也优化了营销支出,更好地与季节性模式对接。
-
客户行为分析与产品生命周期管理:零售商可以通过了解客户购买习惯随时间的变化,来指导营销策略和产品开发。此分析有助于识别趋势,如购买渠道的变化或对某些产品类别的兴趣增加。这反过来有助于在产品推出、停产或重新上市方面做出更好的决策。通过更深入的客户行为分析,还可以制定有效的忠诚度项目,从而提高客户留存率。
-
门店表现分析与员工规划:通过比较不同地点的销售趋势,分析可以识别高表现的门店和需要帮助的门店。这有助于做出有关门店扩张或关闭的决策,并将人员配置与合适的门店及繁忙时段对接。其影响不仅体现在运营效率上,还能改善客户服务。
时间序列分析在零售中的应用影响着业务的方方面面,从库存和定价到营销和员工管理。通过利用历史数据,零售商可以做出明智的决策,从而提升运营效率、客户满意度和盈利能力。
医疗保健
时间序列分析在医疗保健中是跟踪健康相关数据的重要工具。此方法可以观察健康指标的模式、趋势和变化,这对改善患者护理、运营效率和临床结果至关重要。以下是医疗保健中的应用概述:
-
患者监测:在持续监测生命体征(如心率、血压等)时,可以使用时间序列分析对患者健康进行实时评估,并及早发现急性医疗事件。同样,通过分析可穿戴设备的数据,可以监测身体活动、睡眠模式及其他健康指标随时间的变化。这可以在临床环境中进行,也可以用于个人健康意识。
-
流行病学与疾病监测:这一需求的重要性在 COVID-19 期间得到了突出体现。必须随着时间推移追踪传染病的传播,以了解传播模式、识别疫情爆发,并相应规划公共干预措施。在个人层面,患有慢性病的患者可能需要根据病情的发展调整治疗计划。虽然相似,但这与监测生命体征在干预时间尺度上有所不同。
-
医院资源管理:由于大多数公立医院的资源紧张,能够预测医院的入院率以优化床位分配和人员安排是一个巨大的优势。
时间序列分析在医疗行业有众多其他应用,如医疗质量监测、药物研发和医学研究,尤其是在新冠疫情期间,公共卫生监测、分析和政策制定。
通过使用时间序列分析,医疗行业可以提升患者护理质量、提高运营效率,并推动医学研究,最终改善健康结果并推动更为科学的医疗政策。
制造业和公用事业
时间序列分析在制造业和公用事业领域至关重要,能够确保安全、优化运营并提高效率。以下是这些行业中时间序列分析的应用概述:
-
制造业:首先,在规划方面,通过需求预测、生产调度和库存管理,时间序列帮助满足市场需求而不造成过度生产。然后,为了保持生产运行,机器传感器将数据发送到预测性维护模型,以生成潜在故障的警告,从而进行及时维护。这可以显著减少停机时间,同时节省不必要的预防性维护。异常检测进一步帮助提前发现并限制质量问题。
-
石油和天然气:与制造业类似,预测性维护和异常检测确保减少停机时间,同时最大化产出。此外,由于该领域基础设施需要大量前期投资,因此准确的需求和价格预测对规划至关重要。
-
公用事业:公用事业领域的主要应用包括需求和负荷预测,进而帮助规划、配电管理和发展。这进一步促使了电网的最优利用,提高了客户服务,同时防止了停电。最后,时间序列分析和对新能源来源的预测确保它们能够与整体能源结构进行最优整合。
在所有这些领域,时间序列分析有助于资源优化、成本降低和战略规划,最终促进更具韧性和高效的运营。
注
一个主要且快速增长的时间序列数据来源是物联网(IoT)设备和传感器。这是因为连接设备数量的激增。此数据被收集、存储并分析——通常是实时的——应用场景遍及各行各业,其中一些已经讨论过,例如用于预测性维护的机器传感器数据、用于预测消费的能源表数据、健康追踪器等,涵盖范围广泛。
本节总结了行业特定用例,展示了时间序列分析在不同领域中的广泛应用。随着新分析方法和新业务需求的推动,应用案例不断创新并扩展。接下来,我们将通过行业特定数据集,展示一些时间序列分析方法的实际应用。
使用选定的用例进行动手实践
在这一动手实践部分,我们将使用行业特定的数据集,逐步演示一些选定的用例。
预测
对于预测用例,我们从 第一章 中关于温度的示例开始,加载数据集,分析其组成并可视化结果。重点放在过去——即历史数据。在接下来的步骤中,我们将重点展示与未来相关的代码部分——即预测。这基于 ts-spark_ch1_2fp
中的代码,我们已将其导入到 Databricks 社区版,并在 第一章 中详细介绍。
预测步骤如下:
-
加载数据集,内容详见 第一章。
-
使用
Prophet
库,模型在数据上创建并训练(拟合):model = Prophet( n_changepoints=20, yearly_seasonality=True, changepoint_prior_scale=0.001) model.fit(df2_pd)
-
接着我们使用 Prophet 中一个非常有用的函数
make_future_dataframe
来生成未来日期。这些日期将作为输入,并作为参数传递,用于进行预测部分,即使用predict
函数:future_dates = model.make_future_dataframe( periods=365, freq='D') forecast = model.plot_plotly generates *Figure 2**.5*. The right-most part of the graph does not have any collected data points as it is for the forecasted dates:
plot_plotly(model, forecast, changepoints=True)
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_02_5.jpg
图 2.5:温度预测
这是对预测的简要动手实践介绍。接下来我们将在本书的其他部分进行更多的预测,包括使用除 Prophet 之外的其他库。
模式分类
对于模式分类,我们将使用金融时间序列——更具体地说,科技公司股票的股价。我们将探讨使用两个不同的开源库进行 DTW,分别是 fastdtw
和 dtw-python
。这基于 ts-spark_ch2_1.dbc
中的代码,我们可以从 GitHub 上的链接导入,并按照 第一章 中的说明,将其导入到 Databricks 社区版中。
代码 URL 如下所示:
github.com/PacktPublishing/Time-Series-Analysis-with-Spark/raw/main/ch2/ts-spark_ch2_1.dbc
让我们从 fastdtw
开始,以下是步骤代码:
-
首先,我们导入必要的库:
import yfinance as yf import numpy as np from fastdtw import fastdtw yfinance library to download the share prices from Yahoo Finance for several technology companies for a date range:
from_date = “2019-01-01”
to_date = “2024-01-01”
yftickers = [
“AAPL”, “AMZN”, “GOOG”, “META”,
“MSFT”, “NVDA”, “PYPL”, “TSLA”]
yfdata = {
yftick: yf.download(
yftick, start=from_date, end=to_date, multi_level_index=False)[使用 fastdtw 库来计算每对股票的 DTW 距离:
for i in range(num_tickers): for j in range(num_tickers): dtwdistance, _ = fastdtw(X[i], X[j]) dtwmatrix[i, j] = float(dtwdistance)
-
然后我们使用以下代码绘制距离矩阵的热图:
fig = px.imshow( dtwmatrix, labels=dict(x="Tickers", y="", color="DTW distance"), x=yftickers, y=yftickers ) fig.update_xaxes(side="top") fig.show()
这创建了图 2**.6中的可视化,其中突出显示了 AMZN 和 GOOG 股价之间的 DTW 距离值。在分析的股票组合中,这两个股票的 DTW 距离最接近其他股价。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_02_6.jpg
图 2.6:DTW 距离热图
显示 AMZN 和 GOOG 两个时间序列之间 DTW 距离测量的线在图 2**.2中可视化展示。
-
所有股票代码的时间序列图可以通过以下代码简单地生成:
fig = px.line(yfdata, y=yftickers) fig.show()
这创建了图 2**.7:
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_02_7.jpg
图 2.7:选定的技术股价格
-
我们使用以下代码和
dtw-python
库来生成图 2**.2中的对齐图:from dtw import * alignment = dtw( yfdata['GOOG'], yfdata['AMZN'], keep_internals=True, step_pattern=rabinerJuangStepPattern(6, "c")) alignment.plot( type="twoway", offset=-2, xlab="time_index", ylab="GOOG / AMZN") alignment = dtw( yfdata['GOOG'], yfdata['META'], keep_internals=True, step_pattern=rabinerJuangStepPattern(6, "c")) alignment.plot( type="twoway", offset=-2, xlab="time_index", ylab="GOOG / META")
这结束了模式分类的简要实践介绍——更具体地说,是基于 DTW 的距离计算方法的初步步骤,应用于金融时间序列。在这一步之后,你可以继续应用 kNN 分类算法。
异常检测
在本章的最后一个实践示例中,我们将探讨应用于家庭能耗的异常检测用例。这基于ts-spark_ch2_2.dbc
中的代码,以及ts-spark_ch2_ds2.csv
中的数据集。我们将按照第一章中解释的方法,将代码导入到 Databricks 社区版中。
代码网址如下:github.com/PacktPublishing/Time-Series-Analysis-with-Spark/raw/main/ch2/ts-spark_ch2_2.dbc
代码步骤如下:
-
首先,我们导入必要的库:
from pyspark import SparkFiles from sklearn.ensemble import IsolationForest import plotly.express as px
正如本章早些时候所讨论的,Isolation Forest 是一种基于树的模型,可以用来隔离异常值。
-
使用 Spark 读取数据集:
df = spark.read.csv( "file:///" + SparkFiles.get(DATASET_FILE), header=True, sep=";", inferSchema=True )
请注意,这是与我们在第一章中使用的
spark.load()
不同但等效的语法。 -
为了进行列值的计算,我们需要将列的数据类型从字符串更改为双精度:
df = df.dropna() \ .withColumn( 'Global_active_power', df.Global_active_power.cast('double')) \ .withColumn( 'Global_reactive_power', df.Global_reactive_power.cast('double')) \ .withColumn( 'Voltage', df.Voltage.cast('double')) \ .withColumn( 'Global_intensity', df.Global_intensity.cast('double')) \
-
然后,我们选择数据集的第一部分用于训练模型:
df_train = df_pd.iloc[:35000,:]
-
然后可以创建并拟合 Isolation Forest 模型到训练数据集:
isoforest_model = IsolationForest( n_estimators=100, max_samples='auto', contamination=float(0.0025), random_state=123) isoforest_model.contamination level to specify the expected proportion of outliers in the dataset.
-
然后可以使用该模型标记完整数据集中的异常:
df_pd['anomaly_'] = isoforest_model.predict(feature_col)
-
最后,为了显示图 2**.3中的结果:
fig = px.scatter( df_pd, x='Date', y=feature_name, color='anomaly_', color_continuous_scale=px.colors.sequential.Bluered_r) fig.update_traces(marker=dict(size=3)) fig.add_vrect(x0=df_train_lastdate, x1=df_lastdate) fig.show()
这完成了使用能耗时间序列进行异常检测的实践介绍。正如本章所讨论的,Isolation Forest 方法在此处使用,但这只是众多可用方法之一。
总结
在本章中,我们重点讨论了分析时间序列数据在预测建模、趋势识别和异常检测中的实际意义。我们回顾了各行各业的实际应用,突出了时间序列分析的重要性,并且实践了两个不同领域的数据集。
在我们能够扩展这些及其他用例之前,我们需要一个额外的关键组件——Apache Spark,您将在下一章中了解它。
进一步阅读
本节作为一个资料库,汇集了可以帮助您加深对该主题理解的资源:
-
《时间序列分析 - 数据、方法与应用》,由 Chun-Kit Ngan 编著:
www.intechopen.com/books/8362
-
金融服务:
-
《金融应用中的时间序列基础》(Massimo Guidolin 和 Manuela Pedio 著):
www.sciencedirect.com/book/9780128134092/essentials-of-time-series-for-financial-applications
-
《银行变量的时间序列预测技术》(Arindam Bandyopadhyay 著):
academic.oup.com/book/43110/chapter-abstract/361614151?redirectedFrom=fulltext&login=false
-
-
零售业:
-
《基于时间序列分析的零售店盈利预测模型》(Sridevi U. K. 和 Shanthi P 著):
www.researchgate.net/publication/325882164_A_profit_prediction_model_with_time_series_analysis_for_retail_store
-
《零售销售预测的比较研究》(Hasan 等,2022):
arxiv.org/pdf/2203.06848.pdf
-
-
医疗保健:
-
《医疗领域的人工智能:使用统计、神经网络和集成架构进行时间序列预测》(Kaushik 等,2020):
www.frontiersin.org/articles/10.3389/fdata.2020.00004/full
-
《聚焦心血管疾病的医疗诊断和预后时间序列预测》(Bui 等,2018):
www.researchgate.net/publication/320002542_Time_Series_Forecasting_for_Healthcare_Diagnosis_and_Prognostics_with_the_Focus_on_Cardiovascular_Diseases
-
-
制造业 与公用事业:
-
《工业 4.0 中的时间序列预测:全面综述及未来发展展望》(Kashpruk 等,2023):
www.mdpi.com/2076-3417/13/22/12374
-
《智能制造系统中的时间序列模式识别:文献综述与本体分析》(Farahani 等,2023):
www.sciencedirect.com/science/article/pii/S0278612523000997
-
从智能电表数据测量家庭活动的能量强度(Stankovic 等人,2016 年):
www.sciencedirect.com/science/article/pii/S0306261916313897
-
-
库:
-
FastDTW:
cs.fit.edu/~pkc/papers/tdm04.pdf
-
dtw-python:
dynamictimewarping.github.io/python/
-
加入我们的 Discord 社区
加入我们社区的 Discord 空间,与作者和其他读者进行讨论:
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/ds_(1.jpg)
第三章:Apache Spark 简介
本章概述了 Apache Spark,解释了它的分布式计算能力以及处理大规模时间序列数据的适用性。它还解释了 Spark 如何解决并行处理、可扩展性和容错性的问题。这些基础知识非常重要,因为它为利用 Spark 在处理庞大的时间数据集时的优势奠定了基础,从而促进了高效的时间序列分析。了解 Spark 的作用,可以增强从业人员利用其强大计算能力的能力,使其成为可扩展、高性能时间序列应用的宝贵资源。
我们将覆盖以下主要内容:
-
Apache Spark 及其架构
-
Apache Spark 是如何工作的
-
Apache Spark 的安装
技术要求
本章的动手部分将着重于部署一个多节点的 Apache Spark 集群,以帮助熟悉部署过程中的重要组件。本章的代码可以在本书 GitHub 仓库的ch3
文件夹中找到,网址为:https://github.com/PacktPublishing/Time-Series-Analysis-with-Spark/tree/main/ch3。
本章的动手实践部分将进一步详细介绍这一过程。此过程需要一些搭建开源环境的技能。如果你不打算搭建自己的 Apache Spark 环境,而是专注于时间序列并使用 Spark(而不是部署它),你可以跳过本章的动手部分。你可以使用像 Databricks 这样的托管平台,它预先构建了 Spark,我们将在未来的章节中使用该平台。
什么是 Apache Spark?
Apache Spark 是一个分布式计算系统,它是开源的,具有编程接口和用于大规模并行数据处理的集群,并且具备容错能力。Spark 最初作为伯克利 AMPLab 的一个项目启动于 2009 年,并于 2010 年成为 Apache 软件基金会的一部分,开源发布。Spark 的原始创始人后来成立了 Databricks 公司,提供基于其多云平台的托管版 Spark。
Spark 可以处理批处理和流处理,使其成为大数据处理中的一个广泛适用的工具。相较于现有的大数据系统,Spark 通过内存计算和优化的查询执行实现了显著的性能提升,能够对任何规模的数据进行非常快速的分析查询。它基于弹性分布式数据集(RDDs)和数据框架(DataFrames)的概念构建。这些是分布在计算机集群中的数据元素集合,能够并行操作并具备容错能力。在本章的其余部分,我们将进一步扩展这些概念。
为什么使用 Apache Spark?
使用 Spark 有许多优势,这也是其作为大规模数据处理解决方案受欢迎的原因,正如图 3.1所示,这一趋势基于 Google 趋势数据。我们可以看到,Apache Spark 软件在大数据话题上的兴趣不断增加,而 Hadoop 软件的趋势在 2017 年 3 月被 Apache Spark 软件超越后开始下降。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_03_1.jpg
图 3.1:与 Hadoop 和大数据相比,Apache Spark 的兴趣不断增加
这一兴趣激增可以通过一些关键优势来解释,具体如下:
-
速度:与非 Spark Hadoop 集群相比,Spark 在内存中运行速度可快达 100 倍,甚至在磁盘上运行时也能快达 10 倍。
-
容错性:通过使用分布式计算,Spark 提供了一个容错机制,能够在故障发生时进行恢复。
-
模块化:Spark 支持 SQL 和结构化数据处理、机器学习、图处理和流数据处理。凭借各种任务的库,Spark 能够处理广泛的数据处理任务。
-
可用性:Spark 提供了 Python、Java、Scala 和 R 等 API,以及 Spark Connect,能够让广泛的开发者和数据科学家使用。
-
兼容性:Spark 可以在不同平台上运行——包括 Databricks、Hadoop、Apache Mesos 和 Kubernetes,独立运行或在云端。它还可以访问各种数据源,相关内容将在接口和 集成部分中讨论。
Spark 日益流行以及其背后的诸多优势,是经过多年的演变而来的,接下来我们将进行回顾。
演变历程
Apache Spark 多年来经历了几次演进,以下是主要的版本发布:
-
1.x:这些是 Spark 的早期版本,起初基于 RDD 和一些分布式数据处理能力。
-
2.x:Spark 2.0(2016 年)引入了 Spark SQL、结构化流处理和 Dataset API,相比 RDD 更加高效。
-
3.x:自 2020 年起,Spark 3.0 进一步改进,增加了自适应查询执行(AQE),该功能根据运行时统计数据动态调整查询计划,增强了性能优化,并进行了动态分区剪枝。同时,新增对更新版本 Python 的支持,以及对机器学习 库(MLlib)的扩展。
截至目前,最新版本为 3.5.3。为了了解项目的未来发展方向,接下来我们将聚焦于一些最新版本的亮点,具体如下:
-
PySpark为 Python 类型提示提供了用户友好的支持,支持在 Spark 上的 pandas API,并通过优化提升了性能。
-
自适应查询执行(Adaptive Query Execution)的改进促进了更高效的查询执行和资源利用。
-
结构化流处理的改进提升了稳定性和性能。
-
Kubernetes 支持更好的集成和资源管理能力,用于在 Kubernetes 上运行 Spark。这带来了更高的效率和易用性。
-
API 和 SQL 的增强带来了更高效的数据处理和分析,新功能和现有功能的改进提升了效率。这里的关键主题是更好的可用性和性能。
从前述内容可以看出,最近的关注点主要集中在对现代基础设施的支持、性能和可用性上。作为一个大规模数据处理和分析的工具,这使得 Spark 成为一个更加广泛采用的工具。
Spark 的分发版
随着其流行度和广泛的应用,Spark 出现了多个分发版。这些分发版由不同的组织开发,Apache Spark 作为核心,提供了不同的集成能力、可用性特性和功能增强。与其他大数据工具捆绑在一起的这些分发版,通常提供改进的管理界面、增强的安全性以及不同的存储集成。
以下是最常见的分发版:
-
Apache Spark是由 Apache 软件基金会维护的原始开源版本,是其他分发版的基础。
-
Databricks Runtime是由 Databricks 公司开发的,这家公司由 Spark 的创始人创建。它针对云环境进行了优化,提供了一个统一的分析平台,促进了数据工程师、数据科学家和业务分析师之间的协作。Databricks 提供了经过优化的 Spark 性能,采用了 C++重写的版本Photon,互动笔记本,集成的数据工程工作流(包括Delta Live Tables(DLT)),以及与 MLflow 的机器学习支持,且作为其基于 Unity Catalog 的治理功能的一部分,提供企业级的合规性和安全性。
-
Cloudera Data Platform(CDP)将 Spark 作为其数据平台的一部分,平台中还包含了 Hadoop 和其他大数据工具。
-
Hortonworks Data Platform(HDP)在与 Cloudera 合并之前,提供了其自有的分发版,其中包括 Spark。
-
Microsoft Azure将 Spark 作为Azure Databricks的一部分,后者是 Azure 上的第一方服务,此外还包括 HDInsight、Synapse,以及未来的 Fabric。
-
Amazon Web Services(AWS)在其市场中提供 Databricks,以及作为云服务运行的Elastic MapReduce(EMR),可在 AWS 上运行如 Apache Spark 等大数据框架。
-
Google Cloud Platform(GCP)托管了 Databricks,以及Dataproc,这是 Google 为 Apache Spark 和 Hadoop 集群提供的云端托管服务。
从本地解决方案到云原生解决方案,再到与其他数据平台集成的解决方案,每种 Apache Spark 的分发版都能满足不同的需求。当组织选择分发版时,通常考虑的因素包括性能要求、管理的简便性、现有的技术栈以及每个分发版所提供的特定功能。
在了解了 Apache Spark 的基本概念、优势和演变之后,让我们深入探讨它的架构和组件。
Apache Spark 架构
使用 Apache Spark 架构的主要目标是跨分布式集群处理大规模数据集。架构可以根据应用的具体需求而有所不同,无论是批处理、流处理、机器学习、报告查询,还是这些需求的组合。一个典型的 Spark 架构包括多个关键组件,这些组件共同满足数据处理需求。此类架构的示例可见于 图 3.2。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_03_2.jpg
图 3.2:基于 Apache Spark 的架构示例(独立模式)
现在让我们深入探讨一下这些部分的具体功能。
集群管理器
集群管理器负责将资源分配给集群,集群是 Spark 工作负载执行的操作系统环境。包括以下几种:
-
独立模式:Spark 附带一个基本的集群管理器,使得搭建集群并开始使用变得容易。这个集群管理器节点也被称为主节点:
-
Kubernetes:Spark 可以部署到 Kubernetes 上,Kubernetes 是一个开源的基于容器的系统,能够自动化容器化应用的部署、管理和扩展。
-
Apache Mesos:作为集群管理器,Mesos 支持 Spark,同时也能运行 Hadoop MapReduce。
-
Hadoop YARN:在与 YARN 一起运行时,Spark 可以与其他 Hadoop 组件共享集群和数据集。
-
专有和商业:将 Spark 融入的解决方案通常有自己的集群管理器——通常是对先前开源版本的变种和改进。
接下来,我们将查看这些 Spark 集群中的内容。
Spark Core、库和 API
一旦集群管理器提供了一个或多个集群,Spark Core 就会管理内存和故障恢复,以及与 Spark 作业相关的所有事务,如调度、分配和监控。Spark Core 抽象了存储的读写,使用 RDD 和最近的 DataFrame 作为数据结构。
在(并与之紧密合作)Core 的基础上,多个库和 API 提供了针对数据处理需求的附加功能。这些功能包括:
-
Spark SQL 允许通过 SQL 查询结构化数据。
-
Spark Structured Streaming 处理来自各种来源的数据流,例如 Kafka 和 Kinesis。
-
MLlib 提供多种机器学习算法,支持分类、回归、聚类等任务。
-
GraphX 允许使用图算法来创建、转换和查询图。
Spark 涉及数据处理,因此,解决方案中的一个重要部分是数据结构,接下来我们将讨论这个部分。
RDD、DataFrame 和数据集
自本章开始以来,我们提到了几次 RDD 和 DataFrame,但没有详细说明,现在我们将对此进行详细讲解,并引入 Datasets。
简而言之,这些是内存中的数据结构,表示数据并为我们提供了一种程序化的方式,正式来说,这是一种抽象,来操作数据。每种数据结构都有其适用的场景,如下所示:
-
RDD是 Spark 的基本数据结构。它是不可变的和分布式的,可以在集群内存中存储数据。具有容错性,RDD 可以自动从故障中恢复。需要注意的是,在集群内存不足的情况下,Spark 确实会将部分 RDD 存储到磁盘上,但由于这一过程是由后台管理的,因此我们仍然将 RDD 视为存在内存中。
随着越来越多操作变得可以通过更易用的 DataFrame 实现,你将越来越不可能使用 RDD,我们接下来将看到这一点。RDD 更适合进行低级转换,直接操作数据,当你需要对计算进行低级控制时,它们非常有用。
-
DataFrame是建立在 RDD 之上的分布式数据集合,具有命名的列。这类似于关系数据库中的表。除了更易用的高级 API,使代码更加简洁易懂外,DataFrame 还因为 Spark 的 Catalyst 优化器的支持,相较于 RDD 在性能上有了提升,我们将在本章后面讨论这一点。
在之前的动手练习中,我们已经开始使用 DataFrame。你可能已经注意到在做练习时,除了 Spark DataFrame,还有 pandas DataFrame。虽然在概念上它们类似,但它们属于不同的库,底层实现有所不同。从根本上讲,pandas DataFrame 运行在单台机器上,而 Spark DataFrame 是分布式的。pandas DataFrame 可以转换为 pandas-on-Spark DataFrame,除了并行化的优势外,还能支持 pandas DataFrame API。
-
Dataset结合了 RDD 的类型安全性和 DataFrame 的优化。类型安全性意味着你可以在编译时捕捉数据类型错误,从而提高运行时的可靠性。然而,这取决于编程语言是否支持在编码时定义数据类型,并在编译时进行验证和强制执行。因此,Dataset 仅在 Scala 和 Java 中得到支持,而 Python 和 R 由于是动态类型语言,只能使用 DataFrame。
总结来说,RDD 提供低级控制,DataFrame 提供优化后的高级抽象,而 Dataset 则提供类型安全。选择使用哪种数据结构取决于你应用的具体需求。
到目前为止,我们讨论了内部组件。接下来,我们将探讨外部接口部分,介绍 Spark 如何在后端与存储系统集成,并在前端与应用和用户交互。
接口与集成
在考虑与环境的接口和集成时,有几种方法可以通过 Apache Spark 实现。这些方法如下:
-
csv
、json
、xml
、orc
、avro
、parquet
和protobuf
。其中,Parquet 是最常见的格式,因为它在使用 snappy 压缩时提供了良好的性能。此外,Spark 可以通过扩展包来支持多种存储协议和外部数据源。Delta 就是其中之一,我们将在第四章和第五章中进一步讨论。其他格式包括 Iceberg 和 Hudi。请注意,我们这里讨论的是数据的磁盘表示形式,这些数据会被加载到之前讨论的基于内存的 RDD 和 DataFrame 数据结构中。我们已经通过目前为止的实践演练,积累了一些关于 Spark 和存储的经验,在这些演练中,我们已经从 Databricks Community Edition 的 Spark 集群读取了本地存储中的 CSV 文件。
-
应用程序:这是包含数据处理逻辑的代码,调用 Spark API 和库来执行数据变换、流处理、SQL 查询或机器学习等任务。开发人员可以使用 Python、R、Scala 或 Java 编写代码。然后,这些代码会在 Spark 集群上执行。
我们在应用程序方面的经验也已经开始,通过到目前为止的实践代码。
-
平台用户界面:除了我们在实践演练中看到的 Databricks Community Edition 的 Web 界面,开源 Apache Spark 还提供一个 Web 用户界面(UI),用于监控集群和 Spark 应用程序。它提供作业执行的阶段、资源使用情况和执行环境的洞察。其他集成了 Apache Spark 的数据平台也有自己的 UI。
-
应用程序终端用户界面:另一种 UI 是用于终端用户消费 Apache Spark 处理结果的界面。这可以是报告工具,或者例如在后端使用 Apache Spark 进行数据处理的应用程序。
在本节关于 Apache Spark 架构的内容中,我们看到架构如何支持从各种来源将数据引入 Spark 系统,通过 Spark 的库进行处理,然后将结果存储或提供给用户或下游应用程序。所选架构依赖于需求,如延迟、吞吐量、数据大小以及数据处理任务的复杂性和类型。在下一节中,我们将重点讨论 Spark 如何在大规模上执行分布式处理。
Apache Spark 的工作原理
迄今为止,我们已经查看了各个组件及其角色,但对它们的交互了解还不多。接下来我们将讨论这一部分,以了解 Spark 如何在集群中管理分布式数据处理,从变换和操作开始。
变换和操作
Apache Spark 在高层次上执行两种类型的数据操作:
-
filter
和groupBy
。 -
count
和save
类型的操作,如写入 Parquet 文件或使用saveAsTable
操作。Action 操作触发所有在 DAG 中定义的变换的执行,这导致 Spark 计算一系列变换的结果。
变换和动作之间的区别是编写高效 Spark 代码时需要考虑的重要问题。这使得 Spark 能够利用其执行引擎高效地处理作业,接下来将进一步解释。
作业、阶段和任务
Spark 应用程序作为作业执行,作业被拆分为多个阶段,再进一步拆分为多个任务,具体如下:
-
作业:当在 RDD、DataFrame 或 Dataset 上调用 Action 时,Spark 会提交一个作业。作业会转化为一个包含多个阶段的物理执行计划,接下来我们会解释这些阶段。Spark 作业的目的是作为逻辑工作单元执行一系列计算步骤,以实现特定目标,比如聚合数据或排序,并最终生成输出。
-
阶段:一个作业可以有多个阶段,这些阶段在物理执行计划中定义。阶段是一组连续的任务,可以在不跨集群移动数据的情况下完成。阶段之间的数据移动称为洗牌(shuffle)。将作业拆分为多个阶段是有益的,因为洗牌在性能上开销较大。一个阶段进一步被拆分为任务,接下来我们将讨论任务。
-
任务:作为最小的处理单元,任务是在 Spark 内存中的数据分区上执行的单个操作。每个任务处理不同的数据集,并且可以与其他任务并行运行。这些任务在工作节点上运行,接下来我们将讨论工作节点。
总结来说,作业、阶段和任务是层级相关的。Spark 应用程序可以有多个作业,这些作业基于数据洗牌边界被划分为多个阶段。阶段进一步细分为任务,这些任务在集群的不同分区上并行运行。这样的执行层级使得 Spark 能够高效地将工作负载分配到集群的多个节点,从而在大规模数据处理时提高效率。
现在我们已经了解了处理单元,接下来的问题是如何在计算资源上运行这些单元,包括驱动程序和工作节点。
驱动程序和工作节点
驱动程序和工作节点是集群管理器创建的计算资源,用于组成一个 Spark 集群。它们协同工作,利用多台机器的资源并行处理大数据集。
让我们详细讨论这些资源:
-
驱动节点:驱动节点是 Spark 应用程序的主进程运行的地方,主要负责以下任务:
-
资源:驱动程序请求集群管理器分配资源,以便在工作节点上运行进程。
-
SparkSession:这是一个由驱动程序创建的对象,用于以编程方式访问 Spark 并在集群上进行数据处理操作。
-
任务:驱动节点将代码转化为任务,调度任务到工作节点上的执行器,并管理任务的执行。
-
-
工作节点:工作节点是数据处理的核心,数据通过所谓的执行器进程在工作节点上处理。执行器与存储交互,并将数据保存在自己的内存空间中,同时拥有自己的一组 CPU 核心。任务由驱动节点调度到执行器上执行,驱动节点与执行器之间直接通信,传递任务状态和结果。
驱动节点和工作节点的交互:图 3.3 总结了驱动节点和工作节点之间的交互顺序。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_03_3.jpg
图 3.3:驱动节点和工作节点的工作示意图
步骤如下:
-
初始化:当 Spark 应用程序启动时,驱动程序将作业转换为阶段,并进一步拆分为任务。
-
调度:驱动节点在工作节点的执行器上调度任务,跟踪任务状态,并在发生故障时重新调度。
-
执行:驱动节点分配的任务由工作节点上的执行器运行。此外,当数据需要在执行器之间传递时,驱动节点协调执行器之间的操作。这对于某些操作(如联接)是必需的。
-
结果:最终,执行器处理任务的结果被发送回驱动节点,驱动节点汇总结果并将其发送回用户。
驱动节点和工作节点之间的这种协作过程是 Spark 的核心,它使得数据处理能够在集群中并行进行,并能够处理容错问题。
现在我们已经了解了 Spark 集群的工作原理,让我们深入探讨是什么使它更加高效和优化。
Catalyst 优化器和 Tungsten 执行引擎
到目前为止,我们已经讨论了在不同版本中对 Apache Spark 的持续改进,其中两个显著的改进是 Catalyst 优化器和 Tungsten 执行引擎。它们在确保 Spark 过程优化、快速执行时间和高效资源利用方面发挥着关键作用。
Catalyst 优化器
Catalyst 优化器是在 Spark SQL 中引入的一个查询优化框架,通过对查询的 抽象语法树(AST)进行树形转换,显著提高了查询性能。它通过多个阶段实现优化,具体如下:
-
分析:查询被转化为一个名为逻辑计划的操作符树。
-
逻辑优化:优化器使用基于规则的转换来优化逻辑计划。
-
物理规划:逻辑计划被转换为物理计划,物理计划是基于选择的算法来进行查询操作的。
-
成本模型:然后基于成本模型比较物理计划,以找到在时间和资源上最有效的计划。
-
代码生成:作为最终阶段,物理计划被转换为可执行代码。
通过这些阶段,Catalyst 优化器确保运行最具性能和效率的代码。
Tungsten 执行引擎
另一个关注点是 Spark 进程对 CPU 和内存的高效利用。Tungsten 执行引擎通过以下方式实现这一目标:
-
代码生成:Tungsten 与 Catalyst 优化器协作,生成优化且紧凑的代码,从而减少运行时开销,同时最大化速度。
-
缓存意识:减少缓存未命中可以提高计算速度。Tungsten 通过使算法和数据结构具备缓存意识来实现这一点。
-
内存管理:Tungsten 高效管理内存,提高了缓存的影响力,同时减少了垃圾回收的开销。
Catalyst 优化器与 Tungsten 执行引擎共同合作,通过优化查询计划、生成高效代码以及减少计算开销,显著提高了 Spark 的性能。这提升了 Spark 在大数据处理中的效率,且具备可扩展性和高速性。
现在我们已经了解了 Apache Spark 的工作原理,接下来将介绍如何设置我们自己的 Spark 环境。
安装 Apache Spark
到目前为止,在前面的章节中,我们已成功在 Databricks Community Edition 上执行了 Spark 代码。然而,这仅限于单节点集群。如果我们希望充分利用 Spark 的并行处理能力,就需要多节点集群。我们可以选择使用 Databricks 管理的平台即服务(PaaS)云解决方案,或其他等效的云 PaaS,或者我们可以构建自己的 Apache Spark 平台。这正是我们现在要做的,按照图 3.2中展示的Apache Spark 架构来部署环境。
注意
如果您不打算构建自己的 Apache Spark 环境,可以跳过本节的实践部分,改为使用受管 Spark 平台,如 Databricks,我们将在未来的章节中使用。
使用容器进行部署
我们可以直接在本地机器上安装 Apache Spark,但这将只给我们一个节点。通过将其部署在容器中,如 Docker,我们可以在同一台机器上运行多个容器。这有效地为我们提供了一种方法来构建一个多节点集群。这种方法的其他优势包括与本地执行环境的隔离,以及提供一种可移植且可重复的方式,将其部署到其他机器上,包括如 Amazon 弹性 Kubernetes 服务(EKS)、Azure Kubernetes 服务(AKS)或Google Kubernetes 引擎(GKE)等基于云的容器服务。
在接下来的部分中,我们将使用 Docker 容器,首先安装 Docker,然后构建并启动包含 Apache Spark 的容器,最后验证我们的部署。
Docker 替代方案
您可以使用 Podman 作为 Docker 的开源替代方案。请在此查看更多信息:podman.io/
。
Docker
以下说明指导你如何安装 Docker:
-
请参考以下链接,根据你的操作系统下载并安装 Docker:
对于 macOS 用户,请按照此处的说明操作:
-
一旦 Docker 安装完成,按图 3.4所示启动它。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_03_4.jpg
图 3.4:Docker Desktop
在 macOS 上,你可能会看到 Docker Desktop 的警告:“另一个应用程序更改了你的桌面配置”。根据你的设置,以下命令可能解决此警告:
ln -sf /Applications/Docker.app/Contents/Resources/bin/docker-credential-ecr-login /usr/local/bin/docker-credential-ecr-login
一旦 Docker Desktop 启动并运行,我们可以使用 Apache Spark 构建容器。
网络端口
以下网络端口需要在本地机器或开发环境中可用:
-
Apache Spark:
7077
,8080
,8081
-
Jupyter Notebook:
4040
,4041
,4042
,8888
你可以使用以下命令检查当前端口是否被现有应用程序占用,在命令行或终端中运行:
% netstat -an | grep LISTEN
如果你在已使用端口的列表中看到所需端口,你必须停止使用该端口的应用程序,或者修改docker-compose
文件以使用其他端口。
作为示例,假设上述netstat
命令的输出显示本地机器或开发环境中的端口8080
已经在使用,并且你无法停止正在使用该端口的现有应用程序。
在这种情况下,你需要将docker-compose.yaml
文件中用于 Apache Spark 的端口8080
更改为另一个未使用的端口。只需在:
左侧查找并替换8080
为例如8070
,前提是该端口未被占用,如以下示例所示:
-
来自:
ports: - '7077:7077' - '8080:8080'
-
到:
ports: - '7077:7077' - '8070:8080'
记下新端口,并在需要输入相应 URL 时使用此端口替代现有端口。在此示例中,端口8080
已更改为8070
,Airflow Web 服务器的匹配 URL 变更如下:
注意
你需要更改以下各节中所有需要修改的 URL 中的网络端口,以配合本节内容。
构建并部署 Apache Spark
以下说明指导你如何构建和部署 Docker 镜像:
-
我们首先从本章的 Git 仓库下载部署脚本,网址如下:
github.com/PacktPublishing/Time-Series-Analysis-with-Spark/tree/main/ch3
我们将使用适合 git 克隆的 URL,具体如下:
github.com/PacktPublishing/Time-Series-Analysis-with-Spark.git
要做到这一点,启动终端或命令行并运行以下命令:
git clone https://github.com/PacktPublishing/Time-Series-Analysis-with-Spark.git cd Time-Series-Analysis-with-Spark/ch3
请注意,上述命令适用于 macOS 或基于 Linux/Unix 的系统,您需要运行适用于 Windows 的等效命令。
-
在 macOS 上,当您运行此命令时,可能会看到以下错误:
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
在这种情况下,您需要使用以下命令重新安装命令行工具:
xcode-select --install
-
现在我们可以开始容器的构建和启动。提供了一个 Makefile 来简化启动和停止容器的过程。以下命令构建容器的 Docker 镜像并启动它们:
make up
Windows 环境
如果您使用的是 Windows 环境,可以根据以下文档安装 Windows 版本的 Make:gnuwin32.sourceforge.net/packages/make.htm
这将产生以下或等效的输出:
docker-compose up -d
[+] Running 4/4
...
✔ Container ts-spark-env-spark-master-1 Started
✔ Container ts-spark-env-jupyter-1 Started
✔ Container ts-spark-env-spark-worker-1-1 Started
✔ Container ts-spark-env-ts-spark-env-spark-master-1), which is where the cluster manager runs, and two worker nodes (ts-spark-env-spark-worker-1-1 and ts-spark-env-spark-worker-2-1). In addition, there is a separate node (ts-spark-env-jupyter-1) for a notebook environment, called Jupyter Notebook, similar to what you have used in the previous chapters on Databricks Community Edition. In this deployment, this Jupyter node is also the driver node.
Let’s now validate the environment that we have just deployed.
Accessing the UIs
We will now access the UIs of the different components as a quick way to validate the deployment:
1. We start with Jupyter Notebook at the following local URL: [`localhost:8888/lab`](http://localhost:8888/lab)
Note
You will need to change the network port in the preceding URL if you need to modify it as discussed in the *Network* *ports* section.
This will open the web page as per *Figure 3**.5*.
<https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_03_5.jpg>
Figure 3.5: Jupyter Notebook
1. The next (and important) UI is for the Apache Spark master node, accessible via the following local URL: [`localhost:8080/`](http://localhost:8080/)
*Figure 3**.6* shows this master node UI, as well as the worker nodes connected.
<https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_03_6.jpg>
Figure 3.6: Spark master node UI
We now have our own Apache Spark cluster running.
As a final step to conclude this chapter, you can stop the containers with the following command:
make down
If you do not intend to use it further, you can additionally delete the Docker containers created with the Delete action as explained here: [`docs.docker.com/desktop/use-desktop/container/#container-actions`](https://docs.docker.com/desktop/use-desktop/container/#container-actions)
Summary
In this chapter, we dove deep into the Apache Spark architecture, its key components, and its features. The key concepts, how it works, and what makes it such a great tool were explained. We then deployed a multi-node cluster representing an example architecture. The concepts presented in this chapter, while essential, cover only a part of an Apache Spark project. We will view such a project end to end in the next chapter.
Further reading
This section serves as a repository of sources that can help you build on your understanding of the topic:
* Apache Spark official web page: [`spark.apache.org/`](https://spark.apache.org/)
* *Mastering Apache Spark* (Packt Publishing) by Timothy Chen, Mike Frampton, and Tim Seear
* *Azure Databricks Cookbook* (Packt Publishing) by Phani Raj and Vinod Jaiswal
* Google Trends comparison: [`trends.google.com/trends/explore?date=2009-01-01%202024-08-28&q=%2Fm%2F0bs2j8q,%2Fm%2F0ndhxqz,%2Fm%2F0fdjtq&hl=en`](https://trends.google.com/trends/explore?date=2009-01-01%202024-08-28&q=%2Fm%2F0bs2j8q,%2Fm%2F0ndhxqz,%2Fm%2F0fdjtq&hl=en)
* Cluster Overview: [`spark.apache.org/docs/latest/cluster-overview.html`](https://spark.apache.org/docs/latest/cluster-overview.html)
* Spark Connect: [`spark.apache.org/docs/latest/spark-connect-overview.html`](https://spark.apache.org/docs/latest/spark-connect-overview.html)
* Docker Compose: [`docs.docker.com/compose/`](https://docs.docker.com/compose/)
* Make and Makefile: [`www.gnu.org/software/make/manual/make.html`](https://www.gnu.org/software/make/manual/make.html)
* Jupyter: [`jupyter.org/`](https://jupyter.org/)
Join our community on Discord
Join our community’s Discord space for discussions with the authors and other readers:
[`packt.link/ds`](https://packt.link/ds)
<https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/ds_(1>.jpg)
第二部分:从数据到模型
在此基础上,本部分将提供时间序列分析项目中涉及的所有阶段的整体视图,重点关注数据和模型。从时间序列数据的导入和准备开始,我们将进行探索性分析,以了解时间序列的性质。数据准备和分析将引导我们选择用于分析、开发和测试的模型。
本部分包含以下章节:
-
第四章,时间序列分析项目的端到端视图
-
第五章,数据准备
-
第六章,探索性数据分析
-
第七章,构建与测试模型
第四章:时间序列分析项目的端到端视角
在前几章中,我们介绍了时间序列分析及其多个应用场景,以及 Apache Spark——作为这种分析的关键工具——的基础,本章将引导我们完成整个时间序列分析项目的过程。从用例出发,我们将过渡到涵盖 DataOps、ModelOps 和 DevOps 的端到端方法。我们将涵盖关键阶段,如数据处理、特征工程、模型选择和评估,并提供关于如何使用 Spark 和其他工具构建时间序列分析管道的实用见解。
这种全面的时间序列分析项目视角将为我们提供一种结构化的方法,帮助我们处理现实世界的项目,增强我们实施端到端解决方案的能力。这里的信息将为我们提供一个框架,帮助我们以一致的方式使用 Spark,并确保时间序列分析项目的成功执行。我们将以两种实施方法作为结尾。
本章将涵盖以下主题:
-
由用例驱动
-
从 DataOps 到 ModelOps 再到 DevOps
-
实施示例与工具
让我们开始吧!
技术要求
本章的实操部分将是实现时间序列分析项目的端到端示例。该章节的代码可以在 GitHub 仓库中的 ch4
文件夹找到,链接如下:
github.com/PacktPublishing/Time-Series-Analysis-with-Spark/tree/main/ch4
本章的实操部分(实施示例与工具)将进一步详细说明。这需要一些构建开源环境的技能。如果你不打算构建自己的 Apache Spark 环境,且关注点仅在于时间序列分析并使用 Spark 和其他工具,而不是部署它们,那么你可以跳过本章的实操部分。你可以使用像 Databricks 这样的托管平台,它预装了 Spark、MLflow 以及用于工作流和笔记本的工具,正如我们在未来章节中所做的那样。
由用例驱动
在我们深入讨论如何进行端到端时间序列分析项目之前,像往常一样,先从为什么开始总是一个好的选择。可能有许多原因,通常是多种原因的组合,来证明启动时间序列分析项目的必要性。以下是一些原因:
-
技术更新:强调技术的原因可能是由于老化的平台需要替换,且无法再满足需求,或当有新技术出现,提供更好的性能、更低的成本或更多的功能,如高级机器学习模型或可扩展的云资源。
-
方法研究:对于专注于研究的组织或部门,主要驱动力是寻找新的、更好的方法,比如开发和测试用于分析时间序列的新算法。
-
数据探索:与研究类似,但需要更接近数据,这通常嵌入在企业的数据团队中。这里的需求是理解时间序列数据,而不一定需要预先定义的应用目标。其目的是发现数据中的模式、趋势和异常。
-
用例:在这种方法中,我们从结果出发,首先识别最终用户或相关方的具体需求和期望。然后,我们基于时间序列数据分析来设置项目,以回答这些需求。
尽管之前提到的所有理由都有其合理性,并且无疑是有效的,但多年来,我发现以业务驱动的用例方法在投资回报方面是最高的。我们在第二章中已经开始讨论基于时间序列的用例,涵盖了各个行业的应用场景,如库存预测、能源使用预测、金融市场趋势分析或传感器数据中的异常检测;在这里,我们将重点关注这种用例驱动的方法,并进一步探讨。
用例方法首先识别并定义现实世界中具体的业务应用或挑战。接着,选择最适合解决这些需求的技术方案。乍一看,这与任何商业环境中的项目似乎并无太大不同。这里的关键区别在于“具体”一词,用例方法强调的是具体、可衡量的业务成果。这遵循精益方法,因为我们希望避免那些无法为业务成果做出贡献的功能。
用例可以与敏捷软件开发方法中的用户故事进行对比。事实上,敏捷方法通常是实现用例的方式,通过简化的迭代开发过程,始终涉及用户的参与。
以下图 4.1概述了基于迄今为止讨论内容的用例驱动方法,包括它们的关键特征。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_1.jpg
图 4.1:用例驱动方法
现在我们已经定义了用例驱动的方法,接下来我们将介绍这一方法的关键特征,如下所示:
-
业务成果:项目的成功通过业务指标来衡量,具体包括提高收入、降低成本、提升效率以及更好、更快速的决策制定。
-
以用户为中心:从一开始就与最终用户和相关方合作,明确他们的具体需求,项目目标除了回答这些需求外,还包括前述的业务成果。
-
具体:我们已经讨论过这个词几次。项目的具体性为其范围提供了明确的方向,使得执行更加灵活。我们希望解决一个具体的需求,例如销售预测,这个需求甚至可以更为细化,比如为特定产品线或区域进行预测。
-
迭代性:涉及最终用户和利益相关者的反馈和改进循环确保项目保持正轨,满足预期的商业成果。这再次强调了与敏捷方法的相似性,其短开发周期、增量交付、持续反馈和适应性。
遵循这些特征,确保用例范围足够小,能够在几个月内(如果不是几周的话)实现并带来价值。这些较小的用例通常意味着它们在开发资源上并行竞争。这就需要优先排序,以确保资源得到合理投资。以下标准通常用于优先排序用例:
-
影响力:这是用例预期商业影响的衡量标准,最好用货币价值来计算。如果结果是时间的减少,则需估算时间节省的等值货币价值。
-
成本:我们需要计算与用例相关的所有成本,从用例构想到用例上线并为业务带来价值的整个过程。成本可能与开发、基础设施、迁移、培训、支持和生产运营相关。
-
投资回报率(ROI):这可以通过将影响力除以成本来简单估算。例如,对于一家希望更好地预测店铺库存的零售商,如果将库存预测用例投入生产的总成本为 50 万美元,而库存预测改进预计将带来三年 200 万美元的节省,则在此期间 ROI 为 4 倍。
-
技术可行性:用例的技术解决方案存在,并且能够在时间和预算内实现。
-
数据可用性和可访问性:数据可用且可访问,用以构建用例并将其投入运营。
根据前述标准,在资源竞争的情况下,具有高影响力、投资回报率(ROI)为 10 倍、可行且已有数据的用例,应优先于另一个影响较小、ROI 为 3 倍或没有数据访问的用例。
总结来说,从清晰理解用户需求开始,基于用例的项目确保了与业务的适用性和相关性,紧密对接利益相关者的目标,并能量化影响。然而,拥有一个好的用例仅仅是开始。接下来,我们将深入探讨从用例到成功完成时间序列分析项目、并实现商业成果的下一步。
从 DataOps 到 ModelOps 再到 DevOps
一旦确定了一个重要的用例,一些阶段发挥着至关重要的作用,从数据操作(DataOps)到模型操作(ModelOps),最后到部署(DevOps),将业务环境中的价值传递到实际应用中。一个覆盖这些阶段的完整端到端过程确保了我们可以持续地从一个用例交付到下一个,同时确保结果的可重复性。图 4.2概述了这些阶段,接下来将在本节中详细介绍。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_2.jpg
图 4.2:DataOps、ModelOps 和 DevOps
DataOps
DataOps 在时间序列分析项目中的应用包括最佳实践和过程,确保时间序列数据在生命周期中的流动、质量和访问。其目标是及时、高效且准确地进行时间序列分析和建模,从而得出可操作的业务洞察。
DataOps 实践涵盖完整的数据和元数据生命周期,通常可以分为数据源集成、数据处理、数据治理和数据共享。
来源集成
数据源集成首先涉及识别数据源并获取访问权限,然后从源中摄取数据。
数据来源可以是内部的或外部的。内部数据来源主要是数据库,例如交易记录、系统日志或用于遥测的传感器数据。外部数据来源包括市场数据、天气数据或社交媒体数据,而后者现在正成为主流。不同领域的数据来源在数据量、更新频率和数据格式上差异巨大。一旦确定并访问了数据来源,数据摄取就是将数据引入平台进行处理的过程。通常通过自动化的数据摄取管道来实现,按照特定的频率(每小时、每天等)批量运行或持续流式传输。数据摄取机制包括数据库连接、API 调用或基于 Web 的抓取等。
处理与存储
数据处理包括清理数据、将其转化为正确的格式,并为分析存储。推荐的方法是奖牌方法,如图 4.3所示,包含多个处理阶段,从原始数据到精加工数据,再到准备报告的数据。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_3.jpg
图 4.3:数据处理的奖牌阶段
奖牌方法
数据处理的奖牌方法将数据组织为三个阶段:青铜、白银和黄金。这通常用于数据湖和 Delta Lake 架构。在青铜阶段,原始数据从不同来源摄取而不进行转化。白银阶段是通过数据清理、增强和转化来创建一个精加工的数据集。最后,黄金阶段代表最高质量的数据,已清洗、汇总并优化以进行高级分析、报告和商业智能。这种多层结构提高了数据质量,并便于数据管理。
一旦数据从源端摄取,数据质量检查与清洗是构建数据可信度的第一步。这包括处理缺失值、检测并修正错误、去除重复项以及筛选异常值。这些操作能提升数据质量,并为分析提供坚实的基础。对于时间序列数据,特定要求是在此阶段验证并维护时间一致性,以确保数据的顺序性。
来源的原始数据通常不适合直接用于分析,需要经过多次转换,使其适合时间序列分析。此过程包括将半结构化数据转换为结构化格式以便于更快速的访问等多项转换操作。粒度较小或间隔不规则的数据需要聚合到更高层级的时间间隔,例如将每分钟的数据聚合为每小时数据、每小时数据聚合为每日数据,依此类推。日期和时间字段可能需要特别处理,以确保其为可排序格式,并用于设置时间索引,以便更快速地检索。不同的时区需要相应处理。
在较小的项目中常被忽视,元数据在企业环境中是确保数据可追溯性和数据血缘治理的重要要求。例如,这些关于数据的信息包括源标识符、数据摄取和更新的时间、所做的更改以及历史版本。元数据作为数据摄取和转化管道的一部分进行捕获,并且原生支持诸如 Delta 这样的存储协议。
尽管迄今为止描述的所有数据处理可以在内存中完成,但对数据的长期存储和检索仍有需求,以便进行时间跨度较长的分析。此存储需要具有成本效益、可扩展性、安全性,并且能够提供进行及时分析所需的高性能。根据数据的体积和流动速度,可选择的存储方式包括专门的时间序列数据库如 InfluxDB,或结合使用 Delta 等存储协议的云端存储。
我们将在第五章中更深入探讨数据处理,特别是数据准备的内容。现在,我们将焦点转向治理和安全,这些是从风险角度来看,DataOps 中最关键的考虑因素之一。
监控、安全性与治理
数据监控、安全性和治理涵盖了多个交叉的数据实践领域,包括数据质量、隐私、访问控制、合规性以及政策。为了理解这些实践的重要性,让我们来看看在撰写本文时新闻中的以下内容:
一起网络安全事件影响了多个主要组织,包括 Ticketmaster、Banco Santander 和 Ticketek。一个名为 ShinyHunters 的黑客组织获取了 Ticketmaster 的数据库,并因此泄露了 5.6 亿用户的个人信息。泄露的内容包括姓名、地址、电话号码、电子邮件地址和支付详情。据报道,这些数据正在黑客论坛上以高价出售。Banco Santander 也发生了类似的泄露,影响了客户和员工。
这些与第三方云数据仓库服务相关的数据泄露突显了网络安全的挑战,以及对监控、安全和治理强有力措施的需求。
监控
这里的目标是及时识别问题,并能够采取纠正措施,理想情况下在其产生负面后果之前。监控内容包括数据本身、转换管道的执行状态,以及安全和治理漏洞。对于数据监控,这意味着通过衡量数据的准确性和完整性来跟踪数据质量,同时捕捉数据缺口和异常。实现这一目标的一种方法是与一系列特定的时间序列模式进行比较,正如我们在第二章的异常检测示例中所看到的。至于数据管道监控,主要跟踪其性能,以确保数据的新鲜度、服务级别协议(SLA)得到遵守,以及通过数据溯源和完整性跟踪其血统。从安全角度来看,我们希望及时发现任何数据泄露的尝试,并采取相应的行动。监控应为自动化过程,并具备警报功能。
安全
无论是静态数据还是传输中的数据,我们都需要定义角色和相关权限,以确保访问控制。某些时间序列数据具有敏感性,只有授权人员才能查看或操作这些数据。
在受监管行业中,处理个人数据时,我们需要确保数据处理和存储实践符合相关法规(如 HIPAA、GDPR 等)。这还涉及确保隐私并管理个人数据的同意。
治理
除了前述内容,数据治理实践负责分配角色和责任以管理数据。作为其中的一部分,数据管理员负责监督数据质量、合规性和政策。
通过建立正确的流程、人员和工具,我们可以确保预防数据泄露,并在发生时有效减轻其影响。
我们现在已经涵盖了以可信和有用的方式将数据摄取并转化为受治理和安全的数据的过程。作为 DataOps 的一部分,剩下的步骤就是将数据共享给用户或其他系统进行分析和消费。
共享与消费
在数据摄取和处理之后,我们希望经过整理的数据和分析结果能够对用户可见并可访问。一个集中的数据目录,包括描述和使用指南,可以让用户轻松发现并访问可用的数据集。
最后,作为 DataOps 阶段的一部分,我们希望数据科学家、分析师和其他用户能够使用数据进行探索、分析和报告。理想情况下,我们希望将其与治理结合,确保只有授权的用户访问和使用允许的数据集。访问方式和使用方法包括基于文件的访问、数据库连接和 API 等。
正如本节所讨论的,DataOps 是一系列确保数据可用、可访问和可用的过程。它是迭代的,通过来自消费者的反馈以及对数据、管道和实践的持续改进来实现。通过建立一个可扩展且灵活的基础设施,并以 Apache Spark 的处理能力和多功能性为核心,DataOps 确保数据科学家和分析师能够在需要时获得高质量的数据,以获取洞察并推动决策。
我们将在第五章《数据准备》中讨论 DataOps 的实际考虑。目前,让我们专注于 ModelOps,它是继 DataOps 之后的下一个阶段。
ModelOps
虽然 DataOps 关注的是数据生命周期,ModelOps 关注的是模型生命周期——更具体地说,是统计和机器学习模型。其目标是从开发到部署管理模型,确保模型可靠、准确且可扩展,同时根据用例要求提供可操作的洞察。
ModelOps、MLOps 和 LLMOps
这些术语具有重叠的定义,有时可以互换使用。在本书中,我们将“ModelOps”作为不同类型模型(包括仿真模型、统计模型和机器学习模型)的更广泛生命周期管理实践来使用。我们将更具体地使用机器学习运维(MLOps)来指代机器学习模型,并将大语言模型运维(LLMOps)用于特指大语言模型生命周期中的相关考虑。因此,ModelOps 将指代这一系列实践的总和。
ModelOps 实践大致可以分为模型开发与测试,以及模型部署。
模型开发与测试
模型开发与测试涉及基于历史数据创建和微调时间序列分析模型。这个过程从特征工程开始,选择合适的算法,如自回归综合滑动平均(ARIMA)或长短期记忆(LSTM),并将数据划分为训练集和测试集。然后,模型通过反复训练和评估性能指标来确保准确性。接下来,通过在未见过的数据上测试模型,我们可以确保模型能够很好地推广到新的、真实的场景中。
我们现在将进一步详细介绍每个步骤:
-
特征工程:与 DataOps 阶段重叠,特征工程是模型开发的初始阶段,关注的是从时间序列数据中识别现有特征并创建新特征。这包括创建滞后和滚动平均特征,其中使用前一时间步的数据计算新特征,以及创建捕捉时间相关特征的时间特征,如一天中的特定时间、星期几、月份或假期。此外,特征工程阶段还包括对时间序列进行平稳化的转换,如差分或对数变换,或通过重采样使时间序列变得规律化,如在第一章中所讨论的那样。我们将在第八章中看到如何使用 Apache Spark 进行特征工程,涉及模型开发。
-
模型选择:选择模型是从一个不断增长的时间序列候选模型列表中挑选:ARIMA、Prophet、机器学习、深度学习模型(如 LSTM)等。正确的时间序列模型取决于可用的数据和我们要实现的用例,正如我们在第二章中的用例示例中看到的那样。探索性数据分析(EDA),在第六章中详细介绍,帮助我们理解数据的趋势、季节性和潜在模式,从而指导我们完成这一过程。然而,找到最佳模型是一个迭代过程,通过模型验证来不断完善,我们将在下一步中介绍这个过程。
-
数据集划分:一旦我们有了候选模型,训练模型之前的第一步是将历史数据划分为训练集、验证集和测试集。在时间序列数据中进行此操作的具体考虑因素有两个:一是保持数据集内的时间顺序,二是确保在划分之间没有数据泄漏。
-
训练:在这一阶段,模型通过调整其参数来拟合训练数据集。这可以是有监督的,使用预定义的标签或实际结果,或者是无监督的,如在第二章中解释的那样。在有监督训练的情况下,模型参数通过诸如梯度下降的过程进行调整,以最小化模型预测与实际结果之间的差异,使用损失函数进行优化。对于无监督训练,模型会进行调整,直到满足停止标准,如运行次数或分类类别数。
-
验证:作为训练迭代的一部分,模型验证使用未见过的验证数据集,并采用如基于时间的交叉验证等技术。这是为了检查是否存在过拟合,并确保训练后的模型能够以可接受的准确性对未见过的数据进行泛化。模型的准确性通过如平均绝对百分比误差(MAPE)或平均绝对误差(MAE)等指标进行评估。作为一个迭代过程,这一阶段包括超参数调优,在此过程中,不同设置的模型被训练和验证,以找到最佳的模型配置。技术如网格搜索或贝叶斯优化被用来寻找最优的超参数。
参数与超参数
请注意参数和超参数之间的区别。这些术语常常被混淆。模型参数是通过训练过程从数据中学习得来的,例如神经网络的权重和偏差。超参数则是在模型训练之前定义的模型配置,举例来说,在神经网络中,超参数可以是定义其架构的节点数和层数。
- 测试 – 作为模型开发的最后一步,模型会在未见过的测试数据集上进行评估,并与不同的算法或模型类型进行比较。测试还可以包括超出模型准确度的其他标准,如响应时间,以及与模型配合使用的应用代码的集成测试。
模型训练、验证和测试将在第七章中详细讨论。
模型部署与监控
模型部署与监控涉及将时间序列分析模型从开发环境过渡到生产环境,并持续监控其性能。这种持续的监控使得模型能够在数据模式或被分析的底层系统行为发生变化时,进行重新训练和更新。
现在我们将进一步详细说明这些步骤:
-
部署:模型被部署到生产环境中的模型服务框架中。这可以通过像 Kubernetes 和 Docker 这样的工具进行容器化,或者部署到基于云的解决方案中,例如 Databricks 模型服务、Amazon SageMaker、Azure 机器学习或 Google Vertex AI。一旦部署,模型可以用于批量推理,按定期间隔安排,或基于持续流数据源进行实时推理,或响应 API 请求。
-
监控:一旦模型在生产环境中部署,就需要进行监控,以确保模型持续适配目的并有价值。随着数据漂移(数据特征随时间的变化)和概念漂移(模型对现实的表征随时间恶化),模型的准确性会下降。这可以通过模型监控来检测,并根据情况发送警报。
-
再训练:当监控警报提示出现漂移时,如果漂移足够显著,下一步是对模型进行再训练。这可以手动启动,也可以自动化。如果再训练未能产生足够准确的模型,我们将不得不回到模型开发周期,寻找适合目的的其他模型。
-
治理:这包括几个关键的考虑因素。我们需要在模型的整个生命周期和相关过程中跟踪模型版本和生命周期阶段。此外,为了审计目的,会保存训练、部署和准确性指标的日志,在某些情况下,还会保存模型推理的请求和响应。其他考虑因素包括模型的访问控制,并确保它符合所有法律和合规要求,尤其是在处理个人或敏感数据时。
总结来说,时间序列分析项目的 ModelOps 涵盖了从开发、部署到维护模型的端到端过程,同时与 DataOps 的相关数据需求有所交集。ModelOps 确保持续改进、可复现性、协作和与业务目标的适配性。它还维持模型的有效性,并确保模型随时间持续提供价值。
我们将在第七章中详细介绍 ModelOps 的实际考虑因素,构建和测试模型。接下来的阶段是 DevOps,我们现在将详细介绍。
DevOps
紧接着 ModelOps 之后,DevOps 是一组实践和工具,旨在平滑开发(Dev)与运维(Ops)之间的交接。这适用于模型及其相关的应用程序代码。通过自动化时间序列应用的构建、测试、部署和监控,DevOps 确保它们是可靠的、可扩展的,并能持续为业务提供价值。
DevOps 实践大致可以分为持续集成/持续部署(CI/CD)、基础设施管理、监控和治理。
CI/CD
CI/CD 涉及自动化时间序列分析模型的集成和部署,以便对生产环境进行无缝更新。
这包括以下步骤:
-
代码和模型版本管理与仓库:代码和模型的变化需要进行跟踪,并且如果需要,可以回滚到以前的版本。这意味着代码和模型需要进行版本控制,并存储在一个仓库中,便于访问不同的版本。
-
测试:每当时间序列模型和相关代码发生变化时,确保没有回归是至关重要的。确保这一点的一种方法是通过自动化测试,进行单元测试和集成测试,这些测试可以在生产监控检测到性能下降时启动,或者在开发环境中模型或相关代码发生变化时启动。
-
部署:一旦时间序列模型和代码在开发环境中准备好,接下来的步骤就是部署到预生产和生产环境。推荐使用 CI/CD 管道自动化此部署,以最小化由于手动步骤引起的错误风险,并使该过程成为无缝、可重复和可扩展的。
总结来说,CI/CD 管道确保新功能、改进和漏洞修复能够持续集成、测试和部署,同时最大程度地减少停机时间,提高新代码发布的效率。
基础设施管理
基础设施即代码(IaC)是一种推荐的配置方法,因为它使基础设施配置可以进行版本控制、自我文档化、可重现并且可扩展。这是设置计算、存储和网络配置一致性的一种方式。在云环境等虚拟环境中,基础设施本身在某种意义上是版本控制的,因为它是软件定义的。
除了前述核心资源外,安全特定的配置还需要为访问控制、加密和网络安全防火墙提供配置。
随着应用需求的变化,相应的工作负载也会变化,可能需要更多或更少的基础设施资源。一个可扩展的基础设施管理流程确保基础设施根据需求自动进行扩展。
监控、安全性和治理
DevOps 在监控、安全性和治理方面的要求与 DataOps 和 ModelOps 类似。DevOps 的范围涵盖了部署到生产环境中的一切,包括模型、代码和配置。这通常通过诸如应用程序、安全性和合规性监控、日志记录和警报、以及事件管理等流程来实现。
总结来说,DevOps 通过自动化部署、管理和扩展,确保应用程序(包括时间序列分析)具有高可用性和可扩展性。关键在于通过促进协作和使用自动化,使得从 Dev 到 Ops 的过渡无缝化,确保时间序列分析项目能够从用例概念演变为技术实现,再到驱动显著业务影响和价值的全面运营系统。
现在我们已经理解了时间序列分析项目的端到端阶段,接下来的部分将提供实际示例和工具,以实施我们在本章中所学的内容。
实施示例和工具
定义了端到端阶段后,本节将探讨两种实施示例:基于笔记本的方法和基于协调器的方法。
注意
如果你不打算构建自己的端到端环境,可以跳过本节的实践部分,使用像 Databricks 这样的托管平台,正如我们将在后续章节中所做的那样。
让我们从设置运行示例所需的环境开始。
环境设置
我们将使用 Docker 容器,正如在 第三章 中所示,用于平台基础设施。有关安装 Docker 的说明,请参考 第三章 中的 使用容器进行部署 部分。
Docker 的替代方案
你可以使用 Podman 作为 Docker 的开源替代方案。你可以在这里找到更多信息:podman.io/
。
在我们可以部署 Docker 容器之前,我们将在下一部分验证容器将使用的网络端口是否存在冲突。
网络端口
以下网络端口需要在你的本地机器或开发环境中可用:
-
Apache Spark:
7077
、8070
和8081
-
Jupyter Notebook:
4040
、4041
、4042
和8888
-
MLflow:
5001
-
Airflow:
8080
你可以通过以下命令检查现有应用程序是否正在使用这些端口,从命令行或终端运行:
% netstat -an | grep LISTEN
如果你看到所需的端口已在使用的端口列表中,你必须停止使用该端口的应用程序,或者修改 docker-compose
文件以使用其他端口。
作为示例,假设前面的 netstat
命令输出显示本地机器或开发环境中端口 8080
已被占用,且你无法停止使用该端口的现有应用程序。
在这种情况下,你需要在 docker-compose.yaml
文件中将端口 8080
(用于 Airflow Web 服务器)更改为另一个未使用的端口。只需搜索并将冒号(:
)左边的 8080
替换为 8090
,如果该端口未被占用,如下所示:
-
来自此:
ports: - '7077:7077' - '8080:8080'
-
例如:
ports: - '7077:7077' - '8090:8080'
记下新端口,并在需要输入对应 URL 时使用该端口。在此示例中,端口8080
已更改为8090
,Airflow Web 服务器的匹配 URL 更改如下:
-
从此开始:
http://localhost:8080/
-
改为:
http://localhost:8090/
注意
你需要在以下部分中的所有 URL 中更改网络端口,按照本节的说明进行修改。
环境启动
一旦 Docker 安装并运行,且网络端口配置已验证,以下指令将指导你设置和启动环境:
-
我们首先从本章的 Git 仓库下载部署脚本,仓库地址如下:
github.com/PacktPublishing/Time-Series-Analysis-with-Spark/tree/main/ch4
我们将使用
git clone
友好的 URL,具体如下:github.com/PacktPublishing/Time-Series-Analysis-with-Spark.git
为此,启动终端或命令行并运行以下命令:
git clone https://github.com/PacktPublishing/Time-Series-Analysis-with-Spark.git git command:
xcrun: 错误:无效的活动开发者路径(/Library/Developer/CommandLineTools),缺少 xcrun,路径为:/Library/Developer/CommandLineTools/usr/bin/xcrun
In this case, you will need to reinstall the command-line tools with the following command:
xcode-select --install
-
现在我们可以开始构建和启动容器了。提供了一个 makefile 以简化启动和停止容器的过程。以下命令构建容器的 Docker 镜像并启动它们:
make up
Windows 环境
如果你使用的是 Windows 环境,你可以按照以下文档安装 Windows 版本的make
:gnuwin32.sourceforge.net/packages/make.htm
make up
命令将输出以下或等效的内容:
make prep && docker-compose up -d
sh prep-airflow.sh
[+] Running 9/9
✔ Container ts-spark-env-spark-master-1 Started
✔ Container ts-spark-env-postgres-1 Healthy ✔ Container ts-spark-env-mlflow-server-1 Started ✔ Container ts-spark-env-jupyter-1 Started ✔ Container ts-spark-env-airflow-init-1 Exited ✔ Container ts-spark-env-spark-worker-1-1 Started ✔ Container ts-spark-env-airflow-scheduler-1 Running ✔ Container ts-spark-env-airflow-triggerer-1 Running ✔ Container ts-spark-env-airflow-webserver-1 Running
-
当你运行上面的
make
up
命令时,你可能会看到以下错误:open /Users/<USER_LOGIN>/.docker/buildx/current: permission denied make up command.
-
如果你的环境中使用的是
bash
而不是sh
,且脚本无法找到sh
文件,你可能会遇到错误。在这种情况下,将 makefile 中的最后一行从"sh prep-airflow.sh
"更改为"bash prep-airflow.sh
",然后再次运行make
up
命令。
经过该过程的结束,正如第三章所述,你将拥有一个运行中的 Spark 集群和一个独立的 Jupyter Notebook 节点。此外,我们在这里已部署以下组件:
-
MLflow – 一个开源平台,最初由 Databricks 开发,用于管理端到端的机器学习生命周期。MLflow 具有实验和部署功能,旨在与任何机器学习库和编程语言兼容。这使得它在各种环境和用例中具有灵活性,也解释了它被广泛采用的原因。
你可以在这里找到更多信息:
mlflow.org/
。 -
Apache Airflow – 由 Airbnb 创建,Airflow 是一个开源平台,用于协调数据处理管道和计算工作流。通过能够以编程方式定义、调度和监控大规模的工作流,Airflow 被广泛采用,包括数据工程师和数据科学家在内,用于各种类型的工作流。
你可以在这里找到更多信息:
airflow.apache.org/
。 -
Postgres – 这是 Airflow 后台使用的关系型数据库。
现在让我们验证刚刚部署的环境。
访问用户界面
现在我们将访问不同组件的用户界面(UIs),作为快速验证部署的一种方式:
-
请按照第三章中的指示验证 Jupyter Notebook 和 Apache Spark 集群的部署。请注意,由于 Airflow Web 服务器使用端口
8080
,这是我们在第三章中为 Apache Spark 使用的相同端口,因此我们已将 Spark 主节点更改为以下本地网址:http://localhost:8070/
-
MLflow 可以通过以下本地网址访问:
http://localhost:5001/
这将打开如图 4.4所示的网页。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_4.jpg
图 4.4:MLflow
-
下一个 UI,图 4.5,是 Airflow 界面,可以通过以下本地网址访问:
http://localhost:8080/
默认的用户名和密码是
airflow
,强烈建议更改。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_5.jpg
图 4.5:Airflow
我们现在已经设置好环境,接下来将使用这个环境。
Notebook 方法
我们使用了第一章中的笔记本,我们从 Databricks Community 版本开始。在第三章中,我们部署了自己的 Jupyter 笔记本环境,这是一个开源实现。正如我们到目前为止所看到的,笔记本提供了一个功能丰富的文档类型界面,在这里我们可以结合可执行代码、可视化和文本。这使得笔记本在数据科学和机器学习的互动和协作工作中非常流行。笔记本也可以构建为非交互式执行,这与它们已经在早期的数据科学和实验阶段中使用过的事实结合,使得它们能够方便地适应端到端的笔记本。
在这个第一个示例中,我们将使用基于第一章中介绍的基于 Prophet 的代码的全功能笔记本。如果你按照之前的环境设置部分中的指示操作,示例笔记本应该可以直接在 Jupyter Notebook UI 中访问,在左侧文件夹导航面板的work / notebooks
位置,如图 4.6所示,网址为:http://localhost:8888/lab
。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_6.jpg
图 4.6:Notebook
笔记本也可以从以下 GitHub 位置下载:
本文重点更多地放在结构上,而非代码本身,代码内容与第一章变化不大,我们将笔记本分成了以下几个部分:
-
配置
-
DataOps
-
从源获取数据
-
转换数据
-
ModelOps
-
训练并记录模型
-
使用模型进行预测
除了前面解释的结构外,从第一章引入的代码中还有 MLOps 部分,接下来我们将详细说明。
使用 MLflow 进行 MLOps
在此笔记本示例中,我们使用 MLflow 作为工具来实现多个 MLOps 需求。以下代码片段专注于这一部分:
mlflow.set_tracking_uri("http://mlflow-server:5000")
mlflow.set_experiment(
'ts-spark_ch4_data-ml-ops_time_series_prophet_notebook')
with mlflow.start_run():
model = Prophet().fit(pdf)
…
mlflow.prophet.log_model(
model, artifact_path=ARTIFACT_DIR,
signature=signature)
mlflow.log_params(param)
mlflow.log_metrics(cv_metrics)
上述代码中使用的 MLflow 功能如下:
-
set_tracking_uri
– 这个函数设置跟踪服务器的 URI,MLflow 将在该服务器上存储与模型相关的信息。这样可以集中管理模型数据,促进团队成员之间的协作。跟踪服务器可以是远程服务器,也可以是本地文件路径。 -
set_experiment
– 这个函数会创建一个新实验,或者使用现有的实验。实验是运行(单独的模型训练或试验)的逻辑分组,有助于组织和比较不同的试验。 -
start_run
– 这会启动一个新的 MLflow 运行,可以在给定的实验中进行。作为单次训练或试验的表示,run
会将相关的工件(如参数、指标和模型)归类。 -
prophet.log_model
– 该函数将一个 Prophet 模型作为工件记录到当前的 MLflow 运行中。 -
log_params
– 该函数记录运行过程中使用的参数的键值对。参数是模型配置。 -
log_metrics
– 该函数记录运行过程中评估的指标的键值对。指标是关于模型性能的数值(例如均方误差、准确率)。
结果可以通过 MLflow UI 在以下网址访问:http://localhost:5001/
。
这将打开一个类似于图 4.4的 UI 页面,在左侧面板中,你可以导航到名为ts-spark_ch4_data-ml-ops_time_series_prophet_notebook
的实验。UI 中看到的实验名称来自于前面的代码中的标记。
实验的概览标签,如图 4.7所示,包含实验的信息,如创建者、创建日期、状态、创建实验的源代码,以及从实验中记录的模型。它还显示了代码中记录的模型参数和指标。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_7.jpg
图 4.7:MLflow 实验概览
模型指标标签,如图 4.8所示,可以用来搜索并查看指标图。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_8.jpg
图 4.8:MLflow 模型指标
Artifacts标签页的初始界面,见图 4.9,显示了我们在代码中作为签名记录的模型架构。它还提供了如何使用模型的代码示例。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_9.jpg
图 4.9:MLflow 模型架构
MLmodel部分位于Artifacts标签页中,显示了模型工件及其路径,见图 4.10。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_10.jpg
图 4.10:MLflow 模型工件
在这个示例中,我们将使用 MLflow 到此为止。我们将在下一个示例中使用编排器和 MLflow 类似的方式,并在第九章《走向生产》中深入探讨 MLflow 的更多应用。现在,我们将关注笔记本方法的其他考虑因素。
多个笔记本
这里的笔记本示例仅是一个起点,可以根据自身用例的需求以及后续章节将讨论的技术进行适配和扩展。对于更复杂的需求,建议为以下内容使用单独的笔记本:
-
探索性数据分析与数据科学
-
特征工程
-
模型开发、选择及最佳模型的部署
-
生产数据管道,可能还包括特征工程
-
生产模型推理
-
监控
-
模型重训练
尽管笔记本因其交互性、协作简便性、相对简单性和多功能性而备受青睐,但它们也存在限制,接下来的章节将对此进行讲解。
限制
无论笔记本有多优秀,端到端时间序列分析的笔记本都面临若干挑战,具体如下:
-
缺乏调度和编排功能。这使得它难以超越简单的顺序工作流,开发复杂的工作流。
-
可扩展性问题。笔记本代码运行在笔记本内核中,受限于所在机器的资源。请注意,可以通过将任务从笔记本提交到 Apache Spark 集群中运行来解决此问题,正如我们在示例中所做的那样。
-
缺乏错误处理。如果笔记本单元格中的代码失败,整个工作流执行将停止。当然,可以编写错误处理代码,但这会增加额外的编码工作量。
为了应对这些挑战,我们接下来将考虑另一种方法,使用编排器。
编排器方法
在深入了解这种方法之前,首先让我们理解什么是编排器。我们将在此使用的 Airflow,之前作为示例提到过。
编排器在管理工作流(包括数据工程和处理)中扮演着核心角色。工作流或管道是一组计算任务,这些任务按一定顺序并行或顺序执行,通常依赖于前一个任务或多个任务的结果。除了调度工作流外,编排器通常还具备在调度前创建工作流和在调度后监控其执行的功能。
编排器的好处
使用调度器相较于仅使用笔记本的方法提供了以下优点:
-
在工作流中调度任务,考虑任务的依赖关系以及并行或顺序执行的要求。这还包括任务执行的条件逻辑。
-
可扩展和分布式任务执行。
-
监控和记录工作流执行,包括性能和错误。这对于生产环境至关重要。
-
错误处理和警报,提供重试、跳过到下一个任务或失败整个管道的可能性。这也是生产环境中的关键要求。
-
与其他系统和工具的集成。这是构建端到端工作流的必要条件,涵盖 DataOps、ModelOps 和 DevOps,这通常意味着需要使用不同的专业工具。
既然我们已经看到了这些优点,并且环境已设置好,Airflow 作为调度器,现在让我们开始实践。
创建工作流
第一步是创建工作流或有向无环图(DAG),也叫做 DAG。
如果你遵循了之前环境设置部分中的说明,示例 DAG 已经加载并可以直接通过 Airflow UI 访问,如图 4.5所示,网址为:http://localhost:8080/
。此时,你可以跳到下一部分来运行 DAG,或者继续查看 DAG 代码的详细信息。
DAG 定义位于dags
文件夹中的 Python 代码文件中,也可以从以下 GitHub 位置下载:
代码的核心与我们在之前笔记本示例中看到的非常相似。本节重点介绍与 Airflow 的集成以及定义 DAG 的任务,这些任务是 DAG 的各个步骤。
任务定义 – Python 代码
当调度器运行任务时,它调用以下相应的 Python 函数作为需要执行的底层代码。注意传入的函数参数和返回值。这些与任务的定义对齐,我们将在接下来的部分看到:
-
ingest_data
– 对应任务t1
。注意,spark.read
将在 Spark 集群上运行:def ingest_data(): sdf = spark.read.csv( DATASOURCE, header=True, inferSchema=True) pdf = sdf.select("date", "daily_min_temperature").toPandas() return pdf
-
transform_data
– 对应任务t2
:def transform_data(pdf, **kwargs): pdf.columns = ["ds", "y"] pdf["y"] = pd.to_numeric(pdf["y"], errors="coerce") pdf.drop(index=pdf.index[-2:], inplace=True) pdf.dropna() return pdf
-
train_and_log_model
– 对应任务t3
。注意,MLflow 函数,如mlflow.set_experiment
和mlflow.prophet.log_model
,会调用 MLflow 服务器。这里展示了代码的部分摘录:def train_and_log_model(pdf, **kwargs): mlflow.set_experiment( 'ts-spark_ch4_data-ml-ops_time_series_prophet') … mlflow.prophet.log_model( model, artifact_path=ARTIFACT_DIR, signature=signature) … return model_uri
-
forecast
– 对应任务t4
。注意,mlflow.prophet.load_model
从 MLflow 服务器加载模型。这里只是为了展示如何从 MLflow 服务器检索模型。实际上并非严格需要,因为我们本可以在本地保留对模型的引用:def forecast(model_uri, **kwargs): _model = mlflow.prophet.load_model(model_uri) forecast = _model.predict( _model.make_future_dataframe(30)) forecast[ ['ds', 'yhat', 'yhat_lower','yhat_upper'] ].to_csv('/data/ts-spark_ch4_prophet-forecast.csv') return '/data/ts-spark_ch4_prophet-forecast.csv'
这些任务由 DAG 引用,我们将在接下来定义它们。
DAG 定义
在前面的任务定义之上,我们有一个高层次的 Airflow DAG,它按照以下定义:
dag = DAG(
'ts-spark_ch4_data-ml-ops_time_series_prophet',
default_args=default_args,
description='ts-spark_ch4 - Data/MLOps pipeline example - Time series forecasting with Prophet',
schedule_interval=None
)
这指向default_args
,其中包含以下 DAG 参数。
default_args = {
'owner': 'airflow',
'depends_on_past': False,
'start_date': datetime(2024, 1, 1),
'email_on_failure': False,
'email_on_retry': False,
'retries': 1,
'retry_delay': timedelta(minutes=1),
}
这些的更多信息可以在以下 Airflow 文档中找到:
我们没有设置schedule_interval
,因为我们希望通过 Airflow UI 手动触发 DAG。
DAG 任务
DAG 任务按以下方式定义。请注意引用了dag
和先前定义的底层 Python 函数。使用PythonOperator
意味着任务将调用 Python 函数:
-
t1
:t1 = PythonOperator( task_id='ingest_data', python_callable=ingest_data, dag=dag, )
-
t2
:t2 = PythonOperator( task_id='transform_data', python_callable=transform_data, op_kwargs={'pdf': t1.output}, provide_context=True, dag=dag, )
任务
t2
的一个显著特点是,任务t1
的输出t1.output
作为输入pdf
传递给任务t2
。 -
t3
:t3 = PythonOperator( task_id='train_and_log_model', python_callable=train_and_log_model, op_kwargs={'pdf': t2.output}, provide_context=True, dag=dag, )
任务
t2
的输出t2.output
作为输入pdf
传递给任务t3
。 -
t4
:t4 = PythonOperator( task_id='forecast', python_callable=forecast, op_kwargs={'model_uri': t3.output}, provide_context=True, dag=dag, )
任务
t3
的输出t3.output
作为输入model_uri
传递给任务t4
。
然后,这些任务通过以下代码配置,以便由 Airflow 按顺序进行协调:
# Task dependencies
t1 >> t2 >> t3 >> t4
这就结束了在 Airflow 中定义工作流作为 DAG 的过程。这里的示例只是一个起点,展示了一个简单的顺序工作流,可以根据您的具体需求以及接下来章节中讨论的时间序列分析任务进行调整和扩展。
协调笔记本
请注意,还可以通过使用PapermillOperator
操作符从 Airflow 任务调用笔记本,将协调器和笔记本方法结合起来。有关此操作符的更多信息,请访问:airflow.apache.org/docs/apache-airflow-providers-papermill/stable/operators.html
。
一旦 DAG 编写完成并放置在 Airflow 的dags
文件夹中,它将被 Airflow 自动识别,检查 Python 定义文件中的语法错误,然后列出可以运行的 DAG 列表,接下来我们将介绍这一部分内容。
运行工作流
可以通过点击 DAG 右侧的运行按钮(>)来启动工作流,正如图 4.5中所示的访问 UI部分。通过点击左侧面板中的 DAG 名称,可以在 Airflow UI 中查看 DAG 的详细信息和图形,如图 4.11所示。
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/B18568_04_11.jpg
图 4.11:Airflow DAG
要查看 DAG 中特定运行和任务的信息,请在左侧选择运行,然后从图形中选择任务。这将提供查看任务执行日志的选项。
另一个有趣的信息是不同任务的执行时间,可以通过同一界面中的甘特图标签查看。
我们这里只是在探索 Airflow 的表面,它是一个功能丰富的工具,超出了本书的范围。请参阅 Airflow 文档以获取更多信息。
如前所述,部分代码在 Apache Spark 集群上运行。根据第三章中的图 3.6,可以从 Spark 主节点可视化这一过程。URL 为:http://localhost:8070/
。如果应用仍在运行,Spark UI 将显示一个运行中的应用程序。这个应用程序是从 Airflow 任务中启动的 Spark 代码。
对于 MLflow,你可以在以下 URL 中通过 MLflow UI 查看结果:http://localhost:5001/
。
在 MLflow UI 页面上,类似于图 4.4,你可以在左侧面板中导航到名为ts-spark_ch4_data-ml-ops_time_series_prophet
的实验。UI 中看到的实验名称来自代码,在之前的train_and_log_model
代码中有所高亮显示。
`这就结束了本章讨论的第二种方法。我们将在接下来的章节中,使用我们学到的概念,基于这个编排器示例进行构建。
环境关闭
现在我们可以停止容器环境。提供的 makefile 简化了这个过程,使用以下命令:
make down
这将产生如下或等效的输出:
docker-compose down
[+] Running 10/10
✔ Container ts-spark-env-spark-worker-1-1 Removed
✔ Container ts-spark-env-mlflow-server-1 Removed
✔ Container ts-spark-env-airflow-scheduler-1Removed ✔Container ts-spark-env-airflow-webserver-1Removed ✔ ontainer ts-spark-env-jupyter-1 Removed ✔ Container ts-spark-env-airflow-triggerer-1Removed ✔ Container ts-spark-env-airflow-init-1 Removed ✔ Container ts-spark-env-postgres-1 Removed ✔ Container ts-spark-env-spark-master-1 Removed ✔ Network ts-spark-env_default Removed
如果你不打算进一步使用它,可以按照此处的说明,删除通过Delete
操作创建的 Docker 容器:docs.docker.com/desktop/use-desktop/container/#container-actions
。
总结
本章详细介绍了时间序列分析项目的关键阶段,从选择与业务需求相对应的用例开始。接着,将该用例映射到技术解决方案,包括 DataOps、ModelOps 和 DevOps 组件。最后,我们探讨了两种实现方式,包括带有一体化笔记本和带有编排器的基准实现示例,这将在本书接下来的部分进一步扩展。
在下一章中,我们将专注于此,重点是通过数据准备进行 DataOps。
加入我们社区的 Discord
加入我们社区的 Discord 空间,与作者和其他读者进行讨论:
https://github.com/OpenDocCN/freelearn-ds-pt3-zh/raw/master/docs/ts-anal-spk/img/ds_(1.jpg)