土星云 vs 谷歌 Colab 的数据科学和机器学习
哪种工具更适合可扩展数据科学?
没有 GPU、并行编程和 DevOps 团队的端到端数据科学管道的图示。在 Unsplash 上由 amirali mirhashemian 拍摄的照片
向任何数据科学家询问他们在工作中最常用的工具。很有可能,你会听到很多关于 Jupyter notebook 或者 Google Colab 的消息。这并不奇怪,因为数据科学家经常需要一个交互式环境来编码-以立即看到我们数据争论的结果,从可视化中提取见解,并密切监控机器学习模型的性能。就我个人而言,我希望我的代码执行得非常快,如果不是立即执行的话。这通常在 GPU 和并行编程的帮助下完成。
在之后,一个机器学习模型被开发并在本地环境中测试,它必须上线并被部署。不幸的是,部署过程非常复杂。这项工作涵盖了从创建服务器到建立安全协议的所有领域。完成这些工作通常需要一名专门的 DevOps 工程师,他是云服务、操作系统和网络方面的专家。
现在,数据科学家如何大幅加快我们的数据科学发展进程?像我们这样的数据科学家如何绕过 DevOps 工程师的需求,部署我们的模型?
这就是土星云能为数据从业者做的事情。 土星用分布式系统和 GPU 帮助团队训练和部署模型。
好奇?在这篇博文中,我将展示 Saturn Cloud 与 Google Colab 的相似之处(但也有很大不同),以及如何使用 Saturn Cloud 来优化您的数据科学工作流。
以下是土星云和 Colab Pro 的六大区别。
- 定价
- 编码界面的外观
- 易于部署和共享仪表板
- 运行时的可定制性
- 并行计算的代码效率
- 支持水平
定价
土星云和谷歌 Colab 都提供免费和付费服务。下表比较了这两种服务。
谷歌 Colab 和土星云价格对照表。来源于 a Colab 笔记本和 Stackoverflow 。
对于许多初学者来说,Google Colab 免费提供的服务已经足够了。那些想要比谷歌免费 Colab 更多资源的人可以选择 9.99 美元的低价 Colab Pro。然而,那些寻求更大灵活性和易于部署的人会发现土星云是 Google Colab 的一个有吸引力的替代方案。
请注意,虽然本文中讨论的所有功能都适用于自由层 Saturn Cloud,但 Saturn Cloud 的全部功能在 Pro 版本中是不可用的。
编码界面的外观
Google Colab 的界面类似于 Jupyter 笔记本,只是它包含一些独特的功能。这些功能包括显示文件夹目录的左窗格和右上角提醒您资源使用情况的两个栏。
谷歌 Colab 屏幕。作者截图。
另一方面,土星云编码环境和 JupyterLab 的完全一样。事实上,土星是建立在木星实验室上的。JupyterLab 为数据科学家提供了在 Jupyter 笔记本中编码、访问 shell 终端和在 GUI 环境中移动文件的界面。
如果你喜欢在 Jupyter 笔记本上运行你的代码,你也可以在 Saturn Cloud 上运行。
木星实验室的屏幕,位于土星云上。
易于部署和共享交互式控制面板
许多 python 包允许我们构建用户可以与之交互的交互式仪表盘。这些软件包包括 Plotly Dash、Voila 和 Bokeh。这种交互式仪表盘可以在 Google Colab 和 Saturn Cloud 上构建。在这个例子中,我将使用 Google Colab 和 Saturn Cloud 从的 Voila Gallery 复制一个交互式仪表盘。
瞧,交互式仪表板。作者截屏。由画廊制作的仪表板。
为了与访问者共享仪表板,用户需要将仪表板部署到服务器,以便用户可以与可视化交互。易于部署是谷歌 Colab 和土星云的关键区别。
在 Google Colab 上,用户可能需要依赖第三方解决方案 Heroku 或 Ngrok 进行部署,这有些繁琐。另一方面,在 Saturn Cloud 上部署仪表板相对简单,只需要五次点击,因为 Saturn Cloud 已经处理了与部署相关的繁重工作。
在土星上部署仪表板只需几步之遥。作者截屏。
简而言之,虽然可以在 Google Colab 和 Saturn Cloud 上部署交互式可视化,但后者可以为您节省宝贵的时间。
运行时的可定制性
在设置运行时被宠坏了…照片由叶戈尔·迈兹尼克在 Unsplash 上拍摄
Google Colab 最吸引人的额外津贴之一是它的免费运行时,包括 CPU、GPU、TPU 和大约 12GB 的内存(在撰写本文时)。像谷歌 Colab 这样的基于云的笔记本的出现,以及免费的资源,确实使深度学习民主化了。如今,任何拥有谷歌账户的人都可以获得一些 GPU 来训练他们的神经网络。
你可以通过进入菜单>运行时>更改运行时,在 Google Colab 上选择 CPU、GPU 或 TPU 运行时。
然而,为了让 Colab 对所有人免费,Colab 中可用的 GPU 类型会随着时间的推移而变化,并且没有办法选择一个人在任何给定时间可以连接的 GPU 类型,即使你是 Colab Pro 用户。
此外,如果你是一个广泛使用谷歌 Colab 的极客,你一定遇到过这些毁灭性的屏幕之一…
向你们死去的内核致以最深切的哀悼…作者截图。
- 您的 Google Drive 空间不足,无法存储您的数据或模型
- 你的 GPU 内存使用被切断
- 您的会话因内存不足而崩溃
- 您的会话在 1 小时不活动或运行笔记本 12 小时后超时
这些屏幕可能非常具有破坏性。如果 GPU 内存使用被切断,您的模型可能没有得到足够的训练。如果你在训练一个模型的时候运行时崩溃了,你基本上失去了所有的进展。当然,有一些技巧可以确保解决每种情况。然而,我们不能确定这样的黑客攻击会无限期地有效。一个人可以注册 Colab Pro 来获得对这些资源的优先访问权,但是他们不能得到保证。
这就是 Saturn Cloud 的硬件可定制性派上用场的地方。
在土星云上运行笔记本之前,必须创建一个工作空间。用户可以自由定制工作空间,包括所需的磁盘空间(从 10 GB 到 1000 GB)、硬件(CPU/GPU)、大小要求(从 2 核 4GB 到 64 核 512GB)以及关闭持续时间(从 1 小时到从不关闭)。因为您是这个工作区的老板,所以您不需要担心空间、GPU 访问、内存或运行时的不足。
额外的好处是能够用现有的 Docker 图像建立一个工作空间。这意味着工作空间将由 Docker 映像指定的某些包来设置,允许您复制其他人编写的代码。
在土星云上设置可定制的工作空间
并行计算的代码效率
并行计算是同时使用多个计算资源来解决一个计算问题。与顺序解决大问题的非并行(或串行)编程不同,并行编程将一个问题分解成更小的部分,同时解决这些小问题。
并行编程可以加速计算繁重的任务。例如,并行编程允许程序员加载和处理大型数据集(尤其是当它们太大而无法保存在内存中时)。它还允许超参数调整过程更快。
python 中有很多并行编程的包。其中最著名的是 Dask。它被设计为在单机设置和多机集群上工作良好,并且可以与 pandas、NumPy、scikit-learn 和其他 Python 库一起使用。想了解更多关于 Dask 的信息,你可以参考 Saturn Cloud 关于 Dask 的文档。
并行计算分解了一个大问题,因此可以由许多工作人员同时解决。照片由 Salmen Bejaoui 在 Unsplash 上拍摄
你可以在 Google Colab 和 Saturn Cloud 上使用 Dask。然而,一个人在 Saturn Cloud 上比在 Google Colab 上有更大的潜力来加速他们的代码。
这是因为并行化您的代码所能获得的加速量取决于工作空间的规格。直观地说,如果一个 CPU 有更多的核心,那么就有工人来处理这些小问题。这意味着并行编程有更大的加速潜力。
由于用户可以在 Saturn Cloud 中定制工作空间的规范,但不能在 Google Colab 上定制,因此 Saturn Cloud 的用户可以根据需要多少加速来决定运行时的内核数量,而 Google Colab 的用户则不能。
此外,还可以利用 Saturn Cloud 上的 Dask 集群来进一步提高 Dask 命令的速度。这增加了解决问题的工人数量。(免费土星云用户每个月有 3 个小时使用 3 个工作者的黄昏集群。)谷歌 Colab 上没有这个功能。
让我们用一个玩具例子来想象一下。我们首先创建一个 10,000 行的方阵,用随机数填充它,然后是它本身和它的转置的和,然后沿着其中一个轴寻找一个平均值。
下面是说明这一点的三个代码块。
- 写在 NumPy 数组中的代码块在 Google Colab 上免费
- 在 Google Colab 免费上的 Dask 数组中编写的代码块
- 用 Dask 集群写在土星云 Dask 数组中的代码块。
当我们从 NumPy 阵列切换到 Dask 阵列时,速度提高了 56%,当我们从 Google Colab Free 切换到 Saturn Cloud 时,速度又提高了 97%。
代码块 1: NumPy 数组上 Google Colab 免费
>>> import numpy as np >>> def test():>>> x = np.random.random((10000, 10000))>>> y = x + x.T>>> z = y[::2, 5000:].mean(axis=1)>>> return>>> %timeit test()1 loop, best of 5: 2.14 s per loop
代码块 2: Dask 数组上 Google Colab 免费
>>> import dask.array as da>>> def test():>>> x = da.random.random((10000, 10000), chunks=(1000, 1000))>>> y = x + x.T>>> z = y[::2, 5000:].mean(axis=1)>>> return z>>> %timeit test().persist()1 loop, best of 5: 866 ms per loop
代码块 3: 土星云上的 Dask 阵列和土星云上的 Dask 集群
>>> from dask.distributed import Client>>> from dask_saturn import SaturnCluster>>> import dask.array as da >>> cluster = SaturnCluster(n_workers=3)>>> client = Client(cluster)>>> def test():>>> x = da.random.random((10000, 10000), chunks=(1000, 1000))>>> y = x + x.T>>> z = y[::2, 5000:].mean(axis=1)>>> return z >>> %timeit test().persist()26.7 ms ± 2.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
支持的程度
Google Colab 不提供个性化支持,所以解决问题的最佳方法是堆栈溢出。另一方面,土星云有一个松散的社区和一个支持团队,你可以为你的问题寻求帮助。
结论
虽然 Google Colab 是一个令人惊叹的数据科学工具,但它在可定制性、资源可靠性、效率和易于部署方面存在局限性。对于正在起步的数据科学初学者来说,Google Colab 是您的最佳选择。对于正在寻找完整解决方案来高效部署数据科学解决方案的中高级数据科学从业者来说,值得考虑土星云。当然,您可能需要在 Saturn Cloud 上投入一点时间和金钱,但是采用它的效率收益可能会超过它的成本。
总之,Google Colab 非常适合个人小规模数据科学项目,而 Saturn Cloud 是可扩展数据科学的赢家。如果你想尝试一下,可以开始尝试土星云。
使用这个库,只需几行代码就可以完成一个完整的 EDA,节省大量时间
大蟒
学习如何为你的下一个项目使用 QuickDA 并节省工作时间
照片由新数据服务。资料来源:联合国人类住区规划署
无论你是数据分析师还是数据科学家,你都听过专业人士花 80%的时间做数据清理,只有 20%的时间做建模。的确,数据清理和探索性数据分析需要多个步骤来执行,记住所有的代码都需要大量的实践。例如,一个简单的数据可视化需要至少三行代码才能最少地呈现。然而,如果我告诉你有一种方法可以大幅减少花在 EDA 上的时间呢?这时候 QuickDA 就可以派上用场了。
来源:pypi.org
QuickDA 是一个易于使用、直观的低代码库,允许您用几行代码执行数据清理、数据探索和数据可视化。事实上,大多数时候我们将只使用一行代码。我创建了一个小项目来展示 QuickDa 有多强大。你可以在这里找到笔记本。
入门
安装 QuickDA 最简单的方法是在你的终端中键入pip3 install quickda
,差不多就是这样。您可以通过将git clone [https://github.com/sid-the-coder/QuickDA.git](https://github.com/sid-the-coder/QuickDA.git)
复制并粘贴到您的终端来使用git close
。现在,让我们探索这个神奇的图书馆。
对于这个项目,我只会用我们的老朋友熊猫和 QuickDA。NumPy,Matplotlib,Seaborn 都没必要。对于 QuickDA,我将使用以下库:
**# Importing libraries**
import pandas as pd
from quickda.explore_data import *
from quickda.clean_data import *
from quickda.explore_numeric import *
from quickda.explore_categoric import *
from quickda.explore_numeric_categoric import *
from quickda.explore_time_series import *
我将使用loans.csv
。你可以在我的 GitHub 里找到数据集。我无法找到原始来源,所以如果你找到了,请让我知道,这样我就可以添加学分。
**# Importing dataset**
df = pd.read_csv(‘loans.csv’)
作者图片
汇总数据集
现在我们将开始看到 QuickDA 的所有功能。首先,我们可以使用代码explore(df)
汇总我们的数据集,并获得数据类型、计数、空值、唯一值的数量以及描述性统计数据,如最小值、最大值、平均值和中值。请注意,QuickDA 还可以汇总分类数据的统计信息。常规的df.describe()
功能无法做到这一点。让我们来看看这个功能,因为它很强大。
作者图片
那很容易。在我看来,只有这个汇总表才值得一试图书馆。还有一个斜列。该列显示了特征偏斜度。我从未在我的数据分析中使用它,因为我通过数据可视化来检查它。不过,有也挺好的。正如我们所看到的,explore(df)
可以返回很多重要的信息,让我们不用再键入诸如df.dtypes
、df.info
、df.isnull.sum()
、df.nunique()
、df.skew()
、df.describe()
之类的东西。最棒的是,一切都被组织在一个数据框中。厉害!
还不信服?别担心!QuickDA 能提供更多。
我们也可以更直观的得到数据汇总。添加参数method = profile
,QuickDA 将生成一个 HTML 文件,该文件汇总了所有列,并为我们提供了对数据集的深入了解。您可以通过添加report_name = 'Name of the Report'
为您的报告添加一个名称。我们来探讨一下这个函数。
**# Summarize dataset**
explore(df, method=’profile’, report_name=’Loan Dataset Report’)
作者图片
这是大量的信息。您可以通过点击Toggle details
获得关于该功能的更多信息。它将打开关于数据集、公共值甚至要素可视化的描述性统计信息。在下面的例子中,我们可以看到一个直方图,但这将取决于你的数据类型。让我们继续使用这个神奇的函数,因为这里有很多值得探索的地方。您也可以使用顶部的导航栏来浏览表格。
作者图片
正如我提到的,您可以获得大量的描述性统计信息和更好的特性概述。它显示要素中包含不同值、缺失值和无穷大值的百分比。无穷大的值不适用于大多数建模算法。例如,分位数统计信息就在那里,包括范围。下表至少有十行代码。
作者图片
点击Histogram
,您将看到该功能的可视化效果。它看起来足够好,可以在专业报告中呈现。
作者图片
另一件很酷的事情是你可以看到数据集警告。例如,它显示高基数、高相关性、缺失值、均匀分布值以及数据集中零的百分比。这将对你做出与项目相关的决定有很大帮助。太棒了,对吧?
作者图片
稍后我们将进一步探讨这些数据可视化,但我想说的是,您可以获得一个漂亮的关联可视化。你可以看到 xticks 被编辑过——非常好的处理。
作者图片
数据清理
让我们稍微改变一下思路,检查一下 QuickDA 的数据清理功能。熊猫可以很快完成其中的一些功能。但是,我也想展示 QuickDA 的解决方案。
标准化列名
每个做过一些探索性数据分析的人都见过具有不同格式的列名的数据集。有时名字是大写的或带有空格。我们可以很容易地解决这个打字问题。这一行代码将小写列名,并在有空格时添加下划线(_
)。代码如下所示:
**# Standardize column names**
df_name = clean(data, method='standardize')
作者图片
删除列
您也可以删除列。与普通的熊猫.drop()
功能相比,我看不出有什么优势。但是,如果您想只使用 QuickDA 来标准化您的代码,您还有一个选择。
**# Drop columns**
df_name = clean(data, method='dropcols', columns=[column_names])
删除重复值
该数据集没有重复的值。因此,当应用这一行代码时,我们不会看到任何差异。
**# Removing duplicates**
df_name = clean(data, method='duplicates')
作者图片
重命名值
我们也可以很容易地用 QuickDA 替换列中的值。熊猫确实有同样好用的.replace()
功能。不过 QuickDA 也很好用。在这种情况下,我将把值Source Verified
替换为Verified
。
clean(**data**, **method**="replaceval",
columns=[], to_replace="value to be replaced", value="new value")
作者图片
填充缺失值
缺少值?没问题,QuickDA 也能够通过插值来处理。插值是对值序列中两个已知值之间的值的估计。为此,您可以使用以下代码:
df_name = clean(data, method='fillmissing')
移除异常值
我们什么时候应该剔除异常值是有争议的。有时数据是不正确的,有时离群值对于理解所有场景是重要的。然而,如果您认为异常值不重要,可以用下面的代码删除它们:
df_name = clean(data, method='outliers', columns=[column_names])
作者图片
您可以选择要删除异常值的列。如果不选择列,QuickDA 将删除所有列中的异常值。
待续
我们刚刚看到了许多激动人心的信息,还有更多信息要向您展示。然而,这个博客变得有点太长了。出于这个原因,我将写第二部分,在那里我将向您展示更多令人兴奋的东西,我们可以用 QuickDA 来做。例如,如何用它创建数据可视化。敬请期待,过几天我会发表。
更新:正如我承诺的,我已经写了第二篇关于数据可视化的博客。你可以在这里找到: 如何用一行代码用 Python 创建数据可视化
最后的想法
QuickDA 是我见过的最不可思议的 Python 库之一。通常,当我尝试新的库时,会有起伏。然而,我只对 QuickDA 有过正面的体验。就是管用,百分百值得一试。我强烈建议您用自己的数据集尝试一下,感受一下它的神奇之处。我向你保证,你会节省时间。你可以在这个博客和这个笔记本中找到更多的代码。
您的反馈对我很重要。让我知道进展如何。我可以等着看你将如何使用这个神奇的图书馆。编码快乐!
省钱并防止偏斜:Sagemaker 和 Lambda 的一个容器
关于为这两种服务构建容器的教程
答这篇文章写完后,AWS 发布了 Sagemaker 无服务器推断,你可以直接用它来代替。
P 产品生命周期通常需要不频繁的机器学习推理。例如,测试版可能只会收到少量的流量。在这些场景中,托管模型推理可能是昂贵的:即使没有推理请求正在被处理,模型推理服务器也总是开启的。
解决利用不足的一个好办法是无服务器产品,如 AWS Lambda 。这些允许您按需运行代码,但只为您使用的 CPU 时间付费。对于不频繁的推理来说,这是一个很有吸引力的环境,但是通常需要不同的软件栈和打包限制。因此,当需要扩展到无服务器范围之外时(即,当一个功能进入 GA 或我们需要 GPU 进行大批量处理时),工程师需要为实时端点重写推理代码。
重写推理代码耗费了工程师的时间,并且引入了环境偏斜的风险。与培训/服务偏斜一样,环境偏斜是由于软件依赖性或输入数据处理方式的差异而导致的模型性能变化。换句话说,重写推理代码可能会意外地导致模型性能下降。
在本教程中,我将展示如何为 AWS Lambda 和 Sagemaker 端点创建一个 docker 容器。使用这种方法,您可以在不经常访问的模型的无服务器上开始运行推理,然后在需要时转移到始终在线的 Sagemaker 端点。因此,您可以在最初保持低成本,并有效地扩展,而没有环境偏差或重写推理代码的风险。
github 上有完整的代码。
你容器里的叉子
Sagemaker 和 Lambda 都支持自带容器。Sagemaker 需要 HTTP 服务器,而 Lambda 使用运行时作为入口点。这个项目背后的关键思想是根据容器运行的环境来派生容器逻辑,但是使用相同的推理代码:
作者图片
在entry.sh
中分叉实际上相当容易:Sagemaker 在启动时向容器传递一个serve
参数,而 Lambda 传递函数处理程序名。因此,我们的entry.sh
脚本只需要检查命令行参数就可以知道它是在 Sagemaker 还是 Lambda 中运行:
#!/bin/bashif [ "${1:-}" = "serve" ] ; then
# Start an http server for Sagemaker endpoints..
exec /usr/local/bin/python serve.py
else
# run the Lambda runtime environment
exec /usr/local/bin/python -m awslambdaric ${1:-}
fi
(我省略了用于本地测试的 Lambda 仿真器,,但它在 github repo 中)
推理代码
这种方法的一个关键好处是您可以在两种环境中使用相同的推理代码。在这个例子中,我将使用来自 gluoncv 模型动物园的模型对图像进行分类,但是基本概念应该可以扩展到您自己的模型。
使您的推理代码模块化是这里的关键:文件serve.py
和lambda.py
应该只有最少的逻辑来验证输入。为此,inference.py
有两个主要功能:
load_model
-将模型加载到内存中infer
—接受输入和模型,返回推理结果。
加载模型需要一些小心,因为 Sagemaker 可以部署来自模型注册中心的模型,而 Lambda 不能。当这种情况发生时,工件被安装到容器中的/opt/ml/model
,我们将通过变量model_path
来标识它:
def load_model(model_path = None):
"""
Loads a model from model_path, if found, or a pretrained model
specified in the MODEL_NAME environment variable.
""" # Try to load from model_path if we are running on sagemaker.
if model_path and os.path.exists(model_path):
symbol_file = glob(join(model_path, '*symbol.json'))[0]
params_file = glob(join(model_path, '*.params'))[0]
return SymbolBlock.imports(symbol_file, 'data', params_file)
else:
# running in lambda, so load the network from the model zoo
model_name = os.environ['MODEL_NAME']
return gluoncv.model_zoo.get_model(model_name,
pretrained=True, root='/tmp/')
在 Lambda 示例中,上面的代码让用户在MODEL_NAME
环境变量中指定模型,并从模型动物园中加载模型。或者,您可以将模型打包在容器中,或者从 S3 装载。
infer
函数是一个简单明了的例子,说明了如何使用 gluon API 进行推理:
def infer(uri, net):
"""
Performs inference on the image pointed to in `uri.`
""" # Download and decompress the image
img = open_image(uri) # Preprocess the image
transformed_img = imagenet.transform_eval(img) # Perform the inference
pred = net(transformed_img)
prob = mxnet.nd.softmax(pred)[0].asnumpy()
ind = mxnet.nd.topk(pred, k=5 [0].astype('int').asnumpy().tolist() # accumulate the results
if hasattr(net, 'classes'):
results = [{
'label': net.classes[i],
'prob': str(prob[i])
} for i in ind]
else:
results = [{'label': i, 'prob': str(prob[i])} for i in ind] # Compose the results
return {'uri': uri, 'results': results}
Sagemaker 代码
当容器在 Sagemaker 端点中启动时,它启动一个在serve.py
中指定的 HTTP 服务器。服务器在POST /invocations
端点上处理推断请求。我在这个例子中使用了 flask ,但是任何 HTTP 框架都应该可以工作:
# HTTP Server
app = Flask(__name__)# The neural network
net = None[@app](http://twitter.com/app).route("/ping", methods=["GET"])
def ping():
return Response(response="\n", status=200)[@app](http://twitter.com/app).route("/invocations", methods=["POST"])
def predict():
global net
# do prediction
try:
lines = request.data.decode()
data = json.loads(lines)
results = inference.infer(data['uri'], net)
except ValueError as e:
error_message = f"Prediction failed with error '{e}'"
return Response(response=error_message, status=400)
output = json.dumps(results)
return Response(response=output, status=200)
invocations
端点简单地解码请求并将输入传递给上面指定的inference.infer
函数。这使事情变得简单:所有的逻辑都在推理文件中指定。
网络本身应该在启动服务器之前加载 main 函数,这也为一些句柄命令行参数提供了可能性:
def parse_args(args=None):
parser = argparse.ArgumentParser(
description='Server for inference on an image.'
)
parser.add_argument(
"--model-path", type=str, default='/opt/ml/model',
help="The model artifact to run inference on."
)
parser.add_argument(
"--port", type=int, default=8080,
help="Port to run the server on."
)
parser.add_argument(
"--host", type=str, default="0.0.0.0",
help="Host to run the server on."
)
return parser.parse_args(args)if __name__ == "__main__":
# parse command line arguments
args = parse_args()
# load the model
net = inference.load_model(args.model_path)
# start the server
app.run(host=args.host, port=args.port)
您会注意到model_path
被设置为/opt/ml/model
,这是 Sagemaker 从模型注册中心提供工件的默认位置。
拉姆达代码
Lambda 代码甚至更简单:您需要的只是一个处理请求的函数:
# Loads the model when the lambda starts up
net = inference.load_model()def handler(event, context):
global net
try:
return inference.infer(event['uri'], net)
except Exception as e:
logging.error(f'Could not perform inference on {event}', e)
return json.dumps({'error': 'Unable to perform inference!'})
第一次调用 Lambda 时加载模型,这会增加一些冷启动延迟,但只要 Lambda 处于活动状态,它就会留在内存中。
保持精益
AWS Lambda 是减少不经常使用的模型的推理成本的一个很好的方法,但是如果由于功能发布或产品流行而导致调用次数增加,成本会更高。切换到始终在线的 Sagemaker 端点降低了成本,但是可能需要重写推理代码,这需要时间,并且可能引入环境偏差。这里描述的容器可以在两种环境中工作,这使得在两种环境之间切换变得容易和快速,并获得最大的收益。
完整的代码可以在 github 上找到。
我们使用我在这里描述的技术来节省 Bazaarvoice 的推理成本。如果这种工作吸引了你,看看我们的职位空缺。
如果你喜欢这个故事,请考虑支持我,请给我买一杯咖啡或者通过我的推荐注册媒体。
用数据拯救动物的生命
变更数据
动物收容所分析介绍
据估计,目前世界上大约有 5000 家独立经营的动物收容所。我个人觉得可能会更多。这些收容所的运营效率很大程度上取决于它们满足其主要目标的能力,通常是优化选择指标。为了计算这些指标,需要收集、维护和分析数据。
但是,我们在动物收容所遇到过多少次数据的使用呢?我从来没有这样做过,直到我决定带着一份投机性的申请去当地的一家动物收容所,希望被聘为数据分析师实习生。我如何获得这个机会的细节已经在之前的一篇文章中详细讨论过了。
本文总结了不同的实践,这些实践可以付诸行动,以帮助庇护所在数据驱动的帮助下更好地发挥作用。或者我喜欢称之为动物收容所分析。
什么是动物收容所?
对动物收容所最常见的描述围绕着为动物提供一个栖身之所的想法,尤其是当它们被遗弃或受伤时。从更基本的意义上说,动物收容所为有需要的动物提供康复和住所。大多数情况下,经营这些机构的组织都是非盈利性的,它们的运作严重依赖于它们收到的捐款。
第一个动物收容所并不完全是人们所说的“动物友好型”。无家可归或“不受欢迎”的动物被收容所杀死,这是常态。然而,随着时间的推移,庇护系统开始看到一个向他们所保护的生物的利益的范式转变。这种变化甚至可以在所用术语的演变中看到。例如,“动物福利”被创造出来,从而反映了一种更人道的庇护方式。
看待庇护系统的另一种方式是将其视为“控制”流浪动物数量的一种手段。虽然有必要保护动物,但同样重要的是确保人类生活不受不受监督的动物种群的妨碍或威胁。这种观点的一些例子包括对流浪狗进行绝育以控制它们的数量。
通常,动物庇护所是指那些收容家畜或宠物如狗和猫的庇护所。然而,也有像我工作过的组织致力于保护城市野生动物。
城市野生动物指(通常)在城市化地区与人类共存的非驯化物种。例如,松鼠、蛇、风筝等。属于这一类。
数据在动物收容所扮演什么角色?
一个非常大的角色!数据可能是经营动物收容所最重要的部分。需要收集关于动物、手术成本、可用资金等的数据。正是这些数据可以用来在收容所执行几项重要的操作,包括拯救更多的生命、优化运营成本以及将动物与潜在的捐赠者联系起来。
现在,让我们后退一步,确定为什么需要将数据驱动的实践整合到庇护所的运营中。首先,数据帮助验证事实和数字的真实性。这反过来给庇护所带来了透明度。鉴于大多数庇护所都是慈善信托机构或非盈利机构,这种透明感是所有需求中的重中之重。
数据至关重要的另一个原因是,良好的数据收集有助于对进展进行精确评估。一个好的庇护所几乎总是有一个关于它想要达到的目标的强有力的计划。为了了解庇护所的成功程度,它需要能够客观地量化其贡献。
第三个原因是数据为提供了消息灵通的行动计划。例如,考虑庇护所 X 在一周的时间内接收 20 台起重机进行处理的情况。如果没有关于这些动物的数据,庇护所唯一能做的就是尽力拯救这 20 只鹤。然而,如果收集了关于这些起重机的数据,并且如果注意到所有的起重机都是从同一个地方运来的,庇护所就可以派出一个小组来审查在给起重机带来麻烦的地方发生了什么。这是解决问题的根本原因,比解决根本原因的个别结果更有效。
动物收容所数据收集的演变
在这个精彩的演讲中,玛蒂基金会的负责人克里斯汀·哈森和她的同事对收容所收集数据的软件进行了历史评估。
根据他们的观察,shelter 软件已经经历了 3 次浪潮才达到目前的水平。第一波的软件仅仅是用来执行记录动物数量的任务。基本上,它将动物视为“库存”,不支持收养。自然,我们可以想象这种软件运行的原始程度。
第二次浪潮比第一次浪潮要好,因为庇护所软件制造商现在开始认识到收养的重要性。软件变得更加以“拯救生命”的概念为中心。在此期间,收容所软件的另一个受欢迎的变化是,它变得更加用户友好,并提供了存储动物病史和行为模式的机会。
第三次浪潮,即当代,集中在社区。软件帮助跟踪数据,形成动物和人之间的桥梁。“避难所”现在有能力使用他们的数据来量化他们的影响和解决根本原因。
我对第三波略有不同。我相信第三次浪潮对于像印度这样的发展中国家的大多数动物收容所来说仍然是奢侈的。我工作的收容所有一个非常敬业、充满热情的团队收集所有动物的数据,但是他们使用电子表格和手动输入,从而避免使用任何类型的收容所软件。
第三次浪潮也可以被认为是以更严肃的态度将指标纳入庇护所运营的浪潮。度量是可以量化流程状态的量度。
在题为神奇的指标和令人眼花缭乱的数据的演讲中,康奈尔大学收容所医学项目的创始人 Janet Scarlett 博士提供了一个关于指标如何用于改善动物收容所的条件、跟踪疫情和监控收容所动物健康的视角。
在另一个名为更好地利用收容所数据的演讲中,Scarlett 博士强调了动物收容所的指标通常是未充分利用的资源,并介绍了使用平均停留时间(ALOS)来估计住房容量的想法。
动物收容所最常用的一些指标是
- **摄入量:**进入收容所的动物数量
- **结果:**有多少动物被收养、归还、安乐死、死亡、转移?
- **拯救率:**活着离开收容所的动物的百分比
- 实时发布率:(总实时结果/总结果)
- **停留时间:**特定的动物在收容所停留了多长时间?
迈向动物收容所分析理论
现在你已经了解了动物收容所的领域,是时候向你介绍动物收容所分析的概念了。这不是一个普遍定义的学科,但是我相信根据我在庇护所的经验,这个名字是合适的。
一切数据驱动的事情都始于识别利益相关者
数据驱动实践的核心任务是确保相关的利益相关者对解决方案感到满意。为此,首先要确定利益相关者。在动物收容所,基本上有 5 种利益相关者,如下所述。
动物收容所的利益相关者(鸣谢:作者)
根据费尔南德斯等人的说法。为了在动物福利领域做出更好的决策并实现持久的改善,鼓励利益相关者之间的合作的需求日益增长。然而,要做到这一点,必须有清晰的、令人信服的叙述和观点,与上述五类利益相关者中的每一类都有共鸣。
原始数据通常由避难所工作人员在行政层面进行处理。虽然这是庇护所工作人员活动的一个重要部分,但如果他们能够将原始数据可视化,并以有意义的图表和图片的形式查看,也会有所帮助。
实习生/受训人员和志愿者将根据工作人员提供的见解,更好地了解对他们的期望以及他们需要采取的行动。
咨询委员会将能够通过观察可视化来评估避难所影响的深度,他们将能够在很短的时间内做到这一点。
最后,在 PFA 这样的动物收容所中,公众无疑是最重要的利益相关者。让社区了解庇护所的工作和努力是至关重要的,为此,该组织必须通过精心设计的叙述与更广泛的公众沟通。
数据驱动的决策之所以重要,一个关键原因是因为它是的目标。它为庇护所的活动创造了可量化的视图,因此像一个共同的点,供相关各方讨论。
定义动物收容所分析
用学术的方式下定义并不完全是我的优点之一。因此,我将利用一个图表来定义这个动物收容所分析的想法。这个图表非常简单明了。
动物收容所分析的 3 个主要组成部分(鸣谢:作者)
使用动物收容所分析
动物收容所收集数据,如动物信息、救援次数、救援地点等。这些数据集包含的模式可以让我们更深入地了解庇护所的运作。领域专家和数据团队可以坐在一起,讨论关键焦点,分析以获得见解,使用指标来量化庇护所的进展,甚至决定新的指标来定义庇护所的功效,并将这些纳入庇护所的实践中。
以下是我能想到的动物收容所分析有益的广泛使用案例:
了解庇护所的运作
细节,如多少救助,多少志愿者,不同种类的物种,收养和捐赠者的数据等。
了解特定物种的脆弱性
关于某一特定物种的救援和状况的细节
救援热点地理测绘
地理可视化的位置,从那里给定物种的大部分救援发生
建立公共关系,提高社区参与度
引导数据分析,以规划更好的推广计划,并将潜在的捐赠者与受伤的动物联系起来
动物收容所分析的当前挑战
了解了数据分析如何帮助避难所改善运营后,现在是时候讨论一些使这一想法不那么容易实施的关键挑战了。
这里提到的所有挑战都是我在收容所实习时直接面对的。其中一些可能是其他庇护所共有的,而一些可能不是。
挑战 1:数据质量不令人满意
没有坏数据,只有收集或维护得不令人满意的数据。这是我上班第一天学到的一课。该收容所有一些令人印象深刻的记录,记录了它在过去 6 年中救助的动物,然而,仔细观察后发现,它的维护方式存在一些问题。
首先,每年收集数据的方式不一致。每年,栏目都要重新命名或推出新栏目;但是这些列很少被填充,因此导致了丢失数据的问题。这些不一致反映了在收集动物记录时缺乏框架。
另一个突出的问题是数据输入不一致。庇护所数据中发现的不一致之处包括
- 拼写错误:同一物种的名字每次都有不同的拼写
- 大小写错误:随意使用大写和小写
- 学名混淆:一些物种的学名并不是该物种的实际学名
- 日期的不规则格式
如果组织必须做出数据驱动的决策,这些数据问题会导致数据的质量低于应有的水平。质量差的数据可能导致错误见解的上游传播,进而导致错误决策。没人想这样。
清理所有这些数据花了我几天时间。尤其是学名混淆的部分,因为这需要我谷歌每个物种的名字,并检查其记录的学名是否正确。我所遵循的数据清理过程是另一篇文章的主题!
挑战 2:缺乏庇护软件
我不认为自己是这方面的专家,但印度的大多数动物收容所还没有明确的收容所软件。电子表格是这些组织用来存储数据的。
现在,在我的职业生涯中,评论电子表格与其他软件的争论还为时过早。但是,我从实习中学到的一件事是,使用电子表格存储数据比使用专门构建的软件存储数据需要更仔细的考虑。
为数据收集而构建的软件可以强制执行内置的特定标准,从而帮助从源头解决数据质量差的问题。虽然像 MS-Excel 这样的电子表格确实允许你使用约束条件来确保输入数据时的质量水平,但所涉及的复杂程度低于定制软件。
挑战 3:采用数据驱动文化的惰性
再说一次,我不是专家。但是,我坚信动物收容所没有采用数据驱动文化的一个原因是因为这样做太不容易了。从我在收容所的经验来看,他们做的工作是惊人的,而且非常耗时。由于这是一个非营利组织,他们几乎总是在资源方面受到挤压,但每天都设法挽救如此多的生命。
有这么多事情正在进行,整合新的优先级总是一个挑战。而且,总有一个的问题“这值得我们花时间吗?”。回答这个问题总是有点困难,因为任何答案都无法说服利益相关者,除非他们愿意在游戏中加入一些内容。
如何解决这些挑战?
识别挑战是一项相对容易的任务。真正的价值在于产生解决方案的能力。在庇护所面临上述三大挑战的背景下,我在最终报告中向利益相关者提出了一些建议,我将在此讨论其中几项。
解决方案 1:创建数据录入规则手册
这个想法是在输入数据时有一套固定的、特定于组织的指导原则。这将确保数据的统一结构,从而简化以后的分析过程。
解决方案 2:倡导数据驱动的文化
如挑战 3 所述,这并不容易。然而,如果收容所能做到这一点,更多的生命将被拯救。动物收容所发展这种数据驱动文化的几种方式是
- 提高志愿者和员工的数据素养。如果他们知道数据的重要性,他们在处理数据时肯定会更加小心。
- 包括在庇护所进行技术实习,熟悉计算和分析的学生可以提供服务,帮助庇护所的运营。
- 联系那些愿意帮助建立数据库或为庇护所开发 CRM 软件的公司,作为其 CSR 活动的一部分。
- 维护关于数据的相关文档并收集元数据,即关于数据的数据。
- 确保庇护所的每个人都对数据驱动的流程负责。每个员工都必须认识到,任何在 T 时刻乱糟糟的数据,除非被打断,否则在 T+1 时刻只会变得更糟!
结论
动物收容所的数据有很大的潜力,可以积极地平衡人与动物之间的互动。一些避难所已经意识到了这一点,而更多的避难所还没有挖掘出隐藏在电子表格中的大量数据。
如果要帮助更多的动物,现在是所有动物收容所采用数据驱动的做法的时候了。拥有清晰的数据驱动实践也有助于收容所衡量其作为一个组织的进展。正如彼得·德鲁克(Peter Drucker)曾经说过的一句名言*“被衡量的,被管理的”*。
这篇文章最初发表在我的个人博客上。
如果你对这篇文章的内容有任何疑问,请随时联系我。你可以在 Linkedin 和 Twitter 上找到我。
使用数据科学节省资金
为什么班上的那个学生问你的数学老师“我什么时候会用到这些东西?”可能破产了
在之前的一篇文章中,我讨论了如何使用 STL 算法将任何时间序列分解成季节、趋势和噪声部分。我用亚马逊的股票价格向你展示了一个例子。在这篇文章中,我将向你展示如何用同样的技巧在租房时省钱。我将使用公寓列表提供的 2017 年至 2021 年间单卧室公寓的月平均租金。如果你想看示例代码,请看我之前的文章。
如果你没有读过我之前的文章,这里有一篇关于 STL 算法的简介:它将任何时间序列作为输入,并将该时间序列分解为季节、趋势和余数(即噪声)分量。例如,下面是马萨诸塞州波士顿一套一居室公寓的平均月租金(第一个图表),它被分解为三个部分(第二个图表):
作者图片
作者图片
如果我们只关注季节性因素,我们可以看到你应该在一年中的哪个月签订租约,以获得最便宜的月租金。在波士顿,最低到最高的季节性是-60 美元到+50 美元,这意味着在某些月份签署租约将使你的月租金平均减少 60 美元,而在其他月份将增加 50 美元。
作者图片
对于波士顿来说,季节性在八月最高,一月最低。因此,你应该尝试在 12 月和 1 月之间签订年度租约(与季节性高峰相比,你每月将节省 110 美元),避免在 5 月和 8 月之间签订(与季节性最低价格相比,你每月将多支付 110 美元)。因此,如果你住在波士顿,一些带有几行 R 代码的开源数据每年可以为你节省 1300 美元。并非所有城市都表现出与波士顿相同的季节性。例如,让我们看看佛罗里达州的迈阿密和德克萨斯州的奥斯汀。
作者图片
在佛罗里达州的迈阿密,我们看到季节性在三月份最大,大约每月+15 美元,在十月份最小,每月-15 美元;没有波士顿那么戏剧化。选择正确的月份在迈阿密签订租约,佛罗里达州每年将为您节省约 360 美元。德克萨斯州奥斯汀的季节性也有类似的范围:八月的最高值为每月 20 美元,二月的最低值为每月 15 美元。如果您在合适的时间签订租约,在德克萨斯州奥斯汀市(例如,每年 420 美元)比在佛罗里达州迈阿密市可以节省更多。
作者图片
作者图片
公寓列表中的数据集包含 479 个城市的完整数据。一个有趣的问题是:“哪些城市表现出最大和最小季节性之间的最大差异?”按照从大到小的顺序排序,让我们看看所有差价大于 100 美元的城市:
作者图片
全美有 26 个城市,在合适的月份签订公寓租约,每年至少能为你节省 1200 美元。结果似乎偏向于“科技城市”(如山景城、库比蒂诺、西雅图、雷德蒙),如果您在正确的月份签署租约,加利福尼亚州福斯特市每年可节省 2700 美元。我们可以查看季节性图表,找出几个有代表性的城市的“神奇”月份。
作者图片
作者图片
作者图片
在山景城、福斯特城和雷德蒙,在 6 月或 7 月签署公寓租约将比你等 6 个月后在 11 月或 12 月签署多花 100 到 225 美元。在上面列出的 26 个城市中,合理安排时间可以让你每年多赚 1200 到 2700 美元。如果你看到一个学生问“我什么时候才能在现实生活中使用这些东西?“一边抱怨他或她的数学课,一边给他们看这篇文章!
如果你想看看示例 R 代码,更好地理解 STL 算法,看看我早先的文章。但是如果你想读一些不太专业的东西,我推荐我的文章优先化分析工作的最佳实践。如果你今天对统计学更感兴趣,试试关于 A/B 测试的这篇文章或者关于三(3)个最重要的统计测试的这篇文章。最后,如果你想在 1-2 分钟内快速阅读,请尝试这篇文章中的八(8)个技巧来改善数据科学和业务用户之间的交流。
用人工智能拯救卑微的蜜蜂
真实世界人工智能
TinyML 帮助保护蜜蜂免受邪恶贪婪的捕食者的伤害
你昨天吃了什么?它包括杏仁、苹果、蓝莓、花椰菜或卷心菜吗?
对于我们这些有幸获得大量这些食物的人来说,我们不能再认为它们是理所当然的。
而且不是因为气候变化,土地短缺,或者破坏性的农业做法(虽然这些本身就是问题),而是因为卑微的 蜜蜂 。
根据宾夕法尼亚大学的研究,蜜蜂帮助了超过三分之一的全球粮食生产,尤其是像蓝莓、杏仁和苹果这样的作物。
他们受到了威胁。
近年来,蜜蜂受到了一种肉眼几乎看不到的邪恶捕食者的攻击——瓦螨。
这种螨虫是一种致命的寄生虫,它已经给世界各地的蜂群造成了巨大的破坏,首先是削弱个体蜜蜂,然后是感染整个蜂巢。
然而,在澳大利亚,瓦螨还没有找到一个据点——澳大利亚是最后一个没有这种恶性螨的有人居住的大陆。
但是 Varroa 已经侵袭了澳大利亚的两个近邻— 新西兰和巴布亚新几内亚— ,所以澳大利亚的养蜂人不顾一切的想要控制它。
幸运的是,人工智能 (AI)正在赶来救援。
而且不是随便什么 AI,而是tinyML。
TinyML 可以帮助解决巨大的问题
TinyML 是人工智能的一个新兴领域,它将机器学习和深度学习的巨大能力打包到一个微小的形状因子中。
这使得它成为资源受限应用的理想选择,在这些应用中,尺寸、功耗和连接性非常重要,而且有许多这样的应用。
TinyML 通过使用诸如修剪(删除不需要的网络节点)和量化(将浮点数转换为整数)等技术来缩小预先训练好的(大型)机器学习模型。
这些预训练的模型然后被用于 tinyML 部署中的推理(预测或分类),这比训练需要更少的计算能力。
这些模型在微控制器上使用专门的编码平台实现,如 Tensorflow Lite 。
微控制器是紧凑的专用集成电路,是物联网革命的主力。
直到最近,由于资源限制,这些微控制器的功能范围有限。然而,多亏了 tinyML,这些’微型机器已经开始变得’智能’。
无 Varroa 蜜蜂的最后边疆
在澳大利亚,为了帮助抵御瓦螨,个体养蜂人一直在密切监视他们的蜂箱。
此外,在澳大利亚各地的港口和其他入境点设置了特别指定的蜂箱,并由检疫检查员例行检查。
到目前为止,这种方法一直很有效。
但 Varroa 在澳大利亚站稳脚跟可能只是时间问题,而且已经出现了几次差点违约的情况。
例如,2018 年,一艘美国集装箱船抵达澳大利亚,船上有受 Varroa 感染的蜜蜂。幸运的是,澳大利亚当局在那种情况下设法识别并遏制了威胁。
虽然监测过程迄今为止一直有效,但这是"精心手工",的亚当·麦克纳马拉称Bega Cheese,一家大型澳大利亚乳制品生产商最近进入蜂蜜业务。
更重要的是,即使是短时间的未被发现的 Varroa 暴露也会是一个问题。维多利亚养蜂人协会的阿里斯·彼得拉托斯建议说,“如果它已经存在了一个月、一周或两周,那可能已经太晚了”。
因此,澳大利亚农业渴望找到更好的监测 Varroa 的解决方案,他们求助于 T2 的尖端技术。
tinyML 是如何帮助蜜蜂的
Bega 与创新的澳大利亚科技公司【xai lient】和 Vimana Tech 合作,启动了 紫色蜂巢项目 以帮助改善澳大利亚的瓦螨监测。
Purple Hive 的目标是在澳大利亚建立一个能够自动检测瓦螨的蜂巢网络。这将使 Varroa 监控变得更加容易、更具可扩展性和成本效益。
但是自动检测 Varroa 螨虫是一项艰巨的任务——螨虫非常小,几十只蜜蜂可以一次进出一个蜂巢。“做起来挺难的,就像大海捞针”,反映了 Shivy Yohanandan , Xailient 的联合创始人。
许多蜂房也位于偏远地区,电力或通信有限。任何检测设备都需要在严格的资源限制内工作,并达到高度的可靠性。
但是 Xailient 专门研究极其高效的计算机视觉算法,使得有效的、资源受限的解决方案成为可能。
利用他们创新的人工智能能力,Xailient 和 Vimana Tech 开发了一种 tinyML 实现,可以满足自动检测瓦螨的所有挑战。
它是这样工作的:
- 一个特殊的 3D 打印蜂箱—紫色蜂箱— 装有摄像头和人工智能技术
- 蜂巢的入口有 360 度的摄像机,可以捕捉每只进入的蜜蜂的图像
- 然后,人工智能算法帮助识别是否有任何进入的蜜蜂携带瓦螨
- 如果检测到瓦螨,实时警报就会发出,同时还有被感染蜜蜂的图像
作为 tinyML 解决方案,紫色蜂巢中使用的人工智能算法和相关硬件*高效、低功耗,并且具有有限的连接要求——*非常适合部署在广泛的偏远地区。
此外,紫色蜂箱入口设备,实际上包含螨虫检测技术的单元,是太阳能供电的,可以安装到现有的蜂箱上——这使其便携,易于在现有的蜂箱网络中推广。
给蜜蜂一个战斗的机会
澳大利亚很幸运地避免了瓦螨对其蜜蜂造成的破坏,但这种运气可能不会持续太久。
通过转向创新的技术解决方案,像紫色蜂巢这样的项目将为蜜蜂提供一个战斗的机会,以保持领先于邪恶的 Varroa 捕食者。
Purple Hive 的核心 tinyML 显示了资源受限的实现有多么有用——在一个充满资源饥渴技术的世界里,有无数种情况下高效、集中和低资源的解决方案正是所需要的。
这是 tinyML 的承诺。
概括起来
- 蜜蜂在世界粮食生产中扮演着重要的角色,像蓝莓、杏仁和苹果这样的农作物尤其依赖蜜蜂
- 然而,蜜蜂一直受到一种邪恶的捕食者的攻击,这种捕食者是瓦螨,它能在几周内毁灭蜂群
- 澳大利亚是最后一个没有瓦螨的有人居住的大陆,人们对通过有组织的监控努力保持这种状态很感兴趣
- 但是监测瓦螨是一个劳动密集型和困难的过程,所以更有效的方法正在被寻求
- 使用尖端技术和 tinyML 解决方案,澳大利亚公司 Bega 、 Xailient 和 Vimana Tech 在自动监控瓦螨方面处于领先地位,使其成为一个更容易、更具可扩展性和成本效益的过程
- Xailient 利用其专业的计算机视觉算法和 tinyML 专业知识在资源紧张的情况下开发了有效的 Varroa 检测实施方案
告别循环,迎接优化
使用 NumPy 优化 Python 代码
虽然 Python 仍然易于使用,学习起来很快,并提供了大量几乎可以做任何事情的外部库,但它有一个致命的弱点:它很慢。
当然,在人眼看来,它的迟钝似乎可以忽略不计。通常 Python 只落后于其他编程语言几毫秒;然而,当迭代数百万甚至数十亿个数据点时,它会迅速累加。
NumPy 提供了独特的解决方案。在允许用户仍然编写 Python 的同时,它将 Python 转换成专门为数值分析优化的写得很好的 C 代码。
使用 NumPy 数组可以将脚本的性能提高一到两个数量级,并且只需要很少的学习时间。
向量运算
传统的循环方法不是对数组中的每个元素执行一个函数,而是对数组中的所有元素同时应用一个函数。
import random# create a list of random integers
data = [random.randint(0, 100) for i in range(1000000)]
为了演示矢量运算的效用,创建了一个示例数据集。上面的代码生成 1,000,000 个介于 0 和 100 之间的随机整数的列表。
为了举例,将测量对列表中的每个元素取余弦的性能。
# import math for cosine function
import math# create a new list for the data
new_data = []# loop through the data, take cosine and add it to the new list
for i in data:
new_data.append(math.cos(i))
上面的代码使用了一个典型的循环来遍历列表并取每个值的余弦值。这是通常想到的传统迭代方法。不幸的是,这用了大约 0.31 秒,相当慢。
# import math for cosine function
import math# create a new list for the data
new_data = [math.cos(x) for x in data]
除了循环,还可以使用列表理解,这将时间减少到 0.24 秒。虽然比传统的循环有所改进,但仍然有些迟缓。
# transform the data into a NumPy array
data = numpy.array(data)# apply the vector operation
new_data = numpy.cos(data)
最后,NumPy 用于相同的操作。第一行将列表转换成数组,第二行应用向量运算。
注意,不是使用标准库中数学模块的余弦函数,而是必须使用 NumPy 的余弦函数。
除了生成更干净易读的代码,整个过程只需要 0.03 秒左右。这大约比使用传统循环快 10 倍,比理解列表快 90%。
通过数据过滤
NumPy 擅长的另一个常见任务是数据过滤。使用与以前相同的数据,将对超过 50 的所有值进行筛选。
# Using a traditional loop
new_data = []
for i in data:
if i > 50:
new_data.append(i)# Using a list comprehension
new_data = [i for i in data if i > 50]
和以前一样,普通 Python 可以使用传统的循环或列表理解来过滤列表。前者需要 0.23 秒,后者需要 0.11 秒。
# Convert data into a NumPy array
data = numpy.array(data)# Create a filter
data_filter = data > 50# Filter for values greater than 50
new_data = data[data_filter]
然而,NumPy 没有使用循环,而是提供了一种直观的替代方法。将列表转换成数组后,下一行创建一个过滤器。如果迭代,过滤器将输出符合条件的 True 和 False 值。
换句话说,如果数据中的第一个值大于 50,则筛选器中的第一个值将为真,反之亦然。
一旦创建了过滤器,就可以使用熟悉的拼接符号将其应用于数据,创建一个值大于 50 的新数组。整个过程只需要 0.02 秒,无论是循环还是列表理解都是一个巨大的进步。
对广播的解释
广播关注大小不等的数组上的算术运算。要工作,数组的尾轴必须相等,即使维数不相等。下图给出了一个直观的例子。
有效广播的直观示例
在这种情况下,广播是兼容的,因为在水平轴上有一个相等的数字。上述示例采用 1 X 2 数组,并将其添加到 2 X 2 数组中的每一行。
有效广播的另一个直观例子
可选地,垂直轴可以是兼容的。同样的原理适用于 2×1 阵列应用于 2×2 阵列的每一列。
无效广播
如果两个轴都不相等,如上例所示,则可能无法应用广播。相反,Python 会返回一个值错误。
广播代码示例
在将广播应用于更高维度的数据之前,下面的示例使用了与前面的演示中使用的 1,000,000 个 0 到 100 之间的整数相同的列表。
# Very simple broadcasting
new_data = numpy.array(data) * 2
像以前一样,不使用循环或列表理解,而是简单地将列表转换为 NumPy 数组并应用运算(在本例中乘以 2)提供了一种简洁有效的数据转换方法。
从广播的角度来看,一个 1 X 1,000,000 的数组乘以一个 1 X 1 的数组(也就是所谓的一个数字)。
然而,当应用于更复杂的事物时,广播要有趣得多。假设数据是一个 2 X 1,000,000 的数组:
# Create a 2 X 1,000,000 dataset
data = [
[random.randint(0, 100) for i in range(1000000)],
[random.randint(0, 100) for i in range(1000000)]
]
举例来说,第一组 1,000,000 个数据点中的所有数据都将加 1,第二组中的所有数据都将加 2。
new_data_1 = []
new_data_2 = []# Using loops to inefficiently broadcast
for i in range(len(data)):
for j in data[i]:
new_data_1.append(data[i][j] + 1)
for k in data[i]:
new_data_2.append(data[i][k] + 2)
new_data = [new_data_1, new_data_2]
在一个相当不公平的比较中,一组嵌套循环可以用来完成目标,但结果是草率的,需要大量的开销。如果使用另一组尺寸,也需要做很多调整。
然而除此之外,它还需要 0.83 秒的运行时间。
# Using list comprehensions to broadcast
new_data = [
[x + 1 for x in data[0]],
[x + 2 for x in data[1]]
]
列表理解提供了一个有吸引力的选择。上面的代码更短,更容易阅读,运行只需要 0.17 秒;然而,试图将这种方法用于更复杂的数据(如 100 X 100 的数组)将很难复制。
# Convert data into a numpy array
data = numpy.array(data)# Create a small array to broadcast
operator = numpy.array([
[1],
[2]
])# Use NumPy broadcasting
new_data = data + operator
最后,使用 NumPy 进行广播的例子提供了一种更直观的方法。将数据转换为数组后,将创建一个 2 X 1 数组来修改数据集。为此,在最后一行中使用了一个简单的加法运算符。
虽然这种方法比使用 list comprehensions 要多一些行,但是它更灵活,可读性更好,最重要的是,运行起来只需要 0.04 秒。
结论
Python 提供了很多实用工具,但是速度传统上不是它的优势之一。然而,NumPy 库通过直观的语法提供了很大的性能提升。
简单地放弃循环和列表理解,转而支持 NumPy 操作,可以在不增加不必要的复杂性的情况下大幅提高代码速度。理解它的用途是任何大型数据项目的必要条件,实际上也是数据科学的要求。
告别截图,使用 Datapane 进行数据科学报告
7 分钟阅读完整的 Datapane 教程
动机
我经常喜欢在博客上写数据科学相关的文章。更准确地说,我是在介质和 Quora 上写的。有时,我用 python 创建一些交互式数据可视化,或者用 jupyter notebook 的 markdown 选项创建一些美学表现。但是当我想把它发布在 medium 这样的博客上时,我必然会使用截图或 gif 来分享交互式可视化或表示。几天前,我一直在寻找分享这些互动情节和降价展示的方法。在搜索了很多之后,我发现了一些给出了一些方向的文章。不幸的是,没有完整的指导方针让我可以轻松地使用该技术来共享交互式可视化和表示。经过一点研究, Datapane 似乎是完成这项工作最有用的工具。现在,是时候分享我的发现,让你的数据科学相关博文更具互动性和美感。
简单又好玩…让我们开始吧……
数据面板概述
Datapane 是为以编程方式分析数据和创建报告的人准备的。到目前为止,Datapane 支持以下库、语言和文件格式来生成交互式报告。
Datapane 报告非常灵活,还可以包含页面、选项卡、下拉列表等等。
创建后,报告可以上传到 web,在云中动态生成,或者嵌入到您自己的应用程序中,在那里可以浏览数据,并可以交互地使用可视化。
开始使用数据面板
在使用 Datapane 之前,您应该知道 Datapane 是一个开源的 Python 库,它使得用 Python 构建交互式报告变得很容易。Datapane Community 是一个免费的在线发布 Python 报告和协作的服务。
现在,只要按照步骤
- 在你的电脑上安装数据面板库
在您的cmd
或anaconda command
提示符下运行命令
*pip3 install datapane
or
conda install -c conda-forge "datapane>=0.11.0"*
如果你是 mac 或 linux 用户,你可以遵循这里提供的指南。
2。登录到数据面板
首先,你必须在 Datapane 网站注册。登录后,他们会为您提供一个令牌。使用令牌,您可以轻松地从本地 pc 登录到 Datapane。令牌可以从 链接中找到。如果您点击该链接,您将进入一个页面,在那里您可以找到如下令牌。
作者照片
这是整个过程的 gif 图
作者 gif
3。在 Datapane 文本编辑器或 jupyter 笔记本中呈现 markdown 文本,并将其共享给 medium
您可以使用 Datapane 文本编辑器和 python 来创建可共享的降价。下面的 gif 展示了用 Datapane 文本编辑器创建 markdown 文本的全过程,并分享给 medium。
作者 gif
让我们用 python 做同样的事情。为此,我编写了以下代码。
该代码将在您的本地目录中保存一个 html 版本的降价文本。如果你想把它上传到 Datapane 网站,只需把最后一行代码从report.save(path=”Markdown.html”,open=True)
改成report.upload(name=”Markdown down with jupyter notebook”)
。它将保存一个输出到数据面板报告。完整的指南如下所示。共享过程与 Datapane 文本编辑器 gif 中显示的相同。
作者 gif
你会得到如下文本。
4。用 python 渲染 HTML 代码并创建交互式表格
Datapane 也有助于用 python 呈现 html 代码。我按照下面的代码创建了一个交互式表格。
代码将把表格上传到 Datapane 报告中。如果你想把它保存到你的本地目录,只需要在代码的最后一行使用.save(path=’report.html’, open=True)
就可以了。介质中的共享过程与 gif 的markdon
部分所示相同。
输出—
5。带数据面板的可交互数据表
Datapane 的交互式数据表是一个非常棒的工具,可以用交互的方式来表示你的数据集。
我已经编写了一段代码,使用 seaborn 库构建一个内置的数据框架,并使用 datapane 将其导出为数据表。它生成以下输出。
**我觉得不可思议。 ***你可以在内置 EDA 中搜索、过滤、排序、探索等等。它涵盖了一个数据集的全部报告。*gif 演示了数据表的特性。
作者 gif
6。互动情节和可视化
没有其他类似的工具来分享这种类型的交互式绘图和可视化。目前 Datapane 支持**Altair, Matplotlib / Seaborn, Bokeh, Plotly ,Folium**
库进行可视化。dp.Plot
块从一个受支持的 Python 可视化库中取出一个绘图对象,并将其呈现在您的报告中。我以**Plotly**
为例展示了一个演示。
数据面板输出
7。带降价的组合图
这更有趣,因为它看起来像是用任何文本编辑工具创建一个交互式报告。降价文本很容易与互动情节相结合。一个例子和代码。
数据面板中的输出
8。写公式分享
公式块允许您轻松地将 LaTeX 格式的公式添加到您的报告中,并带有可选的标题。关于乳胶配方的简单介绍可以在这里找到。
**import datapane as dpdp.Report(
dp.Formula(r"\frac{1}{\sqrt{x^2 + 1}}", caption="Formula")
).upload(name="First formula")**
输出
在引擎盖下,Datapane 使用 MathJAX 在浏览器中呈现方程,而不是一个完整的 TeX 引擎。这意味着您的一些 TeX 输入可能无法在 Datapane 系统上正确呈现——阅读 MathJAX 文档了解更多信息。
9。在媒体或其他博客上集成代码
代码块允许您将语法突出显示的源代码嵌入到报表中。这个块目前支持 Python 和 JavaScript。比 github gist 更赚钱。
数据面板中的可共享代码
10。将网格布局添加到您的报告中
如果您将一个块列表(比如Plot
和Table
)传递给一个报告,那么默认情况下,它们会被放置在一列中,每个块一行。如果您想定制行和列,Datapane 提供了一个Group
组件,它接受一个块列表和一些列和/或行,并将它们放在一个网格中。
如果我们以前面教程中的例子为例,但是想要并排放置绘图和数据集,我们可以使用 specify this using Group
并指定列数。
数据面板共享报告
11。向您的报告添加多页内容
Datapane 上的报告可以有多个页面,在报告的顶部以选项卡的形式呈现给用户。这些可以像 Excel 文档中的工作表一样使用。
要添加页面,使用报表顶层的dp.Page
块,并用title
参数给它一个标题。下面给出一个例子。
数据面板多页报告
12。多个选项卡并选择报告
当我们需要报告的背景时,这是很有用的。
Datapane 在dp.Select
块上提供了两个选择选项:下拉菜单和选项卡。如果选项少于五个,则默认为制表符,否则将使用下拉菜单。要覆盖默认值,请将参数type = dp.Select.DROPDOWN
或type=dp.Select.TABS
传递给dp.Select
块。
数据面板报告
此外,如果你想你可以添加文件和图像,python 对象,嵌入到你的报告。更多详情请点击 链接 。
我个人认为,如果你能用审美的方式来表现数据,那么数据就是美。数据可视化的最佳方式是交互式可视化。交互式和美观的数据可视化可以提供对数据的有意义的洞察。Datapane 让这个过程变得非常简单。在了解 Datapane 库之前,对我来说,在任何博客上分享数据科学报告是一个大问题,不管我是使用截图还是创建 git 来分享它。
希望这篇文章能对你分享数据科学报告有所帮助。
我还挑了一篇有趣的文章供你进一步阅读……
**
祖贝尔·侯赛因
说美妙的事情:欧洲电视网歌词的情感分析
实践教程
几十年来,欧洲电视网一直在娱乐观众。这篇文章问,关于这场比赛,欧洲电视网的歌词告诉了我们什么?
由 BRUNO EMMANUELLE 在 Unsplash 上拍摄
在过去的 65 年里,欧洲电视网的歌唱比赛娱乐了来自欧洲和更远地方的观众。这场比赛已经发展到与 50 年代和 60 年代的比赛完全不同的地步。这些早期的比赛是二战后通过跨境广播团结各国的一种方式。虽然它看起来确实不同,但在欧洲电视网歌曲的歌词中,什么发生了变化,什么保持不变?
作为一个欧洲电视网的超级粉丝,我对 Kaggle 的“欧洲电视网歌词”数据集产生了兴趣。该数据集包括从 1956 年开始到 2019 年上次比赛期间欧洲电视网歌曲大赛中所有歌曲的排名和歌词。我从克里斯托贝尔·维斯对金属乐队歌词的分析中获得了方法和代码的灵感。在他的博客中,他分析了金属乐队每十年的歌词。这个博客计划实现同样的目标。虽然有 1564 首歌用多种语言演唱使得这种分析有点困难。
在这篇文章中,我会找到欧洲电视网歌词中常用的词。情感分析然后被应用到欧洲电视网的歌曲中。这将显示几十年来歌曲的积极或消极趋势。最后,我使用 Genius API 从被取消的 2020 年比赛中抓取歌曲。通过将这些方法应用于 2020 年版,我检验了这场竞赛是否会以同样的趋势继续下去。
必需的库
- 熊猫和 Numpy 进行数据分析
- Matplotlib 和 Wordcloud 制作漂亮的剧情
- NLTK 为停用词
- Scipy 、 Sklearn 和 StatsModels 获取有用的统计函数
- 用于情感分析的文本块
- LyricsGenius 使用 Genius API 抓取歌词
- 脚本 helpers.py ,最初由克里斯托贝尔·韦亚斯创建,经过修改以帮助这个特殊的数据集
一个笔记本的代码可以在这个链接中找到,所需的文件不包括来自 kaggle 的 Eurovision 歌词数据集,可以在我的 github 中找到。
词频分析
我们首先通过词频分析调查欧洲电视网的热门话题。这里感兴趣的两个函数是 Sklearn 的 CountVectorizer,它计算单词的频率,以及用于绘制单词云的 WordCloud。
第一个预处理步骤是为每首歌曲定义一个唯一单词列表。这意味着本节的分析侧重于歌曲中使用最多的词,而不是总体上使用最多的词。如果我们选择后者,我敢肯定“la”或“oooh”会是最受欢迎的,但这些抒情的选择并不有趣。
另一个重要的预处理步骤是定义停用词。这些词很常见,但没有太多意义。因此,我想把它们从我们的分析中剔除。一些停用词的例子是英语中的“the”,德语中的“der”或瑞典语中的“en”。多年来,比赛中使用了 50 多种语言。这可能是一个问题,因为我们将不得不定义数百个单词来阻止分析。幸运的是,NLTK 包允许我们从竞赛中最流行的语言中定义停用词。它们保存在名为“语言”的列表中。
languages = ['english', 'german', 'spanish', 'french', 'dutch', 'italian', 'danish', 'swedish', 'finnish', 'slovene', 'greek', 'turkish', 'arabic', 'romanian', 'hungarian', 'russian']
敏锐的眼睛可以看出这个列表中的语言不超过 50 种。不幸的是,NLTK 不支持很多 Eurovision 语言。然而,列表中的这些语言包括最流行的。我们会发现,我们的分析并没有因为没有省略挪威语、马耳他语、冰岛语等语言的停用词而受到影响,或者在比利时 2003 年加入的情况下,一种虚构的语言。通过将这些停用词输入 Sklearn 的 CountVectorizer 算法,我们可以找到最流行的词是什么。
每十年欧洲电视网歌词中最流行的词
很明显,从 80 年代到 90 年代,流行语言发生了转变。这很好解释。从 1966 年到 1972 年,然后从 1978 年到 1998 年,各国都被要求用本国语言演唱。更多的参与国将法语作为国家语言,而不是英语。90 年代是一个奇怪的年代,因为这条规则在 1998 年之前一直存在,然而英语“love”却是最流行的。这可能是摩纳哥和卢森堡分别从 1979 年和 1993 年缺席比赛的原因。
“爱”作为一个主题在欧洲电视网的流行是很难改变的。前三十年被法国的“爱情”所主宰。这在 20 世纪 80 年代被“vie”取代。这种用法的一个著名例子是 1986 年比利时唯一一次凭借桑德拉·金的《我的生活》赢得竞赛。在过去的三十年里,“爱”再次位居榜首。尽管欧洲电视网已经发展了,歌唱爱情仍然很受欢迎。“爱”的流行是 2016 年比赛中 interval act 的主题之一,他们剖析了如何写出完美的欧洲电视歌曲。
如果你看过那个视频,你现在应该是欧洲电视网歌曲创作的专家了。
该视频以 2016 年主持人和 2015 年获奖者芒斯·塞默洛问“有公式吗”开始。虽然这种间隔行为集中在欧洲电视网之夜的风格选择,歌词也非常重要。那么哪些选择曾经流行过,现在流行什么呢?为此,为每十年的歌词绘制了一个词云。
50 年代和 60 年代的词汇云
70 年代和 80 年代的词汇云
90、00、10 年代的词云。
恋爱的话题很占优势。这得益于几十年来对“心脏”或“心脏”的反复提及。同样被反复提及的还有“生活”或“vie”,80 年代最流行词汇的获得者。提到“时间”或“温度”是很常见的。这伴随着对“日”和“年”的提及。一些次要但常见的话题包括“世界”、“地球”、“梦”、“夏天”和“太阳”。
在前四个单词云中,内容主要是法语和一点英语。从 90 年代开始,英国人的偏好就很明显了。为了找出任何非英语单词,你必须非常仔细地查看这些单词云。首选语言的变化,从法语到英语,似乎是几十年来欧洲电视网抒情选择的唯一重大变化。尽管这些年来歌曲和表演有所变化,但歌词内容非常相似。
情感分析
随着“爱”、“梦想”和“生活”的过度提及,人们会认为欧洲电视网歌曲的情绪是积极的。本节使用 TextBlob 软件包来分析欧洲电视网的歌词在情感上是积极的还是消极的。情绪由介于-1 和 1 之间的单个评级来表示。如果歌词评分低于-0.05,那么我们认为它总体上是负面的,如果评分高于 0.05,那么我们认为它总体上是正面的,如果它在这些值之间,那么它是中性的。
TextBlob 仅适用于英语,因此在应用情感分析之前必须翻译歌词。这可以通过 TextBlob 实现,我在分析 2020 年竞赛时使用了这一功能,但过度使用这一功能会导致翻译暂停,并停止当天的翻译。因此,大规模翻译变得棘手。幸运的是,翻译的歌词已经在“欧洲电视网歌词”数据集中给出。
哪些歌曲是最积极或最不积极的?将歌词及其翻译插入到 TextBlob 对象中,最积极的是 1963 年来自英国的条目,评分高达 0.81。听听罗尼·卡罗尔的歌曲“说美妙的事情”,我们很容易明白为什么这首歌会名列前茅。这是对 TextBlob 情感分析的一个极好的健全性检查,因为这是一首非常积极的歌曲。那年罗尼以 28 分名列第四。就我个人而言,这是我第一次看到这首歌,它太感人了,我以它命名了这篇博文。
最负面的来自 2009 年以色列的加入,情绪得分为-0.7。这是 Noa & Mira Awad 的歌《一定还有别的路》。重要的一点是,这首歌是用三种语言演唱的,英语、希伯来语和阿拉伯语。在分析中,希伯来语和阿拉伯语没有翻译。这首歌作为最负面的地方带有一个警告,如果这些部分被翻译,它可能会改变位置。然而,值得思考的是为什么这首歌会成为最负面的候选歌曲?首先,犹太人-以色列人和阿拉伯人-以色列人的组合必然会引发争议,而也确实引发了争议。写这首歌是为了强调希望和对共同人性的理解。然而,如果不唱出为什么需要这种希望,就很难唱出这种希望——这导致了一个非常负面的分数。这首歌在决赛中以 53 分的成绩排在第 16 位。
总的来说,Eurovison 的歌曲大多是积极的,平均情绪得分为 0.16,这并不奇怪。
(左)欧洲电视网歌词整体情绪。(右)每十年歌词情绪的密度估计。
有趣的是,当我们关注每十年的情绪时。这由上面的右图表示。查看每个十年的峰值,我们可以看到这些峰值的模式正在向负方向移动。也就是说,平均而言,随着时间的推移,欧洲歌曲的歌词变得越来越消极。下一个问题是,这有意义吗?为此,我们研究了 95%的置信区间。
每十年情感的置信区间
查看这些置信区间,我们可以看到在 70 年代和 80 年代之间有一个变化。由于 80 年代的置信区间与 70 年代的略有重叠,这里没有足够大的变化。虽然 50 年代和 60 年代与 80 年代之间的差别很大。后三十年明显比前三十年更加消极。平均而言,从一开始到现在,欧洲电视网歌词的情绪下降了大约 0.1。这种情绪上的变化非常缓慢,平均而言,歌曲仍然是积极向上的。
欧洲电视 2020 怎么样?
2020 年是欧洲电视网有史以来第一次被取消。这将是一场激动人心的比赛,在欧洲电视网的历史上,冰岛第一次成为夺冠热门。关于我们错过的大赛版本,2020 年欧洲电视网歌曲的歌词能告诉我们什么?为此,我使用 lyricsgenius 包和 genius API 从 Genius 网站上抓取歌词。然后,我使用 TextBlob 将尽可能多的歌词翻译成英语,用于情感分析。
我按照同样的方法进行词频分析,得出字数。这使得“喜欢”成为最常用的词。常用于比喻。例如,德国的条目“暴力的事情”由本·多利奇在他使用的隐喻“像多米诺骨牌一样击倒我”。
大赛 2020 版的歌词 Wordcloud。
“爱”仍然具有强大的影响力,在 2020 年的 41 首歌曲中有 19 首使用了它。历史上常见的主题,包括“世界”和“时间”,也在出现。总的来说,歌词的内容看起来像是这个版本的欧洲电视会跟随以前的欧洲电视歌曲比赛的趋势。
通过调查欧洲电视网歌词的情感,可以看出这些情感的平均值为 0.13,置信区间为[0.075,0.187]。这意味着这些歌词的情绪是积极的,可以与现代版的欧洲歌曲相媲美。
2020 年欧洲电视网最积极的歌曲是伊登·艾儒略的《费克尔·毕丽》,最消极的是桑德罗的《奔跑》。两者都不极端,不足以将前冠军从最积极/最消极的头衔中剔除。
对于欧洲电视网来说,2020 年的比赛似乎一切如常。尽管这个结论有点无聊,但遗憾的是,我们没能在欧洲电视网的舞台上听到这些歌曲的黄金时期。
结论
欧洲电视网改变了他们的外表,但他们歌曲的抒情内容基本保持不变。在过去 70 年中的 6 年里,欧洲电视网歌曲中最流行的词不是“爱”,就是它的法语变体“amour”。有证据表明,歌曲已经变得越来越消极,但这种变化也非常缓慢,平均而言,它们仍然是积极的。就我个人而言,我认为我们被剥夺了 2020 年的比赛,根据我的分析,这将是欧洲电视网正常的比赛。现在,2021 年正在成为一场激动人心的比赛,来自 2020 年比赛的一些艺术家将回到 2021 年。欧洲电视网是一座数据金矿,我只触及了表面(没有双关语的意思)。我希望用一些统计学和数据科学的更重手的工具,来更深入地洞察这场惊人的竞争。
SCADA 报警标准和指标
工业自动化的开源工具
这篇简短的文章是我们使用开源数据科学工具分析 SCADA 系统产生的警报和事件日志的系列文章的继续。
这是本系列的第二篇文章,上一篇文章是,用 ELK 离线处理 SCADA 报警数据。
在前一篇文章中,介绍了 SCADA 系统及其在工业过程监控中的应用。讨论了警报和事件系统,并介绍了良好警报系统管理实践的要求。
在本文中,我们将简要介绍与报警系统管理和报警生命周期相关的标准。这将为后续文章中更详细的警报事件分析打下基础。
警报管理标准
报警系统管理有一个全球标准,即 IEC ( 国际电工委员会)标准 IEC 62682 流程工业报警系统管理[1]。
IEC 标准建立在 ISA[2]和 EEMUA[3]早期工作的基础上,并与之保持一致。
该标准包括报警系统整个生命周期的管理指南;设计、实施、操作、维护、监控和评估以及变更管理。
这里我们将只关注性能指标和监控。
生命周期
下图展示了一个简化的报警生命周期,它与 IEC 标准中的报警生命周期一致。
对于每个报警点,被监控的物理过程包含正常和异常两种状态。
每个报警点报警包含两个动态属性(因此有四种状态,如下所示)。报警属性包括报警状态(正常|报警)和确认(已确认|未确认)。
图片由作者根据 IEC 62682 图 3 绘制
承认
我们所说的确认警报是什么意思?
对于那些不熟悉工业控制系统报警子系统操作的人来说,更详细地描述报警生命周期是值得的。
通常通过将测量的过程变量与固定限值进行比较来产生警报,如果过程值超出允许范围,则产生警报(上述状态 B)。
未确认的报警通常包含在报警显示中,未确认的状态通常由动画和/或颜色表示。未确认的警报通常也会触发声音警报。
SCADA 系统将为操作员提供一些选择和确认警报的机制。完成后,任何声音警报都将静音,警报显示的颜色和/或动画也会发生一些变化。
当过程条件恢复正常时,警报显示将改变,或者警报将从当前警报列表中删除。
韵律学
IEC 标准在第 16.5 节中提供了报警系统性能指标的建议,这些建议总结在标准的表 7 中,复制如下。
这些指标基于单个操作员可以管理的工作量。
乍一看,指标似乎非常低,因为系统平均每 10 分钟不应超过一个警报。这些值来自对操作员理解警报、确定过程状态、制定和实施纠正措施以及监控纠正措施有效性的能力的研究。
来源:IEC 62682
洪水警报
报警泛滥是指报警率可能超过操作员管理报警的能力的一段时间(即 10 分钟内超过 10 个报警)。
当 10 分钟内的报警数量超过 10 个时,报警泛滥开始,当 10 分钟内的报警数量低于 5 个时,报警泛滥结束。
我们可以收集的与警报洪水相关的一些指标包括:
- 洪水事件的数量
- 洪水的持续时间
- 洪水中的警报数量
震颤警报
震颤警报以高频率触发、清除和重新触发。一个常用的定义是每秒触发 2 次以上的警报。
短暂的警报
短暂的警报是在操作员有机会采取行动之前就消失的警报。标准中没有提供定义,所以我们在最初的分析中将使用 1 秒。
陈旧的警报
陈旧报警是指触发并长时间保持报警状态的报警,标准定义为> 24 小时。
结论
在本文中,我们回顾了国际标准中规定的过程自动化报警系统的性能指标。
在以后的文章中,我们将探讨,
- 处理 SCADA 报警记录
- 使用 ELK 在线处理 SCADA 报警记录
- 先进的 SCADA 警报分析技术(序列挖掘和时间序列分析)
参考
- IEC, IEC 62682 流程工业报警系统管理。瑞士日内瓦国际电工委员会。2014 年:国际电工委员会。24–26.
- ISA, ANSI/ISA‐18.2‐2009:流程工业报警系统的管理。2009 年:国际自动化学会。
- EEMUA, EEMUA-191:报警系统——设计、管理和采购指南。2013 年:英国伦敦工程设备和材料用户协会。
进一步阅读
感谢阅读,希望你喜欢这篇文章。
为了进一步探索,
- 订阅电子邮件通知
- 点击文章顶部的“关注”按钮
- 对于工业 4.0 的所有内容,请查看我的工业数字化转型&工业 4.0 出版物
- 欢迎在 LinkedIn 上加入我的社交网络(记得提到你已经读过这篇文章)
为了支持媒体作者,考虑一下订阅。
记得点击订阅和关注按钮,
作者图片
可扩展且可靠的 Kubernetes 日志记录
理解大数据
使用可伸缩工具和快速对象存储为大型 Kubernetes 集群构建可伸缩的可靠日志记录解决方案。
为 Kubernetes 构建一个基本的日志解决方案可能就像运行几个命令一样简单。然而,为了支持大规模的 Kubernetes 集群,日志解决方案本身需要具有可伸缩性和可靠性。
在我之前的博客中,我描述了我的 Kubernetes 监控和日志记录解决方案的概况。当时,我使用了一个日志记录的基本设置:Fluentd 在 Kubernetes 节点上收集的日志被直接发送到 Elasticsearch 和 Kibana 集群进行搜索和可视化,Fluentd 和 Elasticsearch 都在 Kubernetes 集群上运行。这是一个适用于小型集群的简单设置。一旦我们迁移到大型生产集群,它将面临以下挑战:1) Fluentd 可能会丢失日志(数据丢失!)如果 Elasticsearch 停机或无法跟上对传入日志的索引。2)日志输入和输出紧密耦合,因此难以管理。3)日志仅存储在 Elasticsearch 中,因此很难扩展到其他工具,例如用于一般日志处理和分析的 Apache Spark。
在这篇博客中,我将描述我是如何通过使用 Fluentd、Kafka、Elasticsearch、Spark 和 Trino 等可扩展工具构建一个可扩展且可靠的 Kubernetes 日志解决方案来应对这些挑战的。我还将强调像 FlashBlade S3 这样的快速对象存储在此解决方案中的作用。最终的架构如下图所示。
可伸缩的 Kubernetes 日志记录
Apache Kafka 作为管道缓冲器和代理
我们首先需要解耦日志输入(Fluentd)和输出(Elasticsearch)。这增加了日志管道的灵活性和可伸缩性。阿帕奇卡夫卡是最受欢迎的解决方案。该设置需要运行 Kafka 集群。请参考我的博客这里关于如何在 Kubernetes 上建立一个开源的 Kafka 集群。另一个选择是用汇合的卡夫卡来代替 Kubernetes 。融合 Kafka 的一个很好的特性是它对分层存储的支持,这允许 Kafka 将冷数据卸载到远程对象存储,如 FlashBlade S3。稍后将详细介绍。现在,让我们把重点放在 Fluentd 和 Kafka 的整合上。
最简单的入门方法是使用来自Fluentd Kubernetes Daemonset repo的 Kafka2 插件,其中包括预构建的 Docker 图像和 Kubernetes 规范示例。Fluentd-Kafka2 Docker 镜像使用环境变量支持基本配置。例如,Kafka 经纪人和主题可以在 Kubernetes 规范文件中设置如下:
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.12-debian-kafka2-1
env:
- name: FLUENT_KAFKA2_BROKERS
value: "kafka-headless.kafka:29092"
- name: FLUENT_KAFKA2_DEFAULT_TOPIC
value: "k8s-logs"
因为我需要对 Kafka 生产者确认、时间戳格式和日志源分离进行更多的控制,所以我使用 Kubernetes ConfigMap 扩展了配置文件。之后,日志会根据它们的来源被发送到多个 Kafka 主题中。Fluentd 还附加了其他元数据,如摄取时间戳和源标签。当我们用 Elasticsearch 和 Apache Spark 处理日志时,这些将会很有帮助。
将日志从 Kafka 发送到多个输出
为了将日志从 Kafka 发送到其最终输出,在本例中是 Elasticsearch 和 S3 对象存储,我使用了Kafka Connectelastic search sink 和 S3 sink。Kafka Connect 是一个工具,用于在 Apache Kafka 和其他数据系统之间可扩展和可靠地传输数据。每个连接器都以分布式模式作为自己的 Kafka 消费群运行,这意味着内置了可伸缩性和可靠性。因为日志的输入和输出被 Kafka 解耦了,所以扩展系统并不容易。例如,生态系统中有超过 100 个连接器将数据从 Kafka 传输到不同的输出。
通过将 connector pods 作为 Kubernetes 部署来运行,我们可以轻松地扩展日志记录管道,以适应 Kubernetes 集群的增长。下面是在 Kubernetes 集群中运行的 Fluentd 和 Kafka Connect 的示例。
Fluentd 和 Kafka 连接运行在 Kubernetes
融合卡夫卡与 S3 的分层存储
如果使用融合的 Kafka,其分层存储功能,尤其是与 FlashBlade S3 一起,使 Kafka 在 Kubernetes 环境中更加可扩展、可靠和易于操作。基本思想是将冷数据从 Kafka 代理卸载到远程对象存储,这样 Kafka 只需要在代理中管理最少的本地数据(热数据)。这使得 Kafka broker pods 非常轻便,因此更易于扩展和操作。特别是,数据重新平衡可以快几倍。这也降低了存储成本,因为 Kafka 无需在 S3 维护多个数据副本。
以下是使用 Kubernetes 的汇合操作符为汇合 Kafka 分层存储设置 FlashBlade S3 的示例:
融合式 Kafka 分层存储,采用 FlashBlade S3 配置
部署后,我们可以确认 FlashBlade S3 已在融合用户界面上配置为分层存储后端。
融合式卡夫卡分层存储,带闪光灯 S3
Kafka 客户端仍然通过 Kafka 访问所有数据。如果一个请求命中冷数据,Kafka 将从远程对象存储器下载它,缓存它并提供给客户机。FlashBlade S3 是受支持的分层存储目标。与亚马逊 S3 和其他对象存储不同,FlashBlade S3 的设计速度非常快,因此即使数据是远程存储的,提供冷数据的速度也可以接近热数据。
使用 Elasticsearch、Spark 和 Trino 进行日志分析
大型 Kubernetes 集群每小时或更快地生成数百万个日志条目。分析这些日志本身就是一个大数据问题。Elasticsearch、Apache Spark 和 Trino 是一些最流行的日志分析可扩展工具。
我使用 Elasticsearch 进行流日志分析、搜索和仪表板。使用 Kubernetes 上的弹性云,在 Kubernetes 上部署弹性搜索就像几个命令一样简单。
在 Elasticsearch 中搜索 Kubernetes 日志
使用 S3 搜索可搜索的快照
与融合的 Kafka 一样,Elasticsearch 也支持将冷数据和冻结数据卸载到远程对象存储。最初,S3 的快照仅支持备份目的,随着最新的 7.13 版本,快照变得可搜索!
使用 FlashBlade S3 搜索可搜索的快照
通过在本地保留最少的数据,可搜索的快照使弹性搜索更容易操作和扩展,降低存储成本,同时使用 FlashBlade S3 提高冷数据和冻结数据的搜索速度。
可搜索快照最重要的配置是在 Elasticsearch 冻结节点中设置共享缓存存储和大小。在下面的示例中,我将 100GB 闪存阵列支持的持久卷中的 90GB 设置为缓存。
然后,我们可以创建一个可搜索的快照,并将其存储在 FlashBlade S3 存储库中。
POST /_snapshot/reddot-s3-repo/demo/_mount?storage=shared_cache
{
"index": "logstash-2021.05.20",
"renamed_index": "logstash-2021.05.20-mounted"
}
搜索可搜索的快照索引与搜索任何其他索引相同。如果数据在本地不可用,Elasticsearch 将从 S3 下载索引,在本地缓存并从那里提供服务器以备将来请求。
正如您在下面看到的,我已经创建了三个索引:原始的,一个从常规快照完全恢复,另一个从可搜索的快照恢复。可搜索快照的索引使用磁盘上的零字节,表明数据是由 S3 存储库提供的。
GET /_cat/shards/logstash-2021.05.20*/?v&h=index,shard,prirep,state,docs,store,node
使用磁盘上的零字节对可搜索快照进行索引
ETL 和 SQL 分析
虽然 Elasticsearch 非常擅长流日志分析,但它并不能满足所有的日志分析需求。例如,我们使用 Apache Spark 和 Trino 进行 ETL 和 SQL 分析。为此,我们首先需要将原始日志存储在 S3。如上所述,我们使用 Kafka Connect S3 接收器将原始 json 格式的日志发送到 S3。我们还按照来源和摄取时间对数据进行分离/分区,以便于处理。日志存储在 S3,如下所示。
存储在 S3 flash blade 的 Kubernetes 日志
一旦日志被存储在 S3 桶中,我就可以使用 Spark 来研究 JupyterLab 笔记本中的数据。
在 JupyterLab 中用 Spark 记录 ETL
我还可以使用 Trino 直接对 json 数据运行 SQL 查询。
CREATE TABLE IF NOT EXISTS k8s_logs(
ingest_ts varchar,
log varchar,
kubernetes ROW(
container_image_id varchar,
container_name varchar,
...
),
dt varchar,
hour varchar
)
WITH (
format='json',
partitioned_by = ARRAY['dt', 'hour'],
external_location='s3a://deephub/logs/k8s-logs'
);
使用 Trino 的 SQL 分析
因为所有的工具,包括 JupyterLab、Spark 和 Trino,都运行在 Kubernetes 集群中,所以我可以立即开始这些分析,并轻松扩展。我之前的博客这里和这里描述了如何与 Kubernetes 和 S3 一起运行 Spark 和 Trino(前 PrestoSQL)。
摘要
在这篇博客中,我描述了如何扩展我的日志解决方案来收集、存储和处理 Kubernetes 集群中生成的大量日志。虽然它是为 Kubernetes 日志记录而构建的,但该解决方案非常灵活,也适用于其他大数据用例。
为了使解决方案具有可伸缩性和可靠性,我们使用的核心工具需要具有可伸缩性和可靠性。云原生趋势(公共云或本地 Kubernetes)鼓励 Kafka 和 Elasticsearch 等传统大数据系统从本地数据复制转向远程对象存储。正因为如此,像 FlashBlade S3 这样的快速对象存储在解决方案中起着重要作用。
扩展日志解决方案变得更加容易。
使用 Spark 的可扩展机器学习
分布式算法、Map-Reduce 范式、在单机上使用 Spark MLlib 的可扩展 ML、带有 Docker 的 AWS EMR 集群& Nvidia RAPIDS。
自 21 世纪初以来,由于谷歌、网飞、Youtube、亚马逊、脸书等互联网巨头的出现,收集的数据量大幅增加。临近 2010 ,当手机大受欢迎时,另一个“数据浪潮”已经到来。到 2020 年,我们预计当物联网设备变得无孔不入时,数据将会再次呈指数级增长。在这种背景下,构建可扩展的系统成为机器学习解决方案的必要条件。
Spark 中的机器学习:从零到英雄版
任何解决方案都主要取决于这两种类型的任务:
**a)计算量大:**在 2000 年之前,被称为“超级计算机”的并行处理箱在计算量大的任务中很流行。在 2005 年之前,像 MPI 和 PVM 这样的并行处理库在计算繁重任务中很流行,TensorFlow 就是基于这种并行处理库设计的。
b)数据量大:基于关系代数的数据库是在 20 世纪 70 年代设计的,当时硬盘存储非常昂贵。因此,该设计的目的是通过将较大的表格分成较小的表格,并使用关系(规范化)将它们链接起来,从而减少数据冗余。
因此,传统的数据库如 mySQL、PostgreSQL、Oracle 等。不是为扩展而设计的,尤其是在上面提到的数据爆炸的环境中。因此,NoSQL 数据库是为满足不同情况而设计的:
- 用于存储文本文档
- Redis,Memcache: 用于快速键值查找的分布式哈希表
- **弹性搜索:**搜索文本文档
- HBase 和 Cassandra: 柱状商店
- Neo4j 和 Grakn: 图形数据库。
然而,大型数据集上的机器学习和深度学习解决方案是计算密集型和数据密集型。因此,为了制造可扩展的 AI/ML 解决方案,解决方案必须同时满足这两种需求。
图一。作者使用 MPI 并行实现光子映射
2004 年, Jeff Dean 等人发表了开创性的 MapReduce 论文来处理数据繁重的任务[2]。2006 年, Hadoop 实现了 MapReduce 并设计了一个名为 HDFS 的分布式文件系统,将单个大文件拆分存储在多台电脑的磁盘中。这个想法是将巨大的数据库分散在多个主板的硬盘上,每个主板都有独立的 CPU、RAM、硬盘等,通过一个快速局域网互连。
然而, Hadoop 将所有中间数据存储到磁盘,因为它是在 2000 年代设计的,当时硬盘价格暴跌,而 RAM 价格仍然很高。在 2010 年,当 RAM 价格下降时, Spark 诞生了一个大的设计变化将所有中间数据存储到 RAM,而不是磁盘。
火花对双方都有好处,
**i)数据密集型任务:**因为它使用 HDFS &
**ii)计算繁重的任务:**因为它使用 RAM 而不是磁盘来存储中间输出。**例如:**迭代求解
由于 Spark 可以利用 RAM,它成为机器学习中迭代任务的有效解决方案,如随机梯度下降( SGD )。所以是这个原因, Spark MLlib 变得如此受机器学习欢迎,与 Hadoop 的 Mahout 形成对比。
此外,要使用 TF 进行分布式深度学习,您可以使用,
- 多个 GPU 在同一个盒子上 (或)
- 不同机箱上的多个 GPU(GPU 集群)
虽然今天的超级计算机使用 GPU 集群来执行计算密集型任务,但您可以在这样的集群中安装 Spark,使其适用于分布式深度学习等任务,这些任务都是计算和数据密集型的。
Hadoop 和 Spark 简介
Hadoop 中主要有两个组件,
- Hadoop 分布式文件系统(HDFS): 一个容错的分布式文件系统,Hadoop 和 Spark 都使用。HDFS 支持将一个大文件分割成“n”个块,保存在“n”个节点中。当访问文件时,必须通过 LAN 跨节点访问不同的数据块。
- Map-Reduce: 给定一个跨大量数据、分布在多个节点上的任务,必须进行大量的数据传输,并且需要分布处理。让我们详细研究一下这个问题。
地图简化范例
考虑在 900 GB 的大型分布式文件中查找词频的任务。HDFS 将支持将大文件拆分为 3 个区块,分别位于 P1、P2 和 P3,每个区块 300 GB,并在 3 个节点中各保留一个。
任何 Hadoop 代码都会有 3 个阶段:
- Map : Mapper 函数会通过数据,存储在各个节点的磁盘中,并递增输出字典中的字数。它将在每个分布式机器上独立执行**。**
图二。字数统计图-简化工作流程(图片由作者提供)
2。Shuffle: Hadoop 自动在局域网内移动数据,这样相同的键就被组合在一个盒子里。
3。Reduce: 一个函数,它将使用字典并将相同关键字的值相加(以计算总数)。
要在 Hadoop 中实现一个函数,只需要编写 Map & Reduce 函数。请注意,Hadoop 中的每个 Map-Reduce 操作之间都有磁盘 I/O。然而,几乎所有的 ML 算法都是迭代工作的。SGD[下面的等式]中的每个迭代步骤对应于一个 Map-Reduce 操作。在每个迭代步骤之后,中间权重将被写入磁盘,占总收敛时间的 90%。
等式:ML&DL 迭代中的权重更新公式
作为解决方案, Spark 诞生于 2013 年即将磁盘 I/O 操作替换为内存操作。借助Mesos——分布式系统内核——Spark 缓存每次迭代后的中间数据集。因为每次迭代的输出都存储在 RDD 中,所以只需要一次磁盘读写操作就可以完成 SGD 的所有迭代。
Spark 建立在弹性分布式数据集(RDD)之上,存储在主内存中的容错不可变分布式数据集集合。在 RDD 之上,DataFrame API 被设计为抽象掉它的复杂性,并简化在 Spark 上进行机器学习。
RDDs 支持两种类型的操作:****
- **转换: 从现有数据集创建新的数据集
**映射:**通过函数
**reduce by key:**使用函数
**过滤器:仅选择那些使用函数的元素 - **动作: 对数据集运行计算后返回值
**减少:**使用某个函数
**收集:**返回输出数据集的所有元素
**SaveAsTextFile:将数据集的元素作为文本文件写入。
Spark 中的所有转换都是惰性的,也就是说,它们只在“动作”需要结果时才被计算。在下面的代码中,由于懒惰,没有立即计算行长度。只有当“reduce”运行时,Spark 才会将计算分解为在不同机器上运行的任务,以计算总长度。
lines = sc.textFile("data.txt")
lineLengths = lines.map(lambda s: len(s))
totalLength = lineLengths.reduce(lambda a, b: a + b)
下面是一个简单的数据转换示例,用于计算存储在 3 个分区的分布式 RDD 中的键的出现次数:****
计算字母“a”和“b”的出现次数
作为 Map 简化逻辑回归
SGD 迭代中最昂贵的操作是跨越所有数据点的梯度操作[公式。*【以上】。如果数据集很大,比如说“n”亿个数据点,那么我们可以将梯度计算分布在“k”个不同的盒子中。*
- ****贴图阶段:每个盒子将计算 n /k 个亿点的梯度
- ****简化阶段:使用相同的键对每个框中的部分总和求和
- 所有点的损失梯度= ∑部分和
- 因此,很容易计算 w_new 并存储在每个节点的存储器中
这就是你如何分发任何基于优化的 ML 算法。然而,对于分布式 LR 实现,请参见 Hadoop 与 Spark 的性能比较。
图三。运行时间对比:Hadoop vs Spark [3]
由于 Spark RDDs 允许在内存中执行多种映射操作,因此不需要将临时数据集写入磁盘,因此速度提高了 100 倍。注意,第一次迭代花费的时间几乎相同,因为 Hadoop 和 Spark 都必须从磁盘读取。但是在后续的迭代中,Spark 的内存读取只需要 6 秒,而 Hadoop 的磁盘读取需要 127 秒**。**
此外,一个 ML 科学家不需要编码映射和简化函数。大多数 ML 算法包含在 Spark MLlib 中,所有数据预处理都是使用 Spark SQL 完成的。
火花安装和设置
您可以在其中任何一个中设置 Spark,
- 您的本地机顶盒(或)
- 使用 AWS EMR 或 Azure Databricks 的托管集群
下面我们将看到两种方式。首先,在完成 Spark 本地系统设置之后,我们将在您的个人机器上运行一些普通的并行任务。然后我们会拿一个更复杂的 ML 项目,在 Spark Docker、AWS EMR & Spark Rapids 中运行。
Spark:本地系统设置
- docker pull jupyter/pyspark-notebook
- docker run-it-p 8888:8888 jupyter/pyspark-notebook
- 单击带有 Auth-Token 的链接或转到 http://localhost:8888/ 并复制粘贴令牌
- 现在,您可以在 Jupyter 或终端中执行 Spark 代码。要在 docker 中执行,只需运行spark-submit pi-code . py****
任务 1:估计圆周率(π)的值
取一个单位圆,考虑一个外接该圆的正方形。
- 单位正方形的面积= 1
- 因为是单位圆,所以圆的面积= π
- 四分之一圆弧的面积= π/4
- *因此,π = 4 四分之一圆弧的面积
图 4。圆的面积=红色点数/总点数。(图片由作者提供)
四分之一圆弧的面积可以通过下式计算:
- ****数值方法:使用积分
- 蒙特卡罗方法:使用随机抽样寻找答案
在蒙特卡罗方法中,
- 取(x,y)点的均匀分布从 0 到 1(即正方形内)
- **四分之一区域的面积= **%圆内的点,即𝑥+𝑦<1
eg:在 1000 个随机点中,如果“k”个点在圆内,那么阴影区域的面积= k/1000
这些操作是可并行化的**,因为为了检查一个点是否落在圆内,节点之间没有依赖性。在 pyspark 代码下面,一旦在 spark 本地设置上运行,将输出更接近π=3.14 的值,因为我们增加了随机点数 (NUM_SAMPLES)**
- 随机函数将生成一个 0 到 1 之间的数字。
- “inside”函数运行一百万次,只有当随机点在圆内时才返回“True”。
- sc.parallelize()将创建一个分解为 k=10 个实例的 RDD。
- 过滤器将应用传递的函数。
任务 2:计算字数
要在大型分布式文件中查找词频,只需将下面代码中的本地文件路径替换为 HDFS 文件路径。
map 函数将创建一个列表列表& flatMap 将列表合并成一个列表。
任务 3:数据预处理
大多数数据预处理可以通过 DataFrame API 使用 Spark SQL 来完成。在 Spark 数据帧上执行的 Spark SQL 查询将在 Spark 中执行之前转换为 Map 和 Reduce ops。
Spark MLLib 和 ML 管道简介
Spark MLLib 是一个受 sklearn 启发的库,它包含了流行 ML 算法的分布式实现。与 sklearn 的主要区别是使用 sc.parallelize()函数将数据拆分到多个框中。
*将磁盘上的原始数据转换成最终模型所需的所有步骤称为 ML 管道。Pipeline()依次包含*输入和输出级。例如,记号赋予器 → 计数矢量化器 → 逻辑回归流水线序列可以编码为:
因此,训练数据首先被馈入 tokenizer,然后馈入 CV,然后馈入 LR。若要测试模型,请调用 model.transform()。您还可以进行分布式超参数调整,即在具有不同超参数的多个机器上运行相同的架构。然而,将一个大模型分布存储和训练在不同盒子中的 GPU 的 VRAM 中是稍微复杂的。
Spark 中的 ML 算法:自定义实现
只有当一个算法可以被分成独立的子任务时,它才可以被并行化。具体来说,双字节排序可以并行,因为操作序列与数据无关,与合并排序无关。类似地,一些 ML 算法是平凡的可并行化的,而另一些则不是。
a)琐碎并行:以KNN(k-最近邻)为例。
- 将数据集 D 分成“n”个盒子。例如 : 40K 分 4 盒
- 从每个框中的每个 10K 点中找出前 k 个最近的点
- 将所有 4k 个点转移到 1 个盒子中,并找到前 k 个最近的点。
****b)非平凡的平行:以 GBDT 为例。在 GBDT 中的每一棵决策树都是基于先前决策树的剩余部分构建的。因此,训练 GBDT 本质上是一个顺序操作,而不是并行的。
然而,我们可以并行构建每个决策树,因为用于左右子树的数据集是独立的。因此,xgboost 在树级并行化,即左右子树在 2 个节点上独立训练。
基于随机森林的时间序列预测
让我们在独立、Spark 本地&集群模式下解决一个 ML 问题。****
**问题陈述:**从 1990 ~ 2020 年代记录一个地点的每日气温、风、降雨和湿度。鉴于这些特征,**建立时间序列模型预测 2021 年的湿度。为了验证模型,使用 2020Q4 湿度值进行比较,使用公制。
下面实验的完整源代码**可以在 这里 找到。**
图五。输入数据集特征
**图六。湿度值的时间序列性质清晰可见
首先,转换数据以获得对预测湿度有用的新特征。
图 7。新功能:日、周和规模=温度*降雨量
A.独立实现
现在我们可以用上述特征训练 sklearn 的随机森林回归器。
预测湿度值和实际湿度值过于接近(如下图所示)
图 8。2020Q4 湿度:蓝红线表示实际和预测湿度(独立)
B.Spark 本地实施
首先,你需要做上面提到的 Spark 本地系统设置步骤。然后,你可以用 PySpark 的 RandomForestRegressor 做上面同样的事情。
要在 Spark MLlib 中为机器学习模型提供功能,您需要使用 Spark ML 库中的 VectorAssembler 模块将多个列合并为一个向量列。
图九。使用 VectorAssembler 组合特征
然后,您可以运行类似于独立解决方案的训练和测试模块。
图 10。预测回归值(湿度)
图 11。2020Q4 湿度:实际和预测(局部火花)
PySpark 中的分布式随机森林回归器实现似乎也遵循这一趋势,尽管均方误差值稍高一些。即便如此,在 64G RAM 的四核系统上,spark 本地实现的运行时间还是快了3 倍。
图 12。独立:2.14 秒。Spark Local: 0.71 秒用于随机森林回归训练
C.火花簇:AWS 弹性贴图 Reduce + Docker
为了获得计算和数据规模的双重优势,上述解决方案需要跨多个机器部署。然而,使用本地机器用 Spark 设置集群是很耗时的。
相反,您可以使用 Amazon EMR 创建一个集群,负载运行在 Amazon EC2 实例上。亚马逊 EMR 是一个托管集群平台,简化了运行大数据框架,如 Apache Hadoop 和 Spark。
从 Amazon EMR 6.0.0 开始,您可以使用 Docker 容器来处理库依赖关系,而不是将其安装在每个 EC2 集群实例上。但是您需要在 AWS EMR 中的“集群创建”期间配置 Docker 注册表并定义附加参数。
- 创建一个 docker 图像(或修改一个 Docker 图像)
创建一个目录和一个 requirements.txt 文件。requirements.txt 文件应该包含 Spark 应用程序所需的所有依赖项。
mkdir pyspark
vi pyspark/requirements.txt
vi pyspark/Dockerfile**Sample requirements.txt:**
python-dateutil==2.8.1
scikit-image==0.18.1
statsmodels==0.12.2
scikit-learn==0.23.2
在目录中创建一个 Dockerfile 文件,包含以下内容。安装了特定的 numpy 版本,以从 EMR 笔记本确认 docker 执行。
**FROM amazoncorretto:8**RUN yum -y update
RUN yum -y install yum-utils
RUN yum -y groupinstall developmentRUN yum list python3*
RUN yum -y install python3 python3-dev python3-pip python3-virtualenv python-devRUN python -V
RUN python3 -VENV PYSPARK_DRIVER_PYTHON python3
ENV PYSPARK_PYTHON python3RUN pip3 install --upgrade pip
RUN pip3 install 'numpy==1.17.5'RUN python3 -c "import numpy as np"**WORKDIR /app****COPY requirements.txt requirements.txt**
**RUN pip3 install -r requirements.txt**
使用以下命令构建 docker 映像。
****2。创建 ECR 存储库。标记并将本地构建的图像上传至 ECR。
**sudo docker build** -t local/pyspark-example pyspark/
**aws ecr create-repository** --repository-name emr-docker-examples**sudo docker tag** local/pyspark-example 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example**sudo aws ecr get-login** --region us-east-1 --no-include-email | **sudo docker login** -u AWS -p <password> https://123456789123.dkr.ecr.us-east-1.amazonaws.com**sudo docker push** 123456789123.dkr.ecr.us-east-1.amazonaws.com/emr-docker-examples:pyspark-example
也可以上传到 Docker Hub,给’ Docker . io/account/Docker-name:tag '代替上面的 AWS ECR 图像 URI。
3。在 EMR 中创建带火花的集群
打开亚马逊电子病历控制台(参考 此处 )**
点击“进入高级选项”而不是“快速选项”来启用,
- ****Jupyter 企业网关:代表远程笔记本帮助启动内核的网络服务器。
- JupyterHub :托管 Jupyter 笔记本服务器的多个实例。
- Apache Livy: 支持通过 REST 接口与 Spark 集群交互的服务。
根据所需的并行度,选择每种节点类型的的节点数量****
- ****主节点:通过协调其他节点之间的数据和任务分配来管理集群
- ****核心节点:在 HDFS 运行任务和存储数据(多节点至少一个)
- ****任务节点:只运行任务&不在 HDFS 存储数据(可选)
因此,核心节点增加了数据和计算并行性,而任务节点仅增加了计算并行性。
图 13。如何使用 AWS EMR 创建 Spark 集群
4。进入“软件设置”下的配置**
为了避免 userid 错误,请在下面的 JSON 中设置“livy.impersonation”
[
{
"Classification": "container-executor",
"Configurations": [
{
"Classification": "**docker**",
"Properties": {
"docker.trusted.registries": "local,centos,**123456789123.dkr.ecr.us-east-1.amazonaws.com"**,
"docker.privileged-containers.registries": "local,centos,**123456789123.dkr.ecr.us-east-1.amazonaws.com**"
}
},
]
},
{
"Classification":**"livy-conf"**,
"Properties":{
**"livy.impersonation.enabled": "true"**,
"livy.spark.master":"yarn",
"livy.spark.deploy-mode":"cluster",
"livy.server.session.timeout":"16h"
}
},
{
"Classification": "core-site",
"Properties": {
"hadoop.proxyuser.livy.groups": "*",
"hadoop.proxyuser.livy.hosts": "*"
}
},
{
"Classification":"hive-site",
"Properties":{
"hive.execution.mode":"container"
}
},
{
"Classification":**"spark-defaults"**,
"Properties":{
"spark.executorEnv.YARN_CONTAINER_RUNTIME_TYPE":"**docker**",
"spark.yarn.am.waitTime":"300s",
"spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE":"**docker**",
"spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG":**"hdfs:///user/hadoop/config.json"**,
"spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE":**"123456789123.dkr.ecr.us-east-1.amazonaws.com/scalableml:s3spark"**,"spark.executor.instances":"2",
"spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG":**"hdfs:///user/hadoop/config.json"**,
"spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE":**"123456789123.dkr.ecr.us-east-1.amazonaws.com/scalableml:s3spark"**
}
}
]
5。从纱线启用 ECR 访问
为了使 YARN 能够从 ECR 访问图像,我们设置了容器环境变量 YARN _ CONTAINER _ RUNTIME _ DOCKER _ CLIENT _ CONFIG。
但是,我们需要生成 config.json 并放入 HDFS,以便它可以被集群上运行的作业使用。为此,登录到一个核心节点并执行以下命令。
**ssh -i permission.pem** [**hadoop@**ec2-1-23-45-678.compute-1.amazonaws.com](mailto:hadoop@ec2-3-83-46-34.compute-1.amazonaws.com)**aws ecr get-login-password** --region us-east-1 | sudo docker login --username AWS --password-stdin 123456789123.dkr.ecr.us-east-1.amazonaws.com**mkdir -p ~/.docker**
**sudo cp** /root/.docker/config.json ~/.docker/config.json
**sudo chmod** 644 ~/.docker/config.json**hadoop fs -put** ~/.docker/config.json /user/hadoop/
图 14。让 ECR 接触纱线
6。EMR 笔记本和配置
您可以创建 jupyter 笔记本,并连接到运行 Hadoop、Spark 和 Livy 的 Amazon EMR 集群。EMR 笔记本独立于集群保存在 AWS S3 中。
- 点击亚马逊电子病历控制台上的“笔记本”和“创建笔记本”
- 选择运行笔记本的群集
- 在 Jupyter 笔记本中,给出下面的配置作为第一个单元格。
**%%configure -f**
{"conf":
{
"spark.pyspark.virtualenv.enabled": "false",
"spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_TYPE":"**docker**",
"spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG":"**hdfs:///user/hadoop/config.json**",
"spark.executorEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE":"**123456789123.dkr.ecr.us-east-1.amazonaws.com/scalableml:s3spark**",
"spark.executor.instances":"2",
"spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_CLIENT_CONFIG":"**hdfs:///user/hadoop/config.json**",
"spark.yarn.appMasterEnv.YARN_CONTAINER_RUNTIME_DOCKER_IMAGE":"**123456789123.dkr.ecr.us-east-1.amazonaws.com/scalableml:s3spark**"
}
}
- 因此,您可以在 EMR 笔记本中使用笔记本范围的 docker 来解决依赖性。现在您可以在后续单元格中执行 PySpark 代码。
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("docker-numpy").getOrCreate()
sc = spark.sparkContext
import numpy as np
**print(np.__version__)**
理想情况下,如果上面的代码在构建的 docker 中运行,您应该看到 1.17.5 的 numpy 版本。如果没有,您需要找到 S3 集群日志路径。
- 您可以使用上面的 Spark 独立代码,只是输入数据应该从 S3 读取,如下所示,并转换为 RDD。
如下图所示,随着 EMR 集群中节点数量的增加,RandomForest 训练工作负载所用的时间稳步减少。节点间通信的基本开销将保持不变,即使是小数据集。 因此,当训练数据集变大时,图形会下降得更陡。
图 15。不同集群规模的 EMR 集群性能
或者,在通过 SSH 连接到 主节点 之后,您可以使用 spark-submit 命令在集群中执行 PySpark 代码。
- 设置DOCKER _ IMAGE _ NAME&DOCKER _ CLIENT _ CONFIGenv 变量
- 执行。带有 spark 的 py 文件-提交 &部署模式为“集群”
- 您可以从 S3 读取输入并写出输出,如下所示。
但是,通过运行在 Spark 集群上的 Notebook 提交 Spark 作业更方便,同时 docker 可以解析所有集群节点中的依赖关系。
D.GPU 集群:AWS EMR + Spark RAPIDs
您可以使用“Nvidia Spark-RAPIDS plugin for Spark”来加速使用连接到 EC2 节点的 GPU 的 ML 管道。核心和任务实例组必须使用 EC2 GPU 实例类型,而主节点可以是非 ARM 非 GPU。
Spark RAPID 将加速数据处理和模型训练,而无需任何代码更改**。要创建 GPU 加速集群,您可以遵循 C 节中的步骤,但要做以下更改:**
- 在这里 使用步骤 5** 给出的 JSON,而不是 C 节中的 config**
- 保存自举脚本给 此处 在 S3 为my-bootsap-action . sh
- 将步骤 2 中的 S3 文件路径作为引导脚本(在 GPU 上使用 YARN)
- 到主节点的 SSH 并安装依赖项。要执行时序项目,请执行下面的命令。
pip3 install sklearn statsmodels seaborn matplotlib pandas boto3
不需要更改代码。下面是 Spark-RAPIDS 集群上的随机森林回归训练的时间比较,该集群由 1 个 m 5.2 x 大型主节点和 2 个 g4dn . 4x 大型核心节点组成,具有其他执行模式。
图 16。时间比较:独立 vs Spark 本地 vs RAPIDS
然而,在上面的例子中,由于数据集很小,所以速度提高不多。让我们对前面的“字母表计数”代码做一个修改,以比较 Spark Local 和 Spark RAPIDS 之间的时间统计。下面的代码生成 100M 个随机字符串和计数元组,以馈入分布式计数操作。
图 17。AWS EMR 笔记本中的 Spark 作业进度报告
图 18。时间比较:火花本地 vs 火花急流
结束语
为博客的长度道歉。如果您已经读到这里,您应该考虑用一些分布式编码来弄脏您的手。本文为您提供了 Spark 的历史和逻辑背景,以及在 Local、AWS EMR 和 Spark Rapids 上的多个示例实现。如果它激励你进一步探索,那么它就达到了它的目的。
以上实验的完整源代码**可以在 这里 找到。**
如有任何疑问或建议,可在此 联系我https://www.linkedin.com/in/ananduthaman/
参考
[2]迪安、杰弗里和桑杰·格玛瓦特。“MapReduce:大型集群上的简化数据处理。” 美国计算机学会通讯 51.1 (2008)**
[3]巴加瓦蒂、阿伦库马尔&察切娃、安吉丽娜。(2017).分布式环境中基于规则的系统:调查。 10.11159/cca17.107
[4] PySpark 文档:https://spark.apache.org/docs/latest/api/python/index.html
[5] 火花 MLLib:https://spark.apache.org/docs/1.2.1/mllib-guide.html
[6]Spark SQL:https://Spark . Apache . org/docs/2 . 2 . 0/SQL-programming-guide . html # SQL
【7】AWS EMR:https://docs . AWS . Amazon . com/EMR/latest/release guide/EMR-spark-docker . html
[8]AWS EMR with Docker:https://AWS . Amazon . com/blogs/big-data/simplify-your-spark-dependency-management-with-Docker-in-EMR-6-0-0/
[9] GPU 集群(Spark-Rapids):https://docs . AWS . Amazon . com/EMR/latest/release guide/EMR-Spark-Rapids . html
使用 Tensorflow 2 的可扩展机器学习。X
理解大数据
使用 Tensorflow 2 在一台或多台机器上进行大规模 ML 训练,无需更改代码。x 特征
由 Charles Deluvio 在 Unsplash 上拍摄的照片
关于机器学习的一个惊人事实是,如果给予足够的计算能力,即使最简单的模型也可以产生良好的结果。这一方面迅速普及了机器学习工作负载的分布式计算的采用,并且出现了许多分布式计算框架来满足这种需求。这些新生的 ML 框架必须解决分布式计算中的一个基本困难:从共享内存模型(SMM)到分布式内存模型(DMM)的飞跃。这一飞跃是一件大事,并且导致了许多分布式框架的失败。本文将重点介绍 Tensorflow 平台采用的分布式计算方法,尤其是 2.X 版的增强功能。这种新方法在很大程度上成功地弥合了共享内存模型和分布式内存模型之间的差距。此外,这一新模型为异构硬件加速器(如图形处理单元(GPU)和张量处理单元(TPU))引入了统一的方法。本文将以分布式生成对抗网络(GAN)的开发为例,讨论这些最新进展。
介绍
本文的重点是在开发机器学习模型时,提出从共享内存模型到分布式内存模型的无缝过渡。但是,让我们首先讨论一下为什么这种转变如此重要,为什么首先应该进行这种转变。我们大多数人只熟悉共享内存模型。这是一种你只需要处理一台机器的模型,你可以在计算线程之间自由传递变量,因为这台机器中的所有内核都可以访问同一个内存,因此得名“共享内存”。现在,考虑分布式内存模型(DMM)。在分布式范例中,你必须意识到计算线程存在于不同的机器中,你经常需要知道它们的网络地址,你还必须知道如何在它们之间移动数据。您必须考虑数据序列化、机器本机数字格式等等。因此,DDM 显然更复杂,人们可能会提出这样的问题:既然如此困难,为什么还要去那里?
这个问题的简单答案是,尽管共享内存模型对开发人员来说容易得多,但它也有局限性。您拥有单机抽象的优势,但也受限于单台机器的内核数量和内存量。如果您的模型变得比单机中当前可用的 RAM 内存更大,该怎么办?如果您的模型在计算上受到限制,需要数百或数千个内核,该怎么办?这是你进入可扩展机器学习领域的时候,这是你需要忍受分布式内存模型的复杂性以便获得无限可扩展性的好处的时候。
两个加速器的故事
在机器学习领域,当开发硬件加速器时,分布式和共享内存模型之间的差异变得非常明显,如 NVIDIA 的图形处理单元(GPU)和谷歌张量处理单元(TPUs)。最近推出的高端 GPU 允许在单个机器的抽象中获得大量内存和计算能力,并受益于共享内存模型。但是如果您的模型需要 50G 以上的加速器内存和数百个加速器核心,那么您将不得不处理分布式内存模型。另一方面,Google Cloud TPUs 是为分布式内存模型设计的。例如,TPU 加速器有自己的 IP 地址和通信协议(gRPC)。幸运的是,开发人员不需要处理通信层,因为它由加速线性代数(XLA)层负责,并由 Tensorflow API 向开发人员公开。PyTorch 也有 XLA 支持,但本文将只关注 Tensorflow 接口。但是分布式计算的本质确实让习惯于共享内存模型的开发人员感到惊讶。例如,在 TPU 架构中,你通常不会使用共享内存中的变量来来回回地传递数据,相反,你必须以一种称为 TFRecord 的格式来序列化成批记录中的训练数据。这种差异让许多不熟悉数据序列化的开发人员望而却步。然而,采用 TFRecord 数据序列化带来了很多好处,因为它基于简单而有效的“proto buf”架构,该架构已在谷歌大规模使用多年。在任何情况下,使用 GPU 或 TPU 集群的大规模部署都需要数据序列化步骤,因此在采用分布式计算架构时,这实际上是一种“必要的邪恶”。下图显示了使用 GPU 或 TPU 加速器时共享和分布式架构的基本差异。
作者图片
除了数据序列化步骤,在采用分布式计算进行机器学习时,还有其他独特的方面需要注意。Tensorflow API 在某种程度上成功地隐藏了模型训练期间发生的进程间通信的复杂性。但是,在 Tensorflow 版本 1 中。x 访问 TPU 加速器只能通过 TPUEstimator 接口,这严重限制了可以为 TPU 开发的机器学习应用的类型。TF 1 版本中的 TPU 接口。x 基本上期望被精确地传递一个模型(网络),然后被编译成 TPU 格式,并被运送到 TPU 进行训练。如下图所示:
作者图片
这种架构非常棒,因为它大大减少了与 CPU 的通信,从而提高了性能。但是在版本 1 中。x 这个特性仅限于一个模型,因此很难开发多模型的 ML 应用程序,如强化学习、生成性对抗网络(GANs)和许多其他应用程序。例如,GAN 的实现需要一种巧妙的方法来将发生器和鉴别器模型打包到卷积网络中,就像在 TF-GAN,中所做的那样,但是这样的框架使得开发人员很难获得他们自己的定制。在 TF-GAN 中,发生器和鉴别器网络被打包成一个 CNN,然后可以用 TPUEstimator 将其训练成一个模型。TF-GAN 将实现细节隐藏在一个名为 GANEstimator 的接口后面。通过这种方式,TF-GAN 设法在 TF 1.X 版本的 TPU 上运行。然而,开发人员经常需要改变网络逻辑以适应他们的应用。例如,GAN 建模的最新进展利用了定制的“编码器”组件,它实际上是沿着鉴别器和发生器模型训练的第三个模型。在优化用于生成图像空间的“潜在空间”方面也有很多研究。这种定制在 TF-GAN 中是不可能的。好在 Tensorflow 2。x 引入了定制训练循环特性,使得使用梯度带结构同步训练任意数量的模型成为可能…
张量流 2。x 版本还引入了使用@tf.function 装饰器定义的编译函数的概念。当 XLA 编译层遇到这样的函数时,它将利用惊人的“自动签名”功能来自动导出计算图形,然后可以编译该图形并将其发送到 TPU 进行执行。该功能如下所示:
作者图片
自定义函数的引入极大地增强了 TPU 的灵活性,使它们在灵活性和易开发性方面类似于 GPU。Tensorflow 2 中还有其他几个新功能。这实际上使得开发可以在 GPU 或 TPU 上透明运行的 ML 模型成为可能,而无需任何重大修改。这些特性中最重要的是 tf.strategy()概念。tf.strategy 对象用于定义实际的分布式计算范例。tf.strategy 使得并行运行定制函数成为可能,这使得开发人员可以相当容易地实现分布式模型训练技术,例如模型并行和数据并行。在 Tensorflow 2 中。x 还有对 tf.data 对象的扩展,使得指定数据如何在几个内核之间分配变得容易。有了这些介绍,开发人员现在可以指定如何在几个内核之间分配计算和数据。也许最重要的一点是,tf.strategy 和 tf.data 对象对 GPU 和 TPU 的作用是相同的,这使得模型的开发使用了“单一代码路径”,这一点在下一节中讨论时非常重要。
勤奋的海狸
Tensorflow 2 中的另一个重大增强。x 的一个优点是它隐含地假定了执行的“急切模式”。这意味着现在你可以在一个交互式的环境中单步调试你的模型,比如一个 Jupyter 笔记本,你的代码将会像预期的那样一步一步地执行。渴望模式是共享内存模型中您期望的行为方式,因此将渴望模式作为默认模式极大地有助于易用性。开发人员通常依赖于渴望模式,以便在执行过程中观察他们的代码和变量,例如在调试模型时。然而,当编译器遇到标记为 @tf.function 的自定义函数时,它将恢复到延迟执行模式。原因是需要编译一个@tf.function 以便远程执行。延迟执行模型更难调试,因为您必须依赖跟踪而不是交互式执行。这就是“单一代码路径”策略可以发挥作用的地方。通过开发一个利用通用 GPU/TPU 代码路径的模型,使 Tensorflow 2 成为可能。x 开发人员现在可以使用共享内存模型中的 GPU 在急切模式下运行,然后只需切换 tf.strategy,相同的代码将使用 TPUs 在分布式模式下运行。这种实践产生了一种高效的模型开发方法,它利用了共享内存模型的开发便利性和分布式内存模型的可伸缩性。该方法如下:
- 使用 tf.strategy 对象,使用通用 GPU/TPU 代码路径开发您的模型
- 使用 GPU 路径在渴望模式下测试/调试您的模型
- 只需切换 tf.strategy 对象,就可以在延迟执行模式下将您的模型部署到 TPU
使用这种方法还允许开发人员优化加速器资源的使用。在开发阶段不需要使用高功率 GPU,NVIDIA k80 等低端 GPU 应该足以满足基本模型开发和测试。一旦经过测试,就可以通过更改一行代码(tf.strategy 对象)将模型部署到 TPU。该方法如下所示:
作者图片
结论
在为 ML 模型选择共享内存模型还是分布式内存模型时,有一些重要的权衡需要考虑。虽然共享内存模型更容易开发,但分布式内存模型在性能和内存容量方面具有更好的可伸缩性。虽然传统上在分布式内存模型中编程比较困难,但是 Tensorflow 2。x 使得在分布式内存模型中训练 ML 模型变得更加容易,为分布式模型编程所需的额外努力得到了性能收益的丰厚回报。
使用 ModelOps 扩展和管理人工智能计划
卡尔·海尔达尔在 Unsplash 上拍摄的照片
行业笔记
什么是 ModelOps?
在生产中管理模型具有挑战性。为了优化人工智能的价值,人工智能模型必须提高商业应用程序的效率,或者在生产中运行时支持做出更好决策的努力。ModelOps 是在整个组织中扩展和管理企业人工智能计划并确保从这些企业人工智能计划中获得最大价值的关键能力。
本文将讨论支持这种模型操作能力的系统需求。我们将从真实案例中抽取例子,这些案例使用先进的生产企业系统来编排和自动化模型在其整个生命周期中的可操作性,以实现可伸缩的模型操作。
在这些简短的文字中,不可能涵盖与模型操作能力相关的所有挑战和细节。然而,在文章的最后,我们将尽力为您提供正确的参考资料,这些资料将有助于您加深和了解更多关于 ModelOps 的知识。
一些组织讨论了模型操作,他们是如何实现的,以及大企业应该采用什么样的模型操作。一个很好的例子来自 Gartner,在 2020 年 8 月发表的一篇论文中——ModelOps 的创新见解——他们宣称“ModelOps 是任何组织的企业 AI 战略的核心”。
也请阅读【ModelOps 如何帮助你执行你的人工智能策略
还有许多来自 Gartner 和 Forester 的其他出版物,仅举几个例子,以及一个围绕 ModelOps 的不断增长的社区,可供那些希望了解更多信息的人使用。然而,本文的主要重点是强调开始您的 ModelOps 之旅的基础知识。
那么,让我们从关于 ModelOps 的主要问题开始,也就是为什么是 ModelOps?推动大型组织开始认真投资于模型操作能力的价值和难题是什么?
图 1 —为什么选择 ModelOps?—图片由来源提供,经作者许可编辑
我们在图 1 的右侧列出了一些,从我们的角度来看,我们认为它们可能按以下顺序排列:
- 控制风险:越来越多的业务计划和中央决策由人工智能算法和 ML 模型衍生的模型指导,这些模型正在真正影响现有的治理和风险结构。
- 缩短模型投入业务的时间:较新的建模技术逐渐过渡到现有的结构中,这促使大型组织了解并更好地利用 ModelOps 功能,另一方面,不断需要尽快将这些模型引入业务中。因此,在开发这些模型时需要花费时间和精力,这些模型有时具有众所周知的不可预测的保存期限,例如对特定商业制度的适用性。因此,将这些模型快速引入业务,最终会推动 ModelOps 的核心功能。
- 增加透明度:增加透明度和问责制,以便能够随时知道你的模型在哪里。
- 释放人工智能投资的价值:显然,所有这些不仅会释放企业人工智能计划的价值,而且随着时间的推移,此类计划的数量将不可避免地增加。
如果我们看看过去的 30 个月,我们会看到人工智能计划的巨大增长。在指数级变化速度的推动下,组织和创业公司正在努力采用 ModelOps,目标是捍卫和扩大他们的市场机会。
传统模型与人工智能/人工智能模型
在这种背景下,今天的大多数组织都在积极采用更加敏捷、高效的人工智能和机器学习应用交付,当然还有 IT 管理实践,以满足客户不断变化的期望。
如图 2 所示,在左侧,我们有典型的企业范围资产事物的(灰色六边形)表示,例如企业范围工具、企业范围硬件机器、企业设施、企业范围软件和过程,以及特定传统模型的类别类型,它们影响企业监管和治理结构。在金融服务中,这些通常是在模型风险管理系统或 MRM 中注册的模型。因此,在传统模型中,源自业务和领域专业知识的统计模型往往更多地在业务单位上下文中,而不是在企业上下文中,真正专注于推动特定业务单位的绩效。
图 2 —传统模型与人工智能/人工智能模型—图片来自来源,经作者许可编辑
传统模型和 AI/ML 模型有什么不同?AI / ML 模型和传统模型一样是决策模型。这些模型实际上来自于一开始的需求,因为它们来自于专有数据,通常与业务问题相关联。它们是非常复杂的模型
- 因为他们在 AI/ML 的环境中使用算法方法;
- 就与公司流程批准的治理结构的关系而言。
此外,除了完美地适应决策框架,它们还在技术层面上产生影响,它们往往涉及公司的技术结构。由于其技术复杂性,可能需要通过开发运维、企业安全、it 运营等流程,驻留在云服务上,或出于其他原因驻留在本地基础架构上。
另请阅读安全可靠人工智能的模型操作
因此,在人工智能和机器学习的世界中,这些模型比传统模型更像是一种企业资产。正如我们所看到的,它们为业务部门提供支持,而且非常复杂,um 生命周期更快,保质期非常不可预测。由于这个原因,需要非常快速地刷新这些模型,记住它们也可能具有不同的刷新频率。
因此,所有这些导致企业 AI 和 ML 模型的管理面临独特的挑战,如果一家公司或组织希望将这些模型的治理、监控和协调内部化,他们必须考虑到这些代表了一种新的企业级资产,这将真正为他们提供一个前进的基础,并最终理解作为一种能力的模型操作的原因和方式。
所有这些模型都有自己的生命周期,并且暂时与各种现有的业务流程和公司级别的各种技术流程相关。
图 3 给出了生命周期的大致概念。在紫色区域,有模型工厂,从数据科学的角度来看,所有的东西都是为了创建模型而产生的。模型不是传统的软件,由于它们的独特性,它们与企业模式没有相同的关系,但是模型的生命周期确实适合企业范围的模式。
图 3——模型生命周期——图片由来源提供,经作者许可编辑
从这个例子中可以看出,打包部署和执行通常是由模型工厂自己提供的。也可以将它打包到 docker 容器中并发布,或者 ModelOps 平台可以自己提供该功能,因此在每个模型的基础上,都有生命周期中打包部署和执行部分的详细信息。
ModelOps 是关于理解模型的整个生命周期以及它们与业务和技术的集成,以便随着时间的推移在企业中交付价值。
在此图的绿色部分,我们可以看到一个典型的操作周期。这里提供了推理监控、概念漂移监控、统计性能或数据漂移等内容、模型的持续监控以及右下方法规遵从性审核中的治理结构。如果模型有任何变化,例如再培训或 Champion Challenger,这可能是非常复杂的自动再培训流程,这可能会启动新的监管或合规或问责流程。
想象一下,一个企业有成百上千个模型,并且必须能够准确地知道每个模型在其生命周期中的位置,这是非常复杂的,并且成为扩展的真正挑战。如果做得不好,它会影响治理和提供问责制和可审计性的能力,例如基于每个模型的道德公平和偏见。
模型是资产,它们是复杂的资产,不像传统的资产,它们需要生命周期,这些生命周期也是复杂的,必须自动扩展,并且与现有的业务和技术流程有复杂的关系。
图 4 —整个企业的 MLC 图片由来源提供,经作者许可编辑
除此之外,现在重要的是要注意,由于它们的独特性,模型不像软件那样商品化。企业不知道他们是否可以拥有许多小数据模型或大数据模型,模型生命周期像任何企业架构考虑一样,倾向于将自己借给企业范围的模型。我们认为生命周期是一个企业范围内的问题,这设定了企业人工智能架构师的角色。在图 4 中,我们有一些生命周期的例子,如欺诈检测生命周期(我们之前已经深入讨论过),其他用例是反洗钱和一些金融服务。然而,所有这些生命周期都需要管理和设计,它们是真正的架构资产。
人工智能编排平台
企业需要能够在这些资产的整个生命周期中持续管理、自动化和监控这些资产,而这正是 ModelOps Center 等现代生产 ModelOps 系统所做的。
这种系统为企业提供了一种集中、一致和有效地管理所有 AI/ML 模型的方法。该解决方案使团队能够优化整个模型运营生命周期,从初始部署到报废。
在这篇博客中,我们测试了 ModelOp Center 的特性。该平台使团队能够自动化和编排模型监控和治理。该解决方案提供了团队建立可靠、合规和可扩展的人工智能计划所需的所有关键功能。有了这些功能,团队可以最大化其模型的价值,提高运营和成本效率,并控制风险。
图 5 —现代生产模型操作系统的关键能力—图片由来源提供,经作者许可编辑
- 该解决方案使团队能够:
- 定义、细化、标准化和自动化模型运行中涉及的每一个步骤。
- 使用预定义的流程进行注册、运营、风险管理和监控。
- 为所有模型设计一致、优化的端到端运营流程,同时基于收集的元数据实现灵活定制
2.团队可以建立对模型符合性的持续验证。因此,我们可以始终如一、权威地确保法规要求、业务政策和风险控制的持续执行。
3.监测涵盖一系列领域,包括数据漂移、概念漂移、伦理公平性、可解释性和群体评分、特征稳定性等。
4.预打包的集成包括:
- 人工智能模型工厂。
- 模型框架。
- 模型工作台。
- 共享 IT 系统。
- 基于云的 ML 服务。
- BI 可视化工具
5.该解决方案允许以统一的方式跟踪和管理所有模型,并提供了简化跟踪、治理和报告工作的复杂可见性。
无论我们支持哪种类型的业务,通过采用正确的现代生产模型操作系统,我们将能够在企业层面提供自动化和治理,并确保企业层面的所有问题都可以轻松地在每个企业人工智能计划中得到解决。企业人工智能正在成为大型组织中大多数决策的一种战略方向。
ModelOp Center 是一个系统示例,该系统支持管理 AI 和 ML 模型的基本挑战,并能够大规模自动化非常复杂的生命周期,包括业务和技术挑战,并为组织提供了解所有模型位置的能力。
另请阅读数据科学如何推动数字化转型
图 ModelOp 中心的问题解答—图片由来源提供,经作者许可编辑
成功模型操作的 4 个步骤
几十年来,组织一直使用模型来帮助商业决策。然而,人工智能和机器学习模型给模型操作化(后期开发)带来了新的风险。许多模型操作流程是手动的,或者使用本地开发的解决方案进行管理,这些解决方案需要随着新技术、工具和治理要求的引入而不断更新。
因此,开发的模型中有一半以上没有得到部署,而那些模型需要几个月的时间来运行,这往往导致次优的结果以及延迟或降低的价值。
这里有 4 个步骤,任何组织都可以成功地操作 AI/ML 或任何其他类型的模型。
1。 定义端到端的模型运行过程(简称模型生命周期)
- 准备模型用于生产的第一步是建立端到端的模型操作流程,称为模型生命周期(MLC)。
- 企业 AI 架构师通常负责设计模型生命周期。
②。** 调配车型
- 部署是将模型集成到现有生产环境中,以根据数据做出实际业务决策的方法。
- 通常,数据科学家负责部署模型。
3。 监控生产中的车型
- 当一个模型首次在生产系统中实现用于实际业务用途时,监控就开始了,并持续到该模型退役为止,有时甚至超过作为历史档案的时间。
- 模型操作员通常负责监控生产中模型的健康状况。
4。 统辖模型操作
- 模型是一种智力资本,应该作为企业资产来管理。应该使用使审计和报告尽可能高效的工具和技术对它们进行清点和评估。
摘要
自动化和编排模型生命周期的所有方面确保了可靠的模型操作和大规模治理。企业中的每个模型都可以采用多种多样的生产路径,具有不同的监控模式和各种持续改进或淘汰的需求。
公司需要开始将 ModelOps 视为一种基本能力,这种能力可以真正实现业务追求的卓越水平,并确保投资具有有保证的即时 ROI。这件事不能再拖延了。
关注我的每日技术和创新更新
【https://bit.ly/m/ingliguori
参考
使用 MLflow 扩展您的模型开发
在本文中,让我们看看您的数据科学团队如何👩💻👨💻可以通过 MLflow SDK 体验🧪的新模式。如果你对 MLflow 感兴趣,并且想更进一步,请跟我来,✋
图片由 Jorge Ramirez 在 Unsplash 上拍摄。用 MLflow 整理你的数据线!
https://medium.com/@stefanobosisio1/membership
目录
— 什么是 MLflow?
— 十秒钟介绍 MLflow 环境
— 帮助您的团队:迈向 MLflow SDK
— 实现 MLflow 跟踪 SDK 类
—对象构造器
—读取输入参数—
—设置器和获取器
—训练模型例程
什么是 MLflow?
MLflow 是一个机器学习的开源平台,覆盖整个 ML 模型周期,从开发到生产再到报废。MLflow 直接来自 Databricks,它可以与任何库、语言和框架一起工作,并且可以在云上运行,它是跨团队协作的关键产品。
我们可以定义四种 MLflow 产品:
- ml 流量跟踪:该组件涵盖模型实验阶段。数据科学家可以研究和开发不同的数据和模型参数,收集 MLflow 中的所有相关信息,并选择哪个模型可以进入生产阶段
- MLflow 项目:在大型协作中,数据、API、代码需要共享的情况经常发生。合作者经常会遇到安装问题、模型中的问题、代码分段错误和其他类似的“威胁生命”的障碍。允许使用一种通用的格式来打包数据代码,使它们更具可复制性,并在团队间共享而不会引发心脏病
- MLflow 模型:一旦一个团队登陆生产地,下一步就是避免模型的混乱和混乱。模型允许以简单直观的方式在不同的环境中部署机器学习模型
- MLflow Model Registry :以及如何避免生产中最后的混乱?注册中心是一个解决方案,它跟踪所有模型的状态,无论它们是在生产中、在试运行中还是最终退役。
我将写 3 篇关于物流的文章,涉及物流跟踪和物流模型。特别是,在这个故事中,我将向您展示如何通过思考一个 MLflow SDK 来帮助您的团队,以便数据科学家可以跳过编码 MLflow 中的一些繁琐部分。在第二个故事中,我们将扩展 SDK 来检索指标,并为数据科学家创建直观的 Plotly 图,以及一些示例。最后,我将向您展示如何创建一个 MLflow 插件,它可用于在 GCP 人工智能平台中部署模型
十秒钟 MLflow 环境介绍
MLflow 开发人员已经整理了这份精彩而全面的指南,让每个人都可以安装 MLflow 并开始使用它:https://mlflow.org/docs/latest/quickstart.html
在这里,我将让您快速浏览一下,在本地机器上运行。安装 MLflow 后,我们可以编写一个类似这样的小代码:
图 MLflow 的简单介绍代码
通过运行python name_of_your_file.py
执行这段代码,这将在 MLflow 中启动一个记录过程。这就是 MLflow 发挥作用的地方!在您的 CLI 中,只需键入mlflow ui
即可启动 MLflow 图形界面。前往http://localhost:5000
(或http://127.0.0.1:5000)
,你将进入 MLflow 界面(图 2):
图 2: MLflow 用户界面。左边是实验列表,中间是基本信息、参数和指标。
如果你点击一个特定的运行,你会得到一个新的窗口,如图 3 所示。在这里你可以检索运行的参数(例如,这可能是层数,批量大小,初始学习率等),运行的指标作为互动图(例如,准确性作为功能的步骤/时期)和所有保存的人工制品
图 3: MLflow 单次运行用户界面。在这个窗口中,您可以获得关于代码运行和检查工件的更多细节
帮助您的团队:迈向 MLflow SDK
到目前为止一切顺利,但现在是时候扩大规模,帮助您的数据科学团队将 MLflow 集成到他们已经存在的模型中了。构建在 MLflow 包之上的 MLflow SDK 将是一个完美的解决方案,不仅可以降低团队消化新技术的难度,还可以在一个简单的 Python 类中满足数据科学家的请求。
首先,我们需要了解我们的 MLflow 类应该做什么,以及我们想要走什么样的道路。图 4 显示了一个可能的路线图,从 MLflow SDK 的创建到 CI/CD 和通过 MLflow 插件的部署
图 4:路线图草图。MLflow SDK 应该照顾现有的数据科学家的模型,并保存人工制品。然后,MLflow 部署插件可以将最终结果推向生产
实现 MLflow 跟踪 SDK 类
因此,第一步是设计一个实现 MLflow 的类,它可以具有以下功能:
read_params
此函数读取设置新 MLflow 实验所需的跟踪输入参数set_tracking_uri
和get_tracking_uri
:这两个函数分别设置 mlflow 跟踪 uri (mlflow.set_tracking_uri
)并返回当前跟踪 uriset_experiment_id
和get_experiment_id
:set 函数检查是否已经给出了一个experiment_name
,否则创建一个新的。run_training
:这是捕获模型参数和指标的主要函数(主要通过使用 Python 模块inspect
)。模型的参数和指标由mlflow
通过mlflow.package.autolog
功能自动检索。log_any_model_file
:有时 MLflow 自动登录功能无法将保存的模型文件上传到 MLflow-server。在这些情况下,该功能可以帮助数据科学家。事实上,一旦训练完成,调用这个函数,就可以找到工作运行目录中的所有.joblib
、.h5
、.pkl
、.model
文件,以及png
格式的度量和json
元数据文件,并正确地报告给 MLflow-server。
对象构造函数
现在让我们开始编写代码,设置一个类接口和协议以及它的构造函数。有一个云存储选项可能是有用的,所以你可以导入它(例如from your_cloud_provider import storage_module
)并将工件直接保存在云上。
图 5:设置 MLflow SDK 接口和协议。SDK 将存在于这个主对象上
读取输入参数
接下来,我们可以开始考虑解析并读取参数。数据科学家可以使用 Python 字典中给定的指令和参数解析yaml
或json
或txt
输入文件,这些文件可以由类直接读取:
图 6:读取参数功能。数据科学家可以将输入文件解析到字典中,字典提供诸如跟踪 uri(例如, http://localhost:5000)、,)以及存储位置、运行名称和标签等指令
在本例中,我添加了self.caller
,稍后我们将看到这些信息是如何传递给 SDK 的,但是这个变量的目的是记录哪个脚本调用了 MLflow SDK,将 Python 脚本复制到工件中,并实现代码传承。代码沿袭在运行时很有用,因为可以发生许多修改,尽管数据科学家可以跟踪 Github 中的变化,但一些变化可能会丢失,导致令人困惑和神秘的结果。
Setters 和 getters
接下来,我们需要注意设置器和获取器(图 7)。这些函数听起来可能没什么用,但在执行大量长代码时,它们非常重要,可以挽救你的生命!
图 7:主类的 Setters 和 getters。
在set_experiment_id
上花几秒钟来创建一个新实验是值得的experiment_name
和tracking_storage
被传递给mlflow.create_experiment(experiment_name, tracking_bucket)
,从那里experiment_id
被取回。experiment_id
和run_name
都是强制在 MLflow 中开始新的运行,因此我们需要特别注意这些变量。
训练模型例程
现在,我们已经准备好进行日常训练了。通常,MLflow 通过上下文管理器来跟踪模型训练作业,上下文管理器是一种 Python 协议,通常会简化一些资源管理模式:
图 8:来自 MLflow 教程(https://www . ml flow . org/docs/latest/tutorials-and-examples/tutorials . html)的关于培训跟踪的示例
上下文管理器的问题是with mlflow.start_run()
只有在训练 Python 代码中被直接调用时才能记录工件和训练会话。对于数据科学家来说,这可能是一项非常枯燥的重组任务,他们应该重新编写部分代码来适应这一功能。想要的解决方案应该是类似的:
from your_mlflow_sdk import experiment_tracking
...if tracking: # if you decide to track:
experiment_tracking.start_trianing_job(input_parameters)
history = model.fit(**fit_params)
# report additional metrics (we'll see below)
experiment_tracking.end_training_job(input_parameters)
else:
history = model.fit(**fit_params) # normal training
run_training
函数应该可以处理这个问题,它可以监听用户正在做什么,而不会干扰已经编写好的代码:
图 9:主训练函数,可以被调用来记录所有的模型人工制品
该函数调用mlflow.autlog()
函数,对监听xgboost
、sklearn
、tensorflow
、keras
和lightgbm
模块提供了极好的支持,自动将所有模型参数报告给主界面。该函数的核心是mlflow.start_run()
,它设置要记录的运行,正如我上面所说的,它将调用者 Python 脚本self.caller
作为mlflow.log_artifact(self.caller, artifact_path='code')
报告给 artefacts 文件夹code
将任何模型文件/工件记录到 MLflow 中
避免上下文管理器的一个问题是,并非所有生成的模型文件都会自动保存到 MLflow 服务器。例如,在我的例子中,许多模型文件保存在本地或云中,但是我希望它们也在 MLflow 服务器中报告。为了解决这个问题,图 10 中的log_any_model_file
开始发挥作用。
该函数调用新运行的实验。它检查实验运行是否顺利。然后,它查看一个给定的存储位置,本地或云,以查看在那里保存和创建了哪些文件。接下来,扫描想要的格式列表,local_file_to_upload
,运行一个 for 循环,用client.log_artifact(run_id, file_to_upload, artifact_path='model')
将所有找到的文件记录到一个model
文件夹中
图 10:将任何元数据和模型文件记录到 MLflow 服务器。有时不是所有的文件都由 MLflow 直接保存,尤其是在使用混合模型时。因此,该功能在云上或本地寻找额外的工件,并将它们上传到 MLflow 服务器
在一个模块中修补所有内容
现在,您已经创建了 MLflow SDK 的基础,我们可以继续实现一个培训模块,数据科学家可以将其用于他们的实验。模块名可以是实现功能start_training_job
和end_training_job
的experiment_tracking_training.py
。
前一个函数设置 MLflow 跟踪作业。它通过带有caller = traceback.extract_stack()[-2][0]
的traceback
模块检索调用者 Python 脚本代码,这将在工件中报告。然后,它初始化实验参数,最后开始训练运行runner.run_training()
end_training_job
可在模型拟合后调用,通过log_any_model_file()
检索任何其他可能的未保存文件
图 11:使用 MLflow 开始和完成培训工作会话记录的模块。start_training_job 初始化实验跟踪协议,而 end_training_job 检查未保存到 MLflow 服务器的其他工件。
今天就到这里吧!我们经历了很多事情,如果你不熟悉 MLflow,你会一步一步地消化一切。请继续关注我们的下一个故事,它将展示如何向我们的实验报告额外的指标,并且我们将看到一些如何使用我们的 MLflow SDK 的示例:)
如果你有任何问题或好奇,请给我发电子邮件到 stefanobosisio1@gmail.com