深入了解 Colab 的新更新和增强功能
原文:
towardsdatascience.com/a-close-look-at-colabs-new-updates-and-enhancements-f1225fd5d504
充分利用 Google Colab 笔记本
·发表于 Towards Data Science ·阅读时间 8 分钟·2023 年 10 月 3 日
–
图片由作者使用 Excalidraw 创建。
最后更新于 2023 年 12 月 20 日
每当我进行编码研讨会或教程时,Google Colaboratory Notebooks——或称为 Colab——始终是我首选的资源。它消除了讲师和参与者在环境设置上的麻烦,并且提供了对强大计算资源(如 GPUs 和 TPUs)的免费访问。凭借其易于共享的链接,Colab 使整个学习过程更加高效和有效。为了充分利用 Colab 提供的功能,我始终关注其最新发布和更新。
虽然我通常 通过 LinkedIn 分享这些更新,但大量的新功能和增强功能值得这样一篇更全面的文章。我之前的 Colab 重要功能汇总是在 2022 年,显然现在需要一个更新的概述。
towardsdatascience.com
让我们看看 Colab 的一些杰出功能,它们在我的工作中非常宝贵。我希望你也会发现它们同样有用。
1. 来自 Google Sheets 的智能数据粘贴
现在,当用户将数据粘贴到一个空的代码单元格时,Colab 会自动生成代码来创建一个pd.DataFrame
。这一增强功能消除了传统流程中的额外步骤,使用户体验更加流畅。
从 Google Sheets 智能粘贴数据 | 图片由作者提供
而且不仅如此——如果代码单元格中已经有文本,Colab 会贴心地为你添加 CSV 文字。
2. 从 Pandas 数据框自动生成图表
Colab 中的数据可视化现在变得更加便捷,通过其新功能——从 Pandas 数据框自动生成图表。当你执行一个以数据框引用结束的代码单元格时,输出的右下角会出现一个自动绘图按钮。
在 Colab 中自动生成 Pandas 数据框图表的图标 | 图片由作者提供
点击此图标会显示针对你的数据框量身定制的各种推荐图表,每一个图表都可以通过单击无缝地添加到你的笔记本中。
从 Pandas 数据框自动生成图表 | 图片由作者提供
如演示所示,这个功能不仅展示了渲染的图表,还附加了相关代码,并将其整齐地放置在笔记本的后续单元格中。
3. 交互式数据框
Pandas 数据框提供了一种结构化的表格格式,这种格式直观且兼容多种数据操作。使用 Google Colab,用户可以实时与这些数据框进行交互。当数据框在 Colab 中加载并显示时,会出现一个类似计算器的图标,如下所示。
渲染数据框交互式图标 | 图片由作者提供
点击此图标,数据框会转换为交互式表格:
Colab 中的交互式数据框 | 图片由作者提供
如你所见,我们立即展示了良好的表格格式。增强的交互性提供了许多优势,例如:
- 调整页面大小并使用分页功能可以提供更清晰的数据视图。
调整页面大小并使用分页功能可以提供更清晰的数据视图 | 图片由作者提供
- 简单点击列标题可以让用户对整个数据集中的列进行排序,更新会立即可见。
在交互式格式中排序列变得容易 | 图片由作者提供
- 可以通过直接字符串匹配或正则表达式匹配轻松筛选特定行。例如,要突出显示美国原产的汽车,用户可以在
**origin**
字段中搜索USA
。还可以在搜索中设置值的边界。例如,识别 1970-1971 年间所有具有八个气缸且每加仑至少 15 英里燃油效率的美国原产汽车。
交互式数据框中的筛选操作 | 图片由作者提供
- 数据可以以各种格式轻松复制,例如 CSV、markdown 或 JSON。
数据可以轻松以各种格式复制,例如 CSV、markdown 或 JSON | 图片来源:作者
本质上,Google Colab 的交互式表格支持动态数据搜索和过滤。这消除了不断重新运行单元格的需要,使数据洞察更加迅速,并改善了整体数据探索过程。
4. 管理单元格执行
Colab 现在支持两个新功能,旨在简化用户在笔记本中运行代码单元格的方式。
- 其中第一个功能允许用户直接从笔记本的目录运行一组单元格。这可以通过上下文菜单中的
**Run cells in section**
选项完成,该选项由三个垂直点表示。
从笔记本的目录直接运行一组单元格 | 图片来源:作者
- 第二个功能专注于在笔记本中设置先决条件。用户现在可以指定特定单元格在打开笔记本时自动运行。这可以通过位于
**Edit**
菜单下的笔记本设置对话框进行设置,在那里有一个选项可以Automatically run the first cell or section
。如果笔记本仅以一个单元格开始,则该单元格将在每次访问笔记本时自动运行。类似地,如果笔记本以一个部分开始,则在打开笔记本时,该部分的所有初始单元格将自动执行。
指定特定单元格在打开笔记本时自动运行 | 图片来源:作者
5. 语言之间更轻松的转换
Google Colab 更新了其界面,以简化不同语言之间的切换过程。用户现在可以通过进入Edit
然后选择Notebook settings
轻松切换已安装的内核。**R 编程语言是可用选项之一,**因为它是默认安装的。
在 Colab 中转换 Python 和 R | 图片来源:作者
6. 笔记本 X Colab
通过弥合各种笔记本与强大的 Colab 平台之间的差距,Colab 帮助提升用户体验并扩展 Colab 的多功能性。
1. Hugging Face 🤗 笔记本在 Colab 中
用户现在可以轻松访问、查看和运行Hugging Face 笔记本在 Colab 环境中,受益于其先进的执行功能和协作工具。这种集成简化了从 Hugging Face 上的模型托管到 Colab 中的实时演示的过渡。只需点击笔记本右上角的Open in Colab
即可在 Colab 平台内启动和执行它们。你可以在这里了解更多信息。
在 Colab 环境中运行 Hugging Face 笔记本 | 图片来源:作者
2. 移植到 Colab 的流行笔记本
Google Colab 不仅仅是一个编写和执行机器学习模型的平台,它还是一个集成复杂代码的卓越讲故事工具。Colab 拥有一系列有见地的案例研究,例如:
-
斯坦福大学的 Ashwin Rao 教授制作了一个引人注目的 Colab 笔记本,深入探讨了 硅谷银行(SVB)失败的高层原因。
-
Colab 团队还成功移植了流行的 Ten Minutes to Pandas 教程,为用户提供了一个引人入胜的 pandas 入门介绍。
7. 使用 Colab 的新 URL 快捷方式快速创建笔记本
类似于你可以通过链接如 [**docs.new**](http://docs.new)
立即创建新文档,或通过 [sheets.new](http://sheets.new)
创建新电子表格,现在也有一个简单的链接用于 Google Colab!如果你访问 **c**[**olab.new**](http://colab.new)
,你将立即开始一个新的笔记本。
使用 Colab 的新 URL 快捷方式快速创建笔记本 | 图片由作者提供
8. 程序化终止 Colab 会话
另一个新增功能是能够直接从代码中终止运行时。
from google.colab import runtime
runtime.unassign()
unassign()
函数指定要移除的活动运行时,并断开与任何笔记本会话的连接。无论是为了节省内存、重置会话还是结束项目,这个功能都确保用户可以直接在代码环境中轻松准确地完成操作。
程序化终止 Colab 会话 | 图片由作者提供
9. Colab 链接预览在 Docs 套件中
Colab 链接预览已集成到 Google Docs 套件中。现在,Colab 中的 Drive 笔记本链接可以转换为 Docs 套件中的智能卡片。此外,这一增强功能允许用户直接在 Google 生态系统内请求访问 Colab Drive 笔记本,简化了访问过程。
Colab 链接预览在 Docs 套件中 | 来源: https://x.com/GoogleColab/status/1701684666972205243?s=20
10. 生成 Colab 徽章
访问 openincolab.com 为你的 README、网站、文档等创建徽章。只需输入托管在 GitHub 上的笔记本的 URL,测试徽章,并获取 HTML 代码!
生成 Colab 徽章 | 图片由作者提供
11. 在 Colab 中轻松访问 Transformers
Colab 的托管运行时镜像现在预装了 transformers 库,为用户带来了一个小而重要的改进。保持设置的最新状态,定期更新镜像,使用 !pip install transformers --upgrade
强制升级以获取最新功能。
Transformers 库预装在 Colab 中 | 图片由作者提供
这一改进简化了工作流程,并解锁了令人兴奋的功能,例如轻松将 Huggingface 数据集读取到 Pandas 中。
轻松将 Huggingface 数据集读取到 Pandas 中 | 图片由作者提供
12. 使用 Colab 新的秘密功能保护您的 API 密钥
Colab 现在推出了一项新功能,允许您安全地存储私人密钥,如 Huggingface 或 Kaggle API 令牌。通过 Secrets
,这些值保持私密,仅对您和您选择的笔记本可见。这确保了在进行项目时的安全性和安心感。
使用 Colab 新的秘密功能保护您的 API 密钥 | 图片由作者提供
13. Colab 向所有用户推出限时 AI 代码助手试用
Colab 现在向免费计划的用户提供 限时试用 AI 代码助手。AI 驱动的代码助手支持从自然语言生成代码和代码助手聊天机器人。根据官方博客,Colab 预计此服务将持续到 2024 年,只要容量允许。
使用 AI 代码助手来调试代码 | 图片由作者提供
结论
总结来说,这些最近对 Google Colab 的更新和改进在我使用该平台的日常工作中证明是非常有用的。从与 Google Docs 套件的集成到高级数据过滤功能等,这些更新共同提升了 Colab 作为协作数据科学工具的地位。所有这些更新都已从其官方发布说明和博客中整理出来,相关链接已在参考部分共享。我鼓励大家探索这些功能,如果你发现了额外的功能或有个人见解,请与社区分享。你的见解可能对他人有很大帮助!
参考资料
云迁移策略:5 步检查清单
优化迁移到云端的成本和工作
·
关注 发表在 Towards Data Science ·6 分钟阅读·2023 年 4 月 18 日
–
云迁移策略在开始带来好处之前需要大量的初始投资。这是一个复杂的过程,通常需要做出许多困难的决策。在某些情况下,迁移到云端的需求会落在你的技术专家身上,从数据科学家到机器学习工程师,他们可能无法单独处理这项任务。为了缓解这种情况,我们的专业 IT 顾问和 云迁移服务专家 已经联合努力,帮助你解决问题。
以下指南提供了控制云迁移项目的五个关键步骤。
1. 确定你需要多少云容量
传统的互联网基础设施提供商并不出售计算能力。相反,他们出售的是资源,或者更具体地说,是全天候运行的服务器,即使你没有使用这些资源,也按小时收费。在大多数情况下,你的云应用程序或系统在预付时间内并未完全加载,因此你在为服务器的空闲时间付费时浪费了预算。
现在,具体数值会根据你的运营规模有所不同。例如,如果一家本地公司不进行夜间操作,如报告或维护,它将面临 12 小时的停机时间。这意味着 50% 的基础设施预算将浪费。
可扩展性是一个敏感的问题
单凭抽象的流量预测来购买大型服务器可能过于乐观,而购买小型服务器则可能在系统因突发流行而承受巨大压力时出现故障。
因此,云迁移策略的正确方法是选择能够自动扩展的云服务,或使用基于 AWS Lambda、Azure Functions 或类似专业服务的无服务器后台系统。这些服务支持自动后台扩展,意味着你可以享受按需付费和按使用付费的模式。
然而,使用云服务并不总是一个好主意。例如,当托管在云端时,你不知道你的组件将部署在哪些物理服务器上。网络附加存储可能不如本地硬盘高效。在响应时间至关重要的高负载系统中,本地服务器可能表现更好。
2. 调整你的架构
如果你按原样迁移你的系统,云服务将总是比本地存储更贵。为了优化成本,你应该在迁移之前调整你的架构,并选择合适的服务来促进这一复杂过程。
你还应该考虑云提供商的管理成本和可扩展性开销,因为云提供商提供的是完全托管的服务。
考虑到所有这些因素,对云迁移的唯一正确方法是决定哪些系统组件必须保留在本地,哪些需要迁移到云端。
平衡服务利用
在做出重大决策之前,分析那些已满载和未充分利用的服务。首先优化架构将使云服务比专用服务器更便宜。为帮助你完成这一点,以下是一些最典型的开箱即用的步骤:
-
将所有静态资源迁移到 CDN:这应能减轻应用服务器的一部分负担。
-
使用平台内基础设施组件,如负载均衡器、消息队列和缓存服务。
-
用无服务器处理程序(来自 AWS Lambda 或 Azure Functions)替换不常用的例程和服务。
-
对于负载偶尔且对响应时间宽容的简单后端服务,可以完成完全替换。
要发现可以替换的更多服务,你可以咨询云计算提供商,如 AWS 和 Azure,它们目前是最受欢迎的两家。
计算成本
回答臭名昭著的定价问题非常困难。计算结果可能会因你认为的最佳选择——本地还是云——而倾斜到任何一边。
让我们举一个简单的例子。假设你有一个最初设计为本地运行的系统。这个系统非常繁忙,拥有超过 10 TB 的数据,每天有 8,000,000 多次事件更新,以及每分钟 30,000 次事件吞吐量。你需要为这个系统制定一个云迁移策略。
在这种情况下,你将分两步迁移:
-
你将重写基础设施组件,以便从无服务器服务中受益。
-
你将选择最佳的现成云服务。
通过优化和重新工程你的基础设施,你将能够在需要更少语言的情况下迁移。而且,通过使用无服务器服务,你将看到总体成本的显著下降。
通过这种方式迁移的一些好处包括自动扩展、简化开发和支持以及资源优化。
保护你的数据
出于安全原因,某些行业无法完全考虑云迁移:例如,银行和金融、公共部门、保险和医疗保健。然而,包括政府机构在内的许多高度监管组织已经找到了一种在云中托管其系统的方法。
他们选择了混合模型,只需在云中存储数据的一部分,从而通过维护严格的用户访问限制和利用强大的政府防火墙来保护自己免受攻击。
即使你有多个安全顾虑,如果你和你选择的云服务提供商能够共享以下责任,迁移到云中仍然是可能的。
你的责任
云服务提供商的责任
根据云服务提供商的安全认证来选择。
分析安全风险并扫描你的架构漏洞。
制定有效的 SLA,涵盖提供商-客户关系、第三方和云经纪人。
制定针对特定案例的威胁管理计划,明确的事件解决路线图。
选择混合模型,在这种模型中,你可以将关键任务解决方案保存在本地以确保安全。
使用与企业网络隔离的虚拟机来应对安全风险。
维护一个灵活的安全模型,随着威胁的变化不断演进。
选择开源
许多企业在寻求外部软件开发服务并希望采用云服务时,担心所谓的供应商锁定,即在承诺某个供应商后无法离开云服务或更改供应商。其他重要的担忧还包括在更换供应商时应用程序的互操作性和可移植性,以及可能需要支付更多费用来更改基础设施。
为了应对锁定问题,你应该通过研究提供商的文档或咨询专家,发现其品牌名称背后的实际内容。例如,以下是一些来自 AWS 生态系统的开源或可互操作的服务:
-
AWS ElastiCache:使用 Redis 或 Memcached 作为后台缓存服务
-
亚马逊 Aurora:与 MySQL 兼容的数据库服务
-
亚马逊 Redshift:最初基于 PostgreSQL 构建的数据仓库服务,仍然兼容大多数 SQL 功能
你还可以选择使用标准或开放协议的云服务,允许在必要时更换提供商。此外,开放协议为设备互操作性提供了空间,无需使用专有的网关或接口。
现在,如果云服务提供商在开放协议的基础上还提供自己的专有协议,那么建议总是选择后者。例如,Azure 服务总线提供了自己的 API 以及一个支持的 AMQP——一种开放的消息传递协议。通过选择开放标准,你可以保持灵活性。这意味着你可以更换提供商,甚至部署支持相同协议的自有服务实例,而无需对客户端组件做出重大更改。
结论
云迁移是一个复杂的多层次过程,需要大量的规划。本指南概述了关键的云迁移步骤,帮助你最小化基础设施成本,避免供应商锁定,并解决云采用过程中常见的担忧。
时间差(0)与常数-α蒙特卡洛方法在随机游走任务中的比较
·
关注 发表在 Towards Data Science ·9 分钟阅读·2023 年 8 月 24 日
–
由 Midjourney 生成的图像,使用了付费订阅,符合一般商业条款[1]。
引言
蒙特卡洛(MC)方法和时序差分(TD)方法都是强化学习领域的基本技术;它们通过与环境互动的经验解决预测问题,而不是依赖于环境模型。然而,TD 方法是 MC 方法和动态规划(DP)的结合,因此在更新规则、引导和偏差/方差方面与 MC 方法有所不同。与 MC 方法相比,TD 方法在大多数情况下被证明具有更好的性能和更快的收敛速度。
在这篇文章中,我们将比较 TD 和 MC,或更具体地说,比较 TD(0) 和常数-α MC 方法,在一个简单的网格环境和一个更全面的随机游走 [2] 环境中。希望这篇文章能够帮助对强化学习感兴趣的读者更好地理解每种方法如何更新状态值函数,以及它们在相同测试环境中的性能差异。
我们将在 Python 中实现算法和比较,本帖中使用的库如下:
python==3.9.16
numpy==1.24.3
matplotlib==3.7.1
TD 与 MC 的差异
TD(0) 和常数-α MC 的介绍
常数-α MC 方法是一种常数步长参数 α 的常规 MC 方法,这个常数参数有助于使价值估计对最近的经验更加敏感。在实践中,α 值的选择取决于稳定性和适应性之间的权衡。以下是 MC 方法在时间 t 更新状态值函数的方程:
TD(0) 是 TD(λ) 的一个特例,它只看一步前的状态,是最简单的 TD 学习形式。该方法使用 TD 误差更新状态值函数,TD 误差是指状态的估计值与奖励加上下一个状态的估计值之间的差异。一个常数步长参数 α 与上述 MC 方法中的作用相同。以下是 TD(0) 在时间 t 更新状态值函数的方程:
一般来说,MC 和 TD 方法之间的差异体现在三个方面:
-
更新规则:MC 方法仅在回合结束后更新值;如果回合非常长,这可能会导致程序变慢,或者在没有回合的持续任务中,这可能会成为问题。相反,TD 方法在每个时间步更新价值估计;这是一种在线学习,特别适用于持续任务。
-
引导:在强化学习中,“引导”一词指的是基于其他价值估计来更新价值估计。TD(0) 方法基于下一个状态的价值来进行更新,因此它是一种引导方法;相反,MC 不使用引导,因为它直接从回报(G)中更新价值。
-
偏差/方差:MC 方法没有偏差,因为它们通过加权实际观察到的回报来估计值,而在过程中不进行估计;然而,MC 方法有较高的方差,尤其是在样本数量较少时。相反,TD 方法有偏差,因为它们使用了自助法,偏差可能会根据实际实现而有所不同;TD 方法方差较低,因为它使用了即时奖励加上对下一状态的估计,这平滑了因奖励和行动的随机性引起的波动。
在简单的网格世界设置中评估 TD(0) 和常数-α MC
为了使它们的差异更加直观,我们可以设置一个简单的网格世界测试环境,具有两个固定轨迹,运行这两种算法直到收敛,并检查它们如何不同地更新值。
首先,我们可以用以下代码设置测试环境:
图 1 左:环境设置。右:预设路径。来源:作者绘制的图
上图左侧显示了一个简单的网格世界环境设置。所有彩色单元格表示终端状态;代理在进入红色单元格时获得 +1 奖励,但在进入蓝色单元格时获得 -1 奖励。网格上的所有其他步骤返回零奖励。上图右侧标记了两个预设路径:一条到达蓝色单元格,另一条停在红色单元格;路径的交点有助于最大化两种方法之间的值差异。
然后我们可以使用上一节中的方程来评估环境。我们不对回报或估计进行折扣,并将 α 设置为一个小值 1e-3。当值增量的绝对和低于 1e-3 的阈值时,我们认为值已收敛。
评估结果如下:
图 2 TD(0) 和常数-α MC 评估结果。来源:作者绘制的图
上述图像中,两种算法在估计值的方式上的不同变得非常明显。MC 方法忠实于路径的回报,因此每条路径上的值直接表示其结束状态。然而,TD 方法提供了更好的预测,特别是在蓝色路径上——在交点之前的蓝色路径上的值也表示到达红色单元格的可能性。
以这个最小的案例为基础,我们准备转向一个更复杂的示例,尝试找出两种方法之间的性能差异。
随机游走任务
随机游走任务是 Sutton 等人提出的一个简单的马尔可夫奖励过程,用于 TD 和 MC 预测目的[2],如下图所示。在此任务中,代理从中心节点 C 开始。代理在每个节点上以相等的概率向右或向左迈一步。链条的两端有两个终止状态。进入左端的奖励为 0,进入右端的奖励为+1。在终止之前的所有步骤生成的奖励为 0。
图 3 随机游走。来源:作者提供的图
我们可以使用以下代码来创建随机游走环境:
=====Test: checking environment setup=====
Links: None ← Node A → Node B
Reward: 0 ← Node A → 0
Links: Node A ← Node B → Node C
Reward: 0 ← Node B → 0
Links: Node B ← Node C → Node D
Reward: 0 ← Node C → 0
Links: Node C ← Node D → Node E
Reward: 0 ← Node D → 0
Links: Node D ← Node E → None
Reward: 0 ← Node E → 1
在随机策略下,环境中每个节点的真实值为[1/6, 2/6, 3/6, 4/6, 5/6]。该值通过使用贝尔曼方程的策略评估计算得出:
我们的任务是找出两个算法估计的值与真实值的接近程度;我们可以任意假设算法产生的值函数离真实值函数更近,通过平均均方根误差(RMS)来衡量,表示性能更好。
TD(0)和常数-a MC 在随机游走中的表现
算法
环境准备好后,我们可以开始在随机游走环境中运行这两种方法,并比较它们的表现。首先,让我们看一下这两个算法:
来源:latex中由作者编写的算法
来源:latex中由作者编写的算法
如前所述,MC 方法应该等到回合结束后才能更新从轨迹尾部得到的值,而 TD 方法则是逐步更新值。这种差异带来了初始化状态值函数时的一个技巧:在 MC 中,状态值函数不包括终止状态,而在 TD(0)中,该函数应包括终止状态,并且值为 0,因为 TD(0)方法总是提前一步看未来的状态,直到回合结束。
实现
在此实现中的α参数选择参考了书中[2]提出的参数;MC 方法的参数为[0.01, 0.02, 0.03, 0.04],而 TD 方法的参数为[0.05, 0.10, 0.15]。我曾经疑惑为何作者没有在两个算法中选择相同的参数集,直到我用 TD 参数运行 MD 方法:TD 参数对 MC 方法来说太高,因此不能展现 MC 的最佳性能。因此,我们将坚持书中的参数设置。现在,让我们运行这两个算法,找出它们在随机游走设置下的表现。
结果
图 4 算法比较结果。来源:作者提供的图
100 次比较后的结果如上图所示。TD 方法通常比 MC 方法提供更好的值估计,且α = 0.05 的 TD 方法可以非常接近真实值。图表还显示,MC 方法的方差比 TD 方法更高,因为兰花线的波动大于钢蓝线。
值得注意的是,对于这两种算法,当α值(相对)较高时,RMS 损失首先下降然后再上升。这种现象是由于值初始化和α值的共同作用。我们初始化了一个相对较高的 0.5,超过了节点 A 和 B 的真实值。由于随机策略使得有 50% 的机会选择“错误”步骤,从而使智能体远离正确的终端状态,因此更高的α值也会强调错误步骤,使结果偏离真实值。
现在让我们尝试将初始值降低到 0.1,并再次进行比较,看看问题是否得到缓解:
图 5 初始值为 0.1 的算法比较结果。来源:作者绘制的图
较低的初始值显然有助于缓解问题;没有明显的“下降然后上升”现象。然而,较低的初始值的副作用是学习效率较低,因为 RMS 损失在 150 轮后从未低于 0.05。因此,初始值、参数和算法性能之间存在权衡。
批量训练
在这篇文章中,我想提到的最后一点是对两种算法的批量训练比较。
考虑到我们面临以下情况:我们只在随机游走任务上积累了有限数量的经验,或者由于时间和计算限制,我们只能运行一定数量的轮次。批量更新 [2] 的想法是通过充分利用现有轨迹来应对这种情况。
批量训练的想法是反复更新一批轨迹上的值,直到值收敛到一个答案。只有在所有批次经验完全处理后,值才会被更新。让我们在随机游走环境中对这两种算法实施批量训练,看看 TD 方法是否仍优于 MC 方法。
结果
图 6 批量训练结果。来源:作者绘制的图
批量训练结果显示,TD 方法在有限经验下仍优于 MC 方法,两种算法的性能差距十分明显。
结论
在这篇文章中,我们讨论了常数-α MC 方法和 TD(0) 方法之间的区别,并比较了它们在随机游走任务中的表现。TD 方法在本文所有测试中都优于 MC 方法,因此将 TD 作为强化学习任务的方法是一个更可取的选择。然而,这并不意味着 TD 总是优于 MC,因为后者有一个最明显的优势:无偏差。如果我们面对的是一个不能容忍偏差的任务,那么 MC 可能是更好的选择;否则,TD 更能处理一般情况。
参考文献
[1] Midjourney 服务条款: docs.midjourney.com/docs/terms-of-service
[2] Sutton, Richard S., 和 Andrew G. Barto. 强化学习:导论。麻省理工学院出版社,2018。
本文的 GitHub 仓库:链接。
使用 BigQuery 和 Looker Studio 进行队列分析的完整指南
逐步解密队列分析
·发布于 Towards Data Science ·阅读时间 5 分钟·2023 年 3 月 9 日
–
图片来源:Hunter Harritt 于 Unsplash
介绍
让我们承认,队列分析乍看起来可能令人望而却步。但它是一个强大的工具,可以提供有价值的洞察,有时甚至是可视化数据的唯一正确方法。掌握它们将使你在数据分析的旅程中占据明显优势。
但首先,我们所说的队列分析是什么意思?
队列分析是一种研究和比较不同人群随时间变化的方法。
这些群体通过一个共同的特征来定义,例如他们加入服务的日期或首次购买的日期。
队列分析经常用于分析客户终止与产品或服务关系的速率,这一概念通常被称为“流失”。对于基于订阅的企业来说,流失率代表在给定时间内取消订阅的客户百分比。
流失是一个重要的业务指标,可能对收入和增长产生重大影响。虽然高流失率可能是客户不满意的迹象,但低流失率则相反,可能是客户忠诚度和满意度的证明。
现在,让我们通过对一个希望分析其客户在 2023 年行为的基于订阅的应用程序进行流失分析,来展示队列分析的强大功能。
第一步——了解您的数据集
在这个示例中,我们将使用存储在 BigQuery 中的 subscriptions
表。它包含我们产品上的订阅列表,包括注册日期,最重要的是,关于其状态的信息,活跃 或 取消。下面是表的样子:
查询结果(作者提供的图片)
现在你可能想按月查看流失演变。你可以使用以下查询,计算每月流失的客户数,并将其除以相同期间的总客户数:
查询结果(作者提供的图片)
查询结果绘制图(作者提供的图片)
好消息,流失率在这一年中有所下降。但这是否反映了实际情况?我担心它并没有。用这种方式查看流失率只能代表部分情况。这就是为什么需要引入 cohort。
第 2 步 — 数据转换
记住,cohorts 是由共同特征定义的组,在这种情况下,是它们的注册日期。所以我们将其拆分为不同的 cohort;1 月份注册的用户,2 月份注册的用户,依此类推。对于每个 cohort,我们希望知道有多少客户注册,以及在每个时间段内有多少人取消。换句话说,就是在一个月、两个月等之后有多少人取消。
为此,让我们使用以下查询:
查询结果,其中 signup_date = 2023 年 1 月(作者提供的图片)
这个查询将返回总计 78 行;1 月份 12 行,2 月份 11 行,3 月份 10 行,依此类推。以下是帮助你更好理解结果的视觉提示:
查询结果的示意图(作者提供的图片)
现在让我们拆解查询结果中的每一个字段:
-
signup_date
:客户注册的日期。 -
cancellation_date
:客户取消的日期。 -
cohort_month
:signup_date
和cancellation_date
之间的月份差。 -
max_subscriptions
:该月注册的客户总数。 -
sum_cancellations
:每月取消订阅的客户数。 -
r_sum_cancellations
:随时间推移取消订阅的成员的累计总和。我们将在构建可视化时用到这个字段。
例如,看一下第 5 行,我们看到,在 67 个 1 月份注册的客户中,有 2 个在 5 月取消了订阅,即在加入服务后四个月,共有 10 个客户在 1 月到 5 月期间取消订阅。
第 3 步 — 在 Looker Studio 中整合所有内容
现在我们的数据集准备好了,让我们在 Looker Studio 中使用它来可视化 cohorts。
首先,创建一个新的计算字段,名为 churn_rate
,使用以下公式:
SUM(r_sum_cancellations)/MAX(max_subscriptions)
然后,创建一个新的 Pivot Table 图表,按照以下标准:
-
行维度:
signup_date
-
列维度:
cohort_month
-
指标:
churn_rate
以百分比表示 -
排序行 #1:
signup_date
升序 -
排序列 #1:
cohort_month
升序
为了为仪表板添加更多背景信息,我们将把一个包含总订阅数的表格添加到 cohort 图表的左侧。为此,创建一个新的 表格 图表,满足以下条件:
-
维度:
signup_date
-
指标:
max_subscriptions
使用 最大值 聚合 -
排序:
signup_date
升序
添加一点格式设置,就完成了!
Medium — Cohort Analysis Looker Studio(作者提供的图片)
通过这种方式查看流失率,我们可以迅速得出关于用户参与度的结论。例如,2023 年 4 月的 cohort 表现优于所有其他 cohort。换句话说,流失率最低的组表明在 4 月加入的客户对产品更有承诺和参与感。通过分析这个 cohort 成功的原因,我们可以利用这些见解来提高未来的客户留存率和忠诚度。
结论
Cohort 分析对任何愿意监控客户行为和流失的订阅型业务至关重要。它提供了宝贵的见解,用于制定明智的营销和留存策略,从而带来更高的收入和客户满意度。按照本文中的步骤,你已准备好实施 cohort 分析并开始获得其好处。分析愉快!
资源
[1] Google Sheets,medium_cohorts_dataset_public (2023),Damien Azzopardi
[2] Looker Studio,Medium — Cohort Analysis Looker Studio (2023),Damien Azzopardi
你喜欢这篇文章吗?立即成为会员,发现关于任何话题的故事、思考和专业知识。
medium.com](https://medium.com/@damien.azzopardi/membership?source=post_page-----1cd18c0edd79--------------------------------)
数据驱动的客户获取完整指南
·
关注 发表在 数据科学前沿 ·6 分钟阅读·2023 年 1 月 18 日
–
在过去的十年中,我有幸与超过 100 位企业家合作。不论他们的地理位置、产品、财务状况或行业经验如何,他们都有一个共同点:客户获取让他们寝食难安。为了推动客户获取,公司不懈地努力建立其营销引擎。出色的营销带来流量,提高转化率,并降低成本。
作者提供的图片
优化顾客获取的一种方法是通过精准营销,公司只针对目标顾客进行投资。传统上,这些努力主要依赖于行业和营销经验。然而,形成既有行业知识又有营销经验的团队是具有挑战性的。正如你所想象的那样,行业专家专注于他们的市场和产品,通常并不是营销专家。另一方面,偶尔理解特定市场的营销人才既稀缺又昂贵。对于定义新产品类别的初创公司来说,情况更加困难。
这就是数据科学家帮助营销的地方。公司可以通过定期发起实验、实时监控表现,并根据市场反馈快速迭代,从而获得对其行业独特的营销经验。此外,数据科学比人工努力更好地处理高维度的营销数据,并提供更丰富的见解来支持商业决策。在本文中,我将讨论经过验证的低成本数据分析方法,这些方法能有效改善营销决策,并逐步介绍如何应用它们。
选择目标顾客
正如古话所说,做出选择比花费精力更具影响力。当公司资源有限时,这总是情况,过于分散的努力会导致在激烈的市场竞争中失去优势。投资于正确的顾客提供了更多成功的可能性。
如在重点关注最有价值的顾客中讨论的那样,顾客价值可以通过以下方式计算:
顾客的长期价值 = 顾客重复购买的收入 — 获取成本
例如,一家奢侈珠宝品牌的顾客不会频繁购买。在这种情况下,可以将顾客价值计算的时间框架设置为一年。基于其销售和营销归因系统,该品牌可以计算每位顾客(或未转化的访客)的年度收入和获取成本。通过这些数据,品牌可以迅速得出每位顾客的价值,并决定谁值得投入营销预算。
在大多数公司中,顾客价值分布图如下所示。大多数顾客对公司带来的价值较低或为负,因此应予以忽视或劝阻。下图中的左右分界通常遵循 80/20 法则。
作者提供的图片
确定对目标顾客有效的营销活动
商业的本质是一种实验,这意味着大多数商业活动注定不会产生积极的结果。在初创公司中,多达 95%的工作是无效的。公司必须迅速在噪声中找出有效的部分才能成功。通过实时监控市场营销表现,公司有最佳的机会立即区分出好的信号与坏的信号,并采取行动。
图片由作者提供
根据客户价值分析,该珠宝品牌决定针对高价值群体推出营销活动。这些活动在 Google、Facebook、TikTok 等广告平台上进行。品牌根据假设实施所有策略——它认为客户喜欢某些东西,但不确定。只有当品牌收集并评估活动表现数据后,才能确定哪些活动值得投资,哪些不值得。
尽管上述图表的含义似乎很明显,但大多数公司却忽略了这些信号。因此,当公司开始关注时,通过简单地削减那些无效的市场营销举措的预算,它们将获得巨大的增长机会。
揭示市场营销举措为何有效与否
公司通过加倍投入那些有效的市场营销举措,在短期内获得超额回报。通过在新的举措中复制这些成功的经验,公司在竞争中拥有优势。
然而,当外部环境发生变化时,复制和粘贴以前的经验可能不会产生预期的回报。因此,公司需要揭示为什么以及为什么某项举措有效。这样,当市场和时间发生变化时,公司可以更好地确定哪些旧方法仍然适用,哪些不适用。
手动估算市场营销举措背后的原因可能很具挑战性。有太多维度需要分析:客户的 demographic 信息、接触点互动、访问行为、购买行为等等。
客户细分是一种有价值的技术,可以简化上述分析。通过客户细分提供的详细信息,公司可以识别出对每个客户群体最有吸引力的活动、购物体验和产品,并回顾它们为何具有吸引力。
图片由作者提供
这个珠宝品牌在情人节期间测试其活动策略,取得了初步成功。当下一个重要节日母亲节临近时,品牌希望了解情人节的经验是否适用。因此,它进行客户细分分析,以了解哪些因素促成了情人节的成功。从分析中,品牌发现情人节的目标客户只有一部分与母亲节的目标客户重叠。它可能会在母亲节促销中部署针对这部分客户的有效活动策略。
测试和学习
通过实验发现有效的方法后,企业可以在新客户获取机会出现时,应用成功的方案。来自客户细分的丰富信息帮助公司在业务迭代中领先一步。
在大规模实施之前,公司必须通过对样本进行测试和学习,验证经验是否适用于新的机会。常见的测试和学习方法包括 A/B 测试和可视化。
图片由作者提供
在母亲节的大促销之前,珠宝品牌基于情人节的所有经验启动了一次小规模的活动。大多数经验仍然有效,但创意和信息传达可以做一些调整。品牌修改了其活动并在更大范围内进行测试。它在每天的几个周期内重复这个过程,直到获得满意的结果并全面推广。
个性化
与常识相反,对于大多数企业来说,个性化是一种一对多的营销机制。一旦公司找出如何通过营销渠道、活动、创意、信息传达等吸引每个客户细分,他们就准备在客户获取计划中推广个性化。例如,公司可以为每个客户细分预定义其网站、浏览体验和产品推荐。当一个符合特定细分的访问者进入网站时,公司可以自动为他们提供合适的购物体验。
图片由作者提供
在进行了一年的不同促销活动后,这个珠宝品牌收集了足够的客户数据。品牌了解每个客户群体的购物偏好。因此,品牌设计了五种不同的客户体验,以适应最多的目标客户。提供了理想的购物体验后,目标客户转化更快,购买量比之前增加。
背后的数据科学
两组数据科学技术对于实现上述分析至关重要。第一组包括能够连接点滴的数据工程技术。常听说数据管道基础设施是数据科学项目最大的障碍。得益于数据行业的发展,越来越多的连接工具简化了从多个来源获取数据的过程。
第二个关键因素是身份技术。由于 iOS 隐私政策的变化,使用唯一用户标识符来关联用户旅程中的不同接触点变得越来越具有挑战性。幸运的是,独立于个人标识符的营销技术,如营销混合建模,提供了另一种选择。
我在文章中讨论了如何利用数据科学提升业务和优化营销。如果你想讨论客户获取或其他数据科学主题,请在LinkedIn关注我或通过 newsletter@ivyliu.io 联系我。下次见。
数据分析家庭实验室启动完整指南
现在是启动你自己的数据科学家庭实验室的最佳时机,用于分析对你有用的数据、存储重要信息或开发自己的技术技能。
·发表于 Towards Data Science ·阅读时间 13 分钟·2023 年 6 月 10 日
–
我在 Reddit 上的几个技术相关子论坛中看到过一句话,大意是“支付云服务费用就像是在租用别人的计算机。”虽然我认为云计算和存储非常有用,但这篇文章将重点讲述我为什么将我的分析、数据存储和工具从在线服务提供商那里转移到我的家庭办公室。我使用的工具和硬件的链接也可以查看。
介绍
解释我这疯狂方法的最佳方式是分享一个我遇到的商业问题。虽然我是一个风险承受能力较低的传统投资者,但我心中有一个小小的希望,也许,只有也许,我能成为那不到 1%击败标普 500 的人。请注意,我使用了“希望”这个词,因此,也不要在这种希望上投入太多。每年我会给我的 Robinhood 账户 100 美元,并像对待彩票一样对待它——希望能一夜暴富。不过,我要向大家保证,这个账户与我的其他主要账户是分开的,后者主要投资于指数基金,获得稳定的回报,并且我会在这些基金上进行定期的卖出看涨期权。我的 Robinhood 账户则有些类似于赌博,什么都可能发生。不过,我给自己设定了几个规则:
-
我从不使用任何保证金。
-
我从不卖出裸仓,只进行买入开仓操作。
-
我不会将钱投入到追逐亏损交易上。
你可能会想知道我接下来要说什么,我会从我的岔题中回到正题,分享我的“彩票”虽然尚未为我赢得一个 Jeff-Bezos 水平的游艇,但确实教会了我不少关于风险和损失的知识。这些教训也激发了我内心的数据爱好者,尝试改进我量化风险和预测市场趋势及事件的方式。即使在短期内方向性正确的模型也能为投资者提供巨大的价值——无论是散户还是对冲基金。
我看到改善决策的第一步是需要有数据来做数据驱动的决策。剔除投资中的情感是一个著名的成功秘诀。虽然历史数据在股票和 ETF 中广泛可用,并通过诸如 yfinance(我下面的一个例子)等资源开放源代码,但衍生的历史数据集则要昂贵得多,获取也更困难。一些初步了解的 API 提示,常规的数据访问以回测我的投资组合策略可能会花费我数百美元每年,甚至根据我所寻求的粒度可能每月都要付费。
[## 使用 Python 和 Plotly 绘制金融数据及多个叠加趋势
Plotly 为 Python 开发者提供了在使用蜡烛图和其他各种绘图工具建模时的灵活性……
wire.insiderfinance.io](https://wire.insiderfinance.io/graphing-financial-data-and-multiple-overlaid-trends-using-python-and-plotly-f9d948934ecb?source=post_page-----552c9f532ff0--------------------------------)
我决定在这个过程中投资于自己,而不是按我的条件花费数百美元。观众发出呻吟
构建在云端
我对数据抓取和仓储的初步思考使我回到了我在日常工作中使用的相同工具。我创建了一个个人 AWS 账户,并编写了 Python 脚本来部署在 Lambda 上,以在预定的时间间隔抓取免费的实时期权数据集,并代表我写入数据。这是一个完全自动化的系统,并且几乎可以无限扩展,因为会为我的投资组合中的每个股票动态启动不同的抓取器。写入数据更具挑战性,我夹在两条路之间。我可以选择将数据写入 S3,通过 Glue 爬取数据,然后用 Athena 进行无服务器查询,或者使用关系数据库服务,将数据直接从 Lambda 写入 RDS。
快速总结提到的 AWS 工具:
Lambda 是一种无服务器计算,允许用户执行脚本而不需要太多的开销,并且提供非常慷慨的免费层。
S3,也称为简单存储服务,是一个具有相当大免费额度的对象存储系统,每 GB 每月费用为 0.02 美元。
Glue 是一个 AWS 的数据准备、集成和 ETL 工具,具有可用于读取和解释表格数据的网页爬虫。
Athena 是一种无服务器查询架构。
我最终倾向于使用 RDS,仅仅是为了让数据可以轻松查询和监控,如果没有其他原因的话。他们还提供了 750 小时的免费额度和 20GB 的存储,这为我提供了一个很好的沙盒环境,让我可以动手操作。
然而,我没意识到股票期权数据有多庞大。我开始每 15 分钟写入大约 100 MB 的数据,每个股票代码每月都这样,这可能听起来不多,但考虑到我有一个包含 20 个股票代码的投资组合,在年底之前我就会用完所有免费额度。除此之外,免费层中的小计算能力很快就被消耗殆尽,我的服务器在不知不觉中消耗了所有 750 小时(考虑到我想跟踪期权交易,大约每天 8 小时,每周 5 天)。我还经常在白天工作后阅读和分析数据,这也导致了更高的使用量。大约两个月后,我用完了免费额度,收到了第一张 AWS 账单:每月约 60 美元。请记住,一旦免费额度结束,你将为每个服务器小时的处理、从 AWS 生态系统到本地开发机器的每 GB 数据量以及存储费用按 GB/月付费。我预计在一两个月内,我的拥有成本可能增加至少 50%甚至更多,并将继续增加。
哎呀。
离开云计算
到了这个时候,我意识到我宁愿把每月花在租用 Amazon 设备上的 60 美元花在电费上,把剩下的钱投入到我的 Robinhood 账户中,回到我们开始的地方。尽管我很喜欢使用 AWS 工具,但当我的雇主不支付账单时(对我的同事们,我保证我在工作中也是很节俭的),我真的对投资它们不太感兴趣。AWS 的定价对于爱好者来说并不合适。他们提供了很多很棒的免费资源来帮助新手学习,也为专业人士提供了极高的性价比,但对于现在这个中间层级却不适合。
我有一台旧的联想 Y50–70 笔记本电脑,屏幕坏了,我打算将其改装为家庭网页抓取机器人和 SQL 服务器。尽管它们作为新机或认证翻新的价格仍然相当可观(可能由于 i7 处理器和独立显卡),但我坏掉的屏幕几乎完全抵消了电脑的价值,因此将其作为服务器重新启用,使其焕发了新生,也让它积攒了约三年的灰尘。我把它放在客厅角落的一个音响上(旁边有一个侏儒),与 PlayStation 相对,并将其设置为“常开”以完成其新任务。我的女朋友甚至说,电脑键盘刺眼的红色背光“让房间看起来更整洁”,这也算是一种赞美。
画面中是一个侏儒,但拍摄时,服务器尚未配置。
幸运的是,我的 65 英寸《使命召唤》认证电视距离笔记本电脑的 HDMI 电缆足够近,也能看到我写的代码。
我将服务器从云端迁移到我的破旧笔记本电脑,开启了新的征程!现在我可以以仅仅电费为代价进行所有分析,约为 $0.14/kWh,或大约 $0.20–0.30 一天。接下来的一个月或两个月里,我在本地进行了一些实验和调整。通常,这包括每周工作后花几小时打开我的 MacBook,玩弄来自侏儒音响服务器的数据上的 ML 模型,利用本地Plotly 仪表板可视化数据,然后指导我的 Robinhood 投资。
我取得了一些有限的成功。详细情况我会留到另一篇 Medium 文章中分享,一旦有更多的数据和性能指标。不过,我决定从破旧笔记本电脑扩展到自己的微型云。这次,不是租用,而是拥有。
构建家庭实验室
“家庭实验室”这个名字听起来很复杂和酷炫 推了推眼镜,但实际上在拆解后相对简单。基本上,我在使用破旧笔记本电脑时遇到了一些挑战,这些挑战提供了动力,同时也有一些新目标和理想需求给予了灵感。
损坏的笔记本电脑问题:
硬盘很旧,至少有 5 或 6 年了,这给未来数据丢失带来了风险。在承受较大查询压力时,它的速度也显著下降,这是该型号的一个已知问题。
使用我的 TV 和蓝牙键盘来操作安装了 Windows 10 Home 的笔记本电脑非常不便,且不符合人体工程学。
笔记本电脑无法升级,如果我想添加更多的 RAM 超过已安装的容量。
技术在任务并行化方面有限。
单靠笔记本电脑不足以托管我的 SQL 服务器,以及为我的 ML 模型处理仪表板和数据。也不希望在同一台计算机上共享资源,以免影响其他服务。
我会实施的系统必须解决这些问题,但我也希望实现一些新功能。
计划的新功能:
一个新的家庭办公室设置,使在家工作时更加舒适。
整个公寓的以太网布线(如果我支付整个千兆网,我就要使用整个千兆网 AT&T)。
在适当的情况下使用微服务器进行分布式计算。
服务器可以升级和更换。
各种程序和软件可以独立部署,以实现不同的子目标,而不会妨碍当前或并行程序。
我选择的计算机的分布式计算是一个有争议的话题,稍后将在文章中解释。
我花了很多时间进行适当的硬件配置研究。我读过的一个最喜欢的资源是《TinyMiniMicro》,它比较了 Lenovo ThinkCentre Tiny 平台、HP ProDesk/EliteDesk Mini 平台和 Dell OptiPlex Micro 平台。我也曾使用过单板计算机,就像 Project TMM 的作者一样,我有两个 Raspberry Pis 和一个 Odroid XU4。
我喜欢我的 Pis 的地方:
它们体积小,功耗低,新型号有 8GB 的 RAM。
我喜欢我的 Odroid XU4 的地方:
它小巧,拥有 8 个核心,是一个很好的模拟平台。
虽然我相信我的 SBC 仍会在我的家庭实验室中找到用武之地,但请记住,我需要处理我想要托管的服务的设备。我最终还购买了可能是我一生中最贵的 Amazon 订单,并彻底重新装修了我的整个办公室。我的购物车包括:
-
多条 Cat6 以太网电缆
-
RJ45 压接工具
-
绑扎带
-
2 台 EliteDesk 800 G1 i5 Minis(但发了一台 G2 #Win)
-
1 台 EliteDesk 800 G4 i7 Mini(还发了一款更好的 i7 处理器 #Win)
-
2 台 ProDesk 600 G3 i5 Minis(并发了一台稍差的 i5 #Karma)
-
额外的 RAM
-
多个 SSD
-
替换我的书架/桌子的一个新办公室桌
-
新的办公室照明
-
硬盘克隆设备
-
两个 8 端口网络交换机
-
不间断电源
-
一个打印机
-
一个机械键盘(相关的,我还有五个键盘和鼠标组合,如果有人需要的话)
-
两个新显示器
如果你想查看我完整的零件列表,包括每个项目的链接以供检查或购买,请随时 前往我的网站查看完整列表。
一旦我的“夏季圣诞礼物”到达,门口堆满了许多箱子,真正的乐趣就可以开始了。第一步是完成全屋以太网布线。安装人员默认没有将任何以太网电缆连接到有线电视盒上,所以我不得不剪掉电缆末端并自己安装插座。幸运的是,我购买的棒极了的工具包(链接在我的 网站)中包括了压接工具、RJ45 插头和测试设备,以确保我正确布线并确定我公寓中的哪个端口与哪个电缆对应。当然,按我的运气,最后一根电缆正好是我办公室需要的,但我想未来的租户会从我今天的好 deed 中受益。整个过程花了大约 2-3 小时布线千兆连接,幸运的是,我的女朋友很喜欢帮忙,一杯酒让过程变得更快。
在有线网络设置之后,我开始通过组装家具、安装照明和拆卸硬件来布置我的办公室。我的桌面设置非常整洁,我对现在的办公室效果很满意。
前后对比
关于我的硬件设置,我购买的每台计算机都配备了 16GB 的内存,我将其升级到 32GB,同时还有固态硬盘(其中一些我也进行了升级)。由于每台设备都运行 Windows 10 Pro,我能够在我的网络中进行远程登录,并且我已经设置了一些服务。联网这些设备也很有趣,尽管我觉得我的电缆管理还有改进的空间。
家庭实验室节点前面
家庭实验室节点后面
现在,根据我一开始提到的星号,为什么我花费了相当于一年的 AWS 成本来购买五台总共大约 22 核心的计算机,而不是直接购买/构建一台高级现代 PC 呢?原因有几个,我相信这可能会在某些技术爱好者中引发争议。
-
扩展性 — 我可以轻松地向我的集群中添加另一个节点,或移除一个进行维护/升级。
-
成本 — 升级和维护非常简单且便宜。此外,对于大多数单元,功耗约为 35W,运行我的服务器的成本非常实惠。
-
冗余 — 如果一个节点出现故障(例如,CPU 故障),我有纠正脚本来平衡我的分布式工作负载。
-
教育 — 我正在学习大量内容,这些内容提升了我的专业技能和经验,教育是✨宝贵的✨。
-
看起来很酷。这里的第 5 点足以作为理由。
说到教育,这里是我在集群中学到并实施的一些东西:
-
在将驱动器从小容量克隆到大容量时,你需要扩展新驱动器的卷,这通常需要第三方软件来轻松完成(如 Paragon)。
-
你需要手动分配静态 IP 才能在桌面之间远程访问时获得可靠的结果。
-
迁移 SQL 服务器时,从备份恢复比在两个不同服务器之间查询要容易。
我相信在这个过程中我还会学到很多东西……
以下是我现在家庭网络的一个大致示意图。图中没有展示我的 wifi 设备,比如我的 MacBook 和手机,它们会在两个路由器之间跳跃。最终,我还会将我的单板计算机和可能的另一台 PC 加入到集群中。哦,对了,我那台破屏的旧笔记本电脑?没有人愿意在 Facebook Marketplace 上以 $50 的价格购买它,所以我在上面安装了 Windows 10 Pro 以便远程访问,并且也将它添加到集群中,这实际上可能是个好事,因为我可以利用它的 GPU 来辅助构建 Tensorflow 模型(也可以玩一些回合制游戏)。
家庭实验室网络图
说到 Tensorflow,这里是我将在新家庭实验室中实现的一些服务和功能:
-
SQL 服务器(目前托管我的财务数据集以及我正在网络抓取的新数据集,后续将撰写关于我母校的财务状况和我居住城市的公共安全数据集)
-
Docker(用于托管我将要构建的应用程序/容器以及 Minecraft 服务器,因为,为什么不呢)
-
Jenkins CI/CD 系统,用于在我的数据集上构建、训练和部署机器学习模型
-
个人代码库的 Git 仓库
-
网络附加存储,支持我摄影爱好中的大量照片、文档以及其他数据收集活动
-
以及其他待定的项目/服务
结束语:
值得吗?嗯,确实有“只有时间才能证明”的因素。一旦我的信用卡从亚马逊的采购中恢复过来,我相信它也会享受 AWS 定价的缓解。我也期待能够构建和部署更多的兴趣爱好,并收集更多数据来撰写更多的 Medium 文章。我计划的下一些文章包括分析西弗吉尼亚大学目前面临的财政债务问题,以及对纳什维尔公共安全报告的探索性数据分析(可能还会有一个预测紧急事件和分配资源需求的机器学习模型)。这些数据科学项目规模足够大,如果没有某种存储和查询大量相关数据的架构,将无法实现。
你怎么看?离开云服务,建立一个家庭实验室的项目听起来是否是你想做的?你的硬件选择会是什么?
如果你对我使用的硬件感兴趣,可以查看我在 www.willkeefe.com 上的评论。
我已经发布了这篇文章的续集,扩展了使用案例!在 Better Programming 上查看!
我最近在 Medium 上的相关内容:
高效的供应链、生产计划和资源分配管理比以往任何时候都更重要。Python…
towardsdatascience.com ## 使用 Python 和机器学习进行犯罪地点分析与预测
利用 Python、Folium 和 ScyPy,可以建立模型来展示犯罪事件,计算最佳位置…
towardsdatascience.com
在 LinkedIn 上也可以与我联系!
www.linkedin.com/in/will-keefe-476016127/
推荐系统离线评估的完整教程
如何缩小离线与在线评估之间的差距
·发表于 Towards Data Science ·18 分钟阅读·2023 年 3 月 11 日
–
推荐系统跨越离线与在线评估差距(AI 生成的图像)
介绍
在本教程中,我将解释为什么应该关注离线评估。接着我会介绍适量的理论。我不会深入探讨最新的方法,而是停留在经验上效果良好的方法。这对于接下来的实际实施部分将足够。
评估推荐系统
假设你有一个提高推荐系统性能的想法。假设你获得了关于项目的新元数据,例如项目的主要主题,这应该有助于更准确地预测用户在平台上的参与度。那么你如何利用这个新特性呢?在对新数据进行全面探索后,你需要对数据管道进行必要的修改,以转换特性并将其与其他特性一起输入模型。现在你可以启动学习阶段以生成新版本的模型。
太好了!那么,你如何评估新模型的表现?你如何确定新特性是否有助于推荐,并能驱动平台上的更多参与?
好的,你可以直接将新版本与旧版本一起投入生产,将一部分流量重定向到新模型,并使用你为业务定义的最重要的指标(点击率、观看时间、深入时间、订阅等)比较两者的表现。这确实被称为 AB 测试。
作者提供的图像
但如果新版本糟糕,导致收入大幅下降或严重恶化服务质量,那可能会非常糟糕!
通常,作为机器学习从业者,你首先需要验证新版本是否比旧版本更好,采用离线方式进行,即无需向真实用户展示任何内容(我感觉对你们中的大多数人来说这很简单——但请耐心,我马上就会讲到)。
避免收入下降非常重要,但这并不是唯一的关注点。进行在线 AB 测试需要时间,尤其是在流量不大的情况下。在这种情况下,可能需要几周才能得出具有足够统计信心的结论。此外,在这种情况下,你可能需要将模型重写成不同的堆栈,以便它可以扩展并满足延迟要求。这可能需要额外的几周(甚至几个月)的工作。因此,拥有一个强大的离线评估策略可以更快地迭代不同的想法或超参数进行调整。可以在离线评估中评估数千个想法,并仅选择最有前景的候选者进行在线 AB 测试。
使用日志数据 D_0 离线构建多个候选策略
但是在离线环境中,我们无法直接测量点击率或观看时间,因为我们事先不知道未来的用户是否会点击或他们将花多长时间消费推荐的项目。我们在操作一个反事实场景。也就是说,我们无法观察到我们没有采取的行动的奖励,只能看到已采取行动的奖励。
在在线环境中,这一主要评估缺陷不再是问题。我们根据用户在平台上的实际行为收集反馈。相反,离线评估始终会严重偏向于测量过去的行为,并且在评估实际会发生什么方面有限。
那么我们是否要接受这一事实而不加以改变,还是可以对此做些什么呢?
什么是离线策略评估,为什么你应该关心?
让我们首先介绍一些在阅读关于离线策略评估时会遇到的重要词汇。当用户进入你的平台时,会发生以下情况:
图片由作者提供
离线策略评估是指使用从不同策略收集的数据来评估新策略。我们希望提出一个估计器V_hat,该估计器将基于日志数据D_0估计新推荐器π_e的性能,而这些日志数据D_0是用于训练旧策略π_0的:
直接方法
正如我之前所说,在评估我们的推荐系统时,我们在一个反事实环境中操作。我们不知道我们没有采取的行动会产生什么结果。因此,基本上我们有一个缺失标签的问题。
作者提供的图像 — 新推荐项目的缺失标签问题
在上图中,对于第一次推荐,我们成功推荐了记录数据中看到的点击项,因此我们可以说我们有一个积极的预测,而其他项是负面的。但对于其余的评估数据集,我们推荐了完全不同的项目,因此我们不知道结果会是什么。
鉴于我们已经记录了交互数据D_0, 一个简单的想法是,许多机器学习从业者可能会想到,利用这些数据来生成一个机器学习模型,该模型将直接估计缺失的奖励(例如,用我们的最佳猜测替换上面的问号)。然后我们可以像往常一样进行评估。更正式地说,我们希望生成一个奖励模型r_hat,该模型将给出在给定上下文和特定行动时奖励的期望值:
许多机器学习模型可以用于这个任务。这虽然很好,但实际上效果并不理想!让我们来看看原因……
似乎记录的数据和我们想要预测的数据不来自相同的分布。存在较大的协变量偏移。我们记录了某些特定行动的数据,而尝试预测其他(可能完全不同)行动的奖励。假设我们利用了 2 个特征来尽量减少奖励模型的遗憾。我们可以如下绘制奖励空间:
作者提供的图像 — 奖励空间的可视化
绿色点是正观察(用户感兴趣的观察),红色点是负观察。发生的情况是,奖励空间大部分是空的。存在广阔的区域我们没有任何观察数据。但我们的新政策可能需要在这些未知空间中做出决策。这意味着奖励模型如何外推非常重要。决策边界在上述图中的位置也非常重要。而这不会在奖励模型尝试最小化的遗憾函数中反映出来。因此,外推出现错误的可能性非常高。最终,这种方法表现出低方差但可能非常偏倚。
因此,使用模型来预测奖励似乎不是一个有效的方法。我们还能做什么?这时模型无关的方法就派上用场了。
逆倾向评分(IPS)
这个估计器的目标是重新加权奖励,以便根据旧政策和新政策采取行动的倾向来赋予行动更多或更少的重要性。 我们希望降低旧政策比新政策更多采取的行动的重要性(反之亦然)。
让我们可视化一下这个概念。下面是旧政策π_0在给定上下文的情况下采取行动的概率空间**:**
作者提供的图像
红色和绿色的点仍然是观察到的奖励。暗区是条件动作概率质量的集中区域。
现在,新策略π_e将在空间的不同部分采取行动,如下所示:
图片由作者提供
IPS 估计器的目标是通过应用以下公式来重新加权奖励:
两个动作概率之间的比率称为重要性权重。结果如下:
图片由作者提供
可以证明,这种方法是无偏的,意味着我们收集的数据越多,IPS 估计器将越趋近于在线奖励的真实值。
如果你还是很难理解这个概念,让我们进一步简化。假设我们只有 2 个推荐的项目。我们已经收集了这些项目的用户互动数据(如评估数据集中所见):
图片由作者提供
当然,如果你的新策略π_e总是预测项目 1,那么你的推荐系统的整体精度将高于一个总是预测项目 2 的策略。或者会这样吗?现在让我们将显示数据加入其中:
图片由作者提供
现在,从这些角度来看,你肯定能理解离线评估的附加价值。考虑到显示数据,我们看到旧策略π_0(生成了上述日志)高度偏爱项目 1。而这可能不是最佳推荐。偏爱项目 2 似乎是一个更好的选择,但为了实现这一点,我们需要在评估过程中考虑显示数据(例如,策略推荐项目的倾向)。
但这种方法可能会表现出很强的方差,因为某些奖励估计可能完全偏离。这是因为我们在计算两个动作概率的比率,而这些比率有时可能非常小。例如,如果给定观察的旧策略的动作概率非常小,则重要性权重可能变得很大,使得这个特定观察的权重过高。
裁剪反向倾向评分(CIPS)
这个估计器是经典 IPS 的一个变体,试图解决我们刚刚提到的挑战。它通过裁剪重要性权重来实现这一点,以使其不会超过最大值:
问题在于,这种修改破坏了 IPS 估计器的无偏性,但更重要的是,它引入了一个可能非常不实用的超参数。
自归一化反向倾向评分(SNIPS)
这一次,我们通过重要性权重的经验均值的倒数来重新加权普通的 IPS。这只是简单地调整了普通 IPS 的结果。正如我所说,IPS 的问题在于有时我们可能会因为一个微小的旧策略动作概率而获得巨大的重要性权重。SNIPS 估计器通过将这种巨大的重要性权重“取消”来解决这个问题,因为它也会包含在分母中。
最终,估计器在经验上表现非常好,并且没有超参数需要调整,这使得它对大多数机器学习从业者非常有吸引力。
如何实现重新加权的离线策略评估方法?
在研究相关文献时,我们可以看到,大多数机器学习研究者的努力都集中在寻找最佳方法,以获得一个无偏差且方差低的在线奖励离线策略估计器。但几乎没有人讨论实现这些策略的实际问题。更糟糕的是,大多数研究者使用模拟数据来展示他们方法的稳健性。这在理论上很棒,但在实际应用中,实施方法时会遇到困难。
我们已经看到,自我标准化逆倾向评分(SNIPS)估计器在经验上表现良好,没有需要调整的超参数,方差低且一致(尽管有偏)。
那么我们准备好实现这个估计器了吗?嗯,还没有完全准备好。
离线策略评估是否有效很大程度上取决于我们能多准确地计算动作概率π(a_i|x_i)。这实际上是最重要的部分!
为了做到这一点,我们首先要花时间正确地定义这些概率。让我们首先思考概率π在给定上下文x_i的情况下“选择”动作a_i的定义。
人们必须记住,我们的目标是重新加权奖励,以便在新策略π_e 很不可能采取这些动作时,减少对由旧日志策略π_0 收集的动作的重视(反之亦然)。
那么,什么是动作a_i?在这里,区分策略输出推荐项的概率和项被显示给用户的概率是很重要的。这些概率差异很大。确实,一个算法可以输出 1000 个项目,但由于 UI 限制(我们不能在移动设备上显示 1000 个项目),只有一小部分会显示给用户。正如我刚才所说,我们关注的是所采取的动作将最终出现在日志数据中的概率。因此,我们关心的是显示概率,而不是推荐系统的输出概率。这一点非常重要,因为它改变了如果一个人想要估计动作概率(例如,推断显示而不是输出)时需要考虑的数据源。
现在,x_i的背景是什么?实际上,它可以是任何东西。作为建模者,你负责定义它。从理论上讲,背景越相关和精确,也就是说,我们拥有的信息越相关,我们应该能够更准确地估计展示概率。但在实践中,这也使得任务更加困难。特征空间越大,你需要的数据就越多以产生稳健的估计。而拥有稳健的估计至关重要。如果你的展示概率完全错误,你将会给特定奖励过多或过少的重视,这完全违背了离线评估的目的。正如我将简要说明的那样,一个好的做法是简化背景,仅使用最重要的特征。
展示概率估计
首先,一个失败的方法
当我第一次接触离线评估时,我需要了解我的前任之一实施的方法。这是一种高级方法,其中展示概率由深度学习模型直接估计。澄清一下,我们在这里没有使用直接方法。模型没有用于直接估计未知的奖励。它用于估计旧政策和新政策的展示概率π(a|x)。凭借这些概率,我们可以计算重要性权重并应用如 IPS、CIPS 或 SNIPS 等估计器。
不深入细节,我们可以用一张图片来简单解释。这里做的是从一个从非常广角看起来像这样的模型:
作者提供的图像 — 深度推荐系统架构的广泛概述
变成这样:
作者提供的图像 — 修改后的架构以预测展示概率
理论上,这非常整洁,因为我们可以在给定非常精确的输入集合时获得概率。我们可以在非常细粒度的层面上估计展示概率。这是谷歌 YouTube 团队的这篇论文中找到的一个想法的实现。
但在实践中,它失败了,原因如下:
-
我们现在有了两个目标而不是一个(用户和展示作为推荐的序列的下一个视频)。这引入了额外的问题,这些问题没有得到妥善管理,比如:如果我们只有序列中的下一个视频但没有相关的展示(只有一个目标)怎么办?确实,在训练数据中,我们使用的是来自其他来源(外部)的序列视频,而不是我们没有展示任何推荐的平台。
-
拥有两个目标意味着有两个不同的损失函数。你如何将它们结合起来?如果其中一个损失在完全不同的值范围内(这就是发生的情况),那么在你将它们结合时,它可能会变得不重要(这会导致其中一个分支没有学习到任何东西)。
-
整体代码库变得复杂得多。
-
理论上,引入辅助任务对主要任务是有利的,但需要它们之间良好的对齐。在这种情况下,增加的复杂性使得新的显示概率任务使主要任务的性能下降。
-
输出的概率并不是实际的概率。实际上,模型要么过于自信,要么完全没有自信。这是深度学习模型中的一种常见情况,因为这些模型倾向于过拟合而表现出过度自信。
这就是显示概率的内核密度图(使用虚假数据模拟的)会是什么样的。
作者提供的图片 — 估计的显示概率分布
在这里需要注意的是,仅仅因为你在神经网络的最后激活函数中使用了 sigmoïd 或 softmax,并不意味着你会得到正确的概率。网络的输出确实会位于[0,1]的范围内,但概率很可能不会得到良好的校准。当一个良好校准的模型对一个给定的观察值输出 0.6 时,我们在长期内应找到 60%的目标。这里有一篇维基百科文章讨论这个问题。在离策略重要性权重计算的背景下,使用良好校准的概率非常重要,因为我们使用的是两个显示概率的比率。当模型输出 0.4 的概率时,应该意味着目标被找到的次数是模型输出 0.2 概率的两倍。0.2 和 0.4 的比率应具有与 0.4 和 0.8 之间的比率相同的重要性。
更简单、更准确的方法?
鉴于我第一次的经历,并且考虑到它并不成功,我的问题是:我们真的需要使用机器学习模型来估计显示概率吗?为什么不直接使用现有的数据进行估计呢?
如果你想进行离策略评估,你需要记录显示的项目。因此,你应该在你的数据库中拥有这些信息(无论是什么)。如果你的日志系统经过充分考虑,你也会在日志中拥有上下文。
在使用日志数据进行展示概率的直接估计时,我们需要简化问题。上下文越简单,你将能够生成更稳健的估计。例如,如果你正在创建一个推荐系统,试图在特定项目后推荐一组项目,那么最重要的特征就是输入项。你的目标将是估计当特定项目(我们称之为i2)被消费(上下文x_i)时,某个项目(我们称之为i1)被展示(动作a_i)的概率。
为了估计这个概率,你有两种选择。你可以选择:
-
频率估计,即i1在i2被消费时被展示的次数除以i2被消费的总次数。
-
贝叶斯估计:当试验次数(在此情况下为展示次数)过少时,频率估计可能不可靠。当我们在 2 次试验中有 2 次展示时,将展示概率声明为 1.0 似乎不是一个稳健的估计。我们将在最后的专门部分解释其工作原理。
因为我们使用的是由旧策略π_0产生的日志数据来计算这些估计,所以实际上我们是在计算旧策略的展示概率。换句话说,我们是在回答这样一个问题:旧策略在这种特定情况下展示这个特定项目的可能性有多大?
现在,我们如何估计新策略π_e的展示概率,考虑到该策略从未投入生产,我们也没有收集过与之相关的展示日志?
实际上,我们确实拥有用于生成策略π_e的训练数据,因此我们有上下文(在此情况下为每次观察的输入项),并且我们可以记录π_e在训练数据上的预测。所以我们拥有了策略的输入和输出。我们唯一缺少的就是策略的输出是否会展示给用户以及展示的排名。因此,这里有一个技巧。我们知道推荐系统输出顶部的项目更有可能展示给用户。我们甚至可以确定项目在特定排名下被展示的总体概率。例如,它可能看起来像这样:
因此,技巧在于将一个项目(由策略输出)展示给用户视为具有概率 p 的伯努利试验。然后我们可以根据 p 进行样本展示结果。
最终,我们将拥有所有需要的东西,以相同的方式精确计算新策略π_e的展示概率,就像我们对π_0所做的那样(无论是频率方法还是贝叶斯方法)。
拥有展示概率后,我们可以计算重要性权重,并使用 SNIPS 估计器进行离策略评估。
我采用了这种方法,并且效果非常好。事实上,没有离线策略评估时,评估流程的主要指标下降了 10%,但有了离线策略评估,它转变为 2%的增长。于是决定进行一次 AB 测试,结果确实是积极的。
关于展示概率的贝叶斯估计的附注
如上所述,展示概率可以通过贝叶斯方法来估计,以获得更稳健的结果。
在频率主义范式中,我们想要估计的参数有一个真实唯一的值,我们通过不断增加实验次数来逐步接近它。它是一个固定的量,与其无关的是概率。相反,在贝叶斯视角下,感兴趣的参数没有真实的唯一值,而是通过概率分布来描述。
在我们的情况下,频率主义方法有什么问题?
我们感兴趣的参数是基于输入项的展示概率。因此,我们正在计算两个计数变量的比率。问题在于,在某些情况下,比率的分子过低。当展示次数非常少时,我们的估计不确定性非常高。估计器的误差方差非常大。
我们如何解决这个问题?
计数变量遵循二项分布。展示次数遵循参数 p(二项展示的概率)的二项分布。有 p 的概率获得展示,1-p 的概率获得不展示事件。两个计数之间的比率遵循一个参数为 alpha =(成功次数+1)和 beta =(失败次数+1)的贝塔分布。
我们要计算什么?
在贝叶斯范式中,我们定义了一个关于参数分布的先验信念 P(Θ)。我们还定义了一个似然函数 P(X|Θ),它告诉我们在给定对参数分布的信念的情况下观察到数据的可能性。所有的工作都基于贝叶斯公式:
贝叶斯定理
后验分布 P(Θ|X)等于似然函数 P(X|Θ)乘以前验 P(Θ),再除以证据 P(X),即观察数据的概率。现在计算观察数据的概率通常是不可处理的。如果我们确实需要获得精确的概率估计以及可信区间等,我们需要依赖先进的贝叶斯推断方法,如马尔可夫链蒙特卡洛 - MCMC(这就涉及到完全不同的领域)。
现在在我们的情况下,优点是先验遵循一个知名分布,似乎似然也遵循一个知名分布。似然模型描述了在给定试验(显示)中观察到成功(点击)的概率,因此它也遵循二项分布。感兴趣的参数是两个计数变量的比率,这两个变量都遵循二项分布,因此先验遵循 beta 分布。而二项分布和 beta 分布的优点是它们是共轭先验。这意味着我们有一个经过验证的理论结果,可以直接给出后验分布的形式,而无需计算证据。在这种情况下,后验分布也遵循 beta 分布,参数为 alpha_posterior = (alpha_prior + nb_success)和 beta_posterior = (beta_prior + nb_failures)。
现在我们知道后验分布遵循 beta 分布,应用 beta 分布的期望值公式,我们可以直接计算显示概率,该概率只是 alpha_posterior 和 beta_posterior 的比率。有关更多信息,请参见维基百科。
此外,选择贝叶斯方法计算显示概率的额外好处是我们知道后验的确切分布。除了使用期望值进行排序,我们还可以通过对后验分布进行抽样来执行随机排序程序,以获得排序分数。这将有利于探索,但会牺牲开发,但可能会导致更为多样化的推荐。
结论
总之,离线策略评估是一种非常有效的方法,用于减少离线与在线之间的差距,并避免当离线结果是积极的(或相反)时在在线测试中获得包容性结果的失望。
当你开始进行推荐工作时,设置离线策略评估策略可能不是绝对最重要的优先事项,但一旦你开始有了生产中的模型并开始迭代改进模型时,这可能是一个认真考虑的好时机。
此外,从我的经验中可以得出一个重要的教训,即应始终从简单的方法开始,并从那里迭代。
使用 Python 完整的文字处理
读取 PDF 文件,利用正则表达式,导出到 Excel 和 Word 文档,并转换回 PDF 格式
·
关注 发表在 Towards Data Science · 10 分钟阅读 · 2023 年 1 月 25 日
–
最近在一个自学项目中,我不得不处理一个 800 页的 PDF 文件。文件的每一章都包含一组共同的问题,而我需要每章中特定问题的答案。现在,逐页浏览文档并评估这些问题的答案会花费我很长时间。我在想是否有快速的办法来扫描每一页,只提取对我有用的信息。我找到了一个 Pythonic 的解决方案。在这篇文章中,我将分享如何使用 Python 读取 PDF 文件,提取每章中仅相关的信息,将数据导出到 Excel 和可编辑的 Word 文档中,然后使用不同的 Python 包将其转换回 PDF 格式。让我们开始吧。
图片由Dariusz Sankowski提供,来自Unsplash。
数据
我将使用一个4 页的 PDF 文件作为示例,而不是 800 页的文档。在高中最后几天,我的同学们传阅了一本叫做“Auto book”的日记,作为一个记忆,收集彼此的兴趣、偏好和联系信息。我使用的 PDF 文件包含关于四个虚构朋友 Ram、Shyam、Hari 和 Shiva 的虚拟信息。该文件包含他们的国籍、出生日期、偏好(食物、水果、运动、球员、电影、演员)、喜欢的名言、目标、对政治的看法和对世界的留言。
一个名为 autobook.pdf 的 PDF 文件,包含四位朋友的信息和消息。图片由作者提供。
对于几个朋友,直接从 PDF 文件中复制粘贴信息会很简单。然而,如果 PDF 文件很大,使用 Python 来完成将会更加高效和准确。接下来的部分将逐步展示如何在 Python 中完成这项工作。
1. 使用 PyPDF2 或 PyMuPDF 包读取 PDF 文档
a. 使用 PyPDF2 读取第一页
要使用 Python 读取 PDF 文件中的文本,我使用了一个叫做PyPDF2的包及其 PdfReader 模块。在下面的代码片段中,我只读取了 PDF 文件的第一页,并从中提取了文本。
读取 PDF 文件第一页的脚本。图片由作者提供。
b. 使用 PyPDF2 读取整个文件的文本
要从 PDF 文件中读取全部文本,我使用了一个叫做extract_text_from_pdf
的函数,如下所示。首先,函数以二进制格式打开 PDF 文件进行读取,并初始化读取对象。接着,初始化一个名为pdf_text
的空列表。然后,在循环遍历 PDF 文件的每一页时,将每一页的内容提取出来并追加到列表中。
def extract_text_from_pdf(pdf_file: str) -> [str]:
# Open the pdf file for reading in binary format
with open(pdf_file, ‘rb’) as pdf:
#initialize a PDfReader object
reader = PyPDF2.PdfReader(pdf)
#start an empty list
pdf_text = []
#loop through each page in document
for page in reader.pages:
content = page.extract_text()
pdf_text.append(content)
return pdf_text
当文件作为参数传递给上述函数时,它返回一个包含元素的列表,每个元素指向每一页的文本。给定文件 autobook.pdf
被使用 extract_text_from_pdf()
函数读取为 4 个元素,如下所示:
extracted_text
内的元素也可以使用以下方法连接为一个单一元素:
all_text = [''.join(extracted_text)]
len(all_text) #returns 1
all_text
返回一个包含整个 pdf 文件所有页面文本的单一元素的列表。
c. 使用 PyMUPDF 包读取整个 pdf 文件的替代方法。
或者,我发现了一个名为 PyMUPDF 的包来读取 pdf 文件中的所有文本,如下所示:
# install using: pip install PyMuPDF
import fitz
with fitz.open(file) as doc:
text = ""
for page in doc:
#append characeter in each page
text += page.get_text()
print ("Pdf file is read as a collection of ", len(text), "text elements.")
#returns 1786 elements.
首先,pdf 文件作为文档打开。text
被初始化为空字符串。通过循环遍历文档中的每一页,将每一页上的字符附加到 text
中。因此,text
的长度为 1786 个元素,其中包括每个字符、空格、换行符和标点符号。
2. RegEx
RegEx 或正则表达式是一系列字符,形成一个搜索模式。Python 有一个内置的 re
包用于此目的。
从给定的 pdf 文件中的所有文本中,我想提取出特定的信息。下面描述了我为此目的使用的函数,尽管 RegEx 的使用场景可能更广泛。
a. findall
当给定的模式在字符串/文本中匹配时,findall 函数会返回所有匹配项的列表。
在下面的代码片段中,x
、y
和 z
返回文本中 Name
、Nationality
和 Country
的所有匹配项。在文本中,Name
出现了四次,Nationality
出现了三次,而 Country
仅出现了一次。
Findall 函数用于返回所有匹配项的列表。图片由作者提供。
b. sub
Sub 函数用于用字符串替代/替换一个或多个匹配项。
在给定的文本中,Nationality
在名为 Hari 的朋友的情况下被称为 Country
。为了将 Country
替换为 Nationality
,首先我编译了一个 Country
的正则表达式模式。接下来,我使用 sub 方法将模式替换为新词,并创建了一个名为 new_text
的新字符串。在 new_text
中,我发现 Nationality
出现了四次,而在前一个情况下是三次。
Sub 函数用于在字符串中进行替换/查找和替换。图片由作者提供。
c. finditer
finditer 方法可以用来查找字符串中模式的匹配项。
在给定的文本中,Name
和 Nationality
字段之间的文本包含朋友的实际姓名,而 Nationality
和 Date of Birth
字段之间的文本包含实际的国籍。我创建了以下名为 find_between()
的函数,以在给定文本中查找任何两个连续单词之间的文本。
def find_between(first_word, last_word, text):
"""Find characters between any two first_word and last_word."""
pattern = rf"(?P<start>{first_word})(?P<match>.+?)(?P<end>{last_word})"
#Returns an iterator called matches based on pattern in the string.
#re.DOTALL flag allows the '.' character to inclde new lines in matching
matches = re.finditer(pattern, text, re.DOTALL)
new_list = []
for match in matches:
new_list.append(match.group("match"))
return new_list
上述函数中的一个主要参数是 pattern
。pattern
被设置为提取给定文本中 first_word
和 last_word
之间的字符。finditer 函数返回一个迭代器,遍历字符串中所有不重叠的匹配项。对于每个匹配项,迭代器返回一个 Match 对象。一个名为 new_list
的空列表被初始化。通过遍历 matches
,在每次迭代中,确切的 match
被附加到 new_list
中,并由函数返回。
通过这种方式,我能够从 PDF 文件中创建每个字段的列表,如姓名、国籍、出生日期、偏好等,如下方代码片段所示:
使用 find_between 函数从 PDF 中提取每个朋友的相关档案信息。图片由作者提供。
注意:
Python 中的 ‘.’ 特殊字符可以匹配文本/字符串中的任何字符,但不包括换行符。然而,re.DOTALL 标志使得 ‘.’ 字符可以匹配包括换行符在内的任何字符。
3. 导出数据到 Excel
a. 从列表中创建 pandas dataframe
在上一步中,我获取了每个朋友每个档案字段的列表。在这一步,我将这些列表转换为 pandas dataframe:
import pandas as pd
df = pd.DataFrame()
df["Name"] = names
df["Nationality"] = nationalities
df["Date of Birth"] = dobs
df["Favorite Food"] = foods
df["Favorite Fruit"] = fruits
df["Favorite Sports"] = sports
df["Favorite Player"] = players
df["Favorite Movie"] = movies
df["Favorite Actor"] = actors
df["Favorite Quotes"] = quotes
df["Aim"] = aims
df["Views on Politics"] = politics
df["Messages"] = messages
df = df.T
df.columns = df.iloc[0]
df.drop(index = "Name", inplace = True)
df
dataframe df
如下所示:
从每个朋友的每个档案字段的列表中推导 pandas dataframe。图片由作者提供。
b. 使用 pandas dataframe 进行条件格式化
Pandas dataframe 提供了类似于 Excel 的条件格式化功能。假设我想在 df
中突出显示包含我最喜欢的球员 Lionel Messi
的单元格。这可以通过 df.style.applymap()
函数完成,如下所示:
使用 df.style.applymap 函数在选定单元格中应用背景颜色。
当文件以 *.xlsx 格式导出时,如第 [28] 行所示,导出的文件还包含了对包含 Lionel Messi
的单元格的黄色高亮。
4. 从 Python 导出到 Word 格式
a. 使用 Python-docx 创建 Word 文档
要将数据从 Python 导出到 Word 格式,我使用了一个叫做 python-docx 的包。docx 包中的 Document
模块允许创建 Word 文档的不同部分,如标题和段落。
在下面的代码中,我首先为每位朋友添加标题“Name”,接着是包含朋友实际姓名的段落。然后是每个个人资料字段的标题和对应的文本。我在每个朋友的个人资料末尾添加了分页符。
from docx import Document
document = Document()
for column in df.columns:
document.add_heading("Name")
p = document.add_paragraph()
p.add_run(column)
for index in df.index:
document.add_heading(index)
p = document.add_paragraph()
p.add_run(df.loc[index, column])
#add page break after profile of each friend
document.add_page_break()
上述代码有助于在保存后生成以下格式的 Word 文档:
上述代码生成的 Word 文档。图片由作者提供。
b. 使用 Python-docx 高亮段落
Python-docx 包帮助生成具有 Microsoft Word 应用程序中大多数功能的 Word 文档。例如,可以添加不同字体样式、字体颜色和大小的字体,并具有粗体、斜体和下划线等功能。
假设我想在文档末尾创建一个名为 Favorites 的部分,并高亮文档中的文本。可以使用以下代码完成:
from docx.enum.text import WD_COLOR_INDEX
document.add_heading("Favorites")
p = document.add_paragraph()
p.add_run("This section consists of favorite items of each friend.").font.highlight_color=WD_COLOR_INDEX.YELLOW
c. 使用 Python-docx 创建表格
Python-docx 还允许直接从 Python 创建 Word 文档中的表格。假设我想在文档末尾的“Favorites”部分添加一个包含每位朋友最喜欢项目的表格。可以使用 document.add_tables(rows = nrows, cols = ncols)
创建表格。此外,需要为表格的每一行/列或单元格定义文本。
在下面的代码中,我定义了一个具有 8 行和 5 列的表格对象。接下来,我定义了表头和第一列。通过循环遍历数据框 df
,我根据每位朋友的最喜欢项目定义表格中每个单元格的文本。
table = document.add_table(rows = 8, cols = 5)
# Adding heading in the 1st row of the table
column1 = table.rows[0].cells
column1[0].text = ‘Items’
#table header
for i in range(1, len(df.columns)+1):
column1[i].text = df.columns[i-1]
#first column in the table for labels
for i in range(1,8):
table.cell(i,0).text = df.index[i+1]
for i in range(2, 9):
for j in range(1, 5):
table.cell(i-1, j).text = df.iloc[i, j-1]
#define table style
table.style = “Light Grid Accent 1”
d. 保存文档。
文档保存为 *.docx 格式文件:
document.save(“../output/python_to_word.docx”)
包含“favorites”部分和表格的文档的最后一页如下所示:
“Favorites”部分和通过步骤 b 和 c 创建的表格。文件使用步骤 d 中的代码保存为 *.docx 格式。图片由作者提供。
5. 将 Word 文档转换为 pdf 格式。
要使用 Python 将文档从 Word *.docx 格式转换为 *.pdf 格式,我发现了一个叫做 docx2pdf 的包。可以使用该包的 convert 模块 convert(input_path, output_path)
将 Word 文档转换为 pdf 格式。
将 Word 文档从 *.docx 转换为 *.pdf 格式。图片由作者提供。
对我来说,输出文件夹如下所示:
包含 Excel 文件、Word 文档和所有通过 Python 导出的 pdf 文件的输出文件夹。图片由作者提供。
结论
扫描 pdf 文件并提取仅必要的信息可能非常耗时和压力大。Python 中有不同的包可以帮助自动化此过程,减轻繁琐性,并使提取精确信息的过程更高效。
在这篇文章中,我使用了一个包含四个朋友个人档案中常见字段/部分/标题的 pdf 文件作为示例,并提取了每个朋友每个字段的相关信息。首先,我使用了 PyPDF2 或 PyMuPDF 包来读取 pdf 文件并打印出整个文本。其次,我使用正则表达式(RegEx)来检测模式并在文本中找到每个模式的匹配项,以提取仅相关的信息。第三,我将每个朋友每个个人档案字段的信息列表转换为 pandas dataframe,并导出为 Excel 文件。接下来,我使用 Python-docx 包创建了一个 word 文件。最后,我再次使用 docx2pdf 文件将 word 文件转换为 pdf 格式。
本文的笔记本和输入的 pdf 文件可以在这个 GitHub 仓库中找到。感谢阅读!
ML 实验跟踪工具的全面比较
原文:
towardsdatascience.com/a-comprehensive-comparison-of-ml-experiment-tracking-tools-9f0192543feb
图片由 BoliviaInteligente 提供,来自 Unsplash
7 个领先工具的优缺点是什么?
·发表于 Towards Data Science ·12 分钟阅读·2023 年 4 月 26 日
–
构建机器学习模型是一个高度迭代的过程。在为我们的项目构建一个简单的 MVP 之后,我们很可能会进行一系列实验,其中尝试不同的模型(以及它们的超参数)、创建或添加各种特征,或利用数据预处理技术。所有这些都是为了实现更好的性能。
随着实验数量的增加,跟踪它们变得具有挑战性。这时,一张纸或一个 Excel 表格可能已经不够用了。此外,当我们可能需要在将最佳表现的实验投入生产之前重现它时,会出现额外的复杂性。这就是 ML 实验跟踪发挥作用的地方!
什么是 ML 实验跟踪?
ML 实验跟踪是记录、组织和分析 ML 实验结果的过程。它帮助数据科学家跟踪他们的实验,重现实验结果,并有效地与他人协作。实验跟踪工具使我们能够记录实验元数据,如超参数、数据集/代码版本和模型性能指标。此外,我们可以轻松地可视化实验结果并比较它们的性能。通过这样做,我们可以识别出最有效的超参数组合和其他实验设置,从而提高模型的性能。
如何选择适合你需求的 ML 实验跟踪工具?
如果没有合适的工具,运行实验很容易导致工作流程混乱且难以管理,即使是简单的项目也是如此。作为数据科学家,选择最适合你需求和工作流程的实验跟踪工具至关重要。由于选项众多,选择理想的工具可能会令人感到困难。
在本文中,我们将深入探讨一些最流行的实验跟踪工具,并比较它们的功能,以帮助你做出明智的决定。到文章结尾时,你将清楚了解每个工具的优点和限制,从而能够选择最适合你特定需求的工具。
实验跟踪工具概述
1. MLflow
MLflow 是一个开源平台,旨在管理端到端的机器学习生命周期。它提供了一套工具,用于实验跟踪、存储和版本控制 ML 模型、将代码打包成可重现的运行、以及将模型部署到各种服务环境和平台。
主要特征
-
MLflow 是一个高度可定制的开源项目。
-
MLflow 是语言和框架无关的,它提供了与最流行的机器学习和深度学习框架的便捷集成。它还具有 R 和 Java 的 API,并支持 REST API。
-
MLflow 为最流行的机器学习和深度学习库提供了自动日志记录功能。通过使用它,我们不需要使用明确的日志语句来跟踪指标、参数和模型。
-
只需几行代码,MLflow 就可以轻松集成到现有代码库中。
-
MLflow 拥有一个非常大且活跃的社区,并且在业内被广泛采用。
-
MLflow 可以在本地和远程服务器上记录结果,使得数据科学团队能够共享一个单一的仪表板。
-
在存储大文件的情况下,MLflow 可以配置为将其存储在 S3 或其他云存储提供商上。
-
MLflow 的 Web 界面允许查看和比较不同用户进行的众多实验的结果。
-
关于实验的附加说明可以存储在 MLflow 中。
-
MLflow 不仅提供实验跟踪,还提供端到端的机器学习生命周期管理。
请记住
-
MLflow 仅作为开源解决方案提供。因此,在公司环境中使用 MLflow 需要维护服务器和基础设施来支持该工具,这可能对较小的组织来说具有挑战性。
-
在安全性方面,MLflow 默认没有强大的安全功能。因此,可能需要额外的配置和设置,以确保敏感数据的安全处理和访问控制的管理。因此,分享实验结果可能不那么容易。
-
虽然 MLflow 支持协作,但它的协作功能不如某些其他平台。
2. DVC
DVC(数据版本控制)是一个开源的 MLOps 工具,用于数据版本控制和实验跟踪。它通常被描述为一个类似 Git 的系统,用于版本控制数据和模型。实际上,DVC 使我们能够通过 Git 跟踪数据,而无需将数据存储在 Git 仓库中。此外,它提供了管道管理功能,帮助实验的重现。
主要特点
-
DVC 是一个开源的、与语言无关的工具,免费使用。
-
DVC 使用类似 Git 的命令进行版本控制,使得对 Git 已经熟悉的开发人员能够轻松上手。
-
被跟踪的指标存储在纯文本文件中,并与 Git 一起版本化。
-
DVC 以干净的方式处理一切,不会使仓库变得凌乱,因此我们不需要为每个实验创建专用的 Git 分支。
-
DVC 与平台无关,可以与广泛的存储提供商一起使用,使得跨不同平台管理数据变得简单。
-
DVC 可以跟踪代码、数据和工件的更改,使我们即使其中一个组件发生变化,也能轻松重现任何已执行的实验。
-
DVC 使用起来很简单,不需要特殊的基础设施或外部服务。我们可以在本地或使用云远程跟踪实验(和其他组件)。
-
使用 DVC,我们不需要重建之前的模型或数据建模技术来达到相同的过去结果状态。
-
使用 DVC,我们还可以跟踪每个实验的输出图像,例如混淆矩阵或特征重要性图。
-
我们可以通过命令行处理 DVC 跟踪的实验,或利用 Iterative Studio(以前称为 DVC Studio),这是一个可以在线访问或本地托管的 web 应用程序。此外,DVC 还提供了一个 VS Code 扩展,方便在 IDE 内进行实验管理、比较和评估。
-
我们可以使用一个名为 DVCLive 的附加库,轻松记录机器学习参数、指标和其他元数据,它还为最流行的机器学习和深度学习库提供了自动记录功能。
请注意
-
在某些情况下,当处理非常大的数据集或大量实验时,你可能会遇到可扩展性问题。
-
存储以内容可寻址的方式组织,所有操作都使用 Git 仓库进行。如果之前没有接触过,它可能会显得意外,尽管这种方式有很多好处,但可能有些团队无法将这种方法与他们的工具集成。
-
虽然 DVCLive 支持大多数框架的自动记录,但不支持
scikit-learn
。
3. ClearML
ClearML 是一个用于管理机器学习(ML)实验的开源平台。它允许用户轻松跟踪、监控和重现他们的 ML 实验,直观地展示结果,并与团队成员协作。
主要特点
-
ClearML 提供了便捷的实验跟踪和管理,允许用户跟踪实验、指标、超参数、元数据等。
-
ClearML 支持自动日志记录。它还记录任何报告给领先可视化库(如 TensorBoard 和 Matplotlib)的指标。此外,ClearML 捕获并记录所有写入标准输出的内容,从调试信息到错误和库警告信息。最后,它自动跟踪信息,如 GPU、CPU、内存和网络的使用情况。
-
ClearML 与领先的机器学习和深度学习库兼容。
-
ClearML 可以部署在本地或云端。我们可以通过 Web 界面或 Python API 与该平台进行互动。
-
我们可以在离线模式下使用 ClearML 实验,其中所有信息都保存在本地文件夹中。
-
ClearML 允许多个用户在同一项目上进行协作,方便实验和数据的共享。
-
ClearML 为用户提供了各种可视化工具,使得解释和分析实验数据变得容易。此外,其可定制的用户界面使用户能够按不同指标对模型进行排序。
-
ClearML 易于集成到现有工作流程中。
-
ClearML 具有内置的超参数优化功能。
请注意
-
尽管 ClearML 提供了免费版,但更高级的功能(例如超参数优化或基于角色的访问控制)需要付费订阅。
-
与其他类似平台相比,ClearML 的用户基础较小,这可能使得寻找支持或资源更加困难。
-
由于需要为自动日志记录运行大量修改(ClearML 替换了其他框架的一些内置函数),系统可能相对较脆弱。
-
设置和配置 ClearML 可能会很具挑战性,尤其是对于那些新接触该平台的用户。例如,与 MLflow 相比,在服务器上安装开源版本相对复杂。
4. TensorBoard
TensorBoard 是一个开源的基于 Web 的可视化工具,旨在帮助理解、调试和优化 TensorFlow 模型。它提供了一整套可视化工具,用于监控训练进度、评估模型性能和可视化数据流图。
主要特性
-
TensorBoard 通常是 TensorFlow 用户的首选,因为它使我们能够跟踪机器学习实验并可视化各种方面,如指标(例如损失和准确性)或模型图。此外,我们还可以用它来比较实验。
-
TensorBoard 不仅限于跟踪基于 TensorFlow 的实验。
-
TensorBoard 包括 What-If Tool (WIT),这是一个易于使用的界面,用于解释和理解黑箱机器学习模型。
-
强大而庞大的用户社区为 TensorBoard 提供了出色的支持。
-
除了开源的本地托管版本,TensorBoard.dev 还作为一个免费服务在托管服务器上提供,这使我们能够托管、跟踪和与任何人分享我们的 ML 实验。
-
TensorBoard 还提供了用于处理图像的成熟功能。
请注意
-
一些用户可能会发现 TensorBoard 使用复杂,学习曲线陡峭。
-
TensorBoard 可能无法很好地扩展到大量实验,在查看和跟踪大规模实验时可能会导致性能下降。
-
TensorBoard 对实验比较的能力有限。
-
TensorBoard 主要设计用于单用户和本地机器使用,而不是团队使用。
-
它缺乏用户管理功能。虽然可以使用 TensorBoard.dev 进行共享,但没有办法管理共享数据的隐私。
-
TensorBoard 不存储数据或代码版本,无法提供完全的可重现性。
5. Weights and Biases
Weights & Biases(W&B 或 WandB)是一个 MLOps 平台,能够进行实验跟踪、数据/模型版本控制,以及团队协作 ML 项目。
主要特征
-
W&B 记录各种实验元数据(如超参数、指标、工件等),并允许用户比较实验并使用交互式可视化分析性能。
-
W&B 通过跟踪所有依赖项并为每个实验提供一致的环境,使重现实验变得容易。
-
W&B 提供了高度可定制的用户界面,允许团队可视化和组织他们的工作流程,包括任何自定义的指标和可视化。
-
W&B 提供了一系列支持团队协作的功能。
-
W&B 支持所有主要的 ML/DL 框架、云平台和工作流编排工具(如 Airflow)。
-
W&B 支持部署到广泛的平台,包括云服务和容器化环境。
-
W&B 通过与领先库的集成提供内置的超参数优化功能。
-
将 W&B 跟踪集成到现有代码库中非常容易。
-
如果需要处理不能外部共享的敏感数据,可以设置一个自托管的 W&B 实例。
-
它允许对音频、视频和图像对象进行轻松调试。
请注意
-
W&B 是一个商业平台,某些功能可能需要付费订阅。
-
与一些不太知名的 ML 框架的集成有限。
-
协作功能需要付费等级。
-
定价计划基于使用时间(称为跟踪小时),这可能对用户来说有些不直观。
6. Comet
Comet(以前称为 CometML)是一个基于云的平台,用于管理和跟踪机器学习实验。此外,它还可以用于版本控制训练数据、在模型注册表中跟踪我们的模型,并监控生产中模型的性能。
主要特征
-
Comet 允许我们记录和跟踪实验,提供了一个简单的方法来可视化和比较结果随时间的变化。它还为正在进行的实验提供实时指标和图表。
-
Comet 提供了多个功能,促进团队协作。例如,它允许我们共享项目、评论和标记其他团队成员。此外,它还具备用户管理功能。
-
Comet 拥有一套集成的工具,用于优化我们模型的超参数。
-
它能够轻松集成最流行的机器学习和深度学习框架。此外,它还支持除了 Python 之外的其他语言,如 Javascript、Java、R,甚至 REST APIs。
-
Comet 支持对相当多的最流行的机器学习和深度学习库进行自动日志记录。
-
Comet 的平台可以在他们的云环境、虚拟私有云(VPC)或本地部署上使用。
-
Comet 的 UI 高度可定制,允许我们轻松创建报告和仪表盘。我们可以为实验创建自定义可视化,或使用社区提供的一些模板。
-
Comet 不仅支持脚本,还支持笔记本。
-
使用 Comet,我们可以调试模型错误、环境特定错误等。
-
具有专门用于视觉、音频、文本和表格数据的模块,使我们能够轻松识别数据集中的任何问题。
请记住
- Comet 是一个商业平台,某些功能可能需要付费订阅。
7. DagsHub
DagsHub 是一个基于网络的平台,提供了一套用于管理和协作机器学习项目的工具。它旨在帮助数据科学家和机器学习工程师跟踪、版本控制和分享他们的代码,以及相应的数据和实验。
主要特点
-
DagsHub 使得机器学习实验的跟踪和管理变得轻而易举,包括超参数、指标和代码版本。
-
借助协作编码工具,DagsHub 为数据科学团队提供了一个集中位置来可视化、比较和审查他们的实验,消除了设置任何基础设施的需求。
-
DagsHub 提供了两种不同的实验跟踪方式:通过 MLflow 和 Git。
-
使用 MLflow 实现,远程设置由系统自动完成,无需本地存储实验数据或自己托管服务器。此外,该实现已经具备基于团队的访问和安全协议。
-
Git 实现依赖于简单、透明和开放的文件格式。由于 DagsHub Logger,适应任何语言或框架并用简单的 Git 推送导出跟踪的指标变得非常容易。
-
Git 集成意味着实验可以自动重现,并与其代码、数据、管道和模型关联。
-
某些框架由 DagsHub Logger 的自动日志记录功能支持。
-
DagsHub 检测并支持 DVC 的
metrics
和
params
文件格式,同时它还设置了一个 DVC 远程,我们可以在其中对数据进行版本控制。 -
可以使用 DagsHub 与你自己的数据存储,或使用虚拟私有云/本地解决方案。
-
对开源和个人项目免费使用。
请注意
-
DagsHub Logger 的自动日志记录功能目前仅限于包括 PyTorch Lightning、Keras 和 fast.ai v2 在内的几个框架。
-
目前无法创建高级或自定义可视化。
-
对于组织来说,DagsHub 是一个商业平台,某些功能需要付费订阅。
-
目前,使用日志记录器的方法没有对实时日志记录的支持。
其他工具
即使我们已经涵盖了 7 种不同的实验跟踪工具/框架,这也绝未涵盖所有可用选项。为了简洁起见,我们只提及一些其他替代方案,你可以自行进行研究。
其他实验跟踪(不仅仅是)工具包括:
-
Neptune
-
Sacred
-
Guild.ai
-
Polyaxon
-
Valohai
-
Kubeflow
-
Verta AI
-
Amazon Sagemaker Studio
-
Pachyderm
总结
由于选择过多,为你的项目或整个团队选择合适的 ML 实验跟踪工具可能是一项艰巨的任务。在做出决定时,你必须考虑许多因素,例如:
-
开源与商业
-
工具是否带有网页 UI 或基于控制台
-
与 ML/DL 框架、云平台和编程语言的集成
-
具体跟踪了什么以及添加自定义日志内容的难易程度
-
存储 — 云存储或本地存储
-
可视化功能
-
稳定性和可扩展性
-
工具是否促进团队成员之间的协作
-
工具是否需要用户设置远程服务器
-
安全性和基于团队的访问
-
工具是否提供与 ML 生命周期相关的额外功能,例如部署
你可以使用以下表格作为参考,快速比较我们今天涵盖的工具。希望它能帮助你为下一个项目做出决定!
一如既往,任何建设性的反馈都是非常欢迎的。你可以通过 Twitter 或评论与我联系。
喜欢这篇文章?成为 Medium 会员,继续无限阅读来学习。如果你使用 这个链接 成为会员,你将支持我,而不会额外增加你的费用。提前感谢,期待再见!
你可能还会对以下内容感兴趣:
提升你的生产力,使用这些必备工具!
medium.com (/enhance-your-ml-experimentation-workflow-with-real-time-plots-434106b1a1c2?source=post_page-----9f0192543feb--------------------------------) [## 增强你的 ML 实验工作流程,使用实时绘图
本教程的第二部分讲解了如何在不离开 IDE 的情况下运行和评估实验
[towardsdatascience.com eryk-lewinson.medium.com/introducing-the-second-edition-of-python-for-finance-cookbook-f42f59c8acd0?source=post_page-----9f0192543feb--------------------------------
[## 介绍《金融 Python 食谱》第二版
促使我编写第二版的原因以及你可以从中期待的内容
所有图片,除非另有说明,均由作者提供。
这篇文章最初发布在 DagsHub 博客 上。
一本全面的 OpenStreetMap 入门指南
原文:
towardsdatascience.com/a-comprehensive-guide-for-getting-started-with-openstreetmap-e92dff95fc80
学习 OpenStreetMap 的基础概念,同时练习使用该网站
·发表于 Towards Data Science ·阅读时间 6 分钟·2023 年 4 月 24 日
–
图片由 Unsplash+ 提供,照片来源于 Unsplash
这是关于地理空间数据分析系列的第二篇文章:
-
使用 QGIS 进行地理空间数据分析
-
OpenStreetMap 入门指南(本帖子)
-
使用 GeoPandas 进行地理空间数据分析
-
使用 OSMnx 进行地理空间数据分析
本文继续讲述 使用 QGIS 进行地理空间数据分析的实用介绍 的故事。在上一篇文章中,我介绍了地理空间数据分析的神奇世界,这是一种数据科学的子领域,涉及从一种特殊类型的数据(称为地理空间数据)中操作和推断信息。
与普通数据不同,每行地理空间数据对应一个特定的位置,并可以绘制在地图上。最简单的情况是通过经纬度描述的位置数据点,但也可能有更复杂的特征,如道路、河流、国家边界和地形,在这些情况下,一对坐标已经不够用了。
这次我专注于更好地理解 OpenStreet 是什么,它背后的概念,以及如何下载数据。首先,OpenStreetMap 是最大的免费且可编辑的地理数据库和项目,任何人都可以参与贡献,甚至包括你,因为你现在已经知道了这个世界地图的存在。它也被称为制图世界的维基百科,因为它们都由来自世界各地的志愿者维护。这引起了你的兴趣吗?那就开始吧!
目录:
-
OpenStreetMap 的基本组成部分
-
OSM 数据格式
-
开始使用 OpenStreetMap
-
如何下载 OSM 数据
OpenStreetMap 的基本组成部分
在 OpenStreetMap 中,有三个主要组成部分:节点、道路和关系。最简单的数据类型是节点,它由一对坐标(纬度和经度)描述。节点的例子包括餐馆、酒吧、商店、图书馆、银行、博物馆等。
作者截图。OpenStreetMap 上获得的节点示例
在上图中,我选择了 Unicredit 银行,这是一种节点,如左侧边栏所示。如果你尝试从地图上选择不同的特征,也可以注意到每个现实世界的特征都有标签,这些标签描述了该特征的地理属性。
就像 Python 字典一样,它是一个键值对集合,其中键指定节点、道路或关系的属性。在这个例子中,Unicredit 银行的属性包括 amenity、atm 和 name。特别是,amenity 通常用来指定居民和游客使用的设施类型,例如咖啡馆、学校、酒吧和餐馆。
作者截图。OpenStreetMap 上获得的道路(线性特征)示例
现在是时候谈谈道路了,它被表示为一组节点。道路可以是线性特征或多边形特征。当我们处理线性特征时,总是有一个起始节点和一个结束节点。常见的例子有道路和铁路。
另一种情况是多边形特征,其中第一个和最后一个节点重合。在多边形特征中,有两种可能的类型:大型建筑,如教堂和宫殿,以及用于住宅、工业或商业目的的区域。需要注意的是,一条道路最多可以包含 2,000 个节点。
作者截图。OpenStreetMap 上获得的道路(多边形特征)示例
第三种数据类型是关系,它是一种特殊的结构,用于将大量节点或道路组织成一个更大的整体。经典的例子包括国家或城市的边界。与道路类似,你可以区分线性特征和多边形特征。它也可以是一个多边形,描述一个包含多个多边形的区域。
作者截图。 从 OpenStreetMap 获得的关系(多边形)的示例
这是博洛尼亚的一个住宅区示例,其中包含 9 条道路,每条道路由不同的节点组成。
OSM 数据格式
在我之前的教程中,我展示了表示矢量数据和栅格数据的最流行格式分别是 Shapefile 和 GeoTIFF。对于 OSM 数据,最常见的格式是PBF和XML格式。PDF 文件通常比 XML 文件更受欢迎,因为它压缩程度高,优化了空间效率和速度。
开始使用 OpenStreetMap
一旦 OpenStreetMap 的概念清晰后,就该进入教程的最有趣部分了。你不需要安装任何东西,只需要访问 OpenStreetMap 的网站。
我们可以搜索博洛尼亚,这是一座位于意大利艾米利亚-罗马涅地区的充满活力的城市,以世界上最古老的大学和著名菜肴(如意大利饺子和千层面)而闻名。程序如下:
-
输入你喜欢的城市并点击“前往”
-
在左侧边栏选择“City Bologna, Emilia-Romagna, Italy”选项
作者 GIF。从 OpenStreetMap 获得的关系(博洛尼亚的边界)示例
我们可以在城市中移动并选择一个地图元素。例如,我们可以去皮亚察·马焦雷,按下“查询特征”按钮,然后点击“Artwork Il Nettuno”,这是一座献给海神 Nettuno 的喷泉。
作者 GIF。从 OpenStreetMap 获得的节点(Artwork Il Nettuno)示例
这就是在 OpenStreetMap 上查看你感兴趣的元素的主要信息的方法。例如,如果你想提取博洛尼亚的所有餐厅,最好先了解这些地方的共同特点。你需要在网站上进行一些这样的探索,然后再直接提取你的兴趣点。
如何下载 OSM 数据
从 OpenStreetMap 下载数据有很多种方法。合适的方法取决于数据集的大小。如果你只是想下载一个小数据集,比如一个酒吧,一个公园或一个住宅区,你可以直接从 OpenStreetMap 的网站上下载。你有两个选择:可以点击“下载 XML”或“导出”按钮。
作者截图。 从 OpenStreetMap 的网站下载数据。
如果你需要来自整个大陆和国家的 OSM 地图数据,你可以从 geofabrik 下载数据。如果你需要特定国家的数据,可以点击大陆文件的链接或子区域的链接。
作者截图。 从 geofabrik 的网站下载数据。
第三种方法是直接使用 Python 下载 OSM 数据。Python 有一个库叫做 Pyrosm,可以从世界各地的大量位置下载和读取 PBF 数据。
from pyrosm import get_data
fp = get_data("Lisbon")
不幸的是,并不是所有的城市都有提供。你可以通过打印可以下载的城市列表来检查:
print(sources.cities.available)
输出:
['Aachen', 'Aarhus', 'Adelaide', 'Albuquerque', 'Alexandria', 'Amsterdam', 'Antwerpen', 'Arnhem',...]
我需要说明的是,这些并不是下载 OSM 数据的唯一方法。你可以查看我在最后建议的资源中其他的方法。
最后的想法:
就这些了!这只是 OpenStreetMap 世界的一个概述!在开始分析这种数据时,如果对主要数据类型没有任何了解,并且只是通过直观的例子来浏览网站,可能会有些挑战。虽然有很多资源,但我发现它们很分散,因为涵盖的方面很少。希望这个教程能帮助你开始分析地理空间数据的旅程。感谢阅读!祝你有美好的一天!
有用的资源:
分布式数据并行(DDP)的全面指南
原文:
towardsdatascience.com/a-comprehensive-guide-of-distributed-data-parallel-ddp-2bb1d8b5edfb
关于如何使用分布式数据并行(DDP)加速模型训练的全面指南
·发表于 Towards Data Science ·12 分钟阅读·2023 年 10 月 30 日
–
作者提供的图像
引言
大家好!我是 Francois,Meta 的研究科学家。欢迎来到这个新的教程,它是 Awesome AI Tutorials 系列的一部分。
在本教程中,我们将揭示一种称为 DDP 的著名技术,以便在多个 GPU 上同时训练模型。
在我工程学校的日子里,我记得利用 Google Colab 的 GPU 进行训练。然而,在企业领域,情况有所不同。如果你在一个对 AI 投资巨大的组织中工作,特别是如果你在一个科技巨头公司,你很可能有大量的 GPU 集群可供使用。
本节旨在为你提供利用多个 GPU 力量的知识,实现快速高效的训练。你猜怎么着?这比你想象的要简单!在我们继续之前,我建议你对 PyTorch 有一个良好的掌握,包括其核心组件如数据集、数据加载器、优化器、CUDA 和训练循环。
最初,我认为 DDP 是一个复杂且几乎不可实现的工具,认为它需要一个大团队来建立必要的基础设施。然而,我向你保证,DDP 不仅直观而且简洁,只需少量的代码行即可实现。让我们一起开始这段启发性的旅程吧!
DDP 的高层次直觉
分布式数据并行(DDP)一旦拆解就变得简单明了。想象一下你有一个包含 4 个 GPU 的集群。使用 DDP,同一个模型会被加载到每个 GPU 上,包括优化器。主要的区别在于我们如何分配数据。
DDP,图像来自 PyTorch 教程
如果你对深度学习有所了解,你会记得 DataLoader,这是一个将你的数据集分割成不同批次的工具。通常会将整个数据集分割成这些批次,在每个批次计算后更新模型。
更深入地看,DDP 通过将每个批次划分为我们可以称之为“子批次”的部分来改进这个过程。本质上,每个模型副本处理主批次的一部分,从而为每个 GPU 生成不同的梯度计算。
在 DDP 中,我们通过一个叫做DistributedSampler的工具将批次拆分为子批次,如下图所示:
DDP,图像来自 PyTorch 教程
在每个子批次分配到各个 GPU 之后,每个 GPU 计算其独特的梯度。
DDP,图像来自 PyTorch 教程
-
现在进入 DDP 的神奇部分。在更新模型参数之前,需要汇总在每个 GPU 上计算的梯度,以便每个 GPU 都有整个数据批次上计算的平均梯度。
-
这是通过从所有 GPU 获取梯度并进行平均来完成的。例如,如果你有 4 个 GPU,那么某个特定模型参数的平均梯度就是该参数在 4 个 GPU 上的梯度之和除以 4。
-
DDP 使用
NCCL
或Gloo
后端(NCCL 针对 NVIDIA GPU 进行了优化,Gloo 则更为通用)来有效地在 GPU 之间通信和平均梯度。
DDP,图像来自 PyTorch 教程
术语、节点和排名词汇表
在深入代码之前,理解我们将频繁使用的词汇至关重要。让我们揭开这些术语的神秘面纱:
-
节点:
可以把节点想象成一台配备有多个 GPU 的强大机器。当我们谈论集群时,它不仅仅是一堆 GPU 堆在一起。相反,它们被组织成组或“节点”。例如,一个节点可能包含 8 个 GPU。 -
主节点:
在多节点环境中,通常有一个节点负责主控。这个“主节点”处理诸如同步、启动模型副本、监督模型加载和管理日志条目等任务。如果没有主节点,每个 GPU 都会独立生成日志,导致混乱。 -
本地排名:
“排名”这个术语可以类比为一个 ID 或位置。本地排名指的是 GPU 在其特定节点(或机器)中的位置或 ID。它是“本地的”,因为它仅限于那台机器。 -
全球排名:
从更广泛的角度看,全球排名识别所有可用节点中的 GPU。这是一个无论机器如何都唯一的标识符。 -
World Size:
从根本上说,这是所有在所有节点上可用的 GPU 数量的计数。简单来说,这是节点数和每个节点中 GPU 数量的乘积。
从实际情况来看,如果你只使用一台机器,那么事情会更加简单,因为本地排名等于全局排名。
用图像来澄清这个问题:
本地排名,图像来自 教程
本地排名,图像来自 教程
理解 DDP 限制:
分布式数据并行(DDP)在许多深度学习工作流中具有变革性,但理解其局限性非常重要。
DDP 限制的核心在于其内存消耗。使用 DDP 时,每个 GPU 加载一个模型副本、优化器及其相应的数据批次。 GPU 内存通常从几 GB 到高端 GPU 的 80GB 不等。
对于较小的模型,这不是问题。然而,当涉足大型语言模型(LLMs)或类似 GPT 的架构时,单个 GPU 内存的限制可能是不够的。
在计算机视觉中,虽然有很多轻量级模型,但增加批量大小时会遇到挑战,特别是在涉及3D 图像或目标检测任务的场景中。
进入完全分片数据并行(FSDP)。这种方法通过不仅分布数据,还将模型和优化器状态分散到 GPU 内存中,从而扩展了 DDP 的好处。虽然这听起来很有优势,但 FSDP 会增加 GPU 之间的通信,可能会导致训练速度变慢。
总结:
-
如果你的模型及其对应的批量数据能够舒适地适应 GPU 的内存,DDP 是你最好的选择,因为它速度较快。
-
对于需要更多内存的巨型模型,FSDP 是更合适的选择。然而,请记住其权衡:你是在为内存牺牲速度。
为什么你应该更倾向于使用 DDP 而不是 DP?
如果你访问 PyTorch 的网站,实际上有两种选择:DP 和 DDP。但我提到这一点只是为了让你不要迷路或困惑:只使用 DDP,它更快且不限于单个节点。
来自 PyTorch 的比较 教程
代码演示:
实现分布式深度学习比你想象的要简单。美在于你不会被手动配置 GPU 或梯度分布的复杂性所困扰。
你可以在以下位置找到所有模板和脚本:
[## GitHub - FrancoisPorcher/awesome-ai-tutorials: 最佳 AI 教程集合,让你成为数据科学的…
最佳 AI 教程集合,让你成为数据科学的高手! - GitHub …
下面是我们将采取的步骤的细分:
-
进程初始化:这涉及到指定主节点、指定端口,并设置
world_size
。 -
分布式 DataLoader 设置:这个步骤至关重要的是将每个批次在可用 GPU 之间进行分区。我们将确保数据均匀分布而没有任何重叠。
-
模型训练/测试:本质上,这一步与单 GPU 过程几乎没有变化。
在 1 GPU 1 节点上训练(基准)
首先,让我们定义一个简单的代码,它加载一个数据集,创建一个模型,并在单个 GPU 上进行端到端训练。这将是我们的起点:
import torch
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import numpy as np
class WineDataset(Dataset):
def __init__(self, data, targets):
self.data = data
self.targets = targets
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
return torch.tensor(self.data[idx], dtype=torch.float), torch.tensor(self.targets[idx], dtype=torch.long)
class SimpleNN(torch.nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc1 = torch.nn.Linear(13, 64)
self.fc2 = torch.nn.Linear(64, 3)
def forward(self, x):
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x
class Trainer():
def __init__(self, model, train_data, optimizer, gpu_id, save_every):
self.model = model
self.train_data = train_data
self.optimizer = optimizer
self.gpu_id = gpu_id
self.save_every = save_every
self.losses = []
def _run_batch(self, source, targets):
self.optimizer.zero_grad()
output = self.model(source)
loss = F.cross_entropy(output, targets)
loss.backward()
self.optimizer.step()
return loss.item()
def _run_epoch(self, epoch):
total_loss = 0.0
num_batches = len(self.train_data)
for source, targets in self.train_data:
source = source.to(self.gpu_id)
targets = targets.to(self.gpu_id)
loss = self._run_batch(source, targets)
total_loss += loss
avg_loss = total_loss / num_batches
self.losses.append(avg_loss)
print(f"Epoch {epoch}, Loss: {avg_loss:.4f}")
def _save_checkpoint(self, epoch):
checkpoint = self.model.state_dict()
PATH = f"model_{epoch}.pt"
torch.save(checkpoint, PATH)
print(f"Epoch {epoch} | Model saved to {PATH}")
def train(self, max_epochs):
self.model.train()
for epoch in range(max_epochs):
self._run_epoch(epoch)
if epoch % self.save_every == 0:
self._save_checkpoint(epoch)
def load_train_objs():
wine_data = load_wine()
X = wine_data.data
y = wine_data.target
# Normalize and split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler().fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
train_set = WineDataset(X_train, y_train)
test_set = WineDataset(X_test, y_test)
print("Sample from dataset:")
sample_data, sample_target = train_set[0]
print(f"Data: {sample_data}")
print(f"Target: {sample_target}")
model = SimpleNN()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
return train_set, model, optimizer
def prepare_dataloader(dataset, batch_size):
return DataLoader(dataset, batch_size=batch_size, pin_memory=True, shuffle=True)
def main(device, total_epochs, save_every, batch_size):
dataset, model, optimizer = load_train_objs()
train_data = prepare_dataloader(dataset, batch_size)
trainer = Trainer(model, train_data, optimizer, device, save_every)
trainer.train(total_epochs)
main(device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu"), total_epochs=100, save_every=50, batch_size=32)
在多个 GPU,1 节点上训练
现在我们将使用单节点上的所有 GPU,步骤如下:
-
导入进行分布式训练所需的库。
-
初始化分布式环境:(特别是
MASTER_ADDR
和MASTER_PORT
) -
使用
DistributedDataParallel
包装器包装模型。 -
使用分布式采样器确保数据集在 GPU 之间以分布式的方式划分。
-
调整主函数以
spawn
多个进程进行多 GPU 训练。
对于库,我们需要这些:
import torch.multiprocessing as mp
from torch.utils.data.distributed import DistributedSampler
from torch.nn.parallel import DistributedDataParallel as DDP
from torch.distributed import init_process_group, destroy_process_group
import os
然后我们需要设置每个进程。例如,如果我们在 1 节点上有 8 个 GPU,我们将调用以下函数 8 次,每次针对一个 GPU,并设置正确的local_rank
:
def ddp_setup(rank, world_size):
"""
Set up the distributed environment.
Args:
rank: The rank of the current process. Unique identifier for each process in the distributed training.
world_size: Total number of processes participating in the distributed training.
"""
# Address of the main node. Since we are doing single-node training, it's set to localhost.
os.environ["MASTER_ADDR"] = "localhost"
# Port on which the master node is expected to listen for communications from workers.
os.environ["MASTER_PORT"] = "12355"
# Initialize the process group.
# 'backend' specifies the communication backend to be used, "nccl" is optimized for GPU training.
init_process_group(backend="nccl", rank=rank, world_size=world_size)
# Set the current CUDA device to the specified device (identified by rank).
# This ensures that each process uses a different GPU in a multi-GPU setup.
torch.cuda.set_device(rank)
对该函数的一些解释:
-
MASTER_ADDR
是主机(或 rank 0 进程)运行的机器的主机名。在这里是 localhost -
MASTER_PORT
:指定主节点监听来自工作进程或其他进程的连接的端口。12355 是任意的。你可以选择任何未被占用的端口号,只要它不被系统上的其他服务使用,并且被你的防火墙规则允许。 -
torch.cuda.set_device(rank)
:这确保每个进程使用其对应的 GPU。
然后我们需要稍微修改 Trainer 类。我们将简单地用 DDP 函数包装模型:
class Trainer():
def __init__(self, model, train_data, optimizer, gpu_id, save_every):
self.model = model.to(gpu_id)
self.train_data = train_data
self.optimizer = optimizer
self.gpu_id = gpu_id
self.save_every = save_every
self.losses = []
# This changes
self.model = DDP(self.model, device_ids=[gpu_id])
Trainer 类的其他部分保持不变,真是太棒了!
现在我们必须更改 dataloader,因为记住,我们必须在每个 GPU 上拆分批次:
def prepare_dataloader(dataset: Dataset, batch_size: int):
return DataLoader(
dataset,
batch_size=batch_size,
pin_memory=True,
shuffle=False,
sampler=DistributedSampler(dataset)
)
现在我们可以修改main
函数,这个函数会为每个进程调用(所以在我们的例子中是 8 次):
def main(rank: int, world_size: int, save_every: int, total_epochs: int, batch_size: int):
"""
Main training function for distributed data parallel (DDP) setup.
Args:
rank (int): The rank of the current process (0 <= rank < world_size). Each process is assigned a unique rank.
world_size (int): Total number of processes involved in the distributed training.
save_every (int): Frequency of model checkpoint saving, in terms of epochs.
total_epochs (int): Total number of epochs for training.
batch_size (int): Number of samples processed in one iteration (forward and backward pass).
"""
# Set up the distributed environment, including setting the master address, port, and backend.
ddp_setup(rank, world_size)
# Load the necessary training objects - dataset, model, and optimizer.
dataset, model, optimizer = load_train_objs()
# Prepare the data loader for distributed training. It partitions the dataset across the processes and handles shuffling.
train_data = prepare_dataloader(dataset, batch_size)
# Initialize the trainer instance with the loaded model, data, and other configurations.
trainer = Trainer(model, train_data, optimizer, rank, save_every)
# Train the model for the specified number of epochs.
trainer.train(total_epochs)
# Cleanup the distributed environment after training is complete.
destroy_process_group()
最后,在执行脚本时,我们需要启动 8 个进程。这是通过mp.spawn()
函数完成的:
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='simple distributed training job')
parser.add_argument('total_epochs', type=int, help='Total epochs to train the model')
parser.add_argument('save_every', type=int, help='How often to save a snapshot')
parser.add_argument('--batch_size', default=32, type=int, help='Input batch size on each device (default: 32)')
args = parser.parse_args()
world_size = torch.cuda.device_count()
mp.spawn(main, args=(world_size, args.save_every, args.total_epochs, args.batch_size), nprocs=world_size)
终极步骤:在多个节点上训练
如果你已经做到这些,恭喜你!终极步骤是能够招募所有在不同节点上的 GPU。但是如果你理解了我们迄今为止所做的,这将非常简单。
在跨多个节点扩展时,关键的区别在于从local_rank
到global_rank
的转换。这一点非常重要,因为每个进程都需要一个唯一的标识符。例如,如果你在两个节点上工作,每个节点有 8 个 GPU,那么进程 0 和 8 都会有一个local_rank
为 0。
global_rank 由非常直观的公式给出:
global_rank = node_rank * world_size_per_node + local_rank
所以首先让我们修改ddp_setup
函数:
def ddp_setup(local_rank, world_size_per_node, node_rank):
os.environ["MASTER_ADDR"] = "MASTER_NODE_IP" # <-- Replace with your master node IP
os.environ["MASTER_PORT"] = "12355"
global_rank = node_rank * world_size_per_node + local_rank
init_process_group(backend="nccl", rank=global_rank, world_size=world_size_per_node*torch.cuda.device_count())
torch.cuda.set_device(local_rank)
我们需要调整主函数,它现在接受world_size_per_node
作为参数:
def main(local_rank: int, world_size_per_node: int, save_every: int, total_epochs: int, batch_size: int, node_rank: int):
ddp_setup(local_rank, world_size_per_node, node_rank)
# ... (rest of the main function)
最后,我们也要调整mp.spawn()
函数以适应world_size_per_node
:
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='simple distributed training job')
parser.add_argument('total_epochs', type=int, help='Total epochs to train the model')
parser.add_argument('save_every', type=int, help='How often to save a snapshot')
parser.add_argument('--batch_size', default=32, type=int, help='Input batch size on each device (default: 32)')
parser.add_argument('--node_rank', default=0, type=int, help='The rank of the node in multi-node training')
args = parser.parse_args()
world_size_per_node = torch.cuda.device_count()
mp.spawn(main, args=(world_size_per_node, args.save_every, args.total_epochs, args.batch_size, args.node_rank), nprocs=world_size_per_node)
使用集群(SLURM)
你现在可以准备将训练发送到集群。这非常简单,你只需调用所需的节点数量即可。
这是 SLURM 脚本的模板:
#!/bin/bash
#SBATCH --job-name=DDPTraining # Name of the job
#SBATCH --nodes=$1 # Number of nodes specified by the user
#SBATCH --ntasks-per-node=1 # Ensure only one task runs per node
#SBATCH --cpus-per-task=1 # Number of CPU cores per task
#SBATCH --gres=gpu:1 # Number of GPUs per node
#SBATCH --time=01:00:00 # Time limit hrs:min:sec (1 hour in this example)
#SBATCH --mem=4GB # Memory limit per GPU
#SBATCH --output=training_%j.log # Output and error log name (%j expands to jobId)
#SBATCH --partition=gpu # Specify the partition or queue
srun python3 your_python_script.py --total_epochs 10 --save_every 2 --batch_size 32 --node_rank $SLURM_NODEID
现在你可以使用以下命令从终端启动训练
sbatch train_net.sh 2 # for using 2 nodes
恭喜,你完成了!
感谢阅读!在你离开之前:
欲获取更多精彩教程,请查看我在 Github 上的 AI 教程汇编
[## GitHub - FrancoisPorcher/awesome-ai-tutorials: 最佳的 AI 教程集合,让你成为……
最佳的 AI 教程集合,让你成为数据科学的高手! - GitHub …
github.com](https://github.com/FrancoisPorcher/awesome-ai-tutorials?source=post_page-----2bb1d8b5edfb--------------------------------)
你应该在收件箱中获取我的文章。 在这里订阅。
如果你想访问 Medium 上的高级文章,只需每月支付 $5 的会员费用。如果你通过 我的链接注册,你将以额外的费用支持我。
如果你觉得这篇文章有洞察力并且有帮助,请考虑关注我并点赞以获取更多深入内容!你的支持帮助我继续制作有助于我们共同理解的内容。