Categories
程式開發

处理数据,大数据甚至更大数据的 17 种策略


如何处理大数据和真正的大数据?

本文最初发表在 Towards Data Science 博客,经原作者 Jeff Hale 授权,InfoQ 中文站翻译并分享。

处理大数据可能很棘手。不会有人喜欢“内存不足”的错误提示。也不会有人愿意等待代码运行。更别说会有人乐意抛弃 Python。

如果你遇到这些问题,请不要绝望!我将在本文中为你提供一些技巧,并介绍一些即将问世的库,帮助你高效地处理大数据。我还会为你提供解决方案,解决那些无法适合内存的代码问题。而这一切都将会在 Python 中进行。

Python是最流行科学和数值计算编程语言。对于清理代码和探索性数据分析来说,Pandas是最受欢迎的。

在 Python 中使用 Pandas,可以让你处理比 Microsoft Excel 或 Google Sheets 更多的数据。

SQL 数据库在存储数据方面非常流行,但是 Python 生态系统在表达性、测试性、可再现性以及快速执行数据分析、统计和机器学习的能力方面,比 SQL 有很多优势。

不幸的是,如果你是在本地工作的话,那么,Pandas 所能处理的数据量将会受到你机器上的物理内存容量限制。但如果你在云端中工作,更多的内存需求又意味着需要耗费更多的资金。

无论你的代码在哪里运行,你都希望操作能够快速进行,这样你就可以完成任务!

总是要做的事情

如果你听说过或看到过关于加速代码的建议,那么你一定看到过警告:不要过早优化!

诚然 ,这是一条好建议。但懂得一些技巧也是很聪明的做法,这样你才能写出干净、快速的代码。

对于任何规模的数据集来说,下面三种做法都是良好的编码实践。

  1. 尽可能避免嵌套循环。点击此处可以参阅大 O 符号(Big-O notation)和算法分析的简单分析。一个 for 循环嵌套在另一个 for 循环里,一般会导致多项式时间的计算。如果你有不止几个项目要搜索的话,那么就需要等上一段时间。请看此处的图表和解释。

  2. 在 Python 中尽可能使用列表推导(List comprehension)(以及字典推导(Dist comprehension))。按需创建列表比加载列表的 append 属性并将其作为函数反复调用要快:这要感谢 Stack Overflow Answer(译注:Stack Overflow 网站的一款 App,Stack Overflow 是一个程序设计领域的问答网站)。然而,一般来说,不要为了速度而牺牲清晰度,所以在嵌套列表推导务必要小心。

  3. 在 Pandas,使用内置的函数向量化。其原理其实和字典推导的原因是一样的。一次将一个函数应用于整个数据结构比重复调用一个函数要快得多。

如果你发现自己正在申请,请想想你是否真的需要这样做。它将会遍历行或列。向量化方法通常速度更快,代码更少,因此它们是一个双赢的方法。

要避免使用其他在数据上循环的 Pandas Series 和 DataFrame 方法:applymapitterrowsittertuples。在 DataFrame 上使用replace方法,而不是任何其他选项,这样可以节省大量时间。

请注意,这些建议可能不适用于非常少量的数据,但在这种情况下,风险很低,所以谁在乎呢?

这就涉及到我们最重要的规则

如果可以,就继续用 Pandas。这是快乐的源泉。

如果你没有问题,也不希望数据膨胀,就不要担心这些问题。但在某些时候,你会遇到一个大数据集,然后你会想知道该怎么做。让我们来看一些技巧。

处理相当大的数据(大约数百万行)

  1. 如果你要做机器学习,就用你的数据子集来探索、清理,构建一个基线模型。快速解决 90% 的问题,节省时间和资源。这个技巧可以帮你节省很多时间。

  2. 在读取 DataFrame 时,只用usecols参数加载你需要的列。记住,更少的数据输入意味着胜利!

  3. 有效地利用 dtype。将数值列向下转换为对pandas.to_numeric()有意义的最小 dtypes。将基数较低的列(只有几个值)转换为分类 dtype。请参阅这个关于高效 dtype 的Pandas 指南

  4. 在 Scikit-learn 将模型训练并行化,学习尽可能使用更多的处理核心。默认情况下,Scikit-learn 只使用 CPU 的一个核心。许多计算机的 CPU 有 4 个或更多的核心。在使用 GridSearchCV 和许多其他类进行交叉验证时,通过传递参数n_jobs=-1,可以将它们全部用于可并行化的任务。

  5. 将 Pandas DataFrame 保存为 feather 或 pickle 格式,以加快读写速度。感谢 Martin Skarzynski,因为他提供了证据和代码的链接

  6. 使用pd.eval加快 Pandas 的操作。将你常用的代码以字符串形式传递给函数。它的操作速度更快。下面有一个测试图表,DataFrame 为 100 列。

处理数据,大数据甚至更大数据的 17 种策略 1

df.querypd.eval基本相同,但它是作为 DataFrame 方法,而不是顶级 Pandas 函数。

由于存在一些问题,请注意查看文档。

Pandas 在幕后使用的是 Numexpr。Numexpr 还可以与 NumPy 一起工作。向 Chris Conlan 致敬,感谢他的著作《Fast Python》(《快速 Python》),正是这本书,我才知道了 Numexpr。Chris 这本书是一本学习如何加速 Python 代码的优秀读物。

处理真正的大数据(大约数千万行以上)

  1. 使用Numba。如果你在做数学计算,Numba 能给你带来极大的速度提升。安装 Numba 并导入它。然后,当你需要在 NumPy 数据上进行循环,且不能使用向量化方法时,就使用@numba.jit装饰器函数。它只对 NumPy 数据有效。在 Pandas DataFrame 上使用.to_numpy()将其转换为 NumPy 数组。

  2. 在有意义的时候使用SciPy 稀疏矩阵。Scikit-learn 通过一些转换器(如 CountVectorizer)自动输出稀疏数组。当数据主要为 0 或缺少值时,可以将列转换为 Panda 中的稀疏 dtype。要了解更多内容请点击此处

  3. 使用 Dask 将数据集的读取并行化为 Pandas 的数据块。Dask 还可以跨多台机器执行并行化数据操作。它模仿了 Panda 和 NumPy API 的一个子集。Dask_ML是一个姊妹包,用于跨多台机器并行化机器学习算法。它模仿了 Scikit-learn API。与其他流行的机器学习库如 XGBoost、LightGBM、PyTorch 和 TensorFlow 很好地结合在一起。

  4. 不管有没有 GPU,都可以使用 PyTorch。正如我在这篇关于排序的文章中所发现的那样,在 GPU 上使用 PyTorch 可以大大提高速度。

未来处理大数据需要注意/尝试的事项

以下三个方案是截止 2020 年年中的前沿方案。预计将会出现配置问题和早期 API。如果你是在本地 CPU 上工作,这些方案不太可能满足你的需求。但它们看起来都很有前途,值得关注。

  1. 你能使用很多 CPU 核心吗?你的数据是否超过 32 列(到 2020 年年中开始是必需的)?然后考虑一下Modin。它模仿 Pandas 的一个子集,以加快对大型数据集的操作。它在幕后使用的是 Apache Arrow(通过 Ray)或 Dask。Dask 后端是实验性的。在我的测试中,有些事情并不是很快,例如,从 NumPy 数组读取数据就很慢,并且内存管理也是一个问题。

  2. 你可以使用 Jax 代替 NumPy。Jax 是 Google 开源的一款非常前沿的产品。它通过以下五个底层工具来加速操作:autograd、XLA、JIT、向量化器和并行化器。它可以在 CPU、GPU 或 TPU 上工作,并且可能比使用 PyTorch 或 TensorFlow 来获得速度提升更简单。
    Jax 也适用于深度学习。它目前有 NumPy 版本,但尚未提供 Pandas 版本。不过,你可以将 DataFrame 转换为 TensorFlow 或 NumPy,然后再使用 Jax。请点击这里以了解更多内容。

  3. Rapids cuDF在 GPU 上使用 Apache Arrow,并带有类似 Pandas 的 API。这是一个 NVIDIA 开源的 Python 包。Rapids 与 Dask 配合得很好,所以你可以让多个 GPU 并行处理数据。对于最大的工作复杂,它应该能带来一个很好的提升。

其他关于代码速度和大数据的知识

计时操作

如果你想在 Jupyter Notebook 中进行计时操作,你可以使用%time%%timeit魔法命令。它们都在单行或真个代码单元中工作。

处理数据,大数据甚至更大数据的 17 种策略 2

%time运行一次,而%%timeit运行代码多次(默认值为 7)。一定要查看文档,了解其中的微妙之处。

如果你在脚本或 Notebook 中,可以导入时间模块,检查运行某些代码前后的时间,并找出差异。

处理数据,大数据甚至更大数据的 17 种策略 3

在进行测试时间时,请注意不同的机器和软件版本可能会导致差异。如果要重复测试的话,缓存有时候会产生误导。正如所有的实验一样,要尽可能保持一切不变。

存储大数据

GitHub 的最大文件大小为100MB。如果你想使用 GitHub 对大文件进行版本化,你可以使用Git Large File Storage(Git 大文件存储)扩展。

除非你愿意,否则请确保你没有将文件自动上传到 Dropbox、iCloud 或其他自动备份服务。

想了解更多吗?

Pandas 文档中,有关于提高性能扩展到大型数据集的部分。本文其中一些想法就是根据这些章节改编而来。

总结

你已经了解了如何编写更快的代码,你也了解了如何处理大数据和真正的大数据。最后,你还了解到了一些新出的库,它们在处理大数据方面可能会继续变得越来越流行。

我希望本文能够对你有所帮助。

作者介绍:

Jeff Hale,技术撰稿人,撰写数据科学相关的文章,如 Python、SQL、Docker 和其他技术主题。并维护数据科学资源邮件列表:https://dataawesome.com

原文链接:

https://towardsdatascience.com/17-strategies-for-dealing-with-data-big-data-and-even-bigger-data-283426c7d260