NeptuneAI-博客中文翻译-八-
NeptuneAI 博客中文翻译(八)
ML 模型的版本控制:为什么你需要它,它是什么,如何实现它
原文:https://web.archive.org/web/https://neptune.ai/blog/version-control-for-ml-models
版本控制在任何软件开发环境中都很重要,在机器学习中更是如此。在 ML 中,开发过程非常复杂。它包括大量的数据、多个模型的测试、参数的优化、特性的调整等等。
如果你希望你的研究是可重复的,你需要适当的版本控制工具来管理和跟踪上述所有内容。因此,在本文中,我们将探讨机器学习中的版本控制是什么,为什么需要它,以及如何实现它。
“版本控制”是什么意思?
版本控制是随着时间的推移跟踪和管理软件变更的过程。无论你是在构建一个应用程序还是一个 ML 模型,你都需要跟踪软件团队成员所做的每一个修改,以修复错误并避免冲突。
为了实现这一点,您可以使用版本控制框架。开发框架是为了跟踪每个参与者的每个单独的更改,并将其保存在一种特殊的数据库中,在那里您可以识别差异,并在合并时帮助防止并发工作中的冲突。
为什么我们在 ML 中需要版本控制?
机器学习开发过程包括大量的迭代工作,其中开发人员在改变超参数、代码和数据的同时搜索最佳执行模型。保留这些变化的历史以跟踪与参数相关的模型性能是很重要的,这可以节省您为实验而重新训练模型所花费的时间。
Machine Learning process | Source
机器学习版本控制有三个部分:
有建模代码,也有实现代码。建模代码用于实现模型,实现代码用于推理。它们都可以用不同的编程语言编写,但是维护所有的代码和依赖关系可能会更加困难。
还有元数据,它是关于你的数据和模型的信息。然后是实际数据,即用于训练和运行模型的数据集。元数据可以在不改变数据的情况下改变,版本控制应该将数据链接到适当的元。
该模型通过模型参数和超参数将上述所有内容联系起来。当您使用模型版本控制系统时,您会得到很多好处:
- 合作:如果你是一个单独的研究者,这可能并不重要。当你和一个团队一起工作并且你的项目很复杂的时候,如果没有版本控制系统,合作会变得非常困难。
- 版本化: 在进行更改的同时,模型可以中断。有了版本控制系统,当你的模型崩溃时,你会得到一个有用的变更日志,你可以恢复你的变更以回到一个稳定的版本。
- 再现性:通过为整个机器学习管道拍摄快照,您可以再次再现相同的输出,即使使用训练过的权重,这可以节省重新训练和测试的时间。
- 依赖跟踪: 跟踪数据集的不同版本(训练、评估和开发),调整模型超参数和参数。通过使用版本控制,您可以在不同的分支或者存储库上测试不止一个模型,调整模型参数和超参数,并监控每个变更的准确性。
- 模型更新: 模型开发不是一步到位的,它是循环往复的。在版本控制的帮助下,您可以控制发布哪个版本,同时继续开发下一个版本。
机器学习版本控制类型
ML 版本控制有两种类型:
- 集中式版本控制系统。
- 分布式版本控制系统。
一个分布式版本控制系统 (DVCS)是一个版本控制系统,其中完整的代码库可以在开发者的本地计算机上获得,包括历史。这使得开发人员能够在本地合并和创建分支,而根本不需要连接到远程服务器或任何网络。这些系统的一个例子是 Git。
使用这种方法进行模型开发的优势在于,可以在您的机器上单独工作,而不需要联机,并且不依赖于单个服务器进行备份。这对于培训目的和项目仍然很小的时候很有用。然而,当项目存储库变得更大时,这将需要一个大的存储器来保存开发人员计算机上的所有历史和所有分支数据,这就是为什么引入了另一种集中式版本控制方法。
Distributed Version control | Source
一个集中式版本控制 系统 (CVCS ) 是一个版本控制,开发者必须从一个包含所有文件和文件历史的单一集中式服务器中签出存储库。
这些系统使得在一个地方控制完整的代码库变得容易,并且每个人都知道发生的任何变化。然而,如果出现中央服务器连接问题,它会很慢,而且将所有备份放在一个地方也有风险。
这个可以在你的模型足够成熟的时候使用,作为产品的一部分使用。您有不同的团队处理大量的特性和变更,您不需要将所有的代码都放在开发人员的计算机上,并且您希望降低合并和添加变更的复杂性。
此外,CVCS 减少了开发所需的存储空间,因为您将只有一台服务器包含所有的代码更改,开发人员只需要在本地工作的系统的单一版本。
Centralized Version Control | Source
模型版本控制
在模型开发过程中,开发人员会遇到一些问题:
- 模型是在哪些超参数上训练的?
- 上次模型训练后有哪些代码改动?
- 模型是在哪个数据集上训练的?
- 从上次模型培训开始,对依赖关系进行了哪些更改?
- 导致模型失败的变化是什么?
- 使模型表现更好的变化是什么?
- 该型号的最新版本是什么?
为了回答这些问题,您需要跟踪模型开发过程中所做的变更,这就提出了什么需要版本化的问题。
ML 开发中什么需要版本化?
回答这个问题取决于您处于模型开发的哪一步。让我们看看在每个开发步骤中需要对什么进行版本控制。
- 型号选择:
首先,你需要决定使用哪种算法。您可能需要尝试多种算法并比较性能。每个选定的算法都应该有自己的版本,以单独跟踪变化,并选择最佳执行模型。
在编写模型或对模型进行性能更改时,您应该跟踪这些更改,以了解导致性能更改的原因。
这可以通过为每个模型使用不同的存储库来实现。这样,您可以并行测试多个模型,并在模型之间提供一些隔离。
- 模型训练:
应跟踪用于训练的超参数。您可以为每个超参数创建不同的分支来调整它,并跟踪每个超参数变化时的模型性能。
训练参数也应与模型代码和超参数一起进行版本化,以确保相同训练权重的可重复性,甚至在恢复到此版本时节省重新训练模型所需的时间。
要使用版本控制系统实现这一点,您需要为您将要更改的每个特性、参数和超参数创建一个分支。这使您能够一次使用一个变更来执行分析,并在一个存储库中维护与同一个模型相关的所有变更。
- 模型评估:
评估是指开发人员使用保留或测试集来检查模型在从未见过的数据上的表现。
坚持和性能结果应该保存在版本控制系统中,以及每一步性能矩阵的记录。正如在模型训练部分中提到的,在您选择了最适合您需求的参数之后,您将需要将变更合并到一个集成分支,并在这个分支上运行评估。
- 模型验证:
模型验证是验证模型在真实数据上的表现是否符合预期的过程。在这一步中,您必须跟踪每个验证结果,并在模型生命周期中跟踪模型的性能。增强模型性能的模型变化是什么?如果您正在比较不同的模型,那么您应该跟踪用于评估不同模型的验证矩阵。为了实现这一点,在评估了集成分支的性能之后,可以在主分支上进行模型验证,您可以将评估的变更合并到主分支中,对其执行验证,并将符合您的客户规格的变更集标记为准备部署的版本。
- 模型部署:
当您的模型准备好被部署时,您应该跟踪哪个版本被部署以及每个版本中有什么变化。这将使您能够拥有一个分阶段的部署,当您通过在主分支上部署您的最新版本开始时,同时仍然开发和改进您的模型。如果您的模型在部署时失败,这也将为您提供所需的容错能力,以恢复到先前的工作版本。
最后,拥有模型版本控制可以帮助 ML 工程师理解模型中发生了什么变化,研究人员更新了哪些功能,以及功能是如何变化的。当将多个特性集成在一起时,了解做了什么以及如何做,可以影响部署速度和简单性。
如何实现模型版本控制
总结一下上一节中提到的内容,实现模型版本控制的步骤如下:
- 为您将要实现的每个模型创建单独的存储库;
- 为每个要评估的模型参数、超参数或特征创建一个单独的分支。
- 创建一个集成分支,在该分支中,您可以根据对每个功能分别进行的性能分析来收集所需的功能;
- 评估集成分支上的模型;
- 从集成分支合并到主分支并执行验证;
- 用版本号标记主分支上的版本。
选择正确的工具来执行版本控制是非常重要的,所选择的工具应该对管道的每个部分提供清晰的愿景,并在不同类型的版本控制(如数据、代码和模型版本控制)之间建立联系(不仅仅是简单的管理和跟踪文件更改)。
一个好的模型版本化系统将使团队成员之间的协作更加顺畅,提供一种可视化数据变更的方式,并使开发过程自动化。
海王星
Neptune 是为研究和生产而开发的,它配备了一个中枢,在那里您可以找到帮助您处理从机器学习管道中生成的元数据的方法。它使您能够记录、可视化、存储和比较元数据。
你可以在这里阅读更多关于如何在 Neptune 中创建模型检查点的内容。
DVC
专为机器学习项目设计的开源版本控制系统,旨在实现机器学习模型的可复制性和共享。
ML 元数据(MLMD)
一个存储不同组件每次运行时生成的模型元数据的库,包括经过训练的模型及其执行。最初设计用于 Tensorflow,但可以独立使用。
摘要
在模型开发期间和之后,版本控制是一个非常重要的步骤。它支持多个版本的协作、历史记录和性能监控。
您的项目中需要版本控制什么?这取决于你目前处于开发过程的哪个阶段。无论您将使用集中式版本控制系统还是分布式版本控制系统,您都必须选择满足您需求的适当工具。
参考资料:
机器学习研究者的版本控制指南
版本控制用于跟踪和管理项目中的变更,包括关键参数、文档、应用程序等等。当多人在同一代码上工作时,版本控制系统(VCS)就派上了用场。没有 VCS,软件项目将会一片混乱。
版本控制也称为源代码控制、或版本控制。为什么?
什么是版本控制?
版本控制是跟踪对代码库所做更改的一种方式。在 ML 中,版本控制系统支持开发人员和数据科学家之间的顺畅协作,并允许您在出现问题时将代码库恢复到任何以前的版本。
VCS 帮助团队在没有太多复杂性的情况下在同一个项目上协作。开发人员和数据科学家可以根据需要查看、管理和合并变更。新的团队成员可以更容易地适应当前的环境。
在机器学习模型上工作,跟踪用于创建模型的训练数据集、超参数、算法选择、架构和管道总是好的。
Source: Author
版本控制系统的类型
我们将讨论集中式和分布式系统,并详细比较它们。你也可以有一个本地版本控制系统,所有的提交都保存在本地机器上,但是它很容易出错,所以我们不会深入讨论。
1.集中式版本控制
在集中式版本控制中,您有一个单一的存储库,其中每个人同时提交和更新代码。当有人更新代码时,团队中的每个人都会知道,并且必须在他们的工作区中更新代码。所做的每一个改变都被传送到一个中央服务器(存储库)。您的更改会直接影响将在生产中使用的主代码。没有批准或合并系统,只是简单的提交和更新。
Source: Author
- 集中式系统易于理解和管理。
- 你可以接触到大师级的代码,不需要得到最高当局的批准。
- 它可以无缝地处理二进制文件。
使用最多的中央 VCS 系统是 SVN 的 T1 和 T2 的 T3。
2.分布式版本控制
在分布式版本控制中,每个开发人员都有自己的存储库和程序副本。当您更新代码时,只有您可以访问它,直到您将它推送到中央存储库或主代码。简单地说,您提交并推动变更,其他团队成员拉动并更新它们。您不必一直依赖中央存储库,您可以将整个代码克隆到您的本地机器上并离线工作。分布式版本控制也有一个中央存储库,但它是权威的。
Source: Author
- 更好的绩效和治理,
- 分支和合并比集中式版本控制更容易,
- 你可以离线工作。
最流行的分布式版本控制系统是 Git 和 Mercurial 。
集中式和分布式版本控制的差异
集中式和分布式 | 分布式版本控制 |
---|---|
初学者容易上手
|
对初学者来说复杂的
|
| |
在本地机器上离线工作
|
|
这既困难又耗时,并且需要直接与服务器通信。
|
更快,因为你不必为每一个命令都与存储库通信。
|
| 在 CVCS,你不需要把整个历史或者源代码保存到你的本地机器上,所以你节省了大量的空间。 |
如果项目包含大文件,DVCS 会占用你本地机器更多的时间和空间。
|
| 如果服务器瘫痪,就没有办法找回代码。 | 如果服务器宕机,你有足够的机器来获取代码,包括你的本地机器。 |
为什么要使用版本控制
VCS 允许您合并、更改和查看以前对程序所做的所有更改。这是监控程序构建以及开发和生产中的事情的好方法。对于 ML 和 AI 相关的工作,对非二进制文件使用 VCS 很重要,这样数据科学家和 ML 开发人员就可以在一个中心工作,而不会影响其他人的工作。版本控制是机器学习和人工智能领域治理的重要组成部分。
合作
VCS 让开发人员可以在不同时间、不同地点轻松共享、编辑、查看和合并代码。没有 VCS,事情会变得非常复杂,代码会很快出错。VCS 成为一个公共枢纽或中心,船上的每个人都可以在这里监控项目的进展。
存储版本
假设您对程序进行了必要的修改,现在您已经将它合并到生产代码中了。是时候正确地存储那些更改了,用正确的版本名保存文件(例如- profile-redesign-v102)。如果你添加了又长又复杂的版本名,你将来会迷路的。最好保持简单,采用带有一些语义信息的字母数字格式,以便在需要时可以很容易地跟踪。更新文档在软件世界中非常重要。没有适当的文档或自述文件,开发人员就无法跟踪进度。VCS 记录了从第一天开始所做的所有更改,你可以请求任何你想要的版本,并且可以与当前版本进行比较。
审查和备份
每次你推送或者合并代码时,你都必须添加简短的信息关于做了什么改变。这将有助于每个在程序上工作的人知道这个特定的文件已经被改变了。版本控制系统是备份你的文件和代码的最好方式。你可以随时获得完整的更新代码,不会有任何问题。
更快的改进
当推出一个新版本的机器学习模型时,你开始知道它有一些问题或在特定点上失败了。拥有代码的所有记录将帮助您恢复先前的代码,并给你足够的时间来处理问题,同时产品代码保持无 bug。
复杂性
使用标准 VCS 时,您只需跟踪代码文件、文档和文件依赖关系。对于机器学习来说,这是一件不同而复杂的事情,你必须跟踪你的数据集、模型和不同的参数。你必须留意哪些数据用于训练,哪些用于测试。大多数时候,ML 项目中使用多种语言和框架工具,因此跟踪依赖关系成为一项关键任务。开发人员需要时间将模型投入生产,直到他们对性能有信心。VCS 帮助开发者在合适的时间推出版本。
管理
版本控制是机器学习和人工智能治理的重要组成部分。它帮助公司理解工作流,授予访问权限,执行策略,跟踪和控制所有机器学习工作及其结果。如果管理得当,组织可以收集任何可能影响模型性能的信息。
数据
随着时间的推移,数据管道会发生变化。您必须不断训练您的模型,这就是版本控制的范围。您必须跟踪与您的 ML 工作流相关的所有元数据和结果。元数据将帮助您了解数据集中特定值的性质。以正确的格式将所有数据放入模型非常重要,因此元数据必须有正确的版本。
使用 VCS,您可以将数据值连接到特定版本的相应元数据。这有助于开发人员找到数据集和值中的差距。
模型
所有的 ML 项目领导者都想提高他们的 ML 模型的准确性。如果事实证明之前的版本更准确,VCS 会让你快速回到那个版本。
连续累计
持续集成(CI)是一种将功能分支实现到主代码中的方法,可以自动构建和测试。该流程帮助开发人员定位问题并快速找到解决方案。快速失败,快速改进— 这就是 CI 集成帮助您做到的,它提高了您工作流程的质量。
参见—利用机器学习项目改善工作流程的最佳 7 种数据版本控制工具
如何做版本控制
饭桶
最受欢迎的 VCS。世界上大多数开发者都使用 Git。它跟踪对代码文件所做的所有更改,以便您有一个记录。如果当前代码出现问题,您可以很容易地返回到特定的版本。Git 有一个易于管理的协作系统。
Git 的优势:
Source: Author
性能—这是一个易于维护且可靠的版本控制系统。您可以查看和比较在特定时间内对代码所做的更改,并合并它们。
- 灵活性–Git 支持多种开发方法和工作流,旨在处理小型和大型项目。它支持分支和标记操作,以存储对项目所做的每个更改。
- 广泛接受–Git 因其可用性和性能标准而被普遍接受。
- 沙箱
沙盒是一个团队可以构建、测试和部署程序的环境。在沙盒环境中,代码被分成更小的组或单元。Jupyter Notebook 是 ML 沙盒的最佳工具。有时沙盒环境是测试 IT 解决方案的最佳方式。沙盒在项目集成、用户演示和测试以及质量保证方面帮助你。它为机器学习生命周期的每个阶段都提供了功能,而不仅仅是测试阶段。
沙盒环境的优势:
易于使用的工作流程—无缝开发、测试和部署版本。您可以只编辑几行代码并测试它们,而无需推送整个文件/项目。
- 协作—分享并让每个人了解项目的最新进展至关重要。你可以用很少的权限获得关于程序的反馈和更新。你可以在著名的技术上工作,而不会有任何复杂的架构。
- 经济高效–沙盒环境是一种按需付费的服务,因此维护您的工作流程变得很容易,并为您的公司节省了大量资金。
- 数据版本控制
数据版本控制(DVC)是一个用于机器学习和数据科学项目的开源工具,这是给你的人工智能项目版本化的最佳方式。它类似于 Git,但是有选项来跟踪步骤、依赖项、数据文件和更多的。它帮助您存储大型数据集、模型和文件。
DVC 的好处:
独立于语言—ML 流程可以无缝转换为任何语言的可复制管道。
- 易于安装–DVC 是一款开源工具,您可以通过简单的命令轻松安装:
- 数据共享——你可以在任何云平台上共享你的 ML 数据文件,比如亚马逊网络服务或者谷歌云平台。
pip install dvc
- 数据合规性–根据 Git 拉取请求监控数据修改工作。检查项目完善且不可更改的记录,以了解数据集或模型何时获得批准,以及批准的原因。
- 使用 Neptune 进行版本控制
Neptune 是为研究和生产团队开发的 MLOps 的元数据存储。它为您提供了一个记录、存储、显示、组织、比较和查询机器学习生命周期中生成的所有元数据的中心。研究人员和工程师使用海王星进行实验跟踪和模型注册,以控制他们的实验和模型开发。
让我们从初始化 Neptune 开始:
文件数据版本:
import neptune.new as neptune
run = neptune.init('USER_NAME/PROJECT_NAME',
api_token=’ANONYMOUS’)
文件夹数据版本:
from neptunecontrib.versioning.data import log_data_version
FILEPATH = '/path/to/data/my_data.csv'
with neptune.create_experiment():
log_data_version(FILEPATH)
S3 桶数据版本: (可以记录版本和具体密钥,类似于文件版本控制)
from neptunecontrib.versioning.data import log_data_version
DIRPATH = '/path/to/data/folder'
with neptune.create_experiment():
log_data_version(DIRPATH)
前缀: (您可以跟踪多个数据源,只需确保在登录前使用前缀)
BUCKET = 'my-bucket'
PATH = 'training_dataset.csv'
with neptune.create_experiment():
log_s3_data_version(BUCKET, PATH)
用子文件夹记录镜像目录快照: (用 log_image_dir_snapshots 可以记录镜像目录的可视快照;查看该实验了解详细信息)
from neptunecontrib.versioning.data import log_data_version
FILEPATH_TABLE_1 = '/path/to/data/my_table_1.csv'
FILEPATH_TABLE_2 = '/path/to/data/my_table_2.csv'
with neptune.create_experiment():
log_data_version(FILEPATH_TABLE_1, prefix='table_1_')
log_data_version(FILEPATH_TABLE_2, prefix='table_2_')
版本控制最佳实践
from neptunecontrib.versioning.data import log_image_dir_snapshots
PATH = '/path/to/data/my_image_dir'
with neptune.create_experiment():
log_image_dir_snapshots(PATH)
使用良好的提交消息
一个好的提交消息将帮助其他开发人员和团队成员理解你更新了什么。添加一个简短的信息描述会使事情更容易回顾。
让每一次承诺变得重要
确保你的承诺是有目的的,而不仅仅是你工作的备份。添加新功能或修复问题。尽量不要在一次提交中进行多次更改,因为这将很难审查。
在这个过程中,您可能会发现一些 bug,也想修复它们。如果您想一次提交一个文件,下面是针对不同 VCS 的命令:
Git: git commit filename1 filename2
提交两个命名文件。
- SVN:
svn commit filename filename2
提交两个文件。它将所有更新的文件提交到目录中。 - 如果您想要保存一个支持多个变更(例如多个特性)的文件,那么您必须在逻辑块中引入它们,并在进行过程中进行提交。每个 VCS 都支持此操作:
Git:将文件名存储到一个安全的临时位置,然后运行 git checkout 文件名将文件名恢复到其未更改的状态。
- svn:将文件名移动到一个临时位置,然后运行 SVN 更新文件名T3,将文件名恢复到不变的状态。
- 不要破坏构建或强制提交
尝试通过执行完全提交来避免中断构建。您可以为您的提交和新 API 准备测试用例。这有助于其他团队成员在不破坏构建的情况下使用这些文件。假设你正在开发某个 API,它在你的机器上运行得很好,但是在另一台机器上可能会崩溃。另外,如果 VCS 没有推送你的更新或者显示错误信息,最好不要 强行提交任何东西。这可能会打破整个工作流程,把事情搞得一团糟。
审查和分支
每当您提交代码并将其推送到中央存储库时,请确保您做了很好的审查。这将帮助您理解提交,并找到提交中的问题或差距。
在许多情况下,分支有助于改进工作流。它有一些缺点,但是如果您使用良好的分支实践,您可以使管理代码、发布、里程碑、问题、新特性等等变得容易。
进行可跟踪的提交
出于安全和监控的目的,您需要存储关于提交的信息,比如审阅者评论、关于提交的信息、作者详细信息等等。这将确保如果需要,任何提交都可以被撤销。分析问题后,可以重新应用或更新更改。
结论
版本控制系统是监控和跟踪所有代码文件、数据集、依赖项、文档和项目的其他关键资产的变更的最佳方式。
有了 VCS,每个团队成员都在同一个页面上,协作更顺畅,工作流更好,错误更少,开发速度逐渐加快。
额外研究和推荐阅读
Additional research and recommended reading
机器学习和数据科学的版本控制
原文:https://web.archive.org/web/https://neptune.ai/blog/version-control
版本控制跟踪和管理相关实体集合中的变更。它记录了一段时间内的更改和修改,因此您可以调用、还原、比较、引用和恢复任何您想要的内容。
版本控制也称为源代码控制或修订控制。每个版本都有一个时间戳,以及对文档、计算机程序、文件等进行修改的人的 ID。
各种应用程序类型都嵌入了版本控制的概念,如 Sharepoint、Word、电子表格、Photoshop 等等。版本控制防止了并发工作中的冲突,并为更好的决策和促进兼容性提供了一个平台。
版本控制系统(VCM)作为独立的软件工具运行,它实现了一种系统化的方法来跟踪、记录和管理对代码库所做的更改。它促进了平滑和连续的变化流。
在本文中,我们将从不同的角度探索版本控制意味着什么。
版本控制系统的类型
版本控制系统有三种主要类型:
- 本地版本控制系统
- 集中式版本控制系统
- 分布式版本控制系统
本地版本控制系统
这个版本控制系统由您计算机上的本地数据库组成,该数据库将每个文件更改存储为一个补丁(文件之间以唯一格式的差异)。要重新创建文件,需要随时添加各种补丁。
这种系统的一个流行的例子是修订控制系统(RCS ),至今仍分布在许多计算机中。这种系统的一个缺点是变化的本地存储。如果本地磁盘/数据库损坏,所有修补程序都会受到影响。此外,在这个系统中的协作是复杂的,几乎是不可能的。
Local Version Control System | Source: Gitlab
集中式版本控制系统
该系统有一个存储不同文件版本的中央单一服务器。该系统由服务器和客户端组成。多个客户端可以同时访问服务器上的文件,将文件的当前版本从服务器下载到本地计算机,反之亦然。
只有一个存储库包含所有的历史。这种方法支持协作,并且很容易跟踪项目中团队成员的角色。每一个更改都传到中央服务器,并立即影响主代码,因为这是一个简单的提交和更新过程,所以主代码将投入生产。
由于所有东西都存储在一个中央服务器上,如果服务器被损坏或破坏,除了人们碰巧在本地机器上拥有的单个快照之外,丢失项目的整个历史的风险很高。集中式版本控制系统的例子有微软 Team Foundation Server (TFS)、 Perforce 和 Subversion (SVN)。
Centralized Version Control Systems | Source: Gitlab
分布式版本控制系统
在这个系统中,没有中央存储库,而是多个存储库。每个客户端都有自己的服务器,并完全镜像/克隆存储库,包括其整个历史。这个系统使得每个合作者都是整个项目的本地副本,使得本地和离线工作都很容易。
提交变更对于客户端的本地存储库是唯一的,并且需要将其推送到中央存储库(这是权威的)。为了让其他团队成员获得变更,他们必须在有效地进行更新之前提取那些变更。
如果服务器变得不可用、损坏或被破坏,任何客户端的存储库(正确的副本)可以将项目版本的副本分发或发送回服务器或任何其他客户端。分布式版本控制系统的例子有 Git 和 Mercurial 。
Distributed Version Control Systems | Source: Gitlab
版本控制系统的好处
- 高效的团队协作和并发性,因为多个人可以同时在一个给定的项目上工作。分支和合并的概念推动了这种合作。
- 对给定项目的所有变更/修改的可追溯性的访问。这种可追溯性支持根本原因分析、取证分析以及针对停机、崩溃或数据丢失的保险。它帮助管理源代码和资产。
- 它促进团队同时工作的有效整合,并减少错误和冲突的可能性。
- 它作为跨数字资产、团队和源代码的单一真实来源(SSOT)。
- 它使客户能够利用多台计算机来处理一个项目。
- 它提高了开发速度,因为在持续集成(CI)的帮助下,改进被更快地合并。它还通过与团队结构更好的沟通来加速产品交付。
软件工程与数据科学中的版本控制
软件工程和数据科学没什么不同。有一些适度重叠和相互关联的领域在许多方面是相似的。其中一个相似之处是版本控制的概念。
在软件工程中,版本控制系统(VCS)管理、跟踪和存储源代码、工件(软件开发的副产品)和文档的历史和状态。如今,软件开发人员逐渐地将他们的项目提交给一个版本控制系统,如 Git ,通常带有有意义的提交消息。版本化源代码是标准做法。
另一方面,数据科学更多的是一种探索性的工作方式。将数据科学产品化包括将探索性分析的见解转化为可扩展的模型,以推动数据和人工智能驱动的产品以及提供价值的服务的构建和发展。
在将这些产品和服务产品化的过程中,这些工件变得比依赖于数据集、模型、指标和参数的文件更加复杂。你必须了解各种工件的变化,以构建可靠和健壮的数据和人工智能驱动的应用程序。
为了理解数据科学中的版本控制和各自的工件,让我们使用一个激励性的例子——推荐系统来进一步讨论。
推荐系统是信息过滤系统,它试图向最终用户推荐相关的和感兴趣的信息。该建议考虑知识和数据,以充分预测最终用户将分配给项目的偏好或评级。
推荐系统过滤大量的内容,并向用户提供个性化的推荐。当我们浏览网飞、Youtube、Spotify、亚马逊、Linkedin、Pinterest 等网站时,我们一直在使用它们。
网飞有一个强大的推荐系统,占据了 T2 80%的顾客观看的内容。机器学习使用跨领域的数据输入来推动这些建议:
- 用户的人口统计数据,如年龄、性别、位置和注册时选择的喜爱内容
- 用于流式播放电影的设备类型
- 电影的完成率和时间
- 搜索和结果的频率
- 重新看电影
- 电影暂停、倒带或快进
- 信用计算
- 观看节目的性质
- 观看历史和时间戳
- 评级
- 浏览和滚动行为
推荐引擎基于用户偏好使用一些预定义的推荐聚类来过滤标题。机器学习组件频繁更新,并启动各种实验。随着用户不断生成数据,模型的新更新可能每天或每隔几分钟发布一次。
不同的用户倾向于将其他模型的结果视为 A/B 实验或 canary 发布的一部分。这些更新挑战了找出哪个模型做出了特定的预测,或者哪个数据产生了特定的模型。
让我们讨论一个假设的情况,其中网飞推荐引擎向未成年人推荐 18+评级的电影。网飞机器学习工程师将很快开始调查这种推荐模式,因为它带来了一个潜在的问题,可能会对公司品牌产生负面影响,并可能吓跑客户。
首先,探讨这个问题,需要先重现。对于存储在某个数据库中的客户数据,第一个问题是:如果我们再次使用相同的输入,我们会得到相同的结果吗?我们能重现结果吗?如果不能,为什么?
机器学习操作中是否存在不确定性,如预处理、特征选择/提取或工作流的其他部分?或者预测被调查实例的模型有更新吗?
我们需要跟踪和识别所使用的模型版本。我们需要知道我们是否在进行实验,以及客户是否参与了任何可能产生不同模型的特定实验。我们还能接触到那个模型吗?我们是否记录了测试阶段,谁批准了发布?模特被链子拴着吗?这些只是我们可以在模型方面提出的一些问题。
假设我们找到了做出预测的模型,这将引出更多的问题,比如用什么数据来训练和测试模型?机器学习库的所有版本是什么?使用了哪些超参数来调整模型?如果要重复培训,我们会得到同样的模型吗?
现在,让我们进一步假设我们已经确定了用于训练的确切数据集;这也会引发一些问题。数据的来源是什么?什么版本的代码带有哪些预处理步骤?数据集是另一个模型的输出吗?谁参与了数据修改?
监控和追溯数据、模型和管道代码的来源和血统至关重要。无论是出于问责、调试还是调查目的,澄清以下问题(不仅仅是这些)都是至关重要的:
- 我们能复制我们正在调查的观察结果吗?
- 我们能识别生产中不同模型的输入吗?
- 我们能跟踪生产中使用的不同模型版本吗?
- 什么数据被用来训练和测试一个给定的模型?
- 我们能重建模型吗?
- 是否应用了模型链?如果是,它们各自的版本是什么,基于哪些数据?
- 数据来源是什么?
- 数据是如何预处理的?
- 用于调整模型的超参数是什么?
- 模型的学习代码是什么?
版本控制数据
在我们用不同的策略探索数据版本化之前,让我们讨论一下什么是“数据起源”。数据起源只是简单地跟踪数据的起源和历史上的变化。数据起源也称为数据血统。
这些变化来自机器学习管道中的处理/编辑步骤,如数据获取、合并、清理、转换学习和部署。数据来源不足会产生“可见性债务”(对数据依赖和历史的模糊可见性)。
数据来源还包括跟踪谁进行了数据更改或修改的治理和管理。数据由作为输入的独立变量组成。我们还需要跟踪训练和测试数据中的特性是如何变化的,因此产生了特性起源的概念。
对数据进行版本控制的一些策略如下:
- 缓存数据集的副本:在这里,对数据集的每次更改都会存储整个数据集的新副本。这种策略提供了对单个数据版本的轻松访问,但是对大数据的小更改的内存限制将需要额外的存储。通过给定目录中文件的命名约定,这种策略很容易实现。VCS 使用这种策略的一个很好的例子是 Git 。
- 存储数据集之间的差异:由于上面讨论的内存限制,这种策略只存储版本之间的变化。这些更改或差异存储在修补程序中,因此恢复到特定版本需要将所有修补程序添加到数据集中。VCS 使用这种策略的一些好例子是 Mercurial 和 RCS 。
- 存储单个记录上的更改:这里,不是保持对整个数据集的修改,而是关注单个实例/记录。这种策略是通过让每个记录都有单独的历史文档来跟踪每个记录的变化来实现的。实现方法是为每个记录创建一个单独的文件,该文件组合起来形成一个“每个记录的单独历史”目录,该目录跟踪单个零件的所有更改。几个数据库可以跟踪个人级别(或基于案例)的变更的起源信息。这种方法很容易在结构化数据上实现。利用这种方法的一个很好的例子是亚马逊 S3 桶。
- 仅附加数据集中的偏移:这与现有数据不可变且新数据的变化需要被附加到现有数据的理论一起工作。这里,文件大小(偏移量)用于跟踪变化。这种策略需要用于只附加数据,如事件流或日志文件。这是最简单的数据版本化形式。使用这种技术的系统的一个很好的例子是阿帕奇卡夫卡。
- 版本化管道以重新创建衍生数据集:该策略涉及版本化原始数据集和机器学习管道中的所有过程/转换步骤(数据清理、集成、争论、平滑、编码和归约阶段)。按需重新创建数据比保存数据更有效。
策略的选择取决于数据的大小、结构和更新频率。关于存储数据(存储空间)和重建数据(计算工作量)的成本,在不同的方法之间存在权衡。将可用的元数据与数据一起版本化也是最佳实践。
版本化机器学习模型
由于涉及快速实验和迭代的数据科学或机器学习项目的探索性和协作性,跟踪模型历史对于理解和改善这些开发模型的性能至关重要。就像数据一样,模型起源是关于跟踪模型输入、超参数,以及学习具有依赖性、算法选择和架构的代码。这些模型通常是大型二进制数据文件,因为它序列化其参数。
如前所述,机器学习操作是一个寻找最佳模型的迭代过程。在大多数情况下,超参数或数据的微小变化会导致几个模型参数的变化,从而导致不同的模型。
不同的模型不共享结构或参数,因为它们可以通过各种机器学习算法来创建,所以基于它们作为数据的差异来跟踪模型不会完全用于有意义的分析或存储。因此,跟踪这些二进制文件的版本只需要像 Git 和 DVC 这样的存储副本策略就足够了。
版本控制机器学习管道
机器学习流水线是一种工作流,具有各种相互依赖的顺序阶段,这些阶段导致机器学习模型。这里,我们希望跟踪不同阶段的学习代码,例如数据预处理、特征提取和工程、模型训练和超参数优化。这种版本控制对于模型起源是至关重要的。
这些管道代码和超参数表现为脚本文件和配置文件,可以像传统源代码一样进行版本控制。跟踪框架和库版本对于确保可再现性和避免依赖关系的浮动版本也是至关重要的。这些库和框架依赖项可以使用包管理器(如 pip 来创建 requirements.txt 文件)进行版本控制。
此外,管道代码和依赖关系也可以打包在虚拟执行环境中,以确保跟踪环境变化。Docker 就是一个很好的例子。
版本控制机器学习实验
机器学习中的实验是在不同条件下的各种运行,例如系统地改变变量和参数。它由代码、数据和模型元素组成,这些元素可以被编码成管道代码或元数据。不过,在这里,额外的重点是比较结果和可视化实验结果。一些实验适用于笔记本(如 Jupyter notebook),而其他时候更精确的跟踪可能会有所帮助,特别是在探索建模选项及其交互时。
Neptune 是一个很好的例子,它在脚本(Python,R 等)中帮助有效的实验跟踪。)和笔记本(Jupyter notebook,Google Colab,AWS SageMaker)。
机器学习中再现性和可复制性的概念
“再现性”是科学中的一个中心话题,有助于验证研究结果,改进他人的工作,并避免重新发明轮子。它可以被看作是重新创建一个与原始实验差异较小的实验,并且仍然获得相同的定性和定量结果的能力。
根据美国国家科学基金会(NSF)的说法,“再现性是指研究人员使用与原研究人员相同的材料复制先前研究结果的能力”。
这个概念验证结果并确保计算的透明性、一致性、可信度、审计和指导调试。当复制发表在机器学习论文中的结果时,很容易观察到这种概念的低效。根据 Goodman 等人[1],有三种类型的再现性:
- 方法再现性:这是用相同的数据和工具尽可能精确地实施实验和计算方法,以获得与原始工作相同的结果的能力。
- 结果重现性:在新的独立研究中产生确证结果的能力遵循相同的实验程序。
- 推论再现性:不同研究者在调查一组结果后得出同一组推论的能力。
另一方面,“可复制性”是通过完全相同的实验来复制结果的能力。可复制性要求工作流中没有非确定性。
这两者在数据科学中都很重要,因为再现性有助于在各种环境中找到一致的结果,并提高系统的可信度、透明度和信心。而可复制性可以指导 apt 调查和调试,因为工件可以被重新创建和理解。
版本控制的各个方面极大地促进了可再现性和可复制性。这个概念也增加了每个持续集成或持续交付周期(CI/CD)的价值,因为它有助于平稳的活动平稳地流动。良好的编程和版本管理实践对于机器学习中的再现性和可复制性的文档化是必不可少的。
结论
我们已经探索了与数据科学/机器学习中的指南版本化相关的各种概念,涵盖了监控和跟踪数据模型、管道代码和实验中的变化的策略。希望这能帮助你理解版本控制是怎么回事。感谢阅读!
参考
- 古德曼、史蒂文·n、丹尼尔·法内利和约翰·帕·约安尼迪斯。“研究再现性是什么意思?”科学转化医学 8.341 (2016): 341ps12-341ps12
- 技术债务和可见性债务:斯卡利,大卫,加里霍尔特,丹尼尔戈洛文,尤金达维多夫,托德·菲利普斯,迪特马尔埃布纳,维奈乔德里,迈克尔·杨,江泽龙克雷斯波,丹丹尼森。“机器学习系统中隐藏的技术债务”。神经信息处理系统进展,第 2503–2511 页。2015.
- https://www . kdnugges . com/2019/09/version-control-data-science-tracking-machine-learning-models-datasets . html
最佳顶点 ML 元数据替代方案
原文:https://web.archive.org/web/https://neptune.ai/blog/vertex-ml-metadata-alternatives
去年,谷歌宣布了 Vertex AI ,这是一个新的托管机器学习平台,旨在让开发者更容易部署和维护人工智能模型。那么,Vertex AI 有什么好处和坏处呢?在本文中,我们将讨论 Vertex AI,并看看它的替代品,但首先,让我们看看为什么需要这样一个工具?
表征数据集、计算环境和模型的信息称为元数据。简单来说,这是一个一站式商店,提供您构建和部署机器学习模型所需的所有信息。这对 ML 再现性至关重要;没有元数据存储,如果您不记录和保存信息,您将无法重新创建测试。ML 元数据存储将帮助您:
- 跟踪所有实验 和模型元数据。
- 提供工具可视化和比较实验。
- 记录所有可能相关的元数据。
- 获取有关代码、数据、参数和环境版本的信息。
- 分析、监控并提醒您是否检测到模型输入/输出分布的任何意外变化。
数据和工件谱系、再现性和可比性都是通过收集关于每个 ML 管道运行的数据来辅助的。当项目从开发过渡到生产时,再现性确保了数据的一致性和错误的减少。它也有助于调查故障和异常。通常,ML 元数据存储将记录以下元数据:
- 使用的管道和组件的版本。
- 开始和结束日期,以及管道完成每个阶段所需的时间。
- 作为参数提供给管道的参数。
- 在模型评估过程中为训练集和测试集生成的模型评估度量。在模型验证过程中,这些指标允许您将新训练的模型的性能与先前模型的性能进行比较。
- 在模型评估过程中为训练集和测试集生成的模型评估度量。
Basic workflow of Metadata Store | Image by author
顶点人工智能
谷歌推出了 Vertex AI,这是一个新的统一机器学习平台,使用谷歌的人工智能技术来帮助你更快地部署模型。 Vertex AI 将用于机器学习开发的谷歌云服务结合到单一的 UI 和 API 中。 Vertex AI 允许您使用 AutoML 或自定义代码轻松训练和比较模型,并且您的所有模型都保存在单个模型库中。
*Vertex AI Dashboard | Screenshot by Author *
顶点人工智能的特点
有了 Vertex AI,作为最终用户,您现在拥有了一个单一的工作流,它包含了从实验到部署的整个开发生命周期。以下是 vertex AI 的一些功能:
- 支持所有流行的开源框架。
它通过定制的训练和预测容器支持几乎所有的 ML 框架。这允许您以同样的方式对待所有的模型,不管它们是定制的还是用 AutoML 创建的。
您可以获得针对视觉、视频等内容的预训练 API,这不仅是为了简化流程,也是为了提高效率。您可以简单地将它们集成到您现有的应用程序中,或者使用它们创建一个新的应用程序。因此,您可能不需要寻找额外的 AI API 平台来完成您的任务。
- 数据到人工智能的无缝集成
BigQueryML 被广泛用于开发和执行使用 SQL 查询的机器学习模型,这并不奇怪。您将能够访问它并将数据集导出到平台中,以便使用 Vertex AI 将其与流程连接起来。因此,您将拥有端到端的集成。
- 简化的机器学习过程
您将能够利用 AutoML、Explainable、Edge Manager 等工具来处理 ML 模型。把所有东西都放在一个地方应该会改变游戏规则。您还可以使用自定义代码进行训练,同时将所有内容保存在一个地方。
Vertix AI 提供的工具有:
- 模型监控
- 匹配引擎
- ML 元数据
- 张量板
- 管道和更多的东西。
Vertex AI 使用 MLMD 原理来存储元数据。它将元数据呈现为一个可导航的图形,节点代表执行和工件,边连接它们(如下图所示)。执行和对象由上下文进一步连接,上下文由子图表示。顶点 ML 元数据将有助于运行分析、ML 实验和 ML 工件的跟踪等。让我们看一下用来记录元数据的一些最重要的实体。
- 史前古器物
- 实行
- 事件
- 内容
Vertex AI: example lineage graph | Source
顶点人工智能的局限性
Vertex AI 提供了许多好的特性,但它仍然有一些缺点,这可能是许多人担心的原因:
顶点元数据基于 ML 元数据,而 ML 元数据没有客户端 python SDK,而客户端 python SDK 是临时训练操作(例如在笔记本中)所必需的。通过使用临时操作,组织可以节省时间、金钱并减少 IT 工作量。它目前缺乏诸如自动化调试、模型注册、模型工件编译和 Kubernetes 支持等特性,这可能是一些用户的障碍。它也缺乏同步在线和离线功能的能力。
作为新用户,你将有几个月的免费等级,但之后,你将不得不按需付费。与其他解决方案相比,Vertax AI 相对昂贵,随着客户使用更多服务,价格可能会大幅上涨。你必须为其他用于模型监控的谷歌云产品付费,比如 BigQuery storage 或者 Batch Explain。Vertex ML 元数据存储费用从每月 10 美元每吉字节(GiB)开始,如果您使用其他功能,费用可能会增加。你可以在这里找到完整的价格信息。
顶点人工智能元数据目前只能在生产管道中使用。它允许您将 GPU 加速器链接到现有的 CPU 实例,但是它还不支持 A100 实例类型。
- 文档&开发者指南
尽管 Vertex AI 已经推出了一段时间,但很难在网上或开发者社区网站上找到解决方案。由于该产品不是为中小型企业设计的,团队需要可靠的文档和教程来开始。
无论您是有一个成长中的团队,打算扩展和升级现有的解决方案,还是想要向您的产品线添加额外的 ML 解决方案,元数据存储都是实现速度、自动化和智能洞察的理想方式。元数据在机器学习中非常重要,因为它可以帮助您:
- 伪像跟踪
- 对模型审计试验的法律遵从性
- 热身训练
- 跟踪模型签署
- 从以前的错误中学习
以下是您在选择 Vertex ML 元数据替代或任何元数据存储时应该考虑的事项。
1.跟踪能力
您将跟踪超参数、模型、代码、资源、见解等等。元数据存储应该提供各种各样的跟踪功能,包括数据版本控制、跟踪数据和模型血统、源代码版本控制,甚至是测试和生产环境的版本控制。因此,请确保您选择的工具包含项目所需的所有追踪功能。
2.集成
为了捕获在管道的每个阶段创建的生活元素,理想的元数据存储应该能够与所有主要或最重要的工具和框架集成。
3.轻松协作
为了设计一个成功的 ML 解决方案,开发团队、运营团队,甚至商业团队都需要协作。元数据存储应该是可靠的,并允许团队成员之间的简单协作。对于团队在 ML 实验中的合作,你使用的工具应该提供这样的条款。
4.详细见解
虽然元数据存储在不同阶段收集数据,但它也应该提供智能见解,从而加快测试并增强报告。理想的元数据存储平台应该能够为开发人员提供动态可视化,他们可以定制这些可视化来说明管道数据的独特重点领域。
5.可视化
一个像样的视觉表现将使其更容易评估结果。它简化了复杂的概念,并允许您向利益相关者传达可视化的结果。它还可以帮助您执行错误分析,并确定需要改进的地方。
由于上面讨论的所有原因,Vertex AI 可能并不完全适合所有人。因此,让我们来看看目前市场上一些具有吸引力功能的顶级解决方案:
Neptune 是一个元数据存储库。它是一个连接 MLOps 工作流的几个组件的工具,比如数据版本化、实验跟踪、模型注册和监控。它简化了模型开发过程中创建的所有信息的存储、管理、可视化和比较
Neptune 提供了一个 Python 客户端库,让用户在他们的 ML 实验中记录并跟踪任何元数据类型,无论这些是在 Python 脚本、Jupyter 笔记本、Amazon SageMaker 笔记本还是 Google Colab 中运行的。
*Example dashboard with logged metadata | *Source
海王星摘要
Neptune 增强了团队对机器学习项目的管理。它的易于使用的界面让您可以汇总跑步记录,保存自定义仪表板视图,并快速与您的团队分享。
-
记录并显示所有元数据类型,包括参数、模型权重和媒体文件。
-
用户界面易于使用,并为分组运行提供了多种选项。
-
比较见解和参数。
-
自动记录代码、环境、参数、模型二进制文件等等。
-
跟踪在脚本、笔记本和任何基础设施上执行的实验。
-
广泛的实验跟踪和可视化功能。
-
您可以监控硬件,让您的实验自动运行。检查您的模型训练运行消耗的 GPU/CPU 和内存量。
-
Neptune 提供了一个 Python 客户端库。
-
它提供了一个非常直观和灵活的用户界面,允许用户以他们选择的方式查看和排列数据。
-
Neptune 保存了大部分元数据及其版本,使用户更容易重新创建模型。
-
它允许与超过 25 种不同的工具顺利集成。
-
性价比高。
TensorFlow 的 ML 元数据(MLMD)是 TensorFlow Extended (TFX)的一部分,后者是一个用于部署机器学习解决方案的端到端框架。每次运行生产 ML 管道时,都会生成元数据,其中包含有关管道组件、它们的执行(例如,训练运行)以及所生成的工件(例如,训练模型)的信息。
MLMD 建筑由三样东西组成,
- 驱动,为执行程序提供所需的元数据。
- 执行器是组件功能编码的地方。
- 结果由发布者存储在元数据中。
MLMD 摘要
- 跟踪管道中组件之间的元数据流动。
- 支持多个存储后端。
- 您可以通过加载相同类型的两个工件来比较它们。
- 它存储关于管道组件血统的元数据
- 它列出了特定类型的所有工件。
- 存储有关管道执行的信息。
- 它有用于存储和检索元数据的 API。
- 存储后端是可扩展和可插拔的。
- 它记录和查询工作流运行的上下文。
这篇教程将帮助你更好地了解 MLMD。
最大似然元数据(MLMD)与顶点最大似然元数据
- Vertex ML 元数据和 MLMD 都是以相同的方式构建的,尽管它们在 API、工作流和其他方面存在一些差异。
- 顶点人工智能是一个企业级人工智能平台,而 MLMD 是一个用于记录和检索机器学习应用相关信息的库。
- MLMD 是一个强大的开源模型调试库。
- 与模型优先视图相比,它优先考虑管道视图。
MLflow 是一个开源的 ML 生命周期管理工具。它帮助数据科学家和 ML 工程师进行实验、部署和模型注册。它可以与各种 ML 库和工具一起使用。它也是一个开源的模型优先的机器学习元数据存储,您可以使用它来监控您的实验或为生产打包模型。
MLflow example dashboard | Source
MLFlow 摘要
- 它可以与任何机器学习库、语言或任何现有代码一起工作。它在任何云中都以同样的方式运行。
- 它以标准化的格式打包了一个 ML 模型,可以被下游工具使用。
- MLflow 的四个主要组件是 MLflow 跟踪、MLflow 项目、MLflow 模型和 MLflow 注册表。
- 您可以使用 MLflow tracking 来存储和查询您的代码和数据实验。
- MLFlow tracking 让您记录工件、度量、参数、来源、时间等等。
- MLflow projects 是一个数据科学包,其中包含可重用和可复制的代码。它还带有一个 API 和一个命令行工具,用于 ML 和数据科学任务。
- 不同类型的 ML 模型可使用 MLflow 模型进行部署。每个模型都存储为包含任意数量文件的目录。
ML 流与顶点 ML 元数据
- 它是一个开源平台。
- MLflow 是高度可定制的。
- 提供实时实验跟踪。
- MLflow 可以与任何云服务提供商合作。
Kubeflow 是一款面向 Kubernetes 的机器学习工具,是开源的。Kubeflow 将数据科学过程中的各个阶段转化为 Kubernetes 任务,为您的机器学习库、框架、管道和笔记本提供云原生接口。
默认情况下,Kubeflow 包含一个元数据组件,用于存储和提供元数据。在管道运行期间,它会自动记录元数据。这使您可以跟踪管道版本、上次更新时间和元数据等信息,以便分析管道运行。
Kubeflow 摘要
- 部署在各种基础设施上是可重复和可移植的。
- 支持多种框架和平台。
- 特别是 kubeflow pipeline 自动记录关于运行的信息,包括工作流工件、执行和沿袭。
- Kubernetes 用户会发现 Kubeflow 非常适合。
- 除了自动跟踪之外,您还可以手动写入元数据服务器以收集其他元数据。
- 它是可扩展的,并提供了广泛的超参数调谐选项。
Kubeflow 与顶点 ML 元数据
- 它是一个开源平台。
- 即使是中小型企业也能从其可扩展性中受益。
- 对于管理和跟踪模型实验、任务和运行,它提供了一个优秀的用户界面。
- Kubeflow 允许用户快速连接到其他平台,如果需要,用户可以轻松地迁移到另一个平台。
Valohai 是一个自动提取数据和部署模型的 MLOps 平台。有了 Valohai,你的团队在生产机器学习方面向前迈进了一大步。其端到端 MLOps 平台使团队能够快速、自信地创建和部署机器学习系统。
Valohai summary
- 您可以使用 Valohai 在任何云或本地系统上进行测试,并且您不必担心任何常规的 DevOps 任务。
- 你用 Valohai 做的一切都在平台上保存和版本化。
- 从模型到测量,一切都可以在你和你的团队之间轻松共享。
- 您可以跟踪您的执行情况主要 KPI,并根据您的独特指标轻松安排它们。
- 从代码中以 JSON 形式发布的任何内容都有可能被捕获为 Valohai 元数据。
- 您可以将执行指标作为时间序列或散点图进行比较。
你可以在 Valohai 网站上找到更多关于这些功能的信息。
瓦罗海 vs 顶点 ML 元数据
- Valohai 提供了一个名为 valohai-utils 的 Python 实用程序库来帮助处理日常的样板文件。
- 它确保过程是一致的,并且团队中的每个人都知道正在发生什么。
- 你可以用图表或表格的形式比较实验的结果。
- 兼容任何编程语言和 ML 框架。
- 您可以选择将元数据下载为 CSV 或 JSON 文件。
Amazon SageMaker 让数据科学家准备、构建、培训、调整、部署和管理所有的 ML 实验。它有一个用户友好的界面,使 ML 工程师和数据科学家的任务变得相当容易。如果您目前使用 AWS,Sagemaker Studio 是理想的选择,因为它为所有 AWS 产品提供了出色的集成支持。
Amazon SageMaker Studio UI | Source
pagemaker studio 摘要
- 它可以与其他 AWS 工具无缝协作。
- 易于使用的界面。
- 您可以跟踪容器的输入和输出。
- 跟踪并可视化数千次实验。
- Sagemaker 包括一个与 robomaker 集成的 python 库,允许两个系统在整个训练过程中进行通信。
- 它带有用于训练和运行你的实验的内置算法。
- SageMaker 有一个内置调试器来帮助你发现和修复问题。
亚马逊 pagemaker vs vertex ml 元数据
- Sagemaker 可以监控容器的输入和输出。
- 它具有可视化指标的能力。
- 它还允许您从较小的实例开始。
- Sagemaker 支持模型注册和模型工件重新编译。
海王星 | ML 元数据 | MLflow | Kubeflow | 瓦罗海 | 著名的专业排版软件 | |
---|---|---|---|---|---|---|
定价 |
个人免费(+免费额度以上使用量),a 学院:免费,团队:付费
| 开源 | 开源 | 开源 | | |
| 特性 |
- 灵活,与其他框架配合良好
t
- 直观的 UI
t
- 易于与团队和利益相关者协作
|
- 存储是可扩展和可插拔的
t
- 允许您存储广泛的元数据
|
- 高度可定制
t
- 完美契合数据科学工作流程
t
- 可与任何机器学习库、语言或任何现有代码
|
- 完美适合 Kubernetes 用户
t
- 高度可扩展
t
- 自动记录关于运行的信息,包括工作流工件
|
- 易用协作特性
t
- 你用 Valohai 做的一切都保存在平台上并版本化
|
- 与 SageMaker 平台
t
- 易于使用的界面
|
| 主持 | | | | | | |
| 超参数跟踪 | | | | | | |
| 输入/输出工件 | | | | | | |
| 视觉对比 | | | | | | |
| 数据集版本化 | | | | | |
让我们快速比较一下这些平台。
最后的想法
元数据是任何端到端 ML 开发过程的重要部分,因为它不仅加快了过程,而且提高了最终管道的质量。
Vertex AI 是 ML 专业人士中比较新的机器学习平台。它有很大的潜力,但也有一定的局限性,这就是为什么企业正在寻找更加开放和简单的集成解决方案。我们讨论了几个 ML 元数据存储,你可以根据你的机器学习需求选择一个。我希望你喜欢这篇文章。
快乐实验!
参考文献和推荐阅读:
可视化机器学习模型:指南和工具
原文:https://web.archive.org/web/https://neptune.ai/blog/visualizing-machine-learning-models
为什么我们需要可视化机器学习模型?
如果你拒绝将决策权交给你并不完全了解其流程的人,那为什么还要雇人来工作呢?没有人知道人类的大脑(拥有一千亿个神经元!)做决定。”–卡西科兹尔科夫
这句话被一些人用来批评最近对可解释人工智能的推动。起初,这听起来像是一个有效的观点,对吗?但是它没有考虑到我们不想复制人类的大脑。我们想建造更好的东西。
机器学习模型正在用万亿字节的数据进行训练,目标是在提高效率的同时做出正确的决策,这一点人类做得相当好。
我们赋予 ML 模型的责任意味着我们需要使它们尽可能透明,否则,我们无法信任它们。
为此,我们需要可视化 ML 模型。为了理解这一点,让我们进入可视化的 5 W:为什么,谁,什么,何时,何地。
机器学习中模型可视化的 5 W
1.为什么我们要可视化模型?
虽然我们已经在概述中对此进行了一些讨论,但让我们试着深入细节。
可解释性
我们需要了解模型的决策过程。在神经网络的情况下,这个问题的程度变得特别明显。
真实世界的神经网络模型具有数百万个参数和极端的内部复杂性,因为它们在训练期间使用许多非线性变换。可视化这种复杂的模型将有助于我们建立对自动驾驶汽车、帮助医生诊断的医学成像模型或卫星图像模型的信任,这些模型在救援规划或安全工作中可能至关重要。
调试&改进
构建机器学习模型是一个充满实验的迭代过程。寻找超参数的最佳组合可能相当具有挑战性。可视化可以加速这个过程。
反过来,这可以加速整个开发过程,即使模型在开发过程中遇到一些问题。
对比&选择
从一组表现良好的模型中选择最佳模型的行为可以简单地简化为可视化模型中提供最高精度或最低损失的部分,同时确保模型不会过度拟合。
框架可以被设计成在单个模型随时间训练时比较单个模型的不同快照,即,比较 n1 个时期之后的模型和 n2 个时期的训练时间之后的相同模型。
教学理念
也许教学是可视化最有用的地方,用于教育新手关于机器学习的基本概念。
可以设计交互式平台,用户可以在其中摆弄多个数据集并切换参数,以观察对模型中间状态和输出的影响。这将有助于对模型如何工作建立直觉。
2.谁应该使用可视化?
数据科学家/机器学习工程师
主要专注于开发、试验和部署模型的人将从可视化中受益最多。
许多从业者已经使用的一些著名工具包括 TensorBoard、DeepEyes 或 Blocks。所有这些工具都为用户提供了对超参数调整、修剪不必要的层等事情的扩展控制,从而允许他们的模型实现更好的性能。
模型用户
可视化可能对其他涉众有好处,可能有一些技术背景,但主要是通过 API 处理模型服务的消费。
例如 Activis,这是一个由脸书开发的可视化分析系统,供他们自己的工程师探索内部部署的神经网络。
这种可视化工具对于那些只希望使用预训练模型来预测自己任务的人来说非常有用。
新手用户
在“为什么”部分,我提到了可视化如何帮助新学生学习什么是机器学习——这一点在这里也是正确的。
这个群体还可以进一步扩大,包括好奇的消费者,他们由于害怕隐私侵犯而不愿使用 ML 驱动的应用程序。
一些基于 web 的 JavaScript 框架,如 ConvNetJS & TensorFlow.js,使开发人员能够为模型创建高度交互式的可探索解释。
3.我们能想象什么?
模型架构
您可以想象的第一件也是最主要的事情是模型架构。它告诉我们有多少层,它们的位置顺序,等等。
这一部分还包括计算图形,它定义了一个模型在历元迭代后如何训练、测试、保存到磁盘和检查点。
所有这些都可以帮助开发人员更好地理解他们的模型内部发生了什么。
学习参数
在训练的反向传播阶段调整的参数属于这一类。
可视化权重和偏差可能有助于理解模型学到了什么。同样,在卷积神经网络中,我们可以看看学习过的过滤器,看看模型学习了什么样的图像特征。
模型指标
每个时期计算的诸如损失、准确性和其他误差度量的汇总统计可以表示为模型训练过程中的时间序列。
通过一组数字来表示模型可能看起来有点抽象,但是,它们有助于在训练时跟踪模型的进展。
这些指标不仅描述了单个模型的性能,而且对于同时比较多个模型也是至关重要的。
4.什么时候可视化最相关?
训练期间
训练时使用可视化是监控和跟踪模型性能的好方法。有很多工具正好可以做到这一点(neptune.ai、weights 和 biases 等),我们稍后将讨论它们。
例如, Deep View 使用其自身的监测指标(如辨别力和密度指标)来可视化模型,这有助于通过在训练阶段早期简单地观察神经元密度来检测过度拟合。
另一个工具 Deep Eyes ,可以识别稳定和不稳定的层和神经元,因此用户可以修剪他们的模型以加快训练速度。
训练后
有一些技术,如属性可视化,用于重新生成一个突出显示重要区域的图像,以及特征可视化,用于生成一个全新的图像,该图像被认为是同一类别的代表。它们通常在训练模型之后在计算机视觉领域中执行。
一些工具,如嵌入投影仪,专门用于可视化由训练过的神经网络产生的 2D 和 3D 嵌入。
同样,如前所述,ActiVis、RNNVis、LSTMVis 等工具也是在培训后使用的,用于可视化甚至比较不同的模型。
5.可视化应用在哪里?
应用领域&型号
可视化已经在自动驾驶、城市规划、医学成像等领域大量使用,以增加用户对模型的信任。
视觉分析系统正在被开发,以更多地了解更难的网络类型,如 GANs,这种网络仅出现了几年,但在数据生成方面取得了显著的成果。
例子包括 DGMTracker 和 GANViz,它们专注于理解 GANs 的训练动态,以帮助模型开发者更好地训练这些复杂的模型。
研究&发展
将可视化与研究相结合,创造了模型可解释性和民主化的工具和框架。这一快速发展领域的另一个结果是,新的作品立即被公开和开源,而不必等待它在某个会议上“正式”发表。
例如,用于实现神经网络的最流行的库是开源的,并且对改进代码库的所有方面都有一致的贡献。
到目前为止,我们已经讨论了进行可视化的所有理论方面,现在让我们来看看最重要的一个方面。
我们如何可视化模型?
当我们谈论可视化模型时,我们实际上是在谈论绘制一幅允许模型学习和得出推论的关键组件的图片。如果我们想象一下,我们就能很好地看到里面:
1.模型架构
模型的设计给出了一个很好的关于数据如何在模型内部流动的想法。将它可视化有助于跟踪在哪个阶段应用了什么操作。
一种流行的方法,特别是在神经网络中,是用一个节点链接图,其中神经元被显示为节点,边权重被显示为链接。由于 Tensorboard 越来越受欢迎,这种方法也正在成为标准。
除此之外,如果你想窥视内部,某些机器学习算法有内置的规定。我们将在下一节中看看这方面的例子。
2.模特培训
监控和观察一个时期接一个时期计算的多个度量(如损失和准确性)有助于在训练阶段跟踪模型进展。
这可以通过将指标视为时间序列并绘制成线图来实现,这一步不需要外部帮助。
另一种方法是使用 Tensorboard 等专门为此目的设计的复杂工具。使用框架的好处是它们非常灵活,交互性强,并且节省你大量的时间。
3.模型推理
推理是从训练好的模型中得出结论的过程。可视化结果有助于解释和追溯模型如何生成其估计值。有几种方法可以做到这一点:
- 可视化实例级观察,对单个数据实例在整个网络中的转换过程及其最终输出进行深入分析和审查。
- 借助混淆矩阵或热图,这可以进一步扩展到识别和分析错误分类的实例。这将允许我们了解特定实例何时会失败以及它是如何失败的。
- 这个阶段的可视化是进行交互式实验的好方法——用输入数据或超参数进行实验,看看它如何影响结果。Tensorflow 游乐场就是一个很好的例子。
到目前为止,我们已经研究了进入可视化世界所需的所有先决条件。现在,是时候将“如何做”部分扩展到实用性,并检查一些工具来完成这项工作。
模型架构可视化
由于决策树的树状结构,它是容易解释的模型。您可以简单地检查分支上的条件,并在模型预测出来时跟踪流程。
有几种方法可以可视化决策树。先说 sklearn 自己提供的。
进行所需的进口。
import matplotlib.pyplot as plt
from sklearn import tree
from sklearn.datasets import load_iris
如你所见,在这个例子中,我们将使用著名的虹膜数据集。
下一步是定义树并使之适合数据。
iris = load_iris()
X, y = iris.data, iris.target
clf = tree.DecisionTreeClassifier(max_depth=4)
clf = clf.fit(x, y)
现在让我们画出拟合的树。
plt.figure(figsize=(12,8))
tree.plot_tree(clf, filled=True, fontsize=10)
plt.show()
这是它从另一端出来的方式。
- 我们的数据集中有 4 个特征,萼片长度、萼片宽度、花瓣长度、花瓣宽度,顺序相同。根节点根据花瓣长度分割整个种群。
- 这导致具有分类样本的叶节点,而剩余的在花瓣宽度上再次分裂,因为相关联的基尼杂质指数仍然很高。
- 这个循环继续下去,直到我们获得具有低 Gini 杂质指数的同质节点,或者达到 MAX_DEPTH。
- 总而言之,我们对分类决策树模型的架构有了一个相当不错的想法。
另一种可视化决策树的方法是使用 dTreeViz 库。它不仅适用于 scikit-learn 树,还支持 XGBoost、Spark MLlib 和 LightGBM 树。
我们来看看它和 sklearn 的功能有什么不同。
首先,库需要通过 pip 或 conda 安装,你可以在这里找到说明。
安装完成后,就可以进行所需的导入了。
from sklearn import tree
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
from dtreeviz.trees import *
定义、拟合和绘制树。
classifier = tree.DecisionTreeClassifier(max_depth=4)
iris = load_iris()
classifier.fit(iris.data, iris.target)
viz = dtreeviz(classifier, iris.data, iris.target,
target_name='variety',
feature_names= iris.feature_names,
class_names=["setosa", "versicolor", "virginica"])
viz.view()
这就是我们得到的。
- 所获得的图传达了与 sklearn 非常相似的含义,但是对于每个决策节点,它更具有直方图的描述性。
- 您可以通过设置参数 fancy=False 来关闭这些图。
- 类似地,在这个库的帮助下,您还可以可视化回归树、特征-目标空间热图和决策边界。
如果您正在处理一个需要可视化的神经网络模型,这可能是一种方法。让我们来看看如何利用它。
与 dVizTree 类似,这个库也依赖于需要安装的 graphviz。你可以在这里找到安装说明。
进行所需的进口。
import keras
from keras.models import Sequential
from keras.layers import Dense
from ann.visualizer.visualize import ann_viz
现在让我们定义我们的神经网络。
network = Sequential()
network.add(Dense(units=6, activation='relu',
kernel_initializer='uniform', input_dim=7))
network.add(Dense(units=4, activation='relu',
kernel_initializer='uniform'))
network.add(Dense(units=1, activation='sigmoid",
kernel_initializer='uniform'))
绘制网络。
ann_viz(network, view=True, title=’Example ANN’)
这就是输出。
- 这很好地概述了我们定义的神经网络模型的架构。
- 我们可以用代码计算每一层中神经元的数量,并看到它正如我们所希望的那样出现。
- 这个库唯一的缺点是它只能和 Keras 一起工作。
我们刚刚看到了一个如何可视化人工神经网络架构的例子,但这并不是这个库所能做的全部。我们也可以使用这个库来可视化一个卷积神经网络。让我们看看怎么做。
首先,像往常一样,我们来定义一下 CNN。
def build_cnn_model():
model=keras.models.Sequential()
model.add(Conv2D(32, (3, 3), padding="same",
input_shape=(32, 32, 3), activation="relu"))
model.add(Conv2D(64, (3, 3), padding="same",
input_shape=(32, 32, 3),activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(512, activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(10, activation="softmax"))
return model
出于可视化的目的,我们保持网络的规模较小。现在让我们画出来,看看我们会得到什么。
- 这确实为我们的 CNN 的设计描绘了一幅很好的图画,所有的层次都描述得很好。
- 您只需要修改网络代码来获得新的可视化。
正如其创造者所描述的那样,Netron 是深度学习和机器学习模型的查看器工具,可以为模型的架构生成漂亮的描述性可视化。
它是一个跨平台的工具,可以在 Mac、Linux 和 Windows 上工作,支持多种框架和格式,如 Keras、TensorFlow、Pytorch、Caffe 等。我们如何利用这个工具?
作为一个独立于操作系统的工具,你可以按照这些的说明将它安装在你的机器上,或者简单地使用他们的 web 应用程序,我们将在这里使用。
让我们想象一下我们为最后一个工具定义的 CNN。我们需要做的就是保存模型,并以. h5 格式或任何其他支持的格式上传保存的文件。这是我们得到的结果:
-
起初,它可能看起来类似于我们用 ANN visualizer 得到的结果,但两者之间有一个很大的区别——Netron 的交互性更强。
-
我们可以根据自己的方便将图表的方向更改为水平或垂直。
-
不仅如此,所有带颜色的节点都是可扩展的,单击它们可以查看各自节点的属性并获得更好的理解。例如,当我们单击 max_pooling2d 时,我们会得到这样的结果:
-
我们可以看到许多属性,如数据类型、步幅大小、可训练性等。可以由此推断出被点击的节点,使它比我们以前的工具好一点。
这个工具主要用于参数化地说明神经网络(NN ),并将这些图形导出到可缩放矢量图形(SVG ),因此得名 NN-SVG。
该工具可以生成三种类型的图形:
- 经典的全连接神经网络(FCNN)图,
- 卷积神经网络(CNN)数字,以及
- 深度神经网络遵循 AlexNet 论文中介绍的风格。
这个工具是托管的,所以不需要任何安装。以下是借助该工具创建的简单神经网络架构的示例:
- 我们有很多选择,比如:
- 边缘宽度与边缘重量成比例,
- 边缘不透明度与边缘权重成比例,
- 边缘颜色与边缘重量成比例,
- 层间距,
- 操纵建筑和重量。
- 所有这些选项都可以让您非常快速地创建直观的插图。
如上所述,我们还可以使用该工具创建卷积神经网络的设计,如下例所示:
- 我们在 CNN 也有一系列的选择,就像我们在神经网络上做的一样。
- 你可以简单地在那里操作架构来得到一个新的输出,这个工具非常具有交互性,是一个非常好的选择。
- 这个工具在为研究和出版物创建网络图方面非常流行。
没有 TensorFlow 的开源可视化工具包 TensorBoard,任何模型可视化教程都是不完整的。我把它留到了最后,因为它很大。在这里,我们将只讨论它在模型架构中的使用,我们将在下一节中继续讨论它。
因此,首先,TensorBoard 安装可以通过这两个命令中的任何一个来完成。
pip install tensorboard
conda install -c conda-forge tensorboard
现在让我们通过在单元格中运行这个命令来将 TensorBoard 加载到我们的笔记本中。
%load_ext tensorboard
加载后,我们必须创建一个日志目录,TensorBoard 将在其中存储所有日志并从中读取,以显示各种可视化效果,之后 TensorBoard 必须重新加载更改。
log_folder=’logs’
%reload_ext tensorboard
现在让我们进行所需的导入并定义我们的模型。在这个练习中,我们将使我们的模型适合 MNIST 数据集。
import tensorflow as tf
from tensorflow.keras.callbacks import TensorBoard
mnist = tf.keras.datasets.mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X train, X_test = X_train / 255.0, X_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')])
model.compile(optimizer='sgd',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
现在我们需要创建一个 TensorBoard 回调,它负责记录所有的事件,然后指定我们创建的日志目录。
callbacks = [TensorBoard(log_dir=log_folder, histogram_freq=1,
write_graph=True, write_images=True,
update_freq='epoch', profile_batch=2)]
最后,我们使模型适合我们的数据,并传入回调,以便以后可以可视化所有内容。
model.fit(X_train, y_train, epochs=5,
validation_split=0.15, callbacks=callbacks)
现在,让我们通过运行以下命令将 TensorBoard 窗口直接加载到 jupyter 笔记本中:
%tensorboard --logdir={log_folder}
接下来,如果导航到 graphs 选项卡,我们将看到以下输出:
这就是我们如何用 TensorBoard 看到模型的架构。
我们已经探索了可视化模型架构的工具和框架,现在让我们进入下一部分——培训可视化。
模型训练可视化
从我们停止的地方继续,在上一节中,我们已经将我们的神经网络拟合到 MNIST 数据集,并检查了“图形”选项卡。但是,事实证明 TensorBoard 中还有许多其他选项卡可供探索。
让我们从“标量”开始。
如下图所示,该选项卡处理一个又一个历元的损失和精度计算图。
下一个选项卡是“图像”。
该选项卡显示权重和偏差。每个图像都有一个滑块,我们可以调整它来显示不同时期的参数。
接下来是“分发”选项卡。
它显示了每个历元上某个密集层的权重和偏差的分布。
“直方图”选项卡的功能与“分布”选项卡类似,只是借助了直方图。
最有趣的选项卡是“投影仪”。它可以可视化任何类型的向量表示,无论是单词嵌入还是图像的 numpy 数组表示。
默认情况下,它使用主成分分析(PCA)将这种可视化绘制到 3D 空间中,但也有其他降维方法的选项,如 UMAP 或 T-SNE。事实上,您可以定义自己的自定义方法。
用 PCA 看起来是这样的。
我们已经讨论了所有的选项卡,但是我们仍然可以使用 TensorBoard 做很多事情,比如可视化训练数据、绘制混淆矩阵或超参数调整,但是它们超出了本文的范围。
让我们看看另一个工具。
Neptune 是一个元数据存储库,可以免费用于个人项目,也可以作为 API 服务使用。
虽然编码部分可以在任何地方完成,但只要代码连接到 Neptune,持续的跟踪和日志记录就会在 Neptune 的 UI 中持续进行,从而简化项目管理。
让我们从安装所需的东西开始:
!pip install -q neptune-client
!pip install -q neptune-contrib
我们将使用与上述示例相似的模型和 MNIST 数据集,因此我们不会重复这一部分。
为了在每个批次和时期之后记录度量,让我们创建一个 NeptuneLogger 回调。这部分类似于我们在前面的例子中创建的 TensorBoard 回调。
from tensorflow.keras.callbacks import Callback
class NeptuneLogger(Callback):
def on_batch_end(self, batch, logs={}):
for log_name, log_value in logs. items():
run["batch/{}".format(log_name)].log(log_value)
def on epoch_end(self, epoch, logs={}):
for log_name, log_value in logs.items():
run["epoch/{}".format(log_name)].log(log_value)
为了将我们的代码连接到 Neptune 应用程序,我们需要一个 API 令牌。要获得 API 令牌,您需要向 Neptune 注册并创建一个项目。那个项目的名字将违背参数项目和对应的 API 令牌违背 api_token。
现在让我们初始化 API。
run = neptune.init(project=YOUR_PROJECT_NAME, api_token=YOUR_API_TOKEN)
现在让我们来处理我们想要记录的任何内容。
EPOCHS = 5
BATCH_SIZE = 32
run["parameters/epochs"] = EPOCHS
run["parameters/batch_size"] = BATCH_SIZE
run[ "sys/name"] = "metrics"
run[ "sys/tags"].add("demo")
太好了!现在剩下要做的就是将我们的 NeptuneLogger 作为 keras 回调函数传递。
history = model.fit(x=x_train, y=y_train,
epochs=EPOCHS, batch_size=BATCH_SIZE,
validation_data=(x_test, y_test),
callbacks=[NeptuneLogger()])
一旦执行完最后一个代码单元,我们就可以进入 Neptune 应用程序的 UI 来可视化我们记录的任何内容。
针对批次绘制的训练准确度/损失。
训练准确度/损失相对于时期绘制。
验证准确度/损失对时期作图。
除了损失和准确性之类的简单指标,您还可以轻松地绘制其他东西,如混淆矩阵或 AUC-ROC 曲线(参见此处的示例)。
虽然这只是一个有限日志记录的演示,但是您可以想象当处理一个涉及一致的再训练和更新的项目时,这个工具使模型的不同方面可视化是多么容易。
如果你正在自己运行一些实验,并且正在寻找一个可视化工具,TensorBoard 是一个不错的选择。海王星更适合那些寻找复杂工具的研究人员,这将使他们能够更深入地研究实验过程。它还提供团队协作功能。
就像 Neptune 一样,这个工具也有助于跟踪、监控和可视化 ML 模型和项目。
首先,在他们的网站上注册,然后通过以下命令安装&登录:
pip install wandb
wandb login
输入 API 密钥后,您应该就一切就绪了。现在,让我们为 Keras 模型创建所需的导入。
import wandb
from wandb.keras import WandbCallback
让我们初始化 wandb 并开始我们的项目。
wandb.init(project=’blog-demo’)
现在我们需要做的就是训练我们目前使用的模型,并将 WandbCallback 传递给 log metrics。
model.fit(X_train, y_train, validation_data=(X_test, y_test),
callbacks=[WandbCallback()], epochs=5)
现在我们可以进入 UI,看看记录了什么。
这只是看一看它可能是什么样子。然而,就像 Neptune 一样,这可以扩展到绘制许多不同的东西,以及基于这些记录的指标比较不同的模型。
TensorWatch 是微软研究院提供的数据科学调试和可视化工具。大多数当前可用的工具遵循“所见即所得”(WYSIWYL)的方法,该方法使用许多预定义的可视化来表示结果。
这可能会导致模型不断变化的问题。TensorWatch 通过将一切都视为流来解决这一问题。对其工作原理的简单描述是:
- 在 TensorWatch 流中写入内容时,值会被序列化并发送到 TCP/IP 套接字,其中包括您指定的文件。
- 在 Jupyter 笔记本中,以前记录的值将从文件中加载,然后 TCP-IP 套接字将监听任何其他未来的值。
- 然后,可视化器监听流,并在值到达时呈现它们。
使用 TensorWatch 的唯一缺点是目前只支持 PyTorch 框架。
让我们从安装开始吧。
pip install tensorwatch
接下来,我们需要安装一个名为 regim 的 Python 包,它允许我们获取 PyTorch 模型文件,并使用少量代码在指定的数据集上运行训练和测试时期。
使用 regim 包,我们可以使用训练数据集来训练一个跨时期的模型,维护一些指标,并对事件进行回调。在每个时期之后,它可以在测试数据集上运行到目前为止训练好的模型,并在其上维护度量。
它为训练和测试周期维护了单独的观察器,所以我们可以分别看到每个周期的度量。port 参数指定其套接字相对于基线端口的偏移量。
git clone https://github.com/sytelus/regim.git
cd regim
pip install -e .
然后,从安装 regim 的文件夹中运行您的培训脚本。
python mnist_main.py
通过 regim 包,我们可以使用训练数据集来训练一个跨时期的模型,维护一些指标,并对事件进行回调。在每个时期之后,它可以在测试数据集上运行到目前为止训练好的模型,并在其上维护度量。
它为训练和测试周期维护了单独的观察器,所以我们可以分别看到每个周期的度量。port 参数指定其套接字相对于基线端口的偏移量。
train = tw.WatcherClient(port=0)
test = tw.WatcherClient(port=1)
现在,让我们绘制几个指标,如训练损失、训练准确性、测试损失和测试准确性。
loss_stream = train.create_stream(expr='lambda d:
(d.metrics.epochf,
d.metrics.batch_loss)', event_name='batch')
loss_plot = tw.Visualizer(loss_stream, vis_type='line',
xtitle='Epoch', ytitle='Train Loss')
acc_stream = train.create_stream(expr='lambda d:
(d.metrics.epochf, d.metrics.batch_accuracy)', event_name='batch')
acc_plot = tw.Visualizer(acc_stream, vis_type='line',
host=loss_plot, xtitle='Epoch', ytitle='Train Accuracy', yrange=(0,))
test loss_stream = test.create_stream(expr='lambda d:
(d.metrics.epochf, d.metrics.batch_loss)', event_name='batch')
test_loss_plot = tw.Visualizer(test_loss_stream, vis_type='line',
host=loss_plot, xtitle= 'Epoch', ytitle='Test Loss', yrange=(0,))
test_acc_stream = test.create_stream(expr='lambda d:
(d.metrics.epochf,
d.metrics.batch_accuracy)', event_name='batch')
test_acc_plot = tw.Visualizer(test_acc_stream, vis type='line',
host=loss_plot, xtitle='Epoch', ytitle='Test Accuracy',yrange=(0,))
test_acc_plot.show()
这是我们得到的结果:
类似地,我们也可以通过以下方式绘制每层的平均重量梯度:
grads_stream = train.create_stream(expr='lambda
d:grads_abs_mean(d.model)',
event_name='batch', throttle=1)
grads_plot = tw.Visualizer(grads_stream, vis_type='line',
title="Weight Gradients",
clear_after_each=True,
xtitle="Layer",
ytitle="Abs Mean Gradient', history_len=20)
grads_plot.show()
下面是渐变的样子。在这一点上,很明显,这些只是我们可以用这个工具做的一小部分事情,还有更多要探索的。由于这个工具仍在开发中,一旦它开始支持更广泛的框架,我们肯定会看到更多。
这个工具是一个荣誉称号,因为它在学习和教育非专家用户关于神经网络的内部机制方面有更多的用途。
这是谷歌提供的基于 Tensorflow 的开源工具。您可以在浏览器中模拟小型神经网络,并在使用它们时观察结果。
看起来是这样的:
-
您可以在分类和回归之间切换问题类型,并修改网络和问题的每个可能方面,从激活函数到多个隐藏层,从使用纯数据集到有噪声的数据集。
-
一旦一切都设置好了,只需点击播放按钮就可以开始训练,之后您可以观察形成的决策边界(模型如何分隔不同的类)。
-
模型训练看起来很有趣,并且给你这个黑箱背后的直觉。
我们已经介绍了相当多的可视化训练工具,让我们进入可视化的最后一部分。
模型推理可视化
这主要涉及解释模型生成的预测,并收集关于它们最初是如何和为什么达到的想法。
我在这个博客的另一篇文章中广泛讨论了这个问题。它涵盖了相当多的工具,可以成为您的 MLOps 工具库的一个很好的补充。
包扎
在本文中,我们涉及了很多领域,从寻找为什么我们首先需要可视化模型的答案开始,到获得大量可以帮助我们创建可视化的工具的实践经验。
我希望这篇文章能帮助你更好地理解可视化,并且下次当你遇到可视化就是答案的问题时,你会利用这里讨论的工具和获得的知识。
未来方向
这里讨论的工具和框架只是所有工具中最流行的。随着研究的快速发展,你应该时刻留意新的工具。
除此之外,始终积极寻找可视化的新用例,在这些用例中,展示模型的图片或插图可能会解决手头的问题。
目前就这些。感谢阅读!
资源
Wasserstein 距离和文本相似性
原文:https://web.archive.org/web/https://neptune.ai/blog/wasserstein-distance-and-textual-similarity
在许多机器学习(ML)项目中,当我们必须决定不同感兴趣的对象之间的相似程度时,会出现一个点。
我们可能试图理解不同图像、天气模式或概率分布之间的相似性。对于自然语言处理(NLP)任务,我们可能会检查两个文档或句子在语义或语法上是否相似。
为了做到这一点,我们需要找到一个函数(或操作)来生成一个“测量”相似程度的分数。这个函数可以采取多种形式,但是在许多任务中出现的一个公共度量是 Wasserstein 距离 (WD)。
在这篇文章中,我们将探索 WD,也称为推土机距离 (EMD),如何用于测量两个不同文本序列之间的相似性。为此,我们将:
- 回顾距离度量,并展示为什么它们对于许多 ML 相关问题是重要的;
- 描述 WD,并展示如何将其应用于广泛的问题;
- 展示如何将 WD 应用于文本相似性问题;
- 最后,将 WD 与其他距离度量(如余弦相似度)进行比较,并讨论 WD 的一些优点和缺点。
希望我的方法可以帮助你理解 WD 是否可以应用到你的特定 ML 项目中。
注:我们不会深究 WD 的数学。我们会在最后提供一些关于数学背后的资源,以防你想深入了解。
距离度量
维基百科告诉我们“ Wasserstein distance […]是定义在给定度量空间 M 上的概率分布之间的距离函数”。为什么它没有提到识别文本序列之间的相似性?
这不是方法的问题,而是我们如何表现问题。如果我们可以将单词表示为概率分布,那么我们可以使用 WD 来识别两个看似不同的领域中的相似性。但是等等,距离函数到底是什么?
距离函数是我们用来测量两个或更多物体之间距离的东西。很简单,但事实总是如此吗?取决于我们测量什么,有些东西比其他东西更容易测量。
我们来想一些琐碎的例子。如果你住在公园附近,想去对面呢?你需要一个度量函数来回答这个问题。想想吧。你可以走到另一端,在这种情况下,你可以走一条几乎完美的直线穿过公园。或者,你可以开车去,但是那样的话你就不能开车穿过公园,而必须使用最近的道路。
因此,我们可以创建距离度量来了解每种情况下需要行进的距离。对于步行选项,我们可以使用勾股定理来创建我们的距离度量,对于驾驶选项,简单的加法就可以了。
好吧,这是一个好的,干净的,明确的问题。这个问题很容易用数学来表示,只是直线和简单的形状。如果一切都那么容易表示,那么对于 ML 工程师来说,生活会容易得多。
如果我们要测量的距离很抽象,很模糊怎么办?假设你想知道爱尔兰和美国之间的距离。这指出了距离度量需要解决的关键问题:如何“表示”被比较的对象(实体)?像国家这样的实体不是简单的形状,它们可以用许多不同的方式来表示。
我们可以把每个国家描绘成它们海岸线之间最近的点,然后从点到点画一条线。或者,我们可以在每个国家找到一个中心点,并表示问题和这些点之间的距离。我们也可以在每个国家随机选择多个点并测量每个点之间的距离,然后得出平均值。我们不能说这些都是“正确”或“错误”的答案,这完全取决于我们如何描述这个问题。
从距离到相似
测量从美国到爱尔兰的距离是一回事,但这与理解如何将 WD 用于概率分布和 ML 问题(如识别文本相似性)有什么关系呢?使用我们之前的示例,让我们回顾一下测量两点之间的距离需要什么:
- 在数学(即公制)空间中表示物体的方法:在公园的例子中,我们在欧几里得空间中使用了直线和矩形。以国家为例,我们用散点图来表示国家。
- 测量空间中物体之间距离的方法:我们使用简单加法或毕达哥拉斯定理来计算公园距离。对于国家,我们使用两点之间的距离或点的样本。
考虑一个概率分布,我们投掷硬币 100 次。这可以用二项式分布来表示。现在,想象一个场景,你有两个硬币,一个是有偏见的,大约有 70%的时间正面朝上,而另一个是公平的,有 50%的时间正面朝上。我们将这些数字放入二项式分布中,我们得到了类似这样的两个图表:
现在我们有:
- 一种表示事件的方法:我们可以用图形表示在公平和偏见试验中我们看到的 100 次投掷硬币的正面数量;
- 测量距离的方法:我们需要一些方法来测量这两个分布之间的距离。我们可以把它看作是找到一种方法来测量一个分布上的每一点到另一个分布上的每一点之间的距离。如果你想象上面的分布是由数以百万计的灰尘组成的,那么我们可以将这个问题重新想象为将灰尘从一堆(分布)移动到另一堆。这样,我们就可以对这些分布的相似程度进行评分。
瓦瑟斯坦距离和移动的泥土!
我们有两个分布,一个代表一系列公平的硬币投掷,另一个代表一系列有偏见的硬币投掷。我们想知道它们彼此有多相似。现在,我们需要一种方法来测量将一个图上的所有点移动到另一个图上所需的距离。您也可以将图表想象成直方图的形式:
想象一下,每个箱子都是由一系列积木组成的。我们希望将这些块从一个发行版转移到另一个发行版。每个木块都有质量,所以我们需要考虑质量和移动的距离。
这与我们之前提到的度量有一点小小的不同,之前提到的度量包括没有质量的单个点,所以我们只考虑了移动它们所需的距离。现在,我们可以测量将图的一部分(一个块)从一个分布移动到另一个分布所需的“功”。
这就像一个成本函数,因为我们希望做最少的工作。正是以这种方式,WD 被称为推土机的距离(EMD)。
我们可以把上面的每一个分布想象成一堆堆的泥土,而不是扔硬币,我们想计算我们需要移动多少才能让一堆和另一堆一样。我们需要做的“工作量”是两堆泥土相似性的度量。工作越少,两堆土,或者分布,或者任何可以用这种方式表示的东西就越相似。
如果我们把所有这些单独的作品加起来,我们可以得到下面的公式:
这是瓦瑟斯坦距离试图计算的粗略近似值。要看这个公式更好的解释,请看这个精彩的视频(但是先把这篇文章看完!).
以上是一种在离散空间中思考这个问题的方法。当你进入连续空间时,你开始看到积分之类的东西,你会看到 WD 的公式更可能是这样的:
WD 或 EMD 可以应用于许多 ML 问题。一旦你可以把你的问题表示成一个度量空间,那么你就可以对它应用 EMD。这方面的一个例子是图像检索。EMD 用于“移动”像素,并通过这样做来识别哪些图像最相似。
深入挖掘 EMD
在我们离开 EMD 并开始研究如何使用 WD 来识别文本相似性之前,有必要看另一个例子来帮助理解 WD 试图计算什么。
EMD 可用于图像处理。我们可以认为图像是由像素表示的,每个像素都有一个代表其亮度的权重。在 RGB 模式中,红色、绿色和蓝色组合在一起,创造出一系列颜色。每个像素都有一个介于 0 和 255 之间的值来表示其亮度。
在下面的图表中,我们表示需要填充的土堆和坑。但是我们也可以认为点代表像素,大小(值)代表它的亮度。所以,这个问题可能是一个图像或一堆土,我们正在试图计算将一个图像转换成另一个图像,或将土从堆中移到坑中需要做多少工作。
红点 y1 到 y4 代表洞,大小就是需要多少土来填。类似地,黑点 x1 到 x8 代表可以用来填充这些洞的土堆。请记住,我们希望移动地球的距离尽可能短,这是我们的成本函数-我们希望做的工作量。
为了填平一个坑,我们需要从最近的一堆土中移走一些土。因此,例如,我们可以将 x1、x2 和 x3 的所有灰尘放入 y1 孔,但我们仍然需要 7 个单位的灰尘来填充它。
我们可以从 x4 开始。下表显示了我们需要从每一堆土中移走的土量以及我们需要移动的距离。
地球 | 孔 | 金额 | 距离 | 工作 |
---|---|---|---|---|
x[1] | y[1] | 1 | 1 | 1 |
x[2] | y[1] | 1 | 1 | 1 |
x[3] | y[1] | 2 | 1 | 2 |
x[4] | y[1] | 7 | 2 | 14 |
x[4] | y[3] | 1 | 3 | 3 |
x[5] | y[2] | 1 | 1 | 1 |
x[6] | y[2] | 2 | 1 | 2 |
x[7] | y[4] | 1 | 1 | 1 |
x[8] | y[4] | 1 | 2 | 2 |
总计 | 17 | 17 | 27 |
这表明,我们总共需要移动 17 个单位的地球,我们所做的功被计算为 27。因此,EMD 计算结果为 2717 = 1.58。
在我们的小例子中,很容易优化最有效的方式来移动地球。但是想象一下在现实生活中,有更多的变量,甚至更多维度的问题,你可以看到手动解决它是如何变得不可能的。
我们需要做更多的计算,模拟每一个可能的场景,然后选择一个需要最小量或最低 EMD 的场景。然而,这个例子有助于展示 WD 的一个简化版本,并很好地让我们看到如何通过嵌入将它应用于文本相似性。
在一堆泥土中寻找意义
距离度量的美妙之处在于,一旦我们找到了表示它的方法,我们就可以将它们应用于任何问题。如果我们可以在一个度量空间中以离散的方式表示某样东西,那么 WD 不在乎它是在移动泥土还是在解析散文。它将完全一样地工作。
单词嵌入非常适合这项任务,因为它们是多维向量空间中的点,也就是我们应用 WD 所需要的点。
我们不会在这里详细讨论单词嵌入,所以你可以看看我以前写的一些关于 NLP 中嵌入概念的文章这里和这里。简而言之,单词嵌入只是基于它们被训练的文本对意义进行编码的向量。在之前的帖子中,我们展示了如何通过在简单的数据集上训练嵌入并将其投影到 3D 可视化效果上来可视化嵌入:
所以,如果我们可以把单词表示为向量空间中的点,那么我们就可以把每个单词看作一块我们想要移动的泥土。同样,这里的关键是用简单的术语把它想成一个距离函数。我需要将一个单词“移动”多少才能使它与另一个单词相似?
这里的假设是,空间中的一个点,无论它代表概率分布上的一个点,一片地球还是一个词,如果它与另一个点之间的距离为零,则认为它是相同的。
我们将单词从一个地方移到另一个地方来理解它们之间的关系,而不是用洞和成堆的泥土。记住,在嵌入向量空间中,嵌入的位置表明了它与其他单词的关系。如果单词聚集在一起,那么它们是相关的。
在上面的例子中,点数的分布没有模式。他们是随机相关的。当我们更改数据集以确保某些单词之间存在关系时,我们得到了以下可视化结果:
最初的论文介绍了使用 EMD 来识别文本相似性的思想,“从单词嵌入的到文档距离的”,用一个很好的例子显示了这种关系,这个例子通常用于显示如何通过嵌入之间的距离来识别单词相似性。
*How close one embedding is to another here indicates a closer relationship, i.e. the words are semantically related. *
你可以把这个想象成我们在嵌入空间中“移动”每个单词所需的距离,使它们占据相同的空间。你越不需要移动一个单词(你不需要移动“芝加哥”太多来占据与“伊利诺伊”相同的空间),单词之间就越相似。
我们移动文字就像我们移动泥土一样!这就是为什么这种文本相似性的方法被称为单词移动距离(WMD)。
在这一点上,我们应该认识到 EMD 与 WMD 的相似之处。单词“press”和“media”不需要移动太多来呈现同一个单词,即占据嵌入向量空间中的同一点。
相反,如果句子是“总统向他在芝加哥的家人讲话”,那么我们将需要移动“媒体”来占据与“家庭”相同的空间的距离应该比以前更大。
因此,通过将所有这些距离相加,我们应该能够比较不同的句子。就像这个肮脏的例子一样,我们需要做的“单词”越少,或者我们需要移动的距离越少,我们就可以认为句子越相似。
如何使用大规模杀伤性武器
好消息是,开始使用 WMD 计算句子之间的相似度相对简单。它是 Gensim 库的一部分。您可以下载一个预先训练好的 Word2Vec 模型,并使用现成的模型来测试距离方法。
或者,你也可以训练你自己的模型并使用它。对于我们这里的目的,我们将只使用预先训练的一个来显示它是多么容易。你可以在这里找到这个例子的笔记本。
我们将使用现有的最大的预训练模型之一,“word2vec-google-news-300”,它需要很长时间来下载,但如果您只想快速测试它,也可以使用较小的模型。
那么获得大规模杀伤性武器分数就像:
然后你可以比较结果,看看微小的差异对相似性得分有什么影响
注意像“ 我能换衣服 ”和“ 我能换密码 ”这样的句子的区别。根据大规模杀伤性武器,它们看起来没有那么不同,但我们知道它们更不同(或至少一样不同),就像“ 我可以换衣服吗 ”和“ 我想重置我的密码 ”这样的句子。
WMD v 余弦?
如果您试图测量两个句子或文档之间的相似性,您可能会使用类似余弦相似性的东西。
例如,在之前的一篇文章中,为了获得我们数据集中单词之间的相似度,我们使用了 get_similarity 函数,该函数使用余弦相似度。这不是计算单词之间的距离,而是测量两个嵌入之间的角度大小。
如果你看上面的图表,你可以看到,根据这些向量之间的角度余弦,这两个词被认为是相似的。换句话说,余弦相似性忽略了向量的大小,只关注方向。尽管第一张图中的向量在大小上有很大差异,但两个例子中的角度没有区别。
在许多情况下,这似乎不是一个问题,无论您使用什么方法都将取决于您自己的用例。但是,有趣的研究表明,这些向量的长度与单词在文本中的重要性有关,单词嵌入是在文本中训练的。
更具体地说,对于要在许多不同的上下文中使用的单词,它们必须没有什么意义。这种无关紧要的词的主要例子是高频停用词,尽管它们的术语频率很高,但它们确实由短向量表示。
换句话说,一个单词在不同的上下文中使用得越多,嵌入就越代表该单词的加权平均值,并且该平均值影响向量的长度,使其更短。理论上,余弦方法会忽略这种幅度差异,而像 WMD 这样的方法不会。
实际上,如果你想基于情感或类似的东西对文本进行分类,这可能对你的结果没有太大影响。然而,对于个别情况,它可能会影响个别句子的相似性。最好的方法永远是尝试这两种方法(或者我们在这里没有提到的许多其他距离度量方法中的一种),看看哪个单词最适合你的方法。如果你发现在所有情况下都是最好的,你可以最终使用两者的加权平均值。
在比较这些方法时,您还应该考虑这样一个事实,即使用的大多数嵌入都是上下文相关的,因为像 BERT 这样的模型会根据单词的用法生成许多不同的嵌入来捕捉单词的不同含义。这也可能对您使用的方法产生影响。
同样,最好的方法是两者都尝试,看看哪一个最适合您的特定用例。
最终考虑
在这篇文章中,我们从 ML 的角度探索了 WD,以理解如何使用它来度量两个文本序列之间的相似性。为了做到这一点,我们花了一些时间来研究距离度量的一般概念,以及我们如何使用简单的距离方法来测量看似不同的概念,例如概率分布和成堆的灰尘之间的相似性,以及单词和句子之间的相似性。
关键是要理解我们可以用不同的方式来表达每个问题。如果我们可以用某种形式的度量空间来表示它,那么我们可以将 EMD 应用于它,并基于我们需要做的“工作”的数量,理解该空间中实体的相似性。
我们讨论了这种方法如何通过 WMD 来测量单词的相似性,WMD 方法中的一些差异,以及更常见的方法,如余弦相似度。
我们没有解决的一件事是大规模杀伤性武器方法的任何缺点。主要的一个问题是,由于计算的复杂性,它很难用于大型文档。然而,这是一个正在进行的研究和新方法的领域,旨在显著加快大规模杀伤性武器的计算,从而使其适用于更大的文本。
类似地,进一步的工作试图通过句子移动距离 (SMD)将 WMD 扩展到句子,SMD 声称通过使用单词和句子嵌入来从文本序列中准确提取语义相似性,从而显示出改进的结果。
这仍然是一个令人兴奋的快速发展的领域,我迫不及待地想知道接下来会发生什么。感谢阅读!
其他资源:
EMD 的离散例子:这是一篇展示 EMD 离散例子的好文章。我就是用这种方法作为 RGB 图表的基础。这只是一个很好的数据可视化的例子,有助于解释一个问题或概念。
- WD math deep dive :我发现 WD 上的这个视频讲座非常有用,也很容易上手。如果你想了解更多 WD 数学背后的细节,我推荐这个视频。
- 更多 WD 数学知识:这是另一个视频,我发现它非常有助于理解如何通过一个工作示例导出 WD 的简单(离散)形式。
- More WD math: This was another video I found very helpful to understand how to derive a simple (discrete) form of the WD with a worked example.
机器学习团队在生产中使用 CI/CD 的 4 种方式
原文:https://web.archive.org/web/https://neptune.ai/blog/ways-ml-teams-use-ci-cd-in-production
DevOps 中的一个核心概念现在正在走向机器学习操作( MLOps )是 CI/CD——持续集成和持续交付或持续部署。CI/CD 作为核心 DevOps 实践,包含了通过简化应用程序的构建、测试和生产部署来可靠地交付软件应用程序的工具和方法。让我们在下面定义这些概念:
Continuous Integration vs Continuous Delivery vs Continuous Deployment | Source
过去几年开发的大多数 CI/CD 工具都是为传统软件应用程序而专门构建的。您(可能)知道,开发和部署传统软件应用程序与构建和部署机器学习(ML)应用程序在许多方面有很大不同。这些问题就变成了:
- ML 团队如何采用现有的 CI/CD 工具来适应他们的机器学习用例?
- 有没有更好的专门为 ML 应用程序构建的选项?
在本文中,您将了解 4 个不同的团队如何使用或已经使用 CI/CD 概念、工具和技术来构建和部署他们的机器学习应用程序。本文的目的是从这些团队实施的不同解决方案(包括其使用案例)中,为您提供 CI/CD 使用的广阔视角。
使用 Azure DevOps 为机器学习(ML)提供持续集成和交付(CI/CD)
在本节中,我们将介绍一个团队的工作流程,该团队在 Azure DevOps 中为其机器学习工作负载编排 CI/CD 流程。他们的机器学习工作负载大多运行在 Azure Cloud 上。
感谢Emmanuel Raj接受我的采访,介绍他的团队如何为他们的 ML 工作负载进行 CI/CD。这一部分利用了采访中 Emmanuel 的回答和他关于 MLOps 的非常实用的书; 【工程机器学习运算】 。
工业
零售和消费品。
用例
这个团队帮助零售客户使用机器学习以自动化的方式解决问题。当用户提出票证或票证由维护问题产生时,机器学习用于将票证分类为不同的类别,帮助更快地解决票证问题。
概观
为了协调他们的 CI/CD 工作流,团队使用了 Azure DevOps 产品套件。他们还为 ML 工作负载配置了开发和生产环境。这些工作流由所有 CI/CD 流程组成,这些流程发生在将模型部署到生产之前的和部署之后的。
将模型部署到生产之前的 CI/CD 工作流
-
人类验证者,通常是产品所有者,确保模型通过测试,已经被验证,然后批准模型使用发布管道被部署到生产环境中。
将模型部署到生产后的 CI/CD 工作流
-
在将模型部署到生产中后,团队设置 cron 作业(作为其 CI/CD 管道的一部分),每周监控数据漂移和概念漂移的模型指标,以便当出现需要重新训练模型的不可接受的漂移时,管道可以被触发。
-
他们还通过检查 Azure DevOps 管道中的管道版本来监控生产中 CI/CD 管道的性能。检查的目的是确保他们的 CI/CD 管道处于健康和稳定的状态。他们在检查 CI/CD 渠道时遵循的指导方针包括:
- 定期审核系统日志和事件。
- 集成自动化验收测试。
- 需要拉请求来改变管道。
- 在将每个故事或功能添加到管道之前,对它们进行同行代码评审。
- 定期报告对团队所有成员可见的指标。
总而言之,Azure DevOps 为团队提供了一套有用的工具,使开发(机器学习;模型构建)和运营团队和谐地工作。
使用 Jenkins 和 Argo 工作流实现 ML 与 GitOps 的持续集成和交付(CI/CD)
在本节中,您将了解一个团队如何能够创建一个框架来编排他们的机器学习工作流,并使用 GitOps 运行 CI/CD 管道。
感谢格林斯团队前 ML 工程师Tymoteusz Wolodzko接受我的采访。本节利用了 Tymoteusz 在采访中得到的回复以及他在 Neptune.ai 博客上发表的 案例研究博文 。
工业
计算机软件
用例
greens team–一家 i4 Insight 公司为海洋行业提供软件解决方案,帮助减少燃料消耗。过量使用燃料既费钱又对环境有害,T2 国际海事组织要求船只经营者更加环保,到 2050 年减少 50%的二氧化碳排放量。
概观
为了实现 CI/CD,团队利用 Jenkins 运行代码质量检查的 GitOps 和在测试环境中使用类似生产运行的冒烟测试。团队有一个模型代码的单一管道,每个拉请求都经过代码审查和自动化的单元测试。
拉取请求还经过了自动化的冒烟测试,在测试中,他们训练模型并进行预测,在一小块真实数据上运行整个端到端管道,以确保管道的每个阶段都按照预期运行,不会出现任何问题。
对于模型的连续交付,在训练每个模型之后,生成模型质量报告,并且在它们最终被手动部署之前,由领域专家通过手动过程进行审查,在得到领域专家的验证并且通过所有先前的检查之后。
了解 GitOps
GitOps 在一些常见的 DevOps 原则、实践和工具之上应用了以 Git 为中心的方法。在 GitOps 中,存储在存储库中的代码和配置被认为是事实的来源,其中基础设施适应代码的变化。GitOps 帮助他们在亚马逊 EKS 以团队要求的速度交付管道,没有运营问题。
代码质量检查和使用 Jenkins 管理 CI 渠道
Jenkins 是开发人员中最流行的持续集成工具之一。该团队采用 Jenkins 进行持续集成,以使他们的测试、检查和评审套件更加高效。
-
为了保持代码质量的一致性,他们把所有的代码检查都移到了包含模型代码的 Docker 容器中,这样包括 flake8 、 black 、 mypy 、 pytest 在内的代码质量检查工具的版本和配置都统一了。这也帮助他们将本地开发设置与他们在 Jenkins 上使用的相统一。
-
Docker 确保他们不再有不同版本的依赖关系的问题,这些问题可能会导致本地和 Jenkins 或生产中的不同结果。
-
对于代码审查,他们设置了 Jenkins,它作为 CI 管道的一部分运行相同的检查。
使用 Argo 管理 CI/CD 管道
该团队需要在不同的场景中针对不同客户的多个数据集测试他们的模型。正如 Tymoteusz Wolodzko 在他的 explainer 博客帖子中承认的那样,这不是他们想要手动设置和运行的东西。
他们需要能够轻松插入生产环境的流程编排和自动化管道。对他们的 ML 代码进行 Dockerizing 使得跨不同环境移动应用程序变得容易,这包括生产环境。
对于编排,团队从气流切换到 Argo 工作流,因此插入他们的容器只是写几行 YAML 代码的问题。
Argo Workflows & Pipelines 是一个开源的容器原生工作流引擎,用于在 Kubernetes 上编排并行作业。这是一个完全为 Kubernetes 设计的云原生解决方案。您可以定义管道工作流,其中各个步骤被视为一个容器。
Argo 工作流允许团队在其亚马逊 EKS 集群上轻松运行机器学习或数据处理的计算密集型作业。流水线中的模型将根据预定的任务定期进行再训练,并接受必要的测试和检查。但是在部署模型之前,它们要经过领域专家的审查和审计。一旦专家确认模型适合部署,那么模型将被手动部署。
下图显示了团队针对 ML 工作负载的整个体系:
MLOps technological stack at GreenSteams | Source
ML 与 AWS 代码管道和 Step 函数的持续集成和交付(CI/CD)
为了编排他们的 CI/CD 工作流,本节中的团队使用了 AWS 代码管道和 AWS 步骤功能的组合,以确保他们正在构建一个自动化的 MLOps 管道。
感谢 菲尔·巴斯福德 让我采访他的团队如何为一个公开的 ML 用例做 CI/CD。
工业
运输和物流。
用例
对于这个用例,团队来自一家从事公共项目的咨询和专业服务公司。具体来说,他们构建了解决以下问题的机器学习应用程序:
-
预测递送包裹需要多长时间,
-
基于非结构化地址数据预测位置,并将其解析到坐标系(纬度/经度)。
-
AWS code build–一个完全托管的持续集成服务,它编译源代码、运行测试并生成准备好部署的软件包。
-
AWS code pipeline–一项全面管理的持续交付服务,帮助您实现发布渠道的自动化。
-
AWS Step Functions–一个无服务器的函数编排器,可以轻松对 AWS Lambda 函数和多个 AWS 服务进行排序。
概观
AWS Cloud 提供托管 CI/CD 工作流工具,如 AWS CodePipeline 和 AWS Step Functions ,为他们的机器学习项目进行持续集成和持续交付。为了持续集成,团队使用 git 向 AWS CodeCommit 提交,这将触发代码管道中的构建步骤(通过 AWS CodeBuild 作业),AWS 步骤功能处理来自代码管道的每个操作的工作流编排。
理解架构
AWS Step Functions 的工作流编排流程使团队能够轻松管理因使用代码管道运行多个模型和管道而产生的复杂性。团队进行的多模型部署更易于管理和更新,因为 CodePipeline 中的每个管道作业都专注于一个过程,构建也更易于交付和故障排除。
下面是一个使用 AWS CodePipeline 和 Step 函数来编排需要自定义容器的 ML 管道的项目示例。这里,CodePipeline 调用步骤函数,并将容器图像 URI 和唯一容器图像标签作为参数传递给步骤函数:
Architecture to build a CI/CD pipeline for deploying custom machine learning models using AWS services | Source
你可以在这篇博客文章中了解更多关于上述架构的信息。虽然这个团队选择使用这些工具来管理和编排,但值得注意的是,对于持续集成和持续交付(CI/CD)管道,AWS 发布了亚马逊 SageMaker Pipelines ,这是一种易于使用的、专门为 ML 设计的 CI/CD 服务。
Pipelines 是一个用于构建 ML 管道的本地工作流编排工具,它利用了 SageMaker 的直接集成。在这篇博客文章中,你可以了解更多关于使用 Amazon SageMaker Pipelines 构建、自动化、管理和扩展 ML 工作流的信息。
在 Google Cloud 上使用 Vertex AI 和 TFX 为 ML 提供持续集成和交付(CI/CD)
在本节中,我们将了解一个团队,该团队能够在选择和使用工作流编排和管理工具时,利用比传统软件工程项目更适合机器学习项目的管道。
本节利用 【汉尼斯】哈普克 【数字金融公司 ML 工程师】 工作坊 在 Google Cloud 的 应用 ML 在线峰会 期间关于“利用有限的 DevOps 资源进行快速迭代”。
工业
商业智能和金融技术服务。
用例
数字金融公司。是一家金融科技公司,为初创公司和小型企业提供基于机器学习的可视化费用监控仪表板。他们的使用案例侧重于:
- 为现代企业创建最强大的财务引擎,能够吸收公司的财务信息并将其转换为实时业务模型。
- 从非结构化文档中提取信息,为客户预测未来事件。
- 对信息进行聚类,找出对客户业务最重要的内容。
概观
Digits 的团队能够通过托管 Vertex AI Pipelines 产品和 TensorFlow Extended 来协调和管理其机器学习管道的持续集成、交付和部署,所有这些都在谷歌云基础设施上运行。
在传统 CI/CD 工具上使用 ML-native pipeline 工具有助于团队确保模型质量的一致性,并确保模型在一个统一的管道中经历特征工程、模型评分、模型分析、模型验证和模型监控的标准工作流。
TFX 的机器学习管道
随着 Tensorflow 的扩展,当管道部署到测试环境或生产环境时,团队能够将机器学习堆栈的每个组件视为可由第三方工具编排的单独步骤,如 Apache Beam 、 Apache Airflow 或 Kubeflow Pipelines 。他们还能够创建自定义组件并将其添加到管道中,而使用传统的 CI/CD 工具很难利用这些组件。
Machine learning pipelines with TFX | Adapted and modified from this source
与此同时,他们还将他们的 ML 管道从 Kubeflow 转移到了来自 Google Cloud 的 Vertex AI 管道,帮助他们轻松地将模型开发(ML)和运营(Ops)结合到高性能和可复制的步骤中。
使用该团队提供的 Vertex AI 管道的核心优势之一是,它帮助他们从管理管道(自托管 Kubeflow 管道)过渡到利用托管 Vertex AI 管道服务进行工作流编排,从而不再需要维护存储元数据的数据库,启动集群来托管和操作构建服务器和管道。
与顶点人工智能管道协调
Vertex AI 是一个托管的 ML 平台,用于每个从业者加快实验速度,加速机器学习模型的部署。它通过以无服务器的方式编排 ML 工作流,并使用 Vertex ML 元数据存储工作流的工件,帮助团队自动化、监控和管理他们的 ML 系统。
通过将 ML 工作流的工件存储在 Vertex ML 元数据中,他们可以分析其工作流工件的谱系,例如,ML 模型的谱系可能包括团队用于创建模型的训练数据、超参数和代码。
A screenshot of Vertex AI ML pipeline orchestration from the digits team | Source
该团队的工作流程包括用 TensorFlow Extended 准备和执行他们的机器学习管道,并将它们运送到 Vertex AI。然后,他们可以从 Vertex AI 管道管理和协调他们的管道,而不必操作他们自己的集群。
使用机器学习管道的好处
该团队能够从使用 ML 管道中受益,以多种方式编排和管理他们的 ML 工作负载。正如汉尼斯·哈普克在这段视频中所描述的,这家初创公司能够获得以下好处:
- 使用 ML 管道减少了团队的 DevOps 需求。
- 当集群在其基础设施上托管管道时,迁移到托管的 ML 管道减少了运行 24/7 集群的费用。
- 由于 ML 管道是 ML 工作流的原生部分,模型更新很容易集成并且是自动化的,解放了团队去关注其他项目。
- 所有 ML 项目的模型更新都是一致的,因为团队可以运行相同的测试并重用整个管道或管道的组件。
- 所有机器学习相关元数据和信息的一站式位置。
- 模型现在可以被自动跟踪和审计。
结论
这篇文章揭示的一个有趣的观点是使用 CI/CD 工具不足以成功地操作您的机器学习工作负载。虽然本文中的大多数团队仍然使用传统的 CI/CD 工具,但我们开始看到 ML-native 管道工具的出现,这些工具可以帮助团队(无论其规模如何)更快、更可靠地交付更好的机器学习产品。
如果您和您的团队正在考虑为您的机器学习工作负载采用 CI/CD 解决方案,那么与传统的基于软件工程的 CI/CD 工具相比,任何一种 ML-native 管道工具都可能值得开始使用,当然,这取决于您团队的环境以及有利于使用的工具或供应商。
对于这些工具,您可以查看:
关于在 ML 中利用 CI/CD 的后续步骤,您可以查看以下文章:
下次见,行动愉快!
参考资料和资源
使用 Azure DevOps 编排 CI/CD
使用 Jenkins 和 Argo 工作流的 CI/CD 和 GitOps
通过 AWS 代码管道和 Step 函数简化 AWS 云上的 CI/CD
使用顶点人工智能和 TFX 在谷歌云上编排 ML 管道。
斯蒂芬·奥拉德勒
开发者倡导者和 MLOps 技术内容创建者。
阅读下一篇
Continuum Industries 案例研究:如何跟踪、监控和可视化 CI/CD 管道
7 分钟阅读| 2021 年 8 月 9 日更新
Continuum Industries 是一家基础设施行业的公司,希望自动化和优化线性基础设施资产的设计,如水管、架空传输线、海底电力线或电信电缆。
其核心产品 Optioneer 允许客户输入工程设计假设和地理空间数据,并且使用进化优化算法来寻找可能的解决方案,以在给定约束的情况下连接 A 点到 B 点。
首席科学家安德烈亚斯·马莱科斯(Andreas Malekos)致力于研究人工智能发动机,他解释道:
“建造像电力线这样的东西是一个巨大的项目,所以你必须在开始之前获得正确的设计。你看到的设计越合理,你就能做出更好的决定。Optioneer 可以在几分钟内为您提供设计资产,而成本只是传统设计方法的一小部分。”
但是,创建和操作 Optioneer 引擎比看起来更具挑战性:
- 目标函数不代表现实
- 有很多土木工程师事先不知道的假设
- 不同的客户给它提出完全不同的问题,算法需要足够健壮来处理这些问题
与其构建完美的解决方案,不如向他们展示一系列有趣的设计选项,以便他们做出明智的决策。
引擎团队利用来自机械工程、电子工程、计算物理、应用数学和软件工程的各种技能来实现这一目标。
问题
无论是否使用人工智能,构建一个成功的软件产品的一个副作用是,人们依赖它工作。当人们依赖您的优化引擎做出价值百万美元的基础设施设计决策时,您需要有一个强大的质量保证(QA)。
正如 Andreas 所指出的,他们必须能够说,他们返回给用户的解决方案是:
- 好,意思是这是一个土木工程师可以看到并同意的结果
- 更正,这意味着计算并返回给最终用户的所有不同工程数量都尽可能准确
除此之外,该团队还在不断改进优化引擎。但要做到这一点,您必须确保这些变化:
- 不要以这样或那样的方式破坏算法
- 实际上,它们不仅改善了一个基础设施问题的结果,还改善了所有问题的结果
基本上,您需要建立适当的验证和测试,但是团队试图解决的问题的性质带来了额外的挑战:
- 您无法自动判断算法输出是否正确。这不像在 ML 中,你已经标记了数据来计算你的评估集的准确度或召回率。
- 您需要一组示例问题,代表算法在生产中需要解决的那类问题的。此外,这些问题需要被版本化,以便尽可能容易地实现可重复性。
具有机器学习的知识图[指南]
你需要在网上获取一些信息。比如关于尤塞恩博尔特的几段话。你可以从维基百科复制并粘贴信息,这不会有太多的工作。
但是,如果您需要获得关于尤塞恩·博尔特参加的所有比赛的信息,以及关于他和他的竞争对手的所有相关统计数据,该怎么办呢?如果你想对所有运动都这样做,而不仅仅是跑步,会怎么样?
机器学习工程师通常需要建立如上例的复杂数据集来训练他们的模型。网络搜集是收集必要数据的一种非常有用的方法,但也带来了一些挑战。
在这篇文章中,我将解释如何收集公开可用的数据,并从收集的数据中构建知识图,以及来自自然语言处理 (NLP)的一些关键概念。
什么是网页抓取?
Web 抓取(或 web 采集)是用于数据提取的数据抓取。一词通常指用机器人或网络爬虫收集数据。这是一种复制形式,从 web 上收集并复制特定数据,通常复制到本地数据库或电子表格中,以供以后使用或分析。
你可以用在线服务、API 来做网络抓取,或者你可以写你自己的代码来做。
网络抓取有两个关键要素:
- 爬虫:爬虫是一种算法,通过浏览互联网上的链接来浏览网页以搜索特定的数据。
- 抓取器:抓取器从网站中提取数据。刮刀的设计可以有很大变化。这取决于项目的复杂程度和范围。最终,它必须快速准确地提取数据。
现成库的一个很好的例子是 Wikipedia scraper 库。它为你做了很多繁重的工作。您向 URL 提供所需的数据,它从这些站点加载所有的 HTML。scraper 从这个 HTML 代码中获取您需要的数据,并以您选择的格式输出数据。这可以是 excel 电子表格或 CSV,或者类似于 JSON 的格式。
知识图表
网络上可用的内容数量已经令人难以置信,而且还在以越来越快的速度增长。数十亿个网站与万维网相连, 搜索引擎 可以通过这些链接,以极高的精度和速度提供有用的信息。这部分归功于知识图表。
不同的组织有不同的知识图表。例如, 谷歌知识图 是一个知识库,谷歌及其服务利用从各种来源收集的信息来增强搜索引擎结果。为了更好的用户体验,以及存储和检索有用的信息,脸书或亚马逊的产品也使用了类似的技术。
知识图没有正式的定义。广义地说,KG 是一种添加了约束的语义网络。它的范围、结构和特征,甚至它的用途在开发过程中还没有完全实现。
将知识图和机器学习(ML)结合在一起可以系统地提高系统的准确性,并扩展机器学习能力的范围。得益于知识图,从机器学习模型推断出的结果将具有更好的可解释性和可信度。
将知识图和 ML 结合在一起创造了一些有趣的机会。在我们可能没有足够数据的情况下,可以使用 kg 来扩充训练数据。最大似然模型的主要挑战之一是解释最大似然系统做出的预测。通过将解释映射到图中的适当节点并总结决策过程,知识图可以帮助克服这个问题。
另一种看待它的方式是,知识图存储从信息提取任务中产生的数据。KG 的许多实现利用了一个叫做三元组的概念——一组三个项目(一个主语、一个谓语和一个宾语),我们可以用它们来存储关于某件事情的信息。
还有另一种解释:知识图是一种数据科学工具,处理相互关联的实体 ( 组织、人员、事件、地点 ) 。实体是通过边连接的节点。kg 具有实体对,可以遍历这些实体对来发现非结构化数据中有意义的连接。
节点 A 和节点 B 是两个不同的实体。这些节点由表示它们之间关系的边连接起来。这是我们能制造的最小公斤——也被称为三公斤。知识图表有各种形状和大小。
网络抓取、计算语言学、NLP 算法和图论(带 Python 代码)
唷,这是一个冗长的标题。无论如何,要从文本构建知识图,帮助我们的机器理解自然语言很重要。我们使用 NLP 技术来实现这一点,例如句子分割、依存解析、词性(POS)标注和实体识别。
构建 KG 的第一步是收集您的资源——让我们在网上搜索一些信息。维基百科将是我们的来源(经常检查数据来源,网上很多信息都是假的)。
对于这个博客,我们将使用维基百科 API ,一个直接的 Python 包装器。 Neptune 在一个地方管理模型构建元数据。记录、存储、显示、组织、比较和查询您所有的 MLOps 元数据。
实验跟踪以及为运行大量实验的研究和生产团队构建的模型注册表。
安装和设置
安装依赖项并抓取数据
!pip install wikipedia-api neptune-client neptune-notebooks pandas spacy networkx scipy
按照以下链接在您的笔记本上安装和设置 Neptune:rn-Neptune
–Neptune Jupyter 扩展指南
下面的函数在维基百科中搜索给定的主题,并从目标页面及其内部链接中提取信息。
import wikipediaapi
import pandas as pd
import concurrent.futures
from tqdm import tqdm
below 函数允许您根据作为函数输入提供的主题获取文章。
def scrape_wikipedia(name_topic, verbose=True):
def link_to_wikipedia(link):
try:
page = api_wikipedia.page(link)
if page.exists():
return {'page': link, 'text': page.text, 'link': page.fullurl, 'categories': list(page.categories.keys())}
except:
return None
api_wikipedia = wikipediaapi.Wikipedia(language='en', extract_format=wikipediaapi.ExtractFormat.WIKI)
name_of_page = api_wikipedia.page(name_topic)
if not name_of_page.exists():
print('Page {} is not present'.format(name_of_page))
return
links_to_page = list(name_of_page.links.keys())
procceed = tqdm(desc='Scraped links', unit='', total=len(links_to_page)) if verbose else None
origin = [{'page': name_topic, 'text': name_of_page.text, 'link': name_of_page.fullurl, 'categories': list(name_of_page.categories.keys())}]
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
links_future = {executor.submit(link_to_wikipedia, link): link for link in links_to_page}
for future in concurrent.futures.as_completed(links_future):
info = future.result()
origin.append(info) if info else None
procceed.update(1) if verbose else None
procceed.close() if verbose else None
namespaces = ('Wikipedia', 'Special', 'Talk', 'LyricWiki', 'File', 'MediaWiki',
'Template', 'Help', 'User', 'Category talk', 'Portal talk')
origin = pds.DataFrame(origin)
origin = origin[(len(origin['text']) > 20)
& ~(origin['page'].str.startswith(namespaces, na=True))]
origin['categories'] = origin.categories.apply(lambda a: [b[9:] for b in a])
origin['topic'] = name_topic
print('Scraped pages', len(origin))
return origin
让我们测试主题为“新冠肺炎”的函数。
wiki_data = wiki_scrape('COVID 19')
o/p: Links Scraped: 100%|██████████| 1965/1965 [04:30<00:00, 7.25/s]ages scraped: 1749
将数据保存到 csv:
data_wikipedia.to_csv('scraped_data.csv')
导入库:
import spacy
import pandas as pd
import requests
from spacy import displacy
nlp = spacy.load('en_core_web_sm')
from spacy.tokens import Span
from spacy.matcher import Matcher
import matplotlib.pyplot as plot
from tqdm import tqdm
import networkx as ntx
import neptune.new as neptune
%matplotlib inline
run = neptune.init(api_token="your API key",
project="aravindcr/KnowledgeGraphs")
上传数据到海王星:
run["data"].upload("scraped_data.csv")
data = pd.read_csv('scraped_data.csv')
查看第 10 行的数据:
data['text'][10]
输出:
The AbC-19 rapid antibody test is an immunological test for COVID-19 exposure
developed by the UK Rapid Test Consortium and manufactured by Abingdon
Health. It uses a lateral flow test to determine whether a person has IgG
antibodies to the SARS-CoV-2 virus that causes COVID-19. The test uses a single
drop of blood obtained from a finger prick and yields results in 20 minutes.
句子分割
构建知识图的第一步是将文本文档或文章分割成句子。然后我们把例子限制在只有一个主语和一个宾语的简单句上。
docu = nlp('''The AbC-19 rapid antibody test is an immunological test for COVID-19 exposure developed by
the UK Rapid Test Consortium and manufactured by Abingdon Health. It uses a lateral flow test to determine
whether a person has IgG antibodies to the SARS-CoV-2 virus that causes COVID-19\. The test uses a single
drop of blood obtained from a finger prick and yields results in 20 minutes.nnSee alsonCOVID-19 rapid
antigen test''')
for tokn in docu:
print(tokn.text, "---", tokn.dep_)
下载如下所示的预训练空间模型:
python -m spacy download en
SpaCy 管道分配单词向量、上下文特定的标记向量、词性标记、依存解析和命名实体。通过扩展 SpaCy 的注释管道,您可以解析共同引用(在下面的代码中解释)。
知识图可以从词性和依存句法分析中自动构建。使用 NLP 库空间,从语法模式中提取实体对是快速的,并且可扩展到大量文本。
下面的函数将实体对定义为由根动词连接的具有主客体依赖关系的实体/名词块。可以使用其他近似方法来产生不同类型的连接。这种联系可以称为主谓宾三元组。
主要意思是浏览一个句子,提取主语和宾语,以及它们何时出现。下面的函数包含了上面提到的一些步骤。
实体提取
您可以借助词性( POS )标签从句子中提取单个单词实体。名词和专有名词将是实体。
然而,当一个实体包含多个单词时,仅靠 POS 标签是不够的。我们需要分析句子的依存关系树。构建知识图,最重要的是它们之间的节点和边。
这些节点将是出现在维基百科句子中的实体。边是连接这些实体的关系。我们将以无人监督的方式提取这些元素,也就是说,我们将使用句子的语法。
这个想法是通过一个句子,当主语和宾语被重构时,提取它们。
def extract_entities(sents):
enti_one = ""
enti_two = ""
dep_prev_token = ""
txt_prev_token = ""
prefix = ""
modifier = ""
for tokn in nlp(sents):
if tokn.dep_ != "punct":
if tokn.dep_ == "compound":
prefix = tokn.text
if dep_prev_token == "compound":
prefix = txt_prev_token + " "+ tokn.text
if tokn.dep_.endswith("mod") == True:
modifier = tokn.text
if dep_prev_token == "compound":
modifier = txt_prev_token + " "+ tokn.text
if tokn.dep_.find("subj") == True:
enti_one = modifier +" "+ prefix + " "+ tokn.text
prefix = ""
modifier = ""
dep_prev_token = ""
txt_prev_token = ""
if tokn.dep_.find("obj") == True:
enti_two = modifier +" "+ prefix +" "+ tokn.text
dep_prev_token = tokn.dep_
txt_prev_token = tokn.text
return [enti_one.strip(), enti_two.strip()]
extract_entities("The AbC-19 rapid antibody test is an immunological test for COVID-19 exposure developed by the UK Rapid Test")
['AbC-19 rapid antibody test', 'COVID-19 UK Rapid Test']
现在让我们使用函数来提取 800 个句子的实体对。
pairs_of_entities = []
for i in tqdm(data['text'][:800]):
pairs_of_entities.append(extract_entities(i))
句子中的主语和宾语对:
pairs_of_entities[36:42]
输出:
[['where aluminium powder', 'such explosives manufacturing'],
['310 people', 'Cancer Research UK'],
['Structural External links', '2 PDBe KB'],
['which', '1 Medical Subject Headings'],
['Structural External links', '2 PDBe KB'],
['users', 'permanently taste']]
关系抽取
有了实体提取,一半的工作就完成了。为了构建知识图,我们需要连接节点(实体)。这些边是节点对之间的关系。下面的函数能够从这些句子中捕获这样的谓词。我用的是 spaCy 的基于规则的匹配。函数中定义的模式试图找到词根或句子中的主要动词。
def obtain_relation(sent):
doc = nlp(sent)
matcher = Matcher(nlp.vocab)
pattern = [{'DEP':'ROOT'},
{'DEP':'prep','OP':"?"},
{'DEP':'agent','OP':"?"},
{'POS':'ADJ','OP':"?"}]
matcher.add("matching_1", None, pattern)
matcher = matcher(doc)
h = len(matcher) - 1
span = doc[matcher[h][1]:matcher[h][2]]
return (span.text
上面写的模式试图在句子中找到词根。一旦它被识别出来,它就会检查它后面是否跟有介词或代理词。如果答案是肯定的,那么它将被添加到词根中。
relations = [obtain_relation(j) for j in tqdm(data['text'][:800])]
提取的最常见关系:
pd.Series(relations).value_counts()[:50]
让我们建立一个知识图表
现在我们终于可以从提取的实体中创建一个知识图了
让我们使用 networkX 库来绘制网络。我们将创建一个节点大小与度中心性成比例的有向多图网络。换句话说,任何连接的节点对之间的关系都不是双向的。它们只是从一个节点到另一个节点。
source = [j[0] for j in pairs_of_entities]
target = [k[1] for k in pairs_of_entities]
data_kgf = pd.DataFrame({'source':source, 'target':target, 'edge':relations})
- 我们使用 networkx 库从数据帧创建一个网络。
- 这里,节点将被表示为实体,而边表示节点之间的关系
graph = ntx.from_pandas_edgelist(data_kgf, "source", "target",
edge_attr=True, create_using=ntx.MultiDiGraph())
plot.figure(figsize=(14, 14))
posn = ntx.spring_layout(graph)
ntx.draw(graph, with_labels=True, node_color='green', edge_cmap=plot.cm.Blues, pos = posn)
plot.show()
- 从上面的图表中,不清楚在图表中捕捉到了什么关系
- 让我们用一些关系来形象化图表。我在这里选择:
graph = ntx.from_pandas_edgelist(data_kgf[data_kgf['edge']=="Information from"], "source", "target",
edge_attr=True, create_using=ntx.MultiDiGraph())
plot.figure(figsize=(14,14))
pos = ntx.spring_layout(graph, k = 0.5)
ntx.draw(graph, with_labels=True, node_color='green', node_size=1400, edge_cmap=plot.cm.Blues, pos = posn)
plot.show()
- 另一个用关系名“链接”过滤的图可以在这里找到。
记录元数据
我已经把上面的 networkx 图登录到海王星了。你可以找到那个特定的路径。根据获得的输出,将您的图像记录到不同的路径。
run['graphs/all_in_graph'].upload('graph.png')
run['graphs/filtered_relations'].upload('info.png')
run['graphs/filtered_relations2'].upload('links.png')
所有的图表都可以在这里找到。
共指消解
要获得更精确的图形,还可以使用共指解析。
共指消解是内视感知的 NLP 等价物,用于信息检索系统、对话代理和虚拟助手,如 Alexa。这是一项对文本中提及相同潜在实体的内容进行聚类的任务。
【我】【我的】 ,和 【她】 属于同一个集群,和 【乔】 和 【他】 属于同一个集群。
解决共同引用的算法通常寻找与引用表达式兼容的最近的前面提及。也可以训练神经网络,而不是使用基于规则的依存解析树,神经网络将单词嵌入和提及之间的距离作为特征来考虑。
通过规范化文本、删除冗余和指定实体代词,这显著改进了实体对提取。
如果您的用例是特定于领域的,那么训练一个定制实体识别模型是值得的。
知识图表可以自动构建并探索,以揭示关于该领域的新见解。
笔记本上传到海王星。
GitHub 上的笔记本。
大规模知识图表
为了有效地将 1749 页的整个语料库用于我们的主题,使用在 wiki_scrape 函数中创建的列来为每个节点添加属性。然后你可以跟踪每个节点的页面和类别。您可以使用多重和并行处理来减少执行时间。
kg 的一些使用案例包括:
未来的挑战
实体歧义消除和身份管理
在其最简单的形式中,挑战是为一个实体的发言或提及分配一个唯一的规范化身份和类型。
自动提取的很多实体都有非常相似的表面形态,比如同名或相近的人,或者同名或相近的电影、歌曲、书籍。两个名称相似的产品可能指的是不同的列表。没有正确的链接和歧义消除,实体将与错误的事实不正确地关联,并导致下游不正确的推理。
类型成员和解析
今天,大多数知识图系统允许每个实体有多种类型,不同的环境有不同的类型。古巴可以是一个国家,也可以指古巴政府。在某些情况下,知识图系统将类型分配推迟到运行时。每个实体描述其属性,应用程序根据用户任务使用特定的类型和属性集合。
管理不断变化的知识
一个有效的实体链接系统需要基于其不断变化的输入数据有机地增长。例如,公司可能会合并或拆分,新的科学发现可能会将单个现有实体拆分为多个实体。
当一家公司收购另一家公司时,收购公司是否会改变身份?身份是随着姓名权的获得而产生的吗?例如,在医疗保健行业构建的 kg 的情况下,患者数据会随着时间的推移而改变。
从多个结构化和非结构化来源中提取知识
结构化知识(包括实体、它们的类型、属性和关系)的提取仍然是一个全面的挑战。大规模增长的图表需要手动方法以及从开放领域的非结构化数据中进行无监督和半监督的知识提取。
管理大规模运营
管理规模是直接影响与性能和工作负载相关的几项运营的根本挑战。它还会影响其他操作,例如管理大规模知识图的快速增量更新,从而间接证明自己。
注:有关不同科技巨头如何在其产品和相关挑战中实施行业规模知识图的更多细节,请查看本文。
自然语言处理
自然语言处理(Natural Language Processing)是计算机科学的一个分支,旨在让计算机能够处理和理解人类语言。从技术上来说,NLP 的主要任务将是给计算机编程,以分析和处理大量的自然语言数据。
各种学科都学习语言。每个学科都有自己的问题和解决问题的方法。
语言中的歧义
NLP 中使用的歧义可以指的是以一种以上的方式被理解的能力。自然语言是模糊的。NLP 有以下模糊之处:
- 词汇歧义是单个单词的歧义。例如,单词 well 可以是副词、名词或动词。
- 句法歧义是在一个句子或单词序列中存在两种或两种以上可能的意思。例如“鸡肉可以食用了”。这句话要么表示鸡已经熟了,现在可以吃了,要么表示鸡已经可以喂了。
- 回指歧义是指在文本中向后指称(或另一个语境中的实体)。一个短语或单词指的是前面提到的东西,但是有不止一种可能性。例如,“玛格丽特邀请苏珊来访,她给了她一顿美餐。”(她=玛格丽特;她=苏珊)。“玛格丽特邀请苏珊来访,但她告诉她她必须去工作”(她=苏珊;她=玛格丽特。)
- 语用歧义可以定义为有多种解释的词语。当一个句子中的词语意义不明确时,就会产生语用歧义;它以不同的意义结束。
自然语言处理中的文本相似性度量
文本相似性用于确定两个文本文档在上下文或含义方面有多相似。有各种相似性度量,例如:
- 余弦相似度,
- 欧几里德距离,
- Jaccard 相似度。
所有这些指标都有自己的规格来衡量两个查询之间的相似性。
余弦相似性
余弦相似度是在 NLP 中测量两个文档之间的文本相似度的度量,不管它们的大小如何。一个词用向量的形式来表示。文本文档用 n 维向量空间表示。
余弦相似性度量两个 n 维向量在多维空间中投影的夹角余弦。两个文档的余弦相似度将从 0 到 1 的范围变化。如果余弦相似性得分是 1,这意味着 2 个向量具有相同的方向。越接近 0 的值表示 2 个文档的相似度越低。
两个非零向量的余弦相似度的数学方程为:
余弦相似度是比 欧几里德距离 更好的度量,因为如果两个文本文档相距欧几里德距离很远,它们在上下文方面仍然有可能彼此接近。
雅克卡相似性
Jaccard 相似性也称为 Jaccard 指数和 Union 上的交集。
Jaccard 相似度用于确定两个文本文档之间的相似度,即所有单词中存在多少个常用单词。
Jaccard 相似性被定义为两个文档的交集除以两个文档的并集,这两个文档是指总单词数中的共同单词数。
Jaccard 相似性的数学表示为:
Jaccard 相似性得分在 0 到 1 的范围内。如果两个文档相同,Jaccard 相似度为 1。如果两个文档之间没有共同的单词,则 Jaccard 相似性得分为零。
Python 代码查找 Jaccard 相似性
def jaccard_similarity(doc1, doc2):
words_doc1 = set(doc1.lower().split())
words_doc2 = set(doc2.lower().split())
intersection = words_doc1.intersection(words_doc2)
union = words_doc1.union(words_doc2)
return float(len(intersection)) / len(union)
docu_1 = "Work from home is the new normal in digital world"
docu_2 = "Work from home is normal"
jaccard_similarity(docu_1, docu_2)
输出:0.5
doc_1 和 doc_2 之间的 Jaccard 相似度为 0.5
以上三种方法都有一个相同的假设:文档(或句子)如果有常用词就是相似的。这个想法很直白。它适合一些基本情况,如比较前两个句子。
然而,通过比较第一个和第三个句子(例如,尝试使用传达相同意思的不同句子,并使用上面的 Python 函数来比较相似性),分数可以相对较低,即使两者描述了相同的新闻。
另一个限制是上述方法不处理同义词。例如,“buy”和“purchase”应该有相同的意思(在某些情况下),但是上述方法会对这两个词进行不同的处理。
那么解决方法是什么呢?你可以使用单词嵌入(Word2vec,GloVe,FastText)。
对于 NLP 的一些基本概念和用例,我将附上一些我在 Medium 上写的文章,以及一篇在 Neptune 的博客上写的文章,以供参考:
结论
我希望你在这里学到了一些新的东西,这篇文章帮助你理解了 web 抓取、知识图和一些有用的 NLP 概念。
感谢阅读,继续学习!
参考文献:
返程机
由于计划于 1 月 14 日星期五上午 8 点至下午 1 点(太平洋标准时间)停电,一些服务可能会受到影响。
最佳权重和偏差备选方案
原文:https://web.archive.org/web/https://neptune.ai/blog/weights-and-biases-alternatives
权重&偏差,也称为 WandB,是一个 MLOps 工具,用于机器学习模型的性能可视化和实验跟踪。它有助于 ML 模型的自动化、跟踪、培训和改进。
Weights & bias 是一项基于云的服务,允许您在一个中央存储库中托管您的实验,如果您有私有基础架构,Weights & bias 也可以部署在其上。
重量与偏差提供:
一个中央的,用户友好的和交互式的仪表板,您可以查看您的实验和跟踪他们的表现。
- 跟踪模型训练过程的每个部分,可视化模型,并比较实验。
- 使用扫描进行自动超参数调整,提供了超参数组合的样本,有助于模型性能和理解。
- 团队协作报告,您可以在其中添加可视化内容,组织、解释和分享您的模型性能、模型版本和进度。
- 机器学习管道的端到端工件跟踪,从数据准备到模型部署。
- 与 Tensorflow、Pytorch、Keras、Hugging Face 等框架轻松集成。
- 团队中的协作工作,具有共享、实验等多种功能。
- 这些都是 Weights & Biases 提供的有用功能,这使得它成为研究团队寻找发现、学习和获得对机器学习实验的见解的良好工具。
然而,当谈到交付时,重量和偏差并不总是最好的选择。以下是 Weights & Biases 目前没有提供的一些功能:
笔记本托管:从 Jupyter 笔记本到生产部署机器学习模型是每个数据研究人员的梦想,因为它允许快速迭代并节省时间。
- ML 生命周期管理:管理一个模型的整个生命周期在研究期间是很重要的,即从数据源到模型部署,因为它允许他们在开发的任何阶段正确地监控、调试任何问题。
- 生产用例:对于基于生产的团队或项目,权重&偏差不是一个好的选择,因为它缺乏生产引擎。
- 模型部署:研究的一个重要部分是测试和执行实时推理。这就是为什么在构建和评估模型之后就需要模型部署的原因。
- 以下是一些可供选择的工具,您可以尝试一下:
Here are some alternative tools you can try out:
1 海王星
- 2 张量板
- 3 彗星
- 4 MLflow
- 库伯流
- 6 SageMaker Studio
- Neptune 是 MLOps 的元数据存储。它允许您在一个地方记录、存储、组织、显示、比较和查询所有的模型构建元数据。这包括元数据,如模型度量和参数、模型检查点、图像、视频、音频文件、数据版本、交互式可视化、等等。
Neptune 是为进行大量实验的研究和生产团队构建的,他们希望组织和重现实验,并希望确保将模型转移到生产的过程顺利进行。海王星的主要焦点围绕着实验跟踪和模型注册,以及团队协作。
主要特点:
Neptune 允许您以任何想要的结构记录和显示模型元数据。无论是模型的嵌套参数结构,训练和验证度量的不同子文件夹,还是打包模型或生产工件的单独空间。怎么组织就看你自己了。
Neptune 的定价是基于使用的。对于所有的 ML 团队来说,它可能更具成本效益,但对于那些偶尔根本不进行实验的团队,或者那些有许多利益相关者没有深入参与实验过程的团队来说尤其如此。
- 如前所述,Neptune 是为运行大量实验的团队构建的,因此它可以处理成千上万次运行,并且不会变慢。它随着你的团队和项目的规模而扩展。
- Neptune 有 SaaS 版本,但也可以在内部托管。如果选择第二个选项,安装过程非常容易。
- 有了 Neptune,您可以创建定制的仪表板以一种更好的方式组合不同的元数据类型。
- 定价
- Neptune 可以用作托管解决方案,也可以部署在您的场所。有几个可用的计划:
个人:免费(超出免费配额的使用量)
学术界:免费
- 团队:付费
- 查看海王星的定价了解更多信息。
- 重量和偏差 vs 海王星
Neptune 和 Weights & Biases 都是托管服务,它们提供实验跟踪、模型管理和数据版本控制。
Neptune 更加关注模型注册特性,而 Weights & Biases 也提供了自动优化超参数的工具
- 这两种工具提供的开箱即用集成存在一些差异;Neptune 支持 R 语言、DVC 或 Optuna,而 WandB 支持 Spacy、Ray Tune 或 Kubeflow。
- 总的来说,这两个工具非常相似,都是非常好的解决方案,所以主要的区别可以在定价结构中发现(基于使用和基于用户)。
- TensorBoard 由 TensorFlow 团队开发,是一款用于机器学习实验的开源可视化工具。
- 它用于跟踪 ML 度量,如损失和准确性、可视化模型图、直方图、将嵌入投影到低维空间等等。
有了 TensorBoard,你还可以分享你的实验结果。
主要特点:
TensorBoard 允许您跟踪您的实验。
它还允许您跟踪不是基于 TensorFlow 的实验。
TensorBoard 允许你通过一个可共享的链接与任何人分享你的实验结果,用于出版、合作等。
- 它提供对损失和准确性等指标的跟踪和可视化。
- TensorBoard 拥有 What-If 工具(WIT),这是一个易于使用的接口,用于解释和理解黑盒分类和回归 ML 模型。
- TensorBoard 有一个强大的用户社区,提供了巨大的支持。
- 定价
- 它是免费使用的。
- 重量和偏差与 TensorBoard
如果你需要一个个人使用的工具,不打算花钱买,也不需要额外的功能,TensorBoard 可以是一个不错的选择。
TensorBoard 更适合处理张量流的可视化。
Comet 是一个基于云的机器学习平台,开发者可以在这个平台上跟踪、比较、分析和优化实验。
- Comet 安装很快,只需几行代码,您就可以开始跟踪您的 ML 实验,而无需任何库。
- 主要特点:
Comet 允许您为您的实验和数据创建定制的可视化。你也可以在面板上使用社区提供的。
Comet 提供了关于您的实验的实时统计数据和图表。
您可以轻松地比较您的实验,包括代码、指标、预测、见解等等。
使用 comet,您可以调试模型错误、特定于环境的错误等。
- Comet 还允许您监控您的模型,并在出现问题或错误时通知您。
- 它允许团队和业务涉众之间的协作。
- 它可以轻松地与 Tensorflow、Pytorch 等集成。
- 定价
- Comet 提供以下定价方案:
- 个人:免费(超出免费配额的使用量)
- 学术界:免费
团队:付费
你可以在这里阅读他们的详细定价。
- 权重和偏差与 Comet
- 这两个工具都提供了用户管理特性、托管和本地设置、模型管理、超参数搜索和工件存储。
- 如果你需要一个自定义可视化的图库, Comet 就有。
Comet 为开发提供了 Java 和 R SDK,这是 Weights & Biases 中所缺少的。
MLflow 是一个开源平台,有助于管理整个机器学习生命周期。它有助于实验跟踪,再现性,部署,并给出了一个中央模型注册。
- MLflow 包含四个主要功能:
MLflow Tracking :一个 API 和 UI,用于在运行机器学习代码时记录参数、代码版本、指标和工件,并用于以后可视化和比较结果。
MLflow 项目:将 ML 代码打包成可重用、可复制的形式,以便与其他数据科学家共享或转移到生产中。
MLflow Models :管理来自不同 ML 库的模型,并将其部署到各种模型服务和推理平台。
MLflow Model Registry :一个中央模型存储库,用于协作管理 MLflow 模型的整个生命周期,包括模型版本控制、阶段转换和注释。
- 主要特点:
- MLflow Model Registry 为组织提供了一套 API 和直观的 UI,用于注册和共享新版本的模型,以及对现有模型执行生命周期管理。
- MLflow Model Registry 与 MLflow tracking 组件一起使用,它允许您追溯生成模型和数据工件的原始运行,以及该运行的源代码版本,从而为所有模型和数据转换提供生命周期的完整沿袭。
- 当存储在增量表或目录中时,自动对存储在数据湖中的数据进行版本控制。
允许您使用版本号或时间戳获取数据的每个版本。
- 允许您在意外写入或删除错误数据时审核和/或回滚数据。
- 复制实验和报告。
- 要了解更多关于 MLflow 的信息,请查看 MLflow 文档。
- 定价
- 它是免费的。
- 重量和偏差与 MLflow
如果你的预算很低,MLflow 是一个更好的选择,因为它是免费的(开源的)实验性跟踪。
MLflow 是语言不可知的,即它可以与 Python 或 r 中的任何机器学习库一起使用,而 Weights & Biases 仅适用于 Python 脚本。
Weights & Biases 提供托管和内部设置,而 MLflow 仅作为开源解决方案提供,需要您在服务器上进行维护。
MLflow 提供端到端的 ML 生命周期管理,而 Weights & Biases 仅提供实验跟踪、模型管理和数据版本控制等功能。
- Kubeflow 是一个免费的开源机器学习平台,用于在 Kubernetes 上构建简单、可移植(通过容器)和可扩展的模型。Kubeflow 负责跟踪、数据版本控制、模型版本控制和模型部署。
- Kubeflow 是 Google 为数据科学家和 ML 工程师设计的,他们喜欢开发、测试和部署 ML 管道、模型和系统到各种环境中。
- Kubeflow 由以下组件组成:
- 中央仪表盘 : 这个仪表盘提供了一个中央视图,可以快速访问您的所有操作。它容纳了集群中运行的作业和组件,如管道、Katib、笔记本等。
kube flow Pipelines:kube flow pipeline 是一个平台,允许 ml 工程师构建和部署打包在 Docker 映像中的端到端 ML 工作流。它由用于跟踪实验和作业的 UI、用于管道操作的 SDK、多步调度引擎和用于构建 ML 模型的笔记本组成。
KFServing:KFServing 组件是 Kubeflow 的模型部署和服务工具包。它通过在 Kubernetes 上启用无服务器推理来提供生产模型服务,并为在 TensorFlow、XGBoost、scikit-learn、PyTorch 和 ONNX 等框架上的部署提供抽象层。
Katib : Katib 是一个模型不可知的 Kubernetes-native 项目,为 AutoML 模型提供超参数调整、早期停止和神经架构搜索。它支持各种 AutoML 算法和框架,如 TensorFlow、MXNet、PyTorch 等。
- 培训操作员 : 该组件提供 Kubernetes 中 Tensorflow、PyTorch、MXNet、XGBoost、MPI 模型培训作业的操作员。
- Kubeflow 笔记本 : 这个 Kubeflow 的笔记本组件允许你在集群内部运行你的笔记本。您还可以在集群中创建笔记本,并在整个组织中共享它们。
- 主要特点:
- Kubeflow 还在其工件存储中存储工件数据;它使用工件来理解各种 Kubeflow 组件的管道是如何工作的。
- Kubeflow Pipeline 可以输出工件数据的简单文本视图和丰富的交互式可视化。
- Kubeflow 有一个用户界面(UI ),用于管理和跟踪实验、作业和运行。
它为多步 ML 工作流提供调度。
它有一个用于定义和操作管道和组件的 SDK。
- 使用 SDK 与系统交互的笔记本电脑。
- 定价
- 它是免费的。
- 权重和偏差与 Kubeflow
- 使用 Kubeflow 管道或 KF 服务于 Kubeflow 中的组件,你可以在 docker 上部署机器学习模型,这是权重&偏差所缺少的。
- Kubeflow 提供端到端的机器学习编排和管理,Weights & Biases 不提供。
Kubeflow 为所有模型工件提供实验性跟踪和元数据跟踪。
对于不需要交互式可视化的用例,Kubeflow 是更好的选择。
Amazon SageMaker Studio 是一个基于 web 的集成开发环境(IDE ),用于构建、培训、可视化、调试、部署和监控您的 ML 模型。您可以在一个集成的可视化界面中编写代码、跟踪实验、可视化数据以及执行调试和监控。
- 主要特点:
- 它提供了一个模型工件存储,该存储存储了包含模型类型和内容信息的模型的 s3 存储桶位置。
- SageMaker studio 也为 AutoML 实验存储工件。
- 它允许您轻松创建和共享 Jupyter 笔记本。
它提供并管理模型环境的硬件基础设施,以便您可以快速地从一种硬件配置切换到另一种。
SageMaker Studio 支持 Tensorflow、PyTorch、MXNet 等框架。
SageMaker Studio 有超过 150 个预打包的开源模型,用于各种用例。
- SageMaker Studio 提供端到端的数据准备。它允许您使用自己选择的语言(SQL、Python 和 Scala)运行 Spark 作业,并且您还可以轻松连接到运行在 Amazon EMR 上的 Apache Spark 数据处理环境。
- 定价
- 有了亚马逊 SageMaker,你只需为你使用的东西付费。它提供两种付款方式:
- 按秒计费的按需定价,没有最低费用,也没有前期承诺
- SageMaker 储蓄计划提供了一种灵活的基于使用量的定价模式,以换取对一致使用量的承诺。
- 您可以使用 AWS 定价计算器来计划您的账单。
- 重量与偏见 vs 亚马逊 SageMaker 工作室
SageMaker Studio 的设置很简单,不像 Weights & Biases 需要一定水平的专业知识,因为它是一种托管和内部服务。
SageMaker studio 在实验跟踪期间提供实验日志和可视化。
- 在 SageMaker studio 中,您可以设置一个排行榜,自动跟踪您的所有实验,然后对它们的表现进行排名。
- 与 Weights & Biases 相比,SageMaker studio 以相对较低的价格出租计算资源。
SageMaker Studio 允许您交互式地查询、探索和可视化数据,除了实验跟踪,SageMaker studio 还提供数据注释、大量数据处理、调试以及模型和数据漂移检测。
结论
- 对于专注于研究的 ML 研究团队来说,Weights & Biases 是一个很好的工具,因为它擅长进行实验跟踪,但仅此还不够。本文中列出的替代工具有一些独特的价值主张,使它们适合可能不需要权重和偏差的用例。
- 对于开源的实验性跟踪工具,TensorBoard、MLflow、Kubeflow 会是很好的替代品。就元数据和工件的可视化和可伸缩存储而言,付费工具如 Neptune 和 Comet 是更好的选择。此外,它们还为企业团队提供高级别的安全性和支持。
- 因此,根据您的需求,您可以选择上述任何工具。
- 同时,我还会建议你总是寻找更多适合你的需求和任务的工具,并给你足够的灵活性来最大限度地利用你的工作。
- 快乐实验!
Conclusion
Weights & Biases is a great tool for ML research teams focusing on research because it is good at performing experimental tracking but that alone isn’t enough. The alternative tools listed in this article have some unique value propositions that make them fit into use-cases where Weights & Biases might not be needed.
For open-source experimental tracking tools, TensorBoard, MLflow, Kubeflow would be good alternatives. In terms of visualizations and scalable storage for your metadata and artifacts, paid tools such as Neptune and Comet are better options. Additionally, they also provide high-level security and support for enterprise teams.
So, depending on your requirement, you may choose any of the aforementioned tools.
Simultaneously, I will also advise you to be always on the lookout for more tools that suit your needs, tasks, and give you enough flexibility to get the most out of your work.
Happy experimenting!
ML 行业实际使用的图像处理技术有哪些?
处理可用于提高图像质量,或帮助您从中提取有用的信息。它在医学成像等领域很有用,甚至可以用来在图像中隐藏数据。
在这篇文章中,我将告诉你如何在机器学习中应用图像处理,以及你可以使用哪些技术。首先,让我们探索更多真实世界的图像处理示例。
现实世界中的图像处理
医学成像
在医学上,科学家研究生物体的内部结构和组织,以帮助更快地识别异常。医学成像中使用的图像处理有助于为科学和医学研究生成高质量、清晰的图像,最终帮助医生诊断疾病。
安全性
汽车经销公司或商店可以安装安全摄像机来监控该区域,并在窃贼出现时记录下来。但有时,安全摄像头生成的图像需要进行处理,要么将尺寸翻倍,要么增加亮度和对比度,使细节足够清晰,以捕捉其中的重要细节。
军事和国防
图像处理在国防领域的一个有趣应用是隐写术。专家可以将信息或图像隐藏在另一个图像中,并在没有任何第三方检测到信息的情况下来回发送信息。
常规图像锐化和恢复
这可能是图像处理最广泛的应用。使用 Photoshop 等工具增强和处理图像,或者在 Snapchat 或 Instagram 上使用滤镜,让我们的照片更酷。
如果您需要自动处理大量的图像,手动处理将是一种非常乏味的体验。这就是机器学习算法可以提高图像处理速度的地方,而不会失去我们需要的最终质量。
ML 行业中使用的图像处理技术
在我继续之前,重要的是要提到图像处理不同于计算机视觉,但人们经常把这两者混淆起来。
图像处理只是计算机视觉的一个方面,两者并不相同。图像处理系统专注于将图像从一种形式转换为另一种形式,而计算机视觉系统帮助计算机理解图像并从中获取含义。
许多计算机视觉系统采用图像处理算法。例如,面部增强应用程序可以使用计算机视觉算法来检测照片中的面部,然后对其应用图像处理技术,如平滑或灰度过滤器。
许多高级图像处理方法利用深度神经网络等机器学习模型来转换各种任务的图像,如应用艺术滤镜,调整图像以获得最佳质量,或增强特定图像细节以最大限度地提高计算机视觉任务的质量。
卷积神经网络(CNN)接受输入图像并对其使用过滤器,以某种方式学习做诸如对象检测、图像分割和分类之类的事情。
除了进行图像处理,最近的机器学习技术使工程师有可能增加图像数据。机器学习模型只和数据集一样好——但是当你没有必要数量的训练数据时,你该怎么办?
我们可以从现有的数据中构建全新的数据集,而不是试图寻找和标记更多的数据集。我们通过应用简单的图像转换技术(水平翻转、色彩空间增强、缩放、随机裁剪)或使用深度学习算法(如特征空间增强和自动编码器、生成对抗网络(GANs)和元学习)来实现这一点。
使用 Keras 的示例图像处理任务(带代码示例)
让我们了解如何应用数据扩充来生成图像数据集。我们将拍摄一张狗的图像,对其应用变换,如右移、左移和缩放,以创建图像的全新版本,该图像稍后可用作计算机视觉任务(如对象检测或分类)的训练数据集。
通过 Neptune + Keras 集成和 Neptune + matplotlib 集成,了解如何跟踪您的模型训练并将所有元数据放在一个地方
初始设置
在本教程中,我们将主要依赖四个 Python 包:
- Keras: Keras 有一个图像数据预处理类,允许我们无缝地执行数据扩充。
- matplotlib:Python 中最流行的数据可视化库之一。它允许我们创建图形和地块,并使它非常容易产生静态光栅或矢量文件,而不需要任何图形用户界面。
- Numpy:一个非常有用的库,用于对数组执行数学和逻辑运算。在本教程中,我们将使用它的 expand_dim 类来扩展数组的形状。
- Pillow:一个 python 图像库,我们将在本教程中使用它来打开和操作我们的图像文件。
让我们继续安装这些库。
在终端/命令提示符下,键入:
pip3 list
查看您已经安装在计算机上的 python 包。然后安装缺失的软件包:
pip3 install numpy matplotlib keras numpy pillow
现在我们已经安装了必要的包,让我们继续第 1 步。
第一步
创建一个名为data-aug-sample
的文件夹。在里面,创建一个名为 sample.py 的 python 文件,然后从网上下载一张狗的样本照片,并将其作为 dog.jpg 保存在这个文件夹中。然后像这样导入库:
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
image = Image.open('dog.jpg')
plt.imshow(image)
plt.show()
现在,我们的文件夹结构应该是这样的:
保存该文件,并在您的终端中运行它,如下所示:python3 sample.py
。
您应该会看到类似这样的内容:
注意:如果你在 Jupyter 笔记本上运行本教程,你必须在你的导入之后添加行%matplotlib inline
来帮助 matplotlib 容易地显示图形。我更喜欢在 Python 文件中运行我所有的机器学习程序,而不是在 Jupyter notebook 中,因为这让我感觉事情在现实中会是什么样子。
第二步
现在让我们开始在图像上应用变换操作。
旋转
旋转变换在 1 到 359 之间的轴上从右向左旋转图像。在下面的例子中,我们将狗的图像旋转了 90 度。Keras ImageDataGenerator
类允许我们为此传递一个rotation_range
参数:
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
image = Image.open('dog.jpg')
data = img_to_array(image)
samples = expand_dims(data, 0)
data_generated = ImageDataGenerator(rotation_range=90)
it = data_generated.flow(samples, batch_size=1)
for i in range(9):
plt.subplot(330 + 1 + i)
batch = it.next()
result = batch[0].astype('uint8')
plt.imshow(result)
plt.show()
运行上面的代码给了我们一个新的狗数据集:
翻译
我们可以在图像上应用水平、垂直、向左或向右的移位变换。这种转换对于避免数据中的位置偏差非常有用。例如,在人脸位于图像中心的数据集上训练人脸识别模型会导致位置偏差,使模型在位于左侧或右侧的新人脸上表现非常差。为此,我们将使用ImageDataGenerator
类的height_shift_range
和width_shift_range parameters
。
将垂直移动变换应用到我们的狗图像:
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
image = Image.open('dog.jpg')
data = img_to_array(image)
samples = expand_dims(data, 0)
data_generator = ImageDataGenerator(height_shift_range=0.5)
it = data_generator.flow(samples, batch_size=1)
for i in range(9):
plt.subplot(330 + 1 + i)
batch = it.next()
result = batch[0].astype('uint8')
plt.imshow(result)
plt.show()
我们的结果将如下所示:
将水平移动变换应用到我们的狗图像:
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
image = Image.open('dog.jpg')
data = img_to_array(image)
samples = expand_dims(data, 0)
it = data_generator.flow(samples, batch_size=1)
for i in range(9):
plt.subplot(330 + 1 + i)
batch = it.next()
result = batch[0].astype('uint8')
plt.imshow(result)
plt.show()
我们的结果将如下所示:
彩色空间
在这里,我们将应用我们的狗图像的颜色通道空间的转换。这里发生的事情是,它隔离了一个单一的颜色通道(R,G 或 B ),结果是图像的一个明亮或黑暗的版本。通过简单地在ImageDataGenerator
类中指定brightness_range
值(通常是一个元组或两个浮点数的列表),我们可以设置亮度偏移值进行选择。
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
image = Image.open('dog.jpg')
data = img_to_array(image)
samples = expand_dims(data, 0)
datagen = ImageDataGenerator(brightness_range=[0.2,1.0])
it = datagen.flow(samples, batch_size=1)
for i in range(9):
plt.subplot(330 + 1 + i)
batch = it.next()
result = batch[0].astype('uint8')
plt.imshow(result)
plt.show()
结果集是:
变焦
顾名思义,我们可以通过简单地传入ImageDataGenerator
类的zoom_range
属性,对我们的狗图像应用变换来获得图像的放大/缩小版本。
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
image = Image.open('dog.jpg')
data = img_to_array(image)
samples = expand_dims(data, 0)
datagen = ImageDataGenerator(zoom_range=[0.2,1.0])
it = datagen.flow(samples, batch_size=1)
for i in range(9):
plt.subplot(330 + 1 + i)
batch = it.next()
result = batch[0].astype('uint8')
plt.imshow(result)
plt.show()
结果集是:
轻弹
应用翻转变换允许我们通过setting vertical_flip=True
或horizontal_flip=True
水平或垂直改变图像的方向。
from numpy import expand_dims
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
image = Image.open('dog.jpg')
data = img_to_array(image)
samples = expand_dims(data, 0)
datagen = ImageDataGenerator(vertical_flip=True)
it = datagen.flow(samples, batch_size=1)
for i in range(9):
plt.subplot(330 + 1 + i)
batch = it.next()
result = batch[0].astype('uint8')
plt.imshow(result)
plt.show()
我们的结果集是:
有了我们生成的这个新数据集,我们可以清理它,并消除扭曲的图像或那些包含无意义信息的图像。然后,它可以用于训练对象检测模型或狗分类器。
结论
机器学习算法允许你进行大规模的图像处理,并且有很好的细节。我希望你对图像处理如何用于机器学习有所了解,不要忘记图像处理与计算机视觉不一样!
是什么造就了一个成功的机器学习工程师?我的故事
你已经做机器学习有一段时间了,你开始注意到你在整个项目中的工作量并不是恒定的。有高潮,有需要你全身心投入的任务,也有低谷,你主要监督你以前启动的过程。
在低谷时,你可以做很多不同的事情。你可以利用这段时间,投入到你等待名单上的下一个项目中。或者同时处理多项任务,遵循循序渐进的项目管理方法。这个没有严格的规定。这取决于你的个人偏好,以及你对工作场所的管理。
那些时间紧迫的 ML 工程师很可能会从事其他项目来保证进度。但是其他人,有一点空闲,有更多的选择可以考虑:
- 你可能只是放松一下,直到更艰巨的任务出现在你面前。辛苦工作一段时间后休息一下总是个好主意。你不可能一直保持每分钟 1000 转的速度,大脑需要休息才能正常工作。
- 你可能渴望做些别的事情,在这种情况下,你可以把你的空闲时间投入到整个世界的事情中。
我们将要谈论这些事情。对于机器学习工程师来说,有很多选择值得考虑,其中许多我自己也做过,可以自信地推荐。
如果你是机器学习领域的专业人士,你已经做了一件不可思议的工作。当然,你已经学到了很多,做了功课。你所获得的知识是难以置信的强大和有价值的。现在你有了这个优势,有很多方法来应用它,以便成为赚最多钱和最有影响力的专家。
我在这篇文章中建议的选择很容易用你已经有的经验来做。无论你是大三,大四,还是中级机器学习工程师,你的成绩都不重要。你仍然可以遵循这篇文章的建议,将自己提升到一个更好的市场位置。
我们将主要谈论兼职空缺,当你在主要工作场所或项目中有休息时间时,你可以转到这个空缺。当你感觉精力过剩时,你可以多跑一英里。
为什么项目工作量会随着时间的推移而不一致?
在你的机器学习项目中,不一致的工作负荷是意料之中的。经验丰富的 ML 工程师知道每个项目都有自己的生命周期。机器学习团队从来不会在所有不同的成熟阶段都 100%参与项目。每个阶段都是独特的,需要不同的团队和个人做出不同程度的贡献。
每个机器学习项目都有六个不同的阶段:
- 问题(业务)理解;
- 数据收集;
- 数据标注;
- 数据角力;
- 模型开发、培训和评估;
- 生产环境中的模型部署和维护。
你可能已经熟悉了这些阶段。如果你想更新细节,请查看“机器学习项目的生命周期:有哪些阶段?”,每个项目阶段都有非常彻底的评审。
机器学习工程师通常将大部分时间花在数据争论这一步。这是我们处理数据、进行探索性数据分析(EDA)和完成特性准备的时候。在这个阶段,ML 工程师通常非常忙碌,高度参与项目。
还有一些阶段,ML 工程师不需要太多的参与,如果有的话。例如,数据注释通常由第三方执行,因此不需要 ML 工程师干预,除非出现问题。
再比如模特培训阶段。当培训工作启动时,我们只是想随着时间的推移跟踪模型性能,看看它是如何变化的。如果这个过程没有任何问题,我们一般不会干涉。
如果我们将 ML 项目阶段分成两组:需要 ML 团队参与的阶段和不需要 ML 团队参与的阶段,我们会得到以下结果:
需要 ML 团队参与的阶段 | 无需 ML 团队参与即可完成的阶段 |
---|---|
【数据收集(通常由数据工程师执行)
|
| | |
|
模型开发与评估
| |
| |
生产环境中的模型部署和维护
|
现在是有趣的部分——右边的四个阶段是你可能找到成为更成功的机器学习工程师的正确兼职活动的地方。
成为一名成功的机器学习工程师需要什么?
你可能会问自己:“我到底为什么要做额外的活动?我已经有工作了。报酬很高。我的工作生活平衡得很好。是不是该静下心来好好享受一下了?”
即使采用这种方法,您仍然可以定期学习新的东西,并不断扩展您的技能,因为这是任何专业 IT 角色都需要的。科技是一个快节奏的环境。特别是在 ML 中,新的工具和技术不断改变着工程师的工作方式。
要想在科技领域取得成功,你必须始终站在你所在领域的前沿。总是比现在的现状领先一步,而现在的现状可能明天就过时了。所以如果你的工作已经够累了,你不想做额外的工作,这是可以理解的。
但是,只要有可能,而且你有足够的精力去做,我建议你采取两个行动,让你在游戏中保持领先:
- 让学习成为你日常生活的一部分;
- 参与多个项目;
第一个很简单。每天尽可能多地向你的大脑灌输新知识。
第二点,在多个项目上工作,需要更多的解释。
第一,不要通过金融的镜头来看这个。拥有多份工作的主要好处是获得多种收入来源。这是给你自己一个机会,或者更深入地钻研一个特定的主题,或者拓宽你的知识面,获得新的技能。让我举几个例子来让你相信多任务处理的强大。
想象一下,你即将完成一个有趣的机器学习项目。你的模特正在接受最后的训练,你有一些空闲时间。你该怎么办?
一种选择是写一篇文章,介绍你的发现和你用来解决刚刚解决的问题的方法。它会加深你的知识,让你更好地解释你的工作。您将与他人分享您的知识,为全球机器学习社区的发展做出贡献。另外,发表的文章是你知识的证明。作为机器学习专家可以得到更多的认可。最后,如果你找到合适的机会,你可以从你的文章中获得报酬,给你一点额外的收入。
一个很好的机会,不是吗?写作还会提高你的写作技能,这在工作场所大有帮助。善于用文字装扮自己的思想,是一种难得的技能。
再比如。你在考虑参加机器学习竞赛。有很多可以选择。仅 Kaggle 一家就提供了许多不同的机会。你可能会选择一个你已经精通的领域和主题,并争夺一个奖项(可能达到数百万美元)。或者,你可能想选择一个你几乎没有经验的领域,并在与专家团队合作的同时提升你在这个领域的知识。
你将拓宽你的经验,获得新的技能,享受竞争的刺激。如果你的成绩名列前茅,你还有机会为你的工作赢得额外的奖励。
作为一名机器学习工程师,你可以参与的每一项额外活动都将有利于你的成长。你会做得更好,你的收入会反映出来。
好了,我们谈了一点关于写文章的内容——这是你可以做的一项额外活动。还有什么?让我们看看你有哪些主要选择。
所有机器学习工程师都应该知道的增长机会
如果你有信心做一些额外的工作来从你的知识中获得更多,这里有一个基本活动的列表供你考虑。
教学
学习机器学习是艰难的。你已经度过了最困难的部分,但是你可以帮助你经验不足的同事。
有些学生纠结于 Python。其他人发现很难理解让机器学习算法运行的复杂数学概念。这里的关键是,所有这些人都需要一个更有经验的导师的支持。你可以当家教!
在线教育让学习新事物变得简单,只需点击几下鼠标。许多平台为学生提供教育项目,通常为新的和令人兴奋的职业道路打开大门。
你自己可能也上过 MOOC 课程。如果是这样的话,你知道通常会有一个辅助人员来指导学生走向新的职业生涯。它通常是这样工作的:
- 导师和老师回答技术和项目相关的问题;
- 社区经理帮助学生保持积极性,并涵盖大多数非技术问题;
- 职业加速团队与潜在雇主联系,并最终获得工作机会。
整个协助团队通常由有经验的人组成,他们有一个主要职业,但决定通过参加教育项目来丰富他们的工作。
作为一名机器学习工程师,你可以成为世界各地学生的导师或老师。这会消耗掉你的一些时间,因为这平均每周需要 10 个小时左右。
导师们可以指望他们花在学生身上的时间得到相当不错的回报。作品全面上线。无论您身在何处,使用何种设备,都无关紧要。你所需要的只是一个良好的互联网连接和你的大脑。如果你喜欢与他人分享你的经验和知识,这将是一个非常好的机会。
根据学校的不同,领导一个学生团体可能需要一年的时间。一方面,这很好——你签了一份持续时间更长的合同。没有必要每个月都去寻找另一个额外的活动,因为上一个活动已经结束了。另一方面,一年的承诺是一个难以承受的负担,所以要慎重决定。
写作
我们之前讨论过写作,我一直在强调它有多酷!机器学习本质上是实验性的。在处理一项特定的任务时,您可能会尝试多种备选方法来找到您所拥有的数据的最佳解决方案。我们摆弄参数、算法、扩充、预处理和许多其他变量。有时,这类实验的结论令人难以置信地震惊。足够让其他机器学习工程师乐于从你的经验中学习,并采用你能够实现的最佳实践。
写作的另一个途径是写指导性文章(有点像你正在读的那篇)。它们是读者启动和运行某些东西或改变他们做事方式的指南。如果你写的是很酷的新技术,比如一个还不太流行但看起来很有前途的图书馆,那么这类文章的覆盖范围会特别广。
有时,除了阅读官方文档之外,参考这些文章也很方便。文档通常涉及一个玩具项目,而一些写自己文章的人可以展示这项技术在现实生活项目中的表现。这样的实现总是很有趣,因为它们向我们展示了在一个真实问题上的真实经验,以及可能出现的所有优点和缺点。
为了将你的领域知识和写作技能转化为一份高薪的兼职,你应该找一个赞助人一起工作。你可能会惊讶地听到有很多人在找你——一位愿意分享你的知识的经验丰富的机器学习工程师。做一个快速搜索(“机器学习作家的工作”就可以),寻找相关的职位空缺。我相信你会发现许多有吸引力的机会。或者,你可以去你最喜欢的行业杂志或博客,直接联系他们为他们写作。他们通常对新内容非常感兴趣,所以也要准备好接受他们的多次邀请。
至于这个问题的财务方面,你可能希望你的工作能得到体面的报酬。根据你的主题、文章量和内容质量,你可能期望每篇文章高达 500 美元。不错吧?
参加行业会议
在别人面前展示你的工作的另一种方式是参加相关的会议。作为一名演讲者,你有很多好处。首先,你的经历可能会让你成为其他团队和公司感兴趣的候选人。会议中的人际关系网可能会让你接触到一些新的、有趣的联系人和机会,而这些是你从其他途径得不到的。
不足为奇的是,如今几乎所有的会议发言都会被录制下来并上传到 YouTube 或其他流媒体服务上。这样,你的谈话可以为你打开另一扇门,向新的潜在同事、赞助商和雇主展示你的知识和经验。
随着你影响力的增长,你可能希望在行业会议上露面会得到报酬。你在议程上的名字会吸引其他人来听你讲话。在这个领域建立你的个人品牌,享受它带来的好处。
参加机器学习竞赛
是的,我们以前讨论过这个问题,但让我分享一些我在 Kaggle 上检查多个比赛的排行榜时所做的观察。我注意到,大多数参加这些比赛并获得最佳表现的团队不仅仅是由一群在网上找到彼此并聚在一起的人组成的团队。他们通常是已经一起工作了很长时间的团队。
这样的团队通常在每个成员所拥有的技能方面都很均衡。他们彼此了解,知道如何在团队中有效协作。他们可以访问计算资源,并且项目工作流已经建立。他们参加竞赛不仅是为了提高他们的技能和扩大他们的经验,也是为了获得他们所拥有的知识和专长的额外经济利益。
你和你的团队呢?如果你已经为你的公司解决了复杂的问题,你可能也解决了一个竞争问题。至少,为了一路走来获得的经验和知识,值得一试。即使你没有赢,你仍然会成为一支更强的队伍。在我看来这是双赢!
当自由职业者
机器学习有很多自由职业的机会。自由职业者的项目可能会大相径庭。他们中的一些人需要在某个特定领域有深厚的专业知识。其他人可能只需要 Python 和常见 ML 库的基础知识。毫不夸张地说,每个人都有自己的项目。
大多数有自由职业项目的网站都有非常丰富的过滤功能,所以你可以专门搜索符合你需求的项目。
或者,你可以设定一个你希望得到的最低报酬水平,这样你就只能看到在预期报酬范围内的项目。能力是无穷无尽的。如果你看得够久,你一定会为自己找到一个好机会。
作为一名自由职业者,你可以自己当老板,只在你需要的时候做额外的工作。这也是参与不同行业相关项目的一种很酷的方式,你不需要拘泥于你已经是专家的行业。
就我个人而言,我在银行业工作,我处理的大部分数据都是客户交易的历史记录。在这个行业干了几年,感觉已经习惯了这种数据,甚至有点厌烦。自由职业给了我参与一个完全不同的项目的机会,对我来说探索一个全新的数据集真的很有趣。此外,我从自由职业项目中获得的见解让我看到了银行数据的一些新机会。我能够将新知识转移到我主要工作场所的数据和项目中。
结论
作为一名机器学习工程师,你有一套非常有价值的技能和知识可以与世界分享。我们已经讨论了从您的专业知识中获取最大利润的五个机会。所有这些都可以很好地配合你的主要工作。额外的活动补充了你的整体发展,让你成为更有价值的机器学习专家。
如果你喜欢基于项目的工作,你肯定会喜欢自由职业。如果你想在一个全新的环境中尝试,考虑参加教育项目和/或行业会议。
如果你喜欢分享你的知识,写作是一个很好的机会。另外,看到你的文章发表在一个受欢迎的博客或杂志上是一种非常好的感觉。
不要等着。如果你有空闲时间和多余的精力,尝试这些活动中的任何一种,并且随着时间的推移尽可能多地尝试它们。即使只有一项活动坚持了很长时间,它仍然是加速你作为机器学习工程师成长的一个很好的方式。
何时选择 CatBoost 而不是 XGBoost 或 light GBM[实用指南]
原文:https://web.archive.org/web/https://neptune.ai/blog/when-to-choose-catboost-over-xgboost-or-lightgbm
Boosting 算法已经成为对结构化(表格)数据进行训练的最强大的算法之一。为赢得 ML 竞赛提供了各种方法的三个最著名的 boosting 算法实现是:
- 1 催化增强
- 2 XGBoost
- 3 灯 GBM
在本文中,我们将主要关注 CatBoost,它与其他算法相比如何,以及何时应该选择它。
梯度增强概述
为了理解 boosting,我们必须首先理解集成学习,这是一套结合来自多个模型(弱学习器)的预测以获得更好的预测性能的技术。它的策略就是团结的力量,因为弱学习者的有效组合可以产生更准确和更健壮的模型。集成学习方法的三个主要类别是:
- Bagging: 该技术使用数据的随机子集并行构建不同的模型,并确定性地聚合所有预测者的预测。
- Boosting :这种技术是迭代的、连续的、自适应的,因为每个预测器都修正了其前一个预测器的误差。
- 堆叠:这是一种元学习技术,涉及结合多种机器学习算法的预测,如 bagging 和 boosting。
1988 年,Micheal Kearns 在他的论文关于假设提升的思考中,提出了一个相对较差的假设是否可以转化为非常好的假设的想法。本质上是一个学习能力差的人是否可以通过改造变得更好。从那以后,已经有许多成功的技术应用来开发一些强大的 boosting 算法。
The most popular boosting algorithms: Catboost, XGBoost, LightGBM | Source: Author
scope 中的三种算法(CatBoost、XGBoost 和 LightGBM)都是梯度增强算法的变体。随着我们的进展,对梯度推进的良好理解将是有益的。梯度推进算法可以是回归器(预测连续目标变量)或分类器(预测分类目标变量)。
这种技术涉及使用梯度下降优化过程,基于最小化弱学习者的微分损失函数来训练学习者,这与像自适应增强(Adaboost)那样调整训练实例的权重相反。因此,所有学习者的权重是相等的。梯度提升使用串联的决策树作为弱学习器。由于它的顺序架构,它是一个阶段式的加法模型,每次添加一个决策树,现有的决策树不变。
梯度增强主要用于减少模型的偏差误差。基于偏差-方差权衡,它是一种贪婪算法,可以快速地过拟合训练数据集。然而,这种过拟合可以通过收缩、树约束、正则化和随机梯度增强来控制。
CatBoost 概述
CatBoost 是一个开源的机器学习(梯度提升)算法,其名字由“ 类别 ”和“ 提升 ”杜撰而来它是由 Yandex (俄罗斯谷歌)在 2017 年开发的。Yandex 表示,CatBoost 已被广泛应用于推荐系统、搜索排名、自动驾驶汽车、预测和虚拟助手等领域。它是在 Yandex 产品中广泛使用的 MatrixNet 的继任者。
CatBoost 的主要特性
让我们来看看使 CatBoost 优于其同类产品的一些关键特性:
- 对称树 : CatBoost 构建对称(平衡)树,不像 XGBoost 和 LightGBM。在每一步中,前一棵树的叶子都使用相同的条件进行分割。考虑到最低损失的特征分割对被选择并用于所有级别的节点。这种平衡树结构有助于有效的 CPU 实现,减少预测时间,使模型应用程序更快,并在该结构用作正则化时控制过拟合。
Asymmetric tree vs symmetric tree | Source: Author
-
有序推进:由于被称为预测偏移的问题,经典推进算法容易在小/有噪声的数据集上过度拟合。计算数据实例的梯度估计值时,这些算法使用构建模型时使用的相同数据实例,因此不会遇到看不见的数据。另一方面,CatBoost 使用有序提升的概念,这是一种排列驱动的方法,用于在数据子集上训练模型,同时在另一个子集上计算残差,从而防止目标泄漏和过度拟合。
-
原生特性支持: CatBoost 支持所有类型的特性,无论是数字、分类还是文本,节省了预处理的时间和精力。
数字特征
CatBoost 像其他基于树的算法一样处理数字特征,即通过基于信息增益选择最佳可能的分割。
Numerical features | Source: Author
分类特征
决策树基于类别而不是连续变量中的阈值来分割分类特征。分割标准是直观的,因为类被分成子节点。
Categorical features | Source: Author
类别特征在高基数特征中可能更复杂,如' id 特征。每个机器学习算法都需要解析数字形式的输入和输出变量;CatBoost 提供了各种本地策略来处理分类变量:
- 单热编码:默认情况下,CatBoost 用单热编码表示所有二进制(两类)特征。通过改变训练参数one _ hot _ max _ size=N .CatBoost通过指定分类特征和类别来处理一键编码,可以将该策略扩展到具有 N 数量类别的特征,以产生更好、更快、更高质量的结果。
** 基于类别的统计: CatBoost 应用随机排列的目标编码来处理类别特征。这种策略对于高基数列非常有效,因为它只创建了一个新的特性来说明类别编码。将随机排列添加到编码策略是为了防止由于数据泄漏和特征偏差导致的过拟合。你可以在这里详细了解。
- 贪婪搜索组合: CatBoost 还自动组合分类特征,大多数情况下是两个或三个。为了限制可能的组合,CatBoost 不会枚举所有的组合,而是使用类别频率等统计数据来枚举一些最佳组合。因此,对于每个树分割,CatBoost 会将当前树中先前分割已经使用的所有分类特征(及其组合)与数据集中的所有分类特征相加。
文本特征
CatBoost 还通过使用单词包(BoW)、Naive-Bayes 和 BM-25(用于多类)提供固有的文本预处理来处理文本特征(包含常规文本),以便从文本数据中提取单词、创建词典(字母、单词、grams)并将其转换为数字特征。这种文本转换是快速的、可定制的、生产就绪的,并且也可以用于其他库,包括神经网络。
- 排名:排名技术主要应用于搜索引擎,解决搜索相关性问题。排名可以在三个目标函数下大致完成:点方式、成对方式和列表方式。这三个目标函数在较高层次上的区别在于训练模型时考虑的实例数量。
CatBoost 有一个排名模式——CatBoostRanking就像 XGBoost ranker 和 LightGBM ranke r 一样,但是,它提供了比 XGBoost 和 LightGBM 更强大的变化。这些变化是:
- 排名(yetirank,yetirankpairwise)
- 成对(PairLogit,PairLogitPairwise)
- 排名+分类(QueryCrossEntropy)
- 排名+回归(QueryRMSE)
- 选择前 1 名候选人(QuerySoftMax)
CatBoost 还提供了排名基准,通过不同的排名变化来比较 CatBoost、XGBoost 和 LightGBM,其中包括:
- CatBoost : RMSE、QueryRMSE、pairlogit、pairlogitpairwise、yetirank、yetirankpairwise
- XGBoost : reg:线性,xgb-lmart-ndcg,XG b-成对
- LightGBM : lgb-rmse,LG b-成对
这些基准评估使用了四(4)个排名靠前的数据集:
- 百万查询数据集来自 TREC 2008, MQ2008 ,(训练和测试折叠)。
- 微软 LETOR 数据集(we b-10K)(第一套,训练,测试折叠)。
- 雅虎 LETOR 数据集 (C14),雅虎(第一套,set1.train.txt 和 set1.test.txt 文件)。
- Yandex LETOR 数据集、Yandex(features.txt.gz 和 featuresTest.txt.gz 文件)。
使用平均 NDCG 度量进行性能评估的结果如下:
可以看出,CatBoost 在所有情况下都优于 LightGBM 和 XGBoost。可以在 CatBoost 文档这里找到更多关于分级模式变化及其各自性能指标的详细信息。这些技术可以在 CPU 和 GPU 上运行。
- 速度 : CatBoost 通过支持多服务器分布式 GPU(支持多主机加速学习)和容纳旧 GPU 来提供可扩展性。它在大型数据集上设置了一些 CPU 和 GPU 训练速度基准,如 Epsilon 和 Higgs 。它的预测时间比 XGBoost 和 LightGBM 快;这对于低延迟环境极其重要。
Dataset Epsilon (400K samples, 2000 features). Parameters: 128 bins, 64 leafs, 400 iterations | Source: Author
Dataset Higgs (4M samples, 28 features). Parameters: 128 bins, 64 leafs, 400 iterations | Source: Author
Prediction time on CPU and GPU respectively on the Epsilon dataset | Source: Author
- 模型分析: CatBoost 提供固有的模型分析工具,在高效的统计和可视化的帮助下,帮助理解、诊断和提炼机器学习模型。其中一些是:
特征重要性
CatBoost 有一些智能技术,可以为给定模型找到最佳特性:
- 预测值变化:显示预测值相对于特征值变化的平均变化量。由于特征导致的预测变化的平均值越大,重要性越高。要素重要性值被归一化以避免否定,所有要素的重要性都等于 100。这很容易计算,但可能会导致排名问题的误导性结果。
Feature Importance based on PredictionValuesChange | Source: Author
- LossFunctionChange: 这是一种繁重的计算技术,通过获取包括给定特征的模型的损失函数与没有该特征的模型之间的差异来获得特征重要性。差异越大,该特征越重要。
Feature Importance based on LossFunctionChange | Source: Author
- InternalFeatureImportance:该技术使用路径对称树叶上的节点中的分割值来计算每个输入要素和各种组合的值。
Pairwise feature importance | Source: Author
- SHAP: CatBoost 使用SHAP(SHapley Additive exPlanations)将一个预测值分解成每个特征的贡献。它通过测量要素对单个预测值(与基线预测相比)的影响来计算要素重要性。这种技术提供了对模型决策影响最大的特征的可视化解释。SHAP 有两种应用方式:
每个数据实例
First prediction explanation (Waterfall plot) | Source: Author
上面的可视化显示了将模型输出从基础值(训练数据集上的平均模型输出)推至模型输出的要素。红色要素将预测值推高,而蓝色要素将预测值推低。这个概念可以用力图来形象化。
First prediction explanation (Force plot) | Source: Author
整个数据集
SHAP 提供了绘图功能来突出显示模型的最重要的特征。该图按所有数据实例的 SHAP 值大小的总和对要素进行排序,并使用 SHAP 值来突出显示每个要素对模型输出的影响分布。
Summarized effects of all the features | Source: Author
特征分析图表
这是 CatBoost 集成到其最新版本中的另一个独特功能。该功能提供计算和绘制的特定于要素的统计数据,并可视化 CatBoost 如何为每个要素拆分数据。更具体地说,统计数据是:
- 每个条柱(条柱对连续要素进行分组)或类别(当前仅支持一个热编码要素)的平均目标值。
- 每个箱的平均预测值
- 每个箱中数据实例(对象)的数量
- 各种特征值的预测
Statistics of feature | Source: Author
CatBoost 参数
CatBoost 与 XGBoost 和 LightGBM 有共同的训练参数,但提供了一个非常灵活的参数调整界面。下表提供了三种增强算法提供的参数的快速比较。
功能 | CatBoost | XGBoost | LightGBM |
---|---|---|---|
控制过拟合的参数
|
–学习 _ 速率
–深度
–L2 _ reg
|
–学习 _ 速率
–最大 _ 深度
–最小 _ 孩子 _ 体重
|
–learning _ rate
–Max _ depth
–Num _ leaves
–min _ data _ in _ leaf
|
|
用于处理分类值的参数
|
–猫 _ 特性
–one _ hot _ max _ size
| | |
|
控制速度的参数
| |
–col sample _ bytree
–子样本
–n _ estimates
|
–feature _ fraction
T5–bagging fraction
–num _ iterations
|
此外,从下图可以明显看出,CatBoost 的默认参数提供了一个优秀的基线模型,比其他增强算法好得多。
你可以在这里阅读所有关于 CatBoost 的参数。这些参数控制过度拟合、分类特征和速度。
Log loss values (lower is better) for Classification mode.
The percentage is metric difference measured against tuned CatBoost results | Source: Author
其他有用的功能
过拟合检测器: CatBoost 的算法结构抑制了梯度提升偏差和过拟合。此外,CatBoost 有一个过拟合检测器,如果发生过拟合,它可以在训练参数指示之前停止训练。CatBoost 使用两种策略实现过拟合检测:
- Iter:考虑过拟合模型,使用具有最优度量值的迭代,在指定的迭代次数后停止训练。与其他梯度增强算法(如 LightGBM 和 XGBoost)一样,该策略使用 early_stopping_rounds 参数。
- IncToDec:当达到阈值时忽略过拟合检测器,并在用最佳度量值迭代后继续学习指定的迭代次数。通过在参数中设置“od_type”来激活过拟合检测器,以产生更一般化的模型。
- 缺失值支持 : CatBoost 为处理缺失值提供了三种固有的缺失值策略:
- “禁止”:缺少的值被解释为错误,因为它们不受支持。
- “最小值”:缺失值被处理为所观察特征的最小值(小于所有其他值)。
- “最大值”:缺失值被视为所观察特征的最大值(大于所有其他值)。CatBoost 只有数值的缺失值插补,默认模式为最小。
- CatBoost viewer :除了 CatBoost 模型分析工具,CatBoost 还有一个独立的可执行应用,用于在浏览器中绘制具有不同训练统计数据的图表。
- 交叉验证 : CatBoost 允许对给定数据集进行交叉验证。在交叉验证模式中,训练数据被分成学习和评估两部分。
- 社区支持 : CatBoost 有一个庞大且不断增长的开源社区,提供大量关于理论和应用的教程。
- CatBoost 与 XGBoost 和 LightGBM:性能和速度的实际比较
前面几节介绍了 CatBoost 的一些特性,这些特性将作为选择 CatBoost 而不是 LightGBM 和 XGBoost 的有力标准。本节将有一个实践经验,我们将使用一个航班延误预测问题来比较性能和速度。
数据集和环境
该数据集包含 2015 年大型航空运营商运营的国内航班准点性能数据,由美国交通部(DOT)提供,可在 Kaggle 上找到。这种比较分析使用 CatBoost、LightGBM 和 XGBoost 探索和模拟具有可用独立特征的航班延误。该数据的一个子集(25%)用于建模,并且将使用 ROC AUC 评分评估各个生成的模型。在测量训练时间、预测时间和参数调整时间时,分析将涵盖默认和调整的设置。
为了便于比较,我们将使用 neptune.ai ,这是一个用于 MLOps 的元数据存储库,为可能涉及大量实验的项目而构建。具体来说,我们将使用 neptune.ai 来:
所以,事不宜迟,我们开始吧!
通过 Neptune-XGBoost 集成和 Neptune-LightGBM 集成,检查在使用 XGBoost 或 LightGBM 时如何跟踪您的模型构建元数据。
首先,我们必须安装所需的库。
导入已安装的库。
!pip install catboost
!pip install xgboost
!pip install lgb
!pip install neptune-client
设置 Neptune 客户机来适当地记录项目的元数据。你可以在这里阅读更多相关信息。
import lightgbm as lgb
import xgboost as xgb
import catboost as cb
import timeit
import pandas as pd
import numpy as np
import neptune.new as neptune
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import roc_auc_score
数据预处理和争论操作可以在参考笔记本中找到。我们将使用 30%的数据作为测试集。
import neptune.new as neptune
run = neptune.init(project='<YOUR_WORKSPACE/YOUR_PROJECT>',
api_token='<YOUR_API_TOKEN>')
模型
X = data_df.drop(columns=['ARRIVAL_DELAY'])
y = data_df['ARRIVAL_DELAY']
X_train, X_test, y_train, y_test= train_test_split(X,y, random_state=2021, test_size=0.30)
接下来,让我们定义度量评估函数和模型执行函数。指标评估功能记录 ROC AUC 得分。
现在转到模型执行函数,它接受四个主要参数:
def metrics(run, y_pred_test):
score = roc_auc_score(y_test, y_pred_test)
run['ROC AUC score'] = score
模型:生成的各个机器学习模型即 LightGBM、XGBoost 和 CatBoost
- 描述:模型执行实例的描述
- 键:键指定模型训练设置,尤其是要实现的分类特征参数
- cat_features: 用作分类特征名称(对于 LightGBM)或索引(CatBoost)
- 该函数计算并记录元数据,包括描述、训练时间、预测时间和 ROC AUC 分数。
让我们在两种设置下运行相应模型的功能:
def run_model(run, model, description, key, cat_features=''):
if key =='LGB':
run["Description"] = description
start = timeit.default_timer()
model.fit(X_train,y_train, categorical_feature=cat_features)
stop = timeit.default_timer()
run['Training time'] = stop - start
start = timeit.default_timer()
y_pred_test = model.predict(X_test)
stop = timeit.default_timer()
run['Prediction time'] = stop - start
metrics(y_pred_test)
elif key =='CAT':
run["Description"] = description
start = timeit.default_timer()
model.fit(X_train,y_train,
eval_set=(X_test, y_test),
cat_features=cat_features,
use_best_model=True)
stop = timeit.default_timer()
run['Training time'] = stop - start
start = timeit.default_timer()
y_pred_test = model.predict(X_test)
stop = timeit.default_timer()
run['Prediction time'] = stop - start
metrics(y_pred_test)
else:
run["Description"] = description
start = timeit.default_timer()
model.fit(X_train,y_train)
stop = timeit.default_timer()
run['Training time'] = stop - start
start = timeit.default_timer()
y_pred_test = model.predict(X_test)
stop = timeit.default_timer()
run['Prediction time'] = stop - start
metrics(y_pred_test)
1.CatBoost vs XGBoost vs LightGBM:默认超参数
可以在 Neptune 仪表板上查看基于 LightGBM、XGBoost 和 CatBoost 算法的默认设置的比较分析。
model_lgb_def = lgb.LGBMClassifier()
run_model(model_lgb_def,'Default LightGBM without categorical support', key='LGB')
model_lgb_cat_def = lgb.LGBMClassifier()
run_model(model_lgb_cat_def, 'Default LightGBM with categorical support',key='LGB', cat_features=cat_cols)
model_xgb_def = xgb.XGBClassifier()
run_model(model_xgb_def, 'Default XGBoost', key='XGB')
model_cat_def = cb.CatBoostClassifier()
run_model(model_cat_def,'Default CatBoost without categorical support', key='CAT')
model_cat_cat_def = cb.CatBoostClassifier()
cat_features_index = [3,4,5]
run_model(model_cat_cat_def,'Default CatBoost with categorical support','CAT', cat_features_index)
结果:默认设置
从仪表板上可以明显看出:
CatBoost 在没有分类支持的情况下具有最快的预测时间,因此在有分类支持的情况下显著增加。
- 对于测试数据,CatBoost 的 AUC 指标得分最高(AUC 得分越高,模型区分类别的性能越好)。
- 与 LightGBM 相比,XGBoost 在默认设置下的 ROC-AUC 得分最低,训练时间相对较长,但是其预测时间很快(在相应的默认设置运行中时间第二快)。
- 在训练时间上,LightGBM 的表现优于所有其他型号。
- 2.CatBoost vs XGBoost vs LightGBM:优化的超参数
以下是我们将在这次运行中使用的优化的超参数。三种算法中所选的参数非常相似:
“最大深度”和“深度”控制树模型的深度。
- “learning_rate”说明了添加到树模型的修改量,并描述了模型学习的速度。
- n_estimators 和 iterations 说明了树(轮)的数量,突出了增加迭代的数量。CatBoost‘l2 _ leaf _ reg’表示 L2 正则化系数,以阻止学习更复杂或灵活的模型,从而防止过拟合。
- 而 LightGBM num_leaves 参数对应于每棵树的最大叶子数,XGBoost‘min-child-weight’表示每个节点中所需的最小实例数。
- 这些参数被调整以控制过拟合和学习速度。
LightBGM | XGBoost | CatBoost | |
---|---|---|---|
max _ depth:7
learning _ rate:0.08
num _ leaves:100
n _ estimates:1000
| 最大深度:7 | 最大深度:5 | 深度:10 |
| | | | |
超参数调谐部分可在参考笔记本中找到。
现在让我们用前面提到的调整设置运行这些模型。
同样,基于调优设置的比较分析可以在 Neptune 仪表盘上查看。
params = {"max_depth": 7, "learning_rate" : 0.08, "num_leaves": 100, "n_estimators": 1000}
model_lgb_tun = lgb.LGBMClassifier(boosting_type='gbdt', objective='binary', metric='auc',**params)
run_model(model_lgb_tun, 'Tuned LightGBM without categorical support', 'LGB')
model_lgb_cat_tun = lgb.LGBMClassifier(boosting_type='gbdt', objective='binary', metric='auc',**params)
run_model(model_lgb_cat_tun, 'Tuned LightGBM with categorical support', 'LGB', cat_cols)
params = {"max_depth": 5, "learning_rate": 0.8, "min_child_weight": 6, "n_estimators": 1000}
model_xgb_tun = xgb.XGBClassifier(**params)
run_model(model_xgb_tun, 'Tuned XGBoost','XGB')
params = {"depth": 10, "learning_rate": 0.5, "iterations": 1000, "l2_leaf_reg": 5}
model_cat_tun = cb.CatBoostClassifier(**params)
run_model(model_cat_tun,'Tuned CatBoost without categorical support', key='CAT')
model_cat_cat_tun = cb.CatBoostClassifier(**params)
cat_features_index = [3,4,5]
run_model(model_cat_cat_tun,'Default CatBoost with categorical support','CAT', cat_features_index)
结果:调整设置
从仪表板上可以明显看出:
在分类特征支持下,CatBoost 仍然保持了最快的预测时间和最佳的性能得分。CatBoost 对分类数据的内部识别允许它产生最慢的训练时间。
- 尽管进行了超参数调优,但默认结果和调优结果之间的差异并不大,这也凸显了 CatBoost 的默认设置会产生很好的结果这一事实。
- XGBoost 性能随着调整的设置而提高,但是,它产生了第四好的 AUC-ROC 分数,并且训练时间和预测时间变得更差。
- LightGBM 仍然拥有最快的训练时间和最快的参数调整时间。然而,如果你愿意在更快的训练时间和性能之间做出权衡,CatBoost 将是一个很好的选择。
- 结论
CatBoost 的算法设计可能类似于“老”一代 GBDT 模型,但是,它有一些关键属性,如:
排序目标函数
- 自然分类特征预处理
- 模型分析
- 最快预测时间
- CatBoost 还提供了巨大的性能潜力,因为它在缺省参数下表现出色,在调优时显著提高了性能。本文旨在通过讨论这些关键特性及其提供的优势,帮助您决定何时选择 CatBoost 而不是 LightGBM 或 XGBoost。我希望现在你对此有一个很好的想法,下次你面临这样的选择时,你将能够做出明智的决定。
如果你想更深入地了解这一切,下面的链接将帮助你做到这一点。暂时就这样吧!
If you would like to get a deeper look inside all of this, the following links will help you to do just that. That’s all for now!*
训练、可视化和理解单词嵌入:深入定制数据集
原文:https://web.archive.org/web/https://neptune.ai/blog/word-embeddings-deep-dive-into-custom-datasets
人工智能(AI)发展中最强大的趋势之一是自然语言处理(NLP)领域的快速发展。这一进步主要是由深度学习技术在神经网络架构中的应用推动的,这使得像伯特和 GPT-3 这样的模型在一系列语言任务中表现得更好,这些任务之前被教导为超出了大多数 NLP 模型的范围。
虽然这些模型的全部潜力可能存在争议(更多内容见我们关于这些模型是否能真正理解语言的帖子),但毫无疑问,它们对学术界和商界的影响才刚刚开始被感受到。
因此,理解如何为您自己的用例测试和训练这些模型是很重要的。所有这些深度学习模型的一个关键部分是它们能够将语言信息编码到称为嵌入的向量中。
在这篇文章中,我们将看看你可以使用的不同技术,以更好地理解语言模型如何捕捉单词之间的上下文关系。我们将通过以下方式做到这一点:
- 查看数据集,我们需要训练这些模型,看看我们是否可以找到一个简单的方法来帮助我们可视化这些模型如何“学习”不同单词之间的关系
- 看看您可以使用哪些工具和技术来跟踪这些模型的进度,并在它们处理我们的简化数据集时监控结果
- 在那之后,你应该有希望能够在一些真实的数据集上,为更复杂的模型重用那个模板。
有许多因素使这种类型的项目变得困难。首先,语言本身是复杂的,所以很难知道一个词和另一个词的关系有多密切。这个模型说“猫”在意思上更接近“狗”或“狮子”是对的吗?其次,我们如何识别这种上下文关系?有没有我们可以用来理解相似性的分数,以及我们可以用来直观理解这种关系的方法?
我们将看看如何定制您的实验来控制其中的一些变量,以便更好地理解模型在处理文本和输出一些非常大的向量时实际上在做什么。说到矢量…
向量的世界
该信息可以包括特定单词的语义和句法方面。虽然每个词都可以被认为是一个范畴变量,即一个独立的实体,但它总是与其他词有某种联系。例如,都柏林是爱尔兰的首都。都柏林这个词因此与:
- 作为城市的事物,
- 大写的东西,
- 爱尔兰的东西
- 诸如此类…
如你所见,很难完全定义一个特定单词可能具有的所有关系。然而,这正是我们在创建嵌入时试图做的事情。
伯特和 GPT-3 等最新模型在这项任务上表现出色,因为它们可以处理大量文本,并对它们在这些嵌入中学习到的许多关系进行编码。他们的前辈是“不那么深”的神经网络,如 Word2Vec 使用类似的技术来学习单词之间的关联,并将信息编码到嵌入中。
From Jay Alammar’s amazing blog: These models, like GPT-3 here, turn the word into a vector and then do their “magic” to learn the relationship between it and other words depending on the context. (Note you should checkout Jay’s blog for all things deep learning NLP)
虽然这些技术是相似的,但它们比这些语言模型(LMs)的最新实例中使用的一些更复杂和高级的方法更容易理解。因此,这是一个展示如何训练嵌入并理解它们在被训练时所包含的信息的好地方。
希望这将帮助你在你自己的 ML 项目中应用这些技术到更高级的 LMs,跟踪你的进度,并可视化结果。
项目描述
您可能已经接触过大量关于如何创建自己的 word 嵌入的教程和示例。这些资源中的许多都是抓住主题的好方法。
从个人角度来看,我一直在努力理解这些嵌入在给定底层训练数据的情况下表现如何。例如,许多例子使用莎士比亚的作品来训练它们的嵌入。虽然我是“吟游诗人”的粉丝,但在读过他所有的作品后,很难知道“爱”、“家庭”和“战争”这些词应该有多么密切的联系。
同样,Word2Vec 上的原论文中最著名的例子就是“国王”和“王后”之间的关系。相反,我认为创建我们自己的简化语言数据集来训练我们的单词嵌入会更好。这样,我们可以控制词汇之间的关系,并更好地理解嵌入是否确实捕捉到了相关单词之间的关系。
希望这将是一个数据集,您可以使用并改进训练模式高级模型,如那些采用最新 NLP 模型使用的注意力架构的模型,如 BERT 和 GPT-3。
此外,我们将利用海王星来跟踪我们嵌入的进展,并可视化它们的关系。同样,您应该能够使用这些技术轻松地跟踪其他 NLP 项目的进展,在这些项目中,您正在训练自己的嵌入。你可以在这里查看我在 Neptune 上的公共项目,看看你按照下面的代码运行时的一些结果。
该项目的结构如下:
- 数据集:为了能够理解我们“单词”之间的关系,我们将定义我们自己的简单语言数据集。
- 模型:我们将使用 TensorFlow 教程系列中的 Word2Vec 代码。有许多方法可以使用 Word2Vec,例如在 gensim 库中。TF 教程系列的好处是,你可以看到所有血淋淋的内部,并可以改变任何你喜欢的修补和测试模型。
- 实验跟踪 :我们会在训练时设置海王星来跟踪模型的进度。我们可以用它来跟踪损失和准确性,还可以显示“单词”之间的相似性在训练过程中是如何变化的。
- 可视化:我们还将展示如何通过观看 Neptune 中的二维和三维可视化来理解玩具数据集中“单词”之间的关系。
Loss and accuracy charts available in Neptune
让我们开始创建数据集吧。
完美的语言
为了更好地展示像 Word2Vec 这样的模型如何学习单词之间的关系,我们需要创建自己的数据集。我们的目标是创建一个数据集,在这个数据集内,单词的接近度被完美地定义。举个例子,想想你脑海中闪现的任何一个词。
例如,单词“computer”是一个常见的单词,与许多其他单词有关系或“接近”。“计算机”在通常情况下可以互换使用,或者在与 PC、mac、IBM、笔记本电脑和台式机类似的上下文中使用。它通常与屏幕、程序、操作系统、软件、硬件等结合使用。当有人提到“计算机”科学家或“计算机”技术人员时,它与职业相关。
但是嘿!有些人的职业被称为“计算机”,他们负责复杂的计算。这个职业在 17 世纪被提及,当时科学家雇佣“计算机”来帮助他们进行计算,约翰尼斯·开普勒在推进他自己的科学项目之前就是这些计算机中的一员。随着 ENIAC 计算机的出现,这个职业一直繁荣到第二次世界大战结束,那时人类计算机成为了第一批程序员。
考虑到以上所有因素,人们可以期待计算机更人性化。
我们可以在这里继续下去,特定的关系通常是特定于领域的。如果你在医疗保健行业工作,那么“计算机”和 IT 或软件工程师之间的关系可能会有所不同。
这有什么意义?嗯,很难知道“计算机”与这些术语有多相似。是否应该更类似于“操作系统”而不是“笔记本电脑”或“科学家”。不知道这一点,我们将永远谈论 Word2Vec 及其“国王”和“王后”。相反,让我们创建自己的简单语言,这样我们就可以:
- 缩小词汇量,以便快速训练
- 定义测试数据集中每个句子的长度,这样我们就不需要任何填充或者增加不同长度句子的复杂性。
- 在我们的数据集中定义“单词”之间的严格关系,这样我们就可以确切地知道层次结构应该是什么
- 不包括任何连词或例外或任何混乱不规则的语言魔法,使学习一门新语言如此困难!
我能想到的最简单的方法是用一个简单的词汇,我们有 26 个基于字母表的三个字母的单词,例如“aaa”,“bbb”,“ccc”等等。
然后我们就可以定义这些“词”之间我们想要的“接近度”。“AAA”*这个简单的语言里没有大写!)例如,应该只出现在“bbb”或“ccc”旁边。“bbb”应该只出现在“ccc”或“ddd”等旁边。这样,当我们查看单词之间的相似性时,我们希望看到“aaa”在相似性方面总是接近“bbb”和“ccc ”,但应该远离“xxx”或“zzz”。
这样做的好处是你可以开始让你自己的语言变得简单或复杂。你可以开始包括更复杂的关系或连词等等。包括一个类似于“and”用法的单词,这样它就会出现在你的新语言中的任何单词旁边。然后看和不同的词有多相似。现在,我们将创建一些简单的示例来帮助您开始。
随机语言
让我们从一个随机的语言数据集开始,我们不期望你的新语言中的单词之间有任何关系。你可以在这里找到生成你自己语言的所有相关代码。
import string
from random import choice
alpha_d = dict.fromkeys(string.ascii_lowercase, 0)
vocab = {}
for c, l in enumerate(alpha_d, 0):
vocab[c] = l*3
sen_num = 30000
sen_len = 7
vocab_len = 26
text_file = open("random_vocab.txt", "a")
text_file.truncate(0)
for s in range(sen_num):
sentence = []
for w in range(0, sen_len):
i = choice(range(0, vocab_len))
sentence.append(vocab[i])
text_file.write(" ".join(sentence))
text_file.write("n")
text_file.close()
简单的语言
现在让我们用一些关系创建一个简单的语言。正如我们上面提到的,我们的语言会有相同长度的句子,这些句子中的“单词”总是彼此靠近。这就像一个简单的字母表的扩展,其中“aaa”总是靠近“bbb”和“ccc”。
import string
from random import choice
alpha_d = dict.fromkeys(string.ascii_lowercase, 0)
vocab = {}
for c, l in enumerate(alpha_d, 0):
vocab[c] = l*3
sen_num = 30000
sen_len = 7
vocab_len = 26
prev_word = None
text_file = open("proximity_vocab.txt", "a")
text_file.truncate(0)
for s in range(sen_num):
sentence = []
start_word = choice(range(0, 18))
for w in range(0, sen_len):
i = choice([x for x in range(start_word+w+0, start_word+w+3) if x not in [prev_word]])
sentence.append(vocab[i])
prev_word = i
text_file.write(" ".join(sentence))
text_file.write("n")
text_file.close()
现在让我们从 TensorFlow 教程系列中获取 Word2Vec 代码,用于训练我们的数据集,然后我们将能够通过 Neptune 跟踪和可视化结果。
Word2Vec 模型
TensorFlow 教程系列有一个文本部分,其中包括许多例子,如 BERT 和 Word2Vec。正如我们之前提到的,我们将使用 Word2Vec 模型来展示如何使用 Neptune 跟踪您的实验,以记录准确性和损失数据,以及单词之间的相似性如何变化和 3D 可视化。
我们将使用 Word2Vec 代码的精简版本,以便于运行。最初的包含了更多的信息,所以一定要检查一下。这很值得一读。这段代码的伟大之处在于,您几乎可以修改所有可用的参数。通过我们设置的跟踪功能,您将能够监控和比较这些变化。
Word2Vec 模型将读入我们创建的简单数据集,然后基于 word 2 vec 中使用的 Skip-Gram 方法创建训练示例。这种方法试图在给定单词本身的情况下预测单词的上下文。
跳格法试图在给定单词本身的情况下预测其周围的单词
您可以更改所有参数,例如 window_size ,这是您在每一步中尝试预测的上下文或相邻单词的数量。
下面的代码示例可以在一个笔记本这里找到。
def generate_training_data(sequences, window_size, num_ns, vocab_size, seed):
targets, contexts, labels = [], [], []
sampling_table = tf.keras.preprocessing.sequence.make_sampling_table(vocab_size)
for sequence in tqdm.tqdm(sequences):
positive_skip_grams, _ = tf.keras.preprocessing.sequence.skipgrams(
sequence,
vocabulary_size=vocab_size,
sampling_table=sampling_table,
window_size=window_size,
negative_samples=0)
for target_word, context_word in positive_skip_grams:
context_class = tf.expand_dims(
tf.constant([context_word], dtype="int64"), 1)
negative_sampling_candidates, _, _ = tf.random.log_uniform_candidate_sampler(
true_classes=context_class,
num_true=1,
num_sampled=num_ns,
unique=True,
range_max=vocab_size,
seed=SEED,
name="negative_sampling")
negative_sampling_candidates = tf.expand_dims(
negative_sampling_candidates, 1)
context = tf.concat([context_class, negative_sampling_candidates], 0)
label = tf.constant([1] + [0]*num_ns, dtype="int64")
targets.append(target_word)
contexts.append(context)
labels.append(label)
return targets, contexts, labels
您需要运行的代码在您可以使用的笔记本中,或者您可以直接从 TensorFlow 网站上获取这些代码,然后开始编码并复制您需要的代码。
实验跟踪
很难识别单词嵌入中发生的变化。理想情况下,我们希望能够看到随着训练的进行,我们的单词的相似度是如何变化的。我们可以跟踪每个时期的 损失 和 准确性 之类的事情,但跟踪我们单词之间的实际相似性会很棒。这是我们如何使用 TensorFlow 的 回调 功能的一个很好的例子。这将使我们能够准确记录我们想要的,然后在海王星实验中跟踪它。
要设置 Neptune 实验,您只需设置您的凭证并初始化您的 Neptune 模块。
import neptune
from neptunecontrib.api import log_table
from neptunecontrib.api import log_chart
neptune.init(project_qualified_name='choran/sandbox',
api_token='your token',)
然后你需要做的就是开始你的实验,你已经准备好了!
neptune.create_experiment()
这应该会输出您的实验的 URL->https://ui.neptune.ai/<用户>/沙盒/e/SAN-1
为了检查我们的单词嵌入之间的相似性,我们可以比较一个示例单词的相似性,并跟踪它在不同时期之间如何变化。
def get_similarity(word, X, X_vocab, vocab):
vocab_d = {}
for i, w in enumerate(X_vocab):
vocab_d[w] = i
y = X[vocab_d[word]].reshape(1, -1)
res = cosine_similarity(X, y)
df = pd.DataFrame(columns=['word', 'sim'])
df['word'], df['sim']= vocab[1:], res
return(df)
那么我们所需要做的就是调用这个函数时用我们自定义的 回调 函数。你可以阅读更多关于不同的 回调 特性,你可以在这里使用。关于自定义 回调 的示例,请查看 TensorFlow 中关于编写自己的回调的示例,此处为。
你可以把你的结果以熊猫数据的形式记录下来,然后保存到你的实验中,并跟踪它是如何随时间变化的。
这显示了 900 个历元之后‘BBB’和其他单词之间的余弦相似性。正确地说,它看起来接近“aaa”和“ccc”。但是,随着时间的推移,这种情况发生了怎样的变化,它与随机数据集或更大的数据集相比又如何呢?
3d 视觉化
对于我们的 3D 可视化,我们可以使用 plotly 和 PCA 来保存嵌入的 3D 图,并直观地比较它们之间的关系。例如,看看我们的“随机”数据集和更“结构化”的数据集之间的区别。
We can see here that the clustering of our “words” seems fairly chaotic?
Whereas here you can see a “nicer” relationship between our “words”, it seems far more structured and there seems to be a pattern you can investigate by interacting with the visualisation.
您还可以看到,我们的回调函数是多么简单,可以将这些信息记录并跟踪到 Neptune。
class TrackLossAndSimilarity(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs=None):
neptune.log_metric('loss', logs["loss"])
neptune.log_metric('accuracy', logs["accuracy"])
if epoch%100 == 0:
vocab = vectorize_layer.get_vocabulary()
X, X_vocab = get_data(word2vec.get_layer('w2v_embedding').get_weights()[0],
vocab)
check_word = 'bbb'
sim_df = get_similarity(check_word, X, X_vocab, vocab)
sim_fig = get_3d_viz(X, X_vocab)
log_chart(f'3d-plot-epoch{epoch}', sim_fig)
log_table(f'similarity-{check_word}-epoch{epoch}', sim_df.sort_values('sim', ascending=False))
总结和后续步骤
最后,让我们回顾一下我们刚刚完成的内容,看看如何使用来训练和测试模式高级模型。
- 我们创建了自己的“语言学”数据集:这里的目标是创建一个数据集,在这个数据集内我们可以知道(并设计)术语之间的关系。这样,当我们创建嵌入并检查它们的相似性时,我们将知道“aaa”是否更类似于“mmm”而不是“ccc ”,这是有问题的,因为嵌入没有正确地选取我们知道存在的关系。
- 我们找到了一个创建嵌入的模型:我们使用 Word2Vec 模型的一些示例代码来帮助我们理解如何为输入文本创建标记,并使用 skip-gram 方法来学习单词嵌入,而不需要监督数据集。这个模型的输出是我们数据集中每个术语的嵌入。这些是“静态”嵌入,因为每个术语有一个嵌入。
- 我们探索了嵌入:最终目标是理解模型如何将意义编码到嵌入中。因此,我们观察了在随机数据集上训练时嵌入所包含的信息,并将其与结构化数据集进行比较,在结构化数据集上,术语仅在与某些其他术语“接近”的情况下使用。我们通过跟踪示例术语之间的相似性来做到这一点,并显示这种相似性如何随时间变化以及两个实验之间的差异。我们还通过可视化所有嵌入之间的关系来展示这一点。在我们的简单示例中,我们能够看到随机数据集和邻近数据集之间的差异
我如何利用这一点来更好地理解像 BERT 这样的模型?
请记住,不管像 BERT 这样的模型看起来多么先进和复杂,它们最终只是像我们在这里所做的那样将信息编码到一个嵌入中。不同之处在于,设计 Transformer 架构的人(这是大多数新的 NLP 模型,如 BERT 和 GPT-3 的基础)找到了一种“更好的”方法来将信息编码到嵌入中。我们使用的嵌入为每个术语生成一个嵌入。
但是,正如我们所知,真实的语言是混乱的,同样的词在不同的上下文中可能有不同的意思。这是一个博客帖子,但你可以张贴邮件,在篮球比赛中你可以张贴,在足球比赛中你可以击中门柱,你可以通过张贴在门上等方式在公共场合显示信息。对于我们刚刚创建的静态嵌入来说,这是一个问题,但是 Transformer 架构试图通过基于“上下文”创建嵌入来解决这个问题。所以它根据单词使用的上下文产生不同的嵌入。
例如,您可以通过创建一个新的数据集来测试这一点,在该数据集内,一个术语被用于非常不同的术语附近。术语“ccc”可以接近当前设计的“bbb”和“ddd ”,但是您也可以添加代码以确保它也接近“xxx”和“yyy”。在这种情况下,您认为“ccc”的相似性值将如何工作?例如,它们会显示出与“ddd”和“xxx”相同的相似性吗?
这里的关键是,你可以在这里应用同样的技术来尝试和理解其他模型是如何工作的。您可以在这个数据集上训练一个 BERT 模型,并尝试看看静态嵌入和基于上下文的嵌入之间有什么区别。如果你想做类似的事情,这里有一些你可以利用的资源:
- 从零开始用世界语训练 BERT:这个来自 HugglingFace 的指南向你展示如何用一种新的语言从零开始训练 BERT 模型。您可以尝试在您的自定义数据集或更复杂的数据集上进行训练。然后尝试跟踪嵌入,就像我们对 Word2Vec 所做的那样。记住,BERT 嵌入是基于上下文的,所以您不需要像 Word2Vec 那样的查找字典。您将向它输入一个句子,并获得每个单词的嵌入或整个序列的“混合”嵌入。点击了解更多。
- 开始尝试句子嵌入:代替单词嵌入,你可以嵌入整个句子并比较它们的相似性。您可以使用一个简单的自定义数据集,然后获得输入序列的平均嵌入,并使用它来比较整个数据序列并确定它们的相似性。你可以在这里找到这些型号的一些例子。
- 上下文与静态嵌入:我们真的需要上下文嵌入吗?上下文嵌入和静态嵌入有什么不同?我们能从上下文嵌入中生成更好的静态嵌入吗?如果你想找到这些问题的答案,请查看这篇很棒的文章。
单词嵌入终极指南
原文:https://web.archive.org/web/https://neptune.ai/blog/word-embeddings-guide
单词嵌入是自然语言处理(NLP)中最常用的技术之一。人们常说,如果没有单词嵌入,SOTA 模型的性能和能力就不可能实现。正是因为单词嵌入,像 RNN s,LSTMs,ELMo,伯特,阿尔伯特,GPT-2 到最近的 GPT-3 这样的语言模型以惊人的速度进化。
这些算法速度快,可以高精度地生成语言序列和其他下游任务,包括上下文理解、语义和句法属性、以及、词与词之间的线性关系。****
核心上,这些模型使用嵌入作为从文本或语音序列中提取模式的方法。但是他们是怎么做到的呢?单词嵌入背后的确切机制和数学原理是什么?
在本文中,我们将探索一些早期的神经网络技术,这些技术让我们能够为自然语言处理构建复杂的算法。对于某些主题,会有一个论文的链接和一个附带的 colab 笔记本,这样你就可以通过尝试来理解这些概念。这样做会帮助你学得更快。
我们将涉及的主题:
- 什么是单词嵌入?
- 神经语言模型
- word 2 vec
- skip 程序
- 连续的单词袋
- softmax 功能上的
- 提高近似值
- 基于 Softmax 的方法
- 分级 Softmax
- 基于抽样的方法
- 噪声对比估计
- 负采样
- 基于 Softmax 的方法
什么是单词嵌入?
单词嵌入是以数字方式表示单词和整个句子的一种方式。我们知道计算机理解数字语言,所以我们试图将一个句子中的单词编码成数字,这样计算机就可以阅读和处理它。
但是阅读和处理并不是我们希望计算机做的唯一事情。我们还希望计算机在句子中的每个单词之间建立关系,或者在文档中与其他单词建立关系。
我们希望单词嵌入能够捕获段落或之前句子的上下文,同时捕获语义和句法属性以及它们的相似性。
例如,如果我们取一个句子:
“猫躺在地板上,狗在吃东西”,
…然后我们可以把这两个主语(猫和狗)在句子中调换一下,使其成为:
“那只狗躺在地板上,那只猫在吃东西”。
在这两个句子中,保留了语义或意义相关的关系,即猫和狗都是动物。这句话很有道理。
同样,句子也保留了句法关系,即基于规则的关系或语法。
为了实现这种语义和句法关系,我们需要的不仅仅是将句子或文档中的一个单词映射成简单的数字。我们需要这些数字的一个更大的表示,能够表示语义和语法属性。
我们需要向量。不仅如此,还有可学习的向量。
在数学意义上,单词嵌入是单词的参数化函数:
其中是参数,W 是句子中的单词。
很多人也将单词嵌入定义为以向量形式的单词的密集表示。
例如,单词猫和狗可以表示为:
W(cat) = (0.9,0.1,0.3,-0.23 … )
W(狗)= (0.76,0.1,-0.38,0.3 … )
现在,假设来说,如果模型能够保持上下文相似性,那么两个单词在向量空间中将是接近的。
到目前为止,我们已经处理了两个单词(猫和狗),但如果有更多的单词呢?工作嵌入模型的工作是聚集相似的信息并在它们之间建立关系。
如您所见,单词嵌入将相似的单词聚集在一起。
现在有很多浅层算法可以很好地用于聚类。为什么我们需要神经网络?
最大的误解之一是单词嵌入需要深度神经网络。当我们构建不同的单词嵌入模型时,您会看到,对于所有的嵌入,模型都是浅层神经网络,有些还是线性模型。
我们使用神经网络来创建单词嵌入的原因是:
- 这有助于在嵌入空间中找到最近的邻居。
- 它可以用作监督学习任务的输入。
- 它创建了离散变量的映射,例如从单词到向量,再到连续变量的映射。
- 它还解决了维数灾难。
神经语言模型
单词嵌入是由 Bengio 等人提出的。艾尔。(2001,2003)来解决所谓的维数灾难,这是统计语言建模中的一个常见问题。
事实证明,本吉奥的方法可以训练一个神经网络,使得每个训练句子都可以向模型提供一些语义上可用的相邻单词,这被称为单词的分布式表示 。神经网络没有建立不同单词之间的关系,但它也保留了语义和句法属性方面的关系。
Source: Bengio et. al. 2003
这引入了神经网络架构方法,为许多当前方法奠定了基础。
这个神经网络有三个组成部分:
- 生成单词嵌入的嵌入层,参数跨单词共享。
- 一层或多层的隐藏层 r,这给嵌入引入了非线性。
- 一个 softmax 函数,产生词汇表中所有单词的概率分布。
让我们来理解一个神经网络语言模型是如何在代码的帮助下工作的。
第一步:索引单词。我们从索引单词开始。对于句子中的每个单词,我们会给它分配一个数字。
word_list = " ".join(raw_sentence).split()
word_list = list(set(word_list))
word2id = {w: i for i, w in enumerate(word_list)}
id2word = {i: w for i, w in enumerate(word_list)}
n_class = len(word2id)
第二步:建立模型。
我们将完全按照论文中的描述来构建模型。
class NNLM(nn.Module):
def __init__(self):
super(NNLM, self).__init__()
self.embeddings = nn.Embedding(n_class, m)
self.hidden1 = nn.Linear(n_step * m, n_hidden, bias=False)
self.ones = nn.Parameter(torch.ones(n_hidden))
self.hidden2 = nn.Linear(n_hidden, n_class, bias=False)
self.hidden3 = nn.Linear(n_step * m, n_class, bias=False)
self.bias = nn.Parameter(torch.ones(n_class))
def forward(self, X):
X = self.embeddings(X)
X = X.view(-1, n_step * m)
tanh = torch.tanh(self.d + self.hidden1(X))
output = self.b + self.hidden3(X) + self.hidden2(tanh)
return output
我们将从初始化一个嵌入层开始。嵌入层是一个查找表。
一旦单词的输入索引通过一个嵌入层被嵌入,它就会通过第一个隐藏层,并添加偏向。这两个函数的输出然后通过一个双曲正切函数。
如果您还记得原始论文中的图表,那么来自嵌入层的输出也被传递到最终的隐藏层,在那里 tanh 的输出被加在一起。
output = self.b + self.hidden3(X) + self.hidden2(tanh)
现在,在最后一步,我们将计算整个词汇的概率分布。
第三步:损失和优化函数。
现在我们已经有了模型的输出,我们需要确保我们通过 softmax 函数传递它以获得概率分布。
我们使用交叉熵损失。
criterion = nn.CrossEntropyLoss()
交叉熵损失由两个方程组成:对数 softmax 函数和负对数似然损失或 NLLLoss。前者计算 softmax 归一化,而后者计算负对数似然损失。
对于优化,我们使用 Adam 优化器。
第四步:训练。
最后,我们训练模型。
简而言之,单词嵌入可以被定义为单词在低维空间中以向量形式的密集表示。这些嵌入伴随着 l 个可学习向量,或者参数化函数。它们使用损失函数在反向传播过程中更新自己,并试图找到单词之间的良好关系,保留语义和突触属性。
“事实证明,基于神经网络的模型明显优于基于统计的模型” 米科洛夫等人。艾尔。(2013) 。
Word2Vec
Bengio 介绍的方法为 NLP 研究人员提供了新的机会来修改技术和架构本身,以创建一种计算成本更低的方法。为什么?
Bengio 等人提出的方法从词汇表中提取单词,并将其输入具有嵌入层、隐藏层和 softmax 函数的前馈神经网络。
这些嵌入有相关联的可学习向量,这些向量通过反向传播来优化自身。本质上,架构的第一层产生单词嵌入,因为它是一个浅层网络。
这种架构的问题在于隐藏层和投影层之间的计算开销很大。原因很复杂:
- 投影中产生的值是密集。
- 隐藏层为词汇表中的所有单词计算概率分布。
为了解决这个问题,研究人员(Mikolov 等人在 2013 年)提出了一个名为‘word 2 vec’的模型。
Word2Vec 模型本质上解决了本吉奥的 NLM 问题。
它完全删除了隐藏层,但投影层是所有单词共享的,就像 Bengio 的模型一样。缺点是,如果数据较少,这个没有神经网络的简单模型将无法像神经网络一样精确地表示数据。
另一方面,对于更大的数据集,它可以在嵌入空间中精确地表示数据。与此同时,它还降低了复杂性,并且该模型可以在更大的数据集中进行训练。
Mikolov 等人在 2013 年提出了两个模型:
- 连续词袋模型
- 连续跳格模型
连续词袋模型
连续词袋(Bag-of-Words)或 CBOW 模型基本上在目标词(wt)之前和之后取' n' 个词,并预测后者。 n 可以是任何数字。
例如,如果 n=2,句子是“狗正在公园里玩耍”,那么输入到模型中的单词将是(【the,dog,is,in,the,park】),后面是目标单词“正在玩耍“”。
该模型通过计算 log2(V) 消除了计算词汇表中所有单词的概率分布的复杂性,其中 V 是词汇表的大小。因此,这种模式更快更有效。
让我们借助代码来理解 CBOW 模型是如何工作的。
首先,我们不会将单词编码方法改为数字。那将保持不变。
第一步:定义一个函数,用目标词左右 n 个词创建一个上下文窗口。
def CBOW(raw_text, window_size=2):
data = []
for i in range(window_size, len(raw_text) - window_size):
context = [raw_text[i - window_size], raw_text[i - (window_size - 1)], raw_text[i + (window_size - 1)], raw_text[i + window_size]]
target = raw_text[i]
data.append((context, target))
return data
该函数应该有两个参数:数据和窗口大小。窗口大小将定义我们应该从右边和左边获取多少单词。
for 循环:for i in range(window_size,len(raw _ text)–window _ size):从窗口大小开始遍历一个范围,即 2 表示将忽略句子中索引 0 和 1 中的单词,并在句子结束前结束 2 个单词。
在 for 循环中,我们尝试分离上下文和目标单词,并将它们存储在一个列表中。
例如,如果句子是“狗在吃东西,猫躺在地板上”,带有窗口 2 的 CBOW 将考虑单词“”、“狗”、“吃东西”和“和”。本质上使目标词‘是’。
设 i =窗口大小= 2,则:
context = [raw_text[2 - 2], raw_text[2 - (2 - 1)], raw_text[i + (2 - 1)], raw_text[i + 2]]
target = raw_text[2]
让我们调用该函数并查看输出。
data = CBOW(raw_text)
print(data[0])
Output:
(['The', 'dog', 'eating', 'and'], 'is')
第二步:建立模型。
构建 CBOW 类似于我们之前构建的 NNLM,但实际上要简单得多。
在 CBOW 模型中,我们将隐藏层减少到只有一层。所以我们总共有:一个嵌入层,一个穿过 ReLU 层的隐藏层,和一个输出层。
class CBOW_Model(torch.nn.Module):
def __init__(self, vocab_size, embedding_dim):
super(CBOW_Model, self).__init__()
self.embeddings = nn.Embedding(vocab_size, embedding_dim)
self.linear1 = nn.Linear(embedding_dim, 128)
self.activation_function1 = nn.ReLU()
self.linear2 = nn.Linear(128, vocab_size)
def forward(self, inputs):
embeds = sum(self.embeddings(inputs)).view(1,-1)
out = self.linear1(embeds)
out = self.activation_function1(out)
out = self.linear2(out)
return out
这个模型非常简单。上下文词索引被送入嵌入层,然后通过隐藏层,接着是非线性激活层,即 ReLU,最后我们得到输出。
第三步:损失和优化函数。
类似于 NNLM,我们使用同样的技术来计算词汇表中所有单词的概率分布。nn。CrossEntropyLoss()。
对于优化,我们使用随机梯度下降。你也可以使用 Adam 优化器。在 NLP 中,Adam 是首选的优化器,因为它比 SGD 收敛得更快。
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
第四步:训练
培训与 NNLM 模式相同。
for epoch in range(50):
total_loss = 0
for context, target in data:
context_vector = make_context_vector(context, word_to_ix)
output = model(context_vector)
target = torch.tensor([word_to_ix[target]])
total_loss += loss_function(output, target)
optimizer.zero_grad()
total_loss.backward()
optimizer.step()
make_context_vector 把单词变成数字。
值得注意的是,这篇论文的作者发现,NNLM 保留了相似词之间的线性关系。比如【国王】**【王后】与【男人】**【女人】相同,即 NNLM 保留了性别线性。
同样,CBOW 等模型以及我们接下来将讨论的任何神经网络模型都将保持线性关系,即使我们在神经网络中明确定义了非线性。
连续跳格模型
连续跳格,或跳格,类似于 CBOW。它不是预测目标单词(wt),而是通过上下文预测它周围的单词。训练目标是学习擅长预测邻近单词的表示或嵌入。
还需要“n”个单词。例如,如果 n=2,句子是“狗在公园里玩”,那么输入到模型中的单词将是在玩,目标单词将是(狗在公园里)。
让我们借助代码来理解跳格模型是如何工作的。
skipgram 模型与 CBOW 模型相同,但有一点不同。区别在于创造语境和目标词。
步骤 1:设置目标和上下文变量。
由于 skipgram 只需要一个上下文单词和 n 个目标变量,我们只需要从前面的模型中翻转 CBOW。
def skipgram(sentences, window_size=1):
skip_grams = []
for i in range(window_size, len(word_sequence) - window_size):
target = word_sequence[i]
context = [word_sequence[i - window_size], word_sequence[i + window_size]]
for w in context:
skip_grams.append([target, w])
return skip_grams
如你所见,功能几乎相同。
这里你需要明白,当窗口大小为 1 时,我们在目标词前后取一个词。
当我们调用该函数时,输出如下所示:
print(skipgram(word_sequence)[0:2])
Output:
[['my', 'During'], ['my', 'second']]
可以看到,目标词是‘我的’,两个词是‘期间’和‘第二’。
本质上,我们试图创建一对单词,使得每对单词都包含一个目标单词。根据上下文窗口,它将包含相邻的单词。
第二步:建立模型。
这个模型非常简单。
class skipgramModel(nn.Module):
def __init__(self):
super(skipgramModel, self).__init__()
self.embedding = nn.Embedding(voc_size, embedding_size)
self.W = nn.Linear(embedding_size, embedding_size, bias=False)
self.WT = nn.Linear(embedding_size, voc_size, bias=False)
def forward(self, X):
embeddings = self.embedding(X)
hidden_layer = nn.functional.relu(self.W(embeddings))
output_layer = self.WT(hidden_layer)
return output_layer
损失函数和优化保持不变。
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
一旦我们定义了一切,我们就可以训练模型了。
for epoch in range(5000):
input_batch, target_batch = random_batch()
input_batch = torch.Tensor(input_batch)
target_batch = torch.LongTensor(target_batch)
optimizer.zero_grad()
output = model(input_batch)
loss = criterion(output, target_batch)
if (epoch + 1) % 1000 == 0:
print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))
loss.backward()
optimizer.step()
skip-gram 模型增加了计算的复杂性,因为它必须根据相邻单词的数量来预测相邻的单词。距离较远的单词往往与当前单词的相关性稍低。
到目前为止的总结:
- 神经网络语言模型 (NNLM)或 Bengio 的模型优于早期的统计模型,如 n-gram 模型。
- NNLM 还解决了维数灾难,并通过其分布式表示保留了上下文,语言规则和模式。
- NNLM 计算量很大。
- Word2Vec 模型通过移除隐藏层和共享权重来解决计算复杂性
- Word2Vec 的缺点是它没有神经网络,这使得它很难表示数据,但优点是如果它可以在大量数据上训练,那么因为它比神经网络更有效,所以它可以计算非常精确的高维单词向量。
- Word2Vec 有两个型号:CBOW 和 Skipgram。前者比后者快。
关于 softmax 函数
到目前为止,您已经看到了 softmax 函数如何在预测给定上下文中的单词时发挥重要作用。但是它有一个复杂的问题。
回想一下 softmax 函数的等式:
其中w[t]是目标单词, c 是上下文单词, y 是每个目标单词的输出。
如果查看上面的等式,当预测值的数量较高时,softmax 函数的复杂性就会增加。如果 i=3,,那么 softmax 函数将返回三个类别的概率分布。
但是,在自然语言处理中,我们通常要处理成千上万的单词。获得这么多单词的概率分布会使计算变得非常昂贵和缓慢。
请记住,softmax 函数返回精确的概率分布,因此随着参数的增加,它们的速度会变慢。对于每个单词( w [t] ),它在分母中对整个词汇表求和。
那么,有什么不同的方法可以使计算既便宜又快速,同时又能确保近似不被破坏呢?
在下一节中,我们将介绍可以减少计算时间的不同方法。我们将尝试对整个词汇表,甚至是一个样本词汇表进行近似计算,而不是获得整个词汇表的精确概率。这降低了复杂性并提高了处理速度。
我们将讨论两种方法:基于 softmax 的方法和基于采样的方法。
改进预测功能
在本节中,我们探索了三种可能的方法来改进预测,通过修改 softmax 函数来逼近更好的结果,并用新方法替换 softmax。
基于 Softmax 的方法
基于 Softmax 的方法更倾向于修改 softmax 以获得预测单词的更好近似,而不是完全消除它。我们将讨论两种方法:分层 softmax 方法和 CNN 方法。
分级 softmax
分层 softmax 是由 Morin 和 Bengio 在 2005 年引入的,作为完整 softmax 函数的替代,它用分层来代替完整 soft max 函数。它借鉴了二进制哈夫曼树的技术,将计算概率的复杂度从整个词汇 V 降低到 log [2] (V) ,即二进制。
编码一棵霍夫曼树是非常复杂的。我尽量不用代码解释,不过你可以在这里找到笔记本试试看。
为了理解 H-softmax,我们需要理解霍夫曼树的工作原理。
霍夫曼树是一棵二叉树,它从词汇表中提取单词;基于它们在文档中的出现频率,它创建了一个树。
以这段文字为例:“猫在吃东西,狗在叫”。为了创建霍夫曼树,我们需要从整个词汇表中计算单词的频率。
word_to_id = {w:i for i, w in enumerate(set(raw_text))}
id_to_word = {i:w for w, i in word_to_id.items()}
word_frequency = {w:raw_text.count(w) for w,i in word_to_id.items()}
print(word_frequency)
Output:
{'and': 1, 'barking': 1, 'cat': 1, 'dog': 1, 'eating': 1, 'is': 2, 'the': 2}
下一步是创建一个霍夫曼树。我们的方法是用最不常用的词。在我们的例子中,我们有很多只出现一次的单词,所以我们可以任意选择两个。让我们以“狗”和“和”为例。然后,我们将通过一个父节点连接两个叶节点,并添加频率。
在下一步中,我们将选择另一个最不常用的单词(同样,这个单词只出现一次),并将它放在总和为 2 的节点旁边。记住不常用的单词在左边,常用的单词在右边。
同样,我们将继续构建单词,直到我们使用了词汇表中的所有单词。
记住,所有出现频率最低的单词都在底部。
print(Tree.wordid_code)
Output:
{0: [0, 1, 1],
1: [0, 1, 0],
2: [1, 1, 1, 1],
3: [1, 1, 1, 0],
4: [0, 0],
5: [1, 1, 0],
6: [1, 0]}
一旦创建了树,我们就可以开始培训了。
在霍夫曼树中,我们不再计算输出嵌入 w`。相反,我们尝试使用 sigmoid 函数来计算在每个叶节点向右转或向左转的概率。
p(右| n,c)=σ(h⊤w′n),其中 n 是节点,c 是上下文。
正如您将在下面的代码中发现的,sigmoid 函数用于决定是向右还是向左。同样重要的是要知道所有单词的概率总和应该是 1。这确保了 H-softmax 在词汇表中的所有单词上具有归一化的概率分布。
class SkipGramModel(nn.Module):
def __init__(self, emb_size, emb_dimension):
super(SkipGramModel, self).__init__()
self.emb_size = emb_size
self.emb_dimension = emb_dimension
self.w_embeddings = nn.Embedding(2*emb_size-1, emb_dimension, sparse=True)
self.v_embeddings = nn.Embedding(2*emb_size-1, emb_dimension, sparse=True)
self._init_emb()
def _init_emb(self):
initrange = 0.5 / self.emb_dimension
self.w_embeddings.weight.data.uniform_(-initrange, initrange)
self.v_embeddings.weight.data.uniform_(-0, 0)
def forward(self, pos_w, pos_v,neg_w, neg_v):
emb_w = self.w_embeddings(torch.LongTensor(pos_w))
neg_emb_w = self.w_embeddings(torch.LongTensor(neg_w))
emb_v = self.v_embeddings(torch.LongTensor(pos_v))
neg_emb_v = self.v_embeddings(torch.LongTensor(neg_v))
score = torch.mul(emb_w, emb_v).squeeze()
score = torch.sum(score, dim=1)
score = F.logsigmoid(-1 * score)
neg_score = torch.mul(neg_emb_w, neg_emb_v).squeeze()
neg_score = torch.sum(neg_score, dim=1)
neg_score = F.logsigmoid(neg_score)
loss = -1 * (torch.sum(score) + torch.sum(neg_score))
return loss
基于抽样的方法
基于采样的方法完全消除了 softmax 层。
我们将讨论两种方法:噪声对比估计和负采样。
噪声对比估计
噪声对比估计(NCE)是一种替代 softmax 层并降低计算成本的近似方法。它通过将预测问题转换成分类问题来实现。
这一节将包含大量的数学解释。
NCE 采用非标准化多项式函数(即具有多个标签且其输出未通过 softmax 层的函数),并将其转换为二元逻辑回归。
为了学习分布从一些特定的上下文( c )中预测目标词(w[t],我们需要创建两个类:正和负。正类包含来自训练数据分布的样本,而负类包含来自噪声分布 Q 的样本,我们分别将它们标记为 1 和 0。噪声分布是训练集的一个单字分布。
对于给定上下文的每个目标词,我们从分布 Q 生成样本噪声作为 Q(w),,使得它比来自数据分布 P(w | c)的样本更频繁 k 倍。
这两个概率分布可以表示为彼此的和,因为我们有效地从这两个分布中采样单词。因此,
如前所述,NCE 是一个二元分类器,由真标签“1”和假标签“0”组成。直觉上,
当 y=1 时,
当 y=0 时,
我们的目标是开发一个具有参数 θ 的模型,使得给定一个上下文 c,其预测概率 P(w,c) 近似于原始数据分布 P [d] (w,c) 。
通常,噪声分布通过采样来近似。我们通过生成 k 个噪声样本 {wij}: 来做到这一点
其中 Z [θ] (c) 是 softmax 中的一个规格化术语,您记得这是我们试图消除的。我们消除 Z [θ] (c) 的方法是让它成为一个可学习的参数。本质上,我们将 softmax 函数从绝对值(即一次又一次对词汇表中的所有单词求和的值)转换为动态值,该值会不断变化以找到更好的值,这是可以学习的。
但是,事实证明,Mnih 等人(2013)指出 Z [θ] (c) 可以固定为 1。即使它又是静态的,但它归一化得相当好,Zoph 等人(2016)发现 Z [θ] (c)=1 产生一个低方差的模型。
我们可以用 exp(s [θ] (w | c)) 代替 P [θ] (w | c) ,这样损失函数可以写成:
需要记住的一点是,随着噪声样本数量 k 的增加,NCE 导数越来越接近似然梯度,即归一化模型的 softmax 函数。
总之,NCE 是一种通过将数据分布与噪声分布进行比较来学习数据分布的方式,并且修改学习参数,使得模型 P [θ] 几乎等于 P [d] 。
负采样
理解 NCE 是很重要的,因为负抽样是相同的修改版本。这也是一个更简化的版本。
首先,我们了解到,随着我们增加噪声样本 k 的数量,NCE 导数接近似然梯度,或归一化模型的 softmax 函数。
负采样的工作方式是,用 1 代替噪声,从而消除噪声。直觉上,
当 y=1 时,
在负采样中,我们使用 sigmoid 函数,因此我们将上述等式转换为:
我们知道 P [θ] (w | c) 被替换为 exp(s [θ] (w | c)) 。
因此,
这使得等式更短。它必须计算 1 而不是噪声,因此该方程在计算上变得高效。但是我们为什么要简化 NCE 呢?
一个原因是我们关心单词向量的高度表示,所以只要模型产生的单词嵌入保持它们的质量,它就可以简化模型。
如果我们用上面的方程代替最终的 NCE 方程,我们得到:
由于 log(1)=0 ,
因此,
因为我们处理的是 sigmoid 函数。
我们可以将上面的等式修改为:
最后的想法和结论
我们探索了用于 NLP 或机器翻译的基于神经的建模的发展。我们讨论了单词嵌入,这是一种在词汇表中寻找语义、句法和线性关系的方法。虽然前面提到的一些方法不再使用,但它们奠定了该学科的基础,并使进一步的学习更容易。
我们看到了 Begio 和他的团队如何通过他们的单词嵌入方法引入神经语言模型来找到更好的表示,随后是 Mikolov 和他的团队如何修改 Begio 的方法,并通过删除隐藏层引入了一种计算成本更低的方法。虽然 word2vec 模型是一个简单的模型,但是一旦词汇表变大,它的计算开销就会变大。
引入了不同的方法来纠正复杂性问题,我们在本文后面看到的三个模型通过 softmax 函数解决了这个问题。
最后,我们看到了负采样如何超越所有两种方法(分层 softmax 和 NCE ),并使用更有效的近似技术修改了 word2vec 模型,该技术可以捕获更好的表示,如语义、语法,并保留线性表示,同时降低了计算成本。
单词嵌入为 NLP 的研究和开发打开了新的大门。这些模型运行良好,但是它们仍然缺乏概念上的理解。直到 2018 年,彼得斯等人。艾尔。引入了语言模型中的 ELMo:embedding,它通过单词嵌入将寻找上下文表示的缺失部分联系起来。
为了更好的理解和清晰,查看每个主题的笔记本。
资源
XGBoost:您需要知道的一切
原文:https://web.archive.org/web/https://neptune.ai/blog/xgboost-everything-you-need-to-know
梯度推进(GBM)树在没有指定模型的情况下从数据中学习,它们进行无监督学习。 XGBoost 是一个流行的梯度推进库,用于 GPU 训练、分布式计算和并行化。它是精确的,它很好地适应所有类型的数据和问题,它有很好的文档,总体来说它非常容易使用。
目前,它是通过机器学习从预测建模中获得准确结果的事实上的标准算法。对于 R、Python 和 C++来说,它是速度最快的梯度提升库,具有非常高的准确性。
我们将探索如何使用该模型,同时使用 Neptune 来呈现和详述 ML 项目管理的一些最佳实践。
如果您不确定 XGBoost 对您来说是不是一个很好的选择,请跟随教程直到结束,然后您将能够做出一个完全明智的决定。
集成算法–解释
集成学习结合几个学习器(模型)来提高整体性能,增加机器学习和预测建模的预测性和准确性。
从技术上来说,集成模型的力量很简单:它可以结合成千上万个在原始数据子集上训练的较小的学习者。这可能会导致有趣的观察结果,例如:
- 由于装袋,通用模型的方差显著降低
- 由于升压,偏置也会降低
- 由于叠加,整体预测能力提高
集合方法的类型
基于子学习器是如何产生的,集成方法可以分为两组:
- 顺序 系综方法——学习者被顺序生成。这些方法使用基础学习者之间的依赖性。每个学习者都会影响下一个学习者,同样,也可以推导出一般的父性行为。顺序集成算法的一个流行例子是 AdaBoost。
- 并行 集成方法——学习者是并行生成。基础学习者是独立创建的,以研究和利用与他们的独立性相关的效果,并通过平均结果来减少错误。实现这种方法的一个例子是随机森林。
集成方法可以使用同质学习者(来自同一个家庭的学习者)或异质学习者(来自多个类别的学习者,尽可能准确和多样)。
同质和异质 ML 算法
一般来说,同质集成方法具有单一类型的基学习算法。通过给训练样本分配权重,训练数据是多样化的,但是它们通常利用单一类型的基本学习者。
另一方面,异类集成由具有不同基本学习算法的成员组成,这些算法可以被组合并同时用于形成预测模型。
一般的经验法则是:
- 同构 集成对各种数据使用相同的特征选择,并将数据集分布在几个节点上。
- 异类集成对相同的数据使用不同的特征选择方法
*同质系综:
异质系综:
集成算法的重要特征
制袋材料
通过平均多个估计值的性能来减少总体方差。聚合原始数据集的若干个采样子集,用替换法训练随机选择的不同学习者,符合 bootstrap 聚合的核心思想。Bagging 通常使用投票机制进行分类(随机森林)和回归平均。
注: 记住有些学习者比较稳定,对训练扰动不太敏感。这样的学习器,组合在一起,并不能帮助通用模型提高泛化性能。
助推
这种技术将弱学习者——预测能力差且比随机猜测略好的学习者——与原始数据集的特定加权子集相匹配。对先前分类错误的子集给予较高的权重。
然后,在分类或加权和回归的情况下,将学习者预测与投票机制相结合。
众所周知的升压算法
adaboost 算法
AdaBoost 代表 自适应增压。 算法中实现的逻辑是:
- 第一轮分类器(学习器)都使用相等的加权系数来训练,
- 在随后的提升回合中,自适应过程增加被学习者在先前回合中错误分类的数据点的权重,并减少正确分类的数据点的权重。
如果你对算法的描述很好奇,看看这个:
梯度推进
梯度提升使用来自弱学习者的可微分函数损失来概括。在每个提升阶段,学习器被用来最小化给定当前模型的损失函数。提升算法可用于分类或回归。
什么是 XGBoost 架构?
XGBoost 代表极端梯度增强。这是梯度推进算法的并行化和精心优化版本。并行化整个增强过程极大地缩短了训练时间。
我们不是在数据上训练最好的可能模型(像传统方法一样),而是在训练数据集的各个子集上训练成千上万个模型,然后投票选出表现最好的模型。
在许多情况下,XGBoost 比通常的梯度增强算法更好。Python 实现提供了对大量内部参数的访问,以获得更好的精度和准确度。
XGBoost 的一些重要特性是:
- 并行化: 模型实现用多个 CPU 核进行训练。
- 正则化: XGBoost 包括不同的正则化惩罚,以避免过拟合。惩罚正则化产生成功的训练,因此模型可以充分地概括。
- 非线性: XGBoost 可以检测和学习非线性数据模式。
- 交叉验证: 内置和开箱即用。
- 可扩展性: XGBoost 可以分布式运行得益于 Hadoop 和 Spark 这样的分布式服务器和集群,所以你可以处理海量数据。它也适用于许多编程语言,如 C++、JAVA、Python 和 Julia。
XGBoost 算法是如何工作的?
-
考虑一个函数或估计值。首先,我们构建一个从函数梯度导出的序列。下面的等式模拟了一种特殊形式的梯度下降。代表最小化的损失函数,因此它给出了函数减小的方向。是损失函数拟合的变化率,相当于梯度下降中的学习率。被期望适当地近似损失的行为。
-
为了迭代模型并找到最佳定义,我们需要将整个公式表示为一个序列,并找到一个有效函数,该函数将收敛到函数的最小值。该函数将作为一种误差度量,帮助我们降低损耗并保持性能。序列收敛到函数的最小值。这种特殊的符号定义了在评估梯度推进回归量时应用的误差函数。
要了解更多细节和深入了解渐变增强背后的数学原理,我推荐你查看由 克里希纳·库马尔·马赫托撰写的这篇文章。
其他梯度提升方法
梯度推进机
GBM 结合了多个决策树的预测,所有弱学习者都是决策树。该算法的关键思想是,这些树的每个节点采用不同的特征子集来选择最佳分割。由于这是一个提升算法,每个新的树都会从以前的错误中学习。
有用的参考- > 了解渐变增压机
光梯度推进机(LightGBM)
LightGBM 可以处理海量数据。这是训练和预测最快的算法之一。它的通用性很好,这意味着它可以用来解决类似的问题。它可以很好地扩展到大量的内核,并且具有开源代码,因此您可以在您的项目中免费使用它。
有用参考- > 了解 LightGBM 参数(以及如何调优它们)
分类增强(CatBoost)
这一组特定的梯度增强变量通常具有处理分类变量和数据的特定能力。CatBoost 对象可以处理分类变量或数值变量,以及混合类型的数据集。这还不是全部。它还可以使用未标记的示例,并在训练过程中探索内核大小对速度的影响。
有用参考- > CatBoost:一个自动处理分类(CAT)数据的机器学习库
将 XGBoost 与 Neptune 集成在一起
开始创建您的项目
安装所需的 Neptune 客户端库:
pip install neptune-client
安装 Neptune 笔记本插件,保存你所有的工作,并与 Neptune UI 平台链接:
pip install -U neptune-notebooks
启用 jupyter 集成:
jupyter nbextension enable --py neptune-notebooks
在 Neptune 平台上注册,获取您的 API 密钥,并将您的笔记本与您的 Neptune 会话连接起来:
要完成设置,请在笔记本中导入 Neptune 客户端库,并调用 neptune.init()方法初始化连接:
import neptune
neptune.init(project_qualified_name='aymane.hachcham/XGBoostStudy)
准备好您的数据集以供使用
为了说明我们可以用 XGBoost 做的一些工作,我挑选了一个数据集,它包含了决定和预测学校学生考试分数的因素。该数据集基于在不同学校水平学习了 4 至 6 个月的学生的数据,包括他们每周的小时数和他们的表现。
该数据集将决定学习质量对学生考试成绩的影响程度。该数据集包含表示在三次考试中获得的关于几个社会、经济和金融因素的结果的数据。
数据集具有以下特征:
- 性别
- 种族/民族
- 父母的教育水平
- 午餐
- 备考课程
我们可以仔细看看种族和性别的分布情况:
- 按种族分列的数学、阅读和写作成绩:
import plotly.graph_objects as go
groupe_math_eth = data_exams.groupby(['race/ethnicity'])['math score'].sum().reset_index()
groupe_reading_eth = data_exams.groupby('race/ethnicity')['reading score'].sum().reset_index()
groupe_writing_eth = data_exams.groupby('race/ethnicity')['writing score'].sum().reset_index()
fig = go.Figure(data=[
go.Bar(name='Math Score', x=groupe_math_eth['race/ethnicity'], y=groupe_math_eth['math score']),
go.Bar(name='Reading Score', x=groupe_reading_eth['race/ethnicity'], y=groupe_reading_eth['reading score']),
go.Bar(name='Writing Score', x=groupe_writing_eth['race/ethnicity'], y=groupe_writing_eth['writing score'])
])
fig.update_layout(barmode='group')
fig.show()
C 组在所有得分指标上都很突出。这表明,在与种族和民族血统相关的学习成绩方面会有差异。
- 按性别分列的数学、阅读和写作成绩
groupe_math_gen = data_exams.groupby(['gender'])['math score'].sum().reset_index()
groupe_reading_gen = data_exams.groupby('gender')['reading score'].sum().reset_index()
groupe_writing_gen = data_exams.groupby('gender')['writing score'].sum().reset_index()
fig = go.Figure(data=[
go.Bar(name='Math Score', x=groupe_math_gen['gender'], y=groupe_math_gen['math score']),
go.Bar(name='Reading Score', x=groupe_reading_gen['gender'], y=groupe_reading_gen['reading score']),
go.Bar(name='Writing Score', x=groupe_writing_gen['gender'], y=groupe_writing_gen['writing score'])
])
fig.update_layout(barmode='group')
fig.show()
相反,我们发现性别对所有三个学科的总体得分没有太大影响。性别似乎不是决定性因素。
对数据进行采样
为了对数据进行采样,我们将使用 XGBoost Python 库中的 DMatrix 对象。将数据采样到子集的过程称为数据分离。DMatrix 是一种内部数据结构,有助于内存管理和数据优化。我们将把数据分成训练和测试子集,然后开始训练。
import xgboost as xgb
from sklearn.model_selection import train_test_split
features = data_exams.iloc[:,:-3]
target = data_exams.iloc[:,-3:]
将分类变量转换为数值:
所有特征仍被注册为分类值。为了训练模型,我们需要将每个变量与一个数字代码相关联来识别它,并因此相应地转换 5 个特征列。
- 首先,使用 pandas 将对象数据类型转换为字符串:
features['gender'].astype('string')
features['race/ethnicity'].astype('string')
features['parental level of education'].astype('string')
features['test preparation course'].astype('string')
- 将性别转换为 0/1 值:
features.loc[features['gender'] == 'male', 'gender'] = 0
features.loc[features['gender'] == 'female', 'gender'] = 1
- 改变父母的教育水平:
features.loc[features['parental level of education'] == 'high school', 'parental level of education'] = 1
features.loc[features['parental level of education'] == 'some college', 'parental level of education'] = 2
features.loc[features['parental level of education'] == 'some high school', 'parental level of education'] = 3
features.loc[features['parental level of education'] == 'associate's degree', 'parental level of education'] = 4
features.loc[features['parental level of education'] == 'bachelor's degree', 'parental level of education'] = 5
features.loc[features['parental level of education'] == 'master's degree', 'parental level of education'] = 6
- 转变午餐价值观:
features.loc[features['lunch'] == 'standard', 'lunch'] = 0
features.loc[features['lunch'] == 'free/reduced', 'lunch'] = 1
- 转变备考课程:
features.loc[features['test preparation course'] == 'none', 'test preparation course'] = 0
features.loc[features['test preparation course'] == 'completed', 'test preparation course'] = 1
区分数据特征、我们将尝试用于预测的列以及数据目标,数据目标是代表这些学生获得的数学、阅读和写作分数的最后 3 列。
x_train, x_test, y_train, y_test = train_test_split(features, target, test_size=0.30, random_state=123)
d_matrix_train = xgb.DMatrix(x_train, y_train, enable_categorical=True)
d_matrix_test = xgb.DMatrix(x_test, y_test, enable_categorical=True)
将您的脚本连接到海王星
import neptune.new as neptune
experiment = neptune.init(project='aymane.hachcham/XGBoost-Complete-Guide', api_token='API TOKEN')
- 前往你的 jupyter 笔记本,启用 Neptune 扩展来访问你的项目阅读如何。
注意 :我强烈建议你看一下为新的 Neptune Python AP I 发布的新文档,它结构良好,非常直观。
训练模型
一旦我们正确地分离了我们的训练和测试样本,我们就可以开始将数据拟合到模型中了。在培训过程中,我们将尝试共同记录所有即将到来的评估结果,以便实时了解我们的模型性能。
为了开始使用 Neptune 进行日志记录,我们创建了一个实验和一个定义每个模型版本的超参数列表。
import neptune
from neptunecontrib.monitoring.xgboost import neptune_callback
params = {
'max_depth':7,
'learning_rate':0.1,
'objective': 'reg:squarederror',
'num_estimators':1000,
'num_boost_round':1000
}
neptune.create_experiment(
name='XGBoost-V1',
tags=['XGBoost', 'Version1'],
params=params
)
使用我们之前设置的参数和 DMatrix 数据开始训练过程。我们还添加了 neptune_callback()函数,它自动完成所有必要的工作,以实时监控损失和评估指标。
watchlist = [(d_matrix_test, 'test'), (d_matrix_train, 'train')]
num_round = 20
xgb.train(params, d_matrix_train, num_round, watchlist, callbacks=[neptune_callback()])
neptune.stop()
一旦您的项目连接到平台,Neptune 就会跟踪和监控您的物理资源的当前状态,比如 GPU、内存、CPU 和 GPU 内存。在你做培训的时候,总是密切关注你的资源是非常方便的。
让我们仔细看看,并尝试解释 XGBRegressor 超参数:
- Learning_rate :用于控制和调整内部模型估计器的权重。learning_rate 应该始终是一个小值,以强制进行长期学习。
- Max_depth: 表示估计器(本例中为树)的深度程度。小心操作此参数,因为它会导致模型过度拟合。
- Alpha: 一种特定类型的惩罚正则化(L1)来帮助避免过度拟合
- Num_estimators: 模型将基于的估计器的数量。
- Num_boost_round: 升压级数。虽然 num_estimators 和 num_boost_round 保持不变,但你应该记住,每次更新参数时,num_boost_round 都应该重新调整。
如果你回到 Neptune,在 所有元数据 下,你会看到注册的模型和登录的所有初始参数。
培训启动后,您可以通过单击当前实验并转到“图表”部分来监督培训和评估指标日志。Neptune 提供的直观和符合人体工程学的 UI,以及与大量 ML 算法和框架的紧密集成,使您能够快速迭代和改进不同版本的模型。
使用 Neptune 回调,我们可以访问关于模型的更多信息,比如特性重要性图和内部估计器的结构。
特征重要性图
XGBRegressor 通常对用于预测的每个特征的重要性顺序进行分类。使用梯度提升的一个好处是,在构建提升的树之后,检索每个属性的重要性分数相对简单。这可以通过计算特征重要性图、可视化提升树中每个特征之间的相似性(特征方面或属性方面)来完成。
这篇文章解释了如何在 R->-中使用 GBM 包计算每个特征的重要性分数
我们可以看到,种族/民族和父母的教育水平是学生成功的主要因素。
版本化您的模型
您可以在 Neptune 中以二进制格式对模型的多个版本进行版本化和存储。一旦训练完成,Neptune 会自动保存模型的当前版本,因此您可以随时返回并加载以前的模型版本进行比较。
在'All Metadata->Artifacts '下,您将找到所有已存储的相关元数据:
与您的团队协作和共享工作
该平台还允许你以无缝的方式交叉比较你的所有实验。只需检查您想要的实验,就会出现一个显示所有必需信息的特定视图。
你可以通过发送一个链接来分享任何 Neptune 实验。
注 :使用团队计划,你可以和队友分享你所有的工作和项目。
如何超调 XGBRegressor
当时间和资源不成问题时,处理参数调整的最有效方法是对所有参数运行巨大的网格搜索,并等待算法输出最优解。如果您正在开发一个小型或中型数据集,这样做是有好处的。但是对于更大的数据集,这种方法会很快变成一场噩梦,消耗太多的时间和资源。
处理大型数据集时超调 XGBoost 的技巧
数据科学家中有一句广为人知的话:“如果你的数据有信号,你可以让你的模型创造奇迹,如果没有信号,就没有信号”。
当有大量训练数据时,我建议最直接的方法是尝试手动研究具有重大预测影响的特征。
- 首先尝试减少你的特征。100 或 200 个功能是很多的,你应该尽量缩小功能选择的范围。您还可以根据特定的标准依靠 Sele ctKBest 来选择最佳表现者,在该标准中,每项功能都获得 K 分,并据此进行选择。
- 糟糕的性能也可能与测试数据集的质量评估有关。与您的训练数据相比,测试数据可能代表完全不同的数据子集。因此,您应该尝试进行交叉验证,以便要素的 R 平方值足够可信且足够可靠。
- 最后,如果您发现您的超参数调整仍然影响很小,请尝试切换到更简单的回归方法,如线性、套索、弹性网,而不是坚持 XGBRegression。
因为我们例子中的数据不是很大,我们可以选择第一个选项。然而,由于这里的目标是公开您可以利用的更可靠的模型调优选项,我们将毫不犹豫地选择这个选项。请记住,如果您知道哪些超参数对数据有更大的影响,那么您的工作范围就会小得多。
网格搜索方法
幸运的是,XGBoost 实现了 scikit-learn API,因此使用网格搜索并基于原始超参数集开始为模型推出最佳结果非常容易。
让我们创建一个每个超参数可以取值的范围:
parameters = {
'learning_rate': [0.1, 0.01, 0.05],
'max_depth': range (2, 10, 1),
'n_estimators': range(60, 220, 500, 1000),
'num_boost_round': range(60, 250, 500, 1000)
}
配置您的 GridSearchCV。在这种情况下,评估性能的最佳指标是比较 10 倍交叉验证结果的 ROC AUC 曲线。
from sklearn.model_selection import GridSearchCV
grid_search = GridSearchCV(
estimator=estimator,
param_grid=parameters,
scoring = 'roc_auc',
n_jobs = 10,
cv = 10,
verbose=True
)
发布培训:
grid_search.fit(x_train, y_train)
处理步骤如下所示:
Fitting 10 folds for each of 96 candidates, totalling 960 fits
[Parallel(n_jobs=10)]: Using backend LokyBackend with 10 concurrent workers.
[Parallel(n_jobs=10)]: Done 30 tasks | elapsed: 11.0s
[Parallel(n_jobs=10)]: Done 180 tasks | elapsed: 40.1s
[Parallel(n_jobs=10)]: Done 430 tasks | elapsed: 1.7min
[Parallel(n_jobs=10)]: Done 780 tasks | elapsed: 3.1min
[Parallel(n_jobs=10)]: Done 960 out of 960 | elapsed: 4.0min
可以使用字段 best_estimator_ 访问最佳估计值:
xgb_best = grid_search.best_estimator_
XGBoost 利弊
优势
- 梯度推进带有一个易于阅读和解释的算法,使其大多数预测易于处理。
- 增强是一种弹性和稳健的方法,可以很容易地防止和避免过度拟合
- XGBoost 在具有子组的中型、小型数据和没有太多特征的结构化数据集上表现非常好。
- 这是一个很好的方法,因为现实世界中的大多数问题都涉及到分类和回归,而 XGBoost 是这两个任务的主宰。
不足之处
- XGBoost 在稀疏和非结构化数据上表现不佳。
- 一个经常被遗忘的事情是,梯度提升对异常值非常敏感,因为每个分类器都被迫修复前一个学习器中的错误。
- 整个方法很难扩展。这是因为估计者将他们的正确性建立在先前的预测值上,因此这个过程需要很大的努力来简化。
结论
我们已经涵盖了梯度推进的许多方面,从理论的角度出发,到更实际的路径。现在,您可以看到将实验跟踪和模型管理添加到 XGBoost 训练和 Neptune 超调中是多么容易。
和往常一样,我会在下面给你留下一些有用的参考资料,这样你就可以扩大你的知识面,提高你的编码技能。
敬请关注更多内容!
参考文献:*
XGBoost 与 LightGBM:它们有什么不同
原文:https://web.archive.org/web/https://neptune.ai/blog/xgboost-vs-lightgbm
近年来,由多个社区提供的梯度推进机器及其变体获得了很大的吸引力。这主要是由于与产品和机器学习竞赛中的其他机器学习算法相比,决策树在性能上有所提高。
XGBoost 和 LightGBM 是基于梯度增强机器的两种最流行的算法。虽然我们可能会进行反复试验来检查这两种算法中哪一种算法比另一种算法更有优势,但在选择它们时理解其原因和时间也很重要。
在这篇博客中,我们将回顾 XGBoost 和 LightGBM 之间的基本区别,以便在我们的机器学习实验中提供帮助。但是在我们深入研究算法之前,让我们快速了解一下梯度增强的基本概念,它是 XGBoost 和 LightGBM 的一部分。
什么是梯度增强?
梯度推进指的是机器学习中的一种方法,其中弱学习者的集合用于在效率、准确性和可解释性方面提高模型性能。这些学习者被定义为比随机机会有更好的表现。这种模型通常是决策树,它们的输出被组合以获得更好的总体结果。
Gradient Boosting Algorithm | Source
假设是筛选出难以准确预测的实例,并开发新的弱学习器来处理它们。
对初始模型进行训练,并对整个数据集进行预测。计算实际值和预测值之间的误差,并对不正确的预测值给予更大的权重。随后,尝试修正先前模型的误差的新模型以及以类似方式创建的几个模型由此被创建。我们通过加权所有模型的平均值得到最终模型。
梯度提升可应用于以下情况:
- 回归——取弱学习者输出的平均值
- 分类–找到出现次数最多的类别预测
在企业和数据科学竞赛中广泛使用的一些最受欢迎的 boosting 算法是 XGBoost、LightGBM 和 CatBoost。一些数据科学从业者花费大量时间思考使用哪种算法,并经常以大量尝试告终。
由于 XGBoost 和 LightGBM 越来越受欢迎,我们将从实践的角度和一点点理论来探索这两者,以便更好地理解它们的优缺点。
LightBGM 和 XGBoost:算法
XGBoost
XGBoost (极限梯度提升)是一种专注于计算速度和模型性能的机器学习算法。它是由陈天琦介绍的,目前是 DMLC(分布式机器学习社区)的一个更广泛的工具包的一部分。该算法可用于回归和分类任务,并且设计用于处理大型复杂数据集。
该模型支持以下类型的升压:
- 由学习率控制的梯度增强
- 随机梯度提升,在每个分离级别的行、列或列利用子采样
- 使用 L1(拉索)和 L2(岭)正则化的正则化梯度增强
从系统性能的角度来看,其他一些特性包括:
- 使用一组机器训练一个使用分布式计算的模型
- 在为并行化构建树的过程中,利用 CPU 的所有可用内核
- 处理不适合内存的数据集时的核外计算
- 通过高速缓存优化充分利用硬件
除了上述框架之外:
- 接受多种类型的输入数据
- 适用于树和线性增强器的稀疏输入数据
- 支持使用定制的目标和评估函数
LightGBM
与 XGBoost 类似, LightGBM (由微软开发)是一个分布式高性能框架,使用决策树进行排序、分类和回归任务。
其优点如下:
- LightGBM 是一种基于直方图的算法,可以对值进行分块(也需要较少的内存),因此训练速度更快,精度更高
- 也与大型复杂数据集兼容,但在训练过程中速度更快
- 支持并行学习和 GPU 学习
与 XGBoost 中的水平增长相反,LightGBM 执行分叶(垂直)增长,从而减少更多损耗,进而提高精度,同时速度更快。但是这也可能导致对训练数据的过拟合,这可以使用指定分裂将在哪里发生的最大深度参数来处理。因此,XGBoost 能够构建比 LightGBM 更健壮的模型。
XGBoost 和 LightGBM 之间的结构差异
从我们到目前为止的讨论来看,这两种算法似乎都表现得相当不错。LightGBM 比 XGBoost 快得多,但性能几乎相当。我们可能会想,LightGBM 和 XGBoost 到底有什么区别?
在本文的这一部分,我们将讨论这两种算法之间的一些基本差异——叶生长、分类特征处理、缺失值处理以及各自的特征重要性方法。
叶子生长
LightGBM 具有更快的执行速度,并且能够保持良好的精度水平,这主要是由于利用了两种新技术:
1。基于梯度的单侧采样(GOSS):
- 在梯度提升决策树中,数据实例没有 GOSS 利用的原生权重。
- 梯度越大的数据实例对信息增益的贡献越大。
- 为了保持信息的准确性,GOSS 保留具有较大梯度的实例,并对具有较小梯度的实例执行随机采样。
- 我们可以在文章中进一步了解这个概念——是什么让 LightGBM 快如闪电?
- YouTube 频道机器学习大学也在 LightGBM 上发布了一个关于戈斯的视频。
2。独家功能捆绑(EFB):
- EFB 是一种减少有效特征数量的接近无损的方法。
- 就像独热编码特征一样,在稀疏空间中,许多特征很少同时取非零值。
- 为了降低维度,提高效率,并保持准确性,EFB 捆绑了这些功能,这种捆绑被称为排他性功能捆绑。
- EFB 的这个帖子和 LightGBM 的论文可以参考,以获得更好的见解。
另一方面, XGBoost 使用预排序和基于直方图的算法来计算最佳分割,这是在 LightGBM 中用 GOSS 完成的。预分类拆分的工作方式如下:
- 对于每个节点,枚举所有功能
- 对于每个特性,按特性值对实例进行排序
- 使用线性扫描,决定分割以及特征基础信息增益
- 选择最佳分割解决方案以及所有功能
处理分类特征
LightGBM 和 XGBoost 都只接受数字特征。这意味着我们数据中的名义特征需要转换成数字特征。
假设我们想要预测它是“热”、“冷”还是“未知”,即 2、1 或 0。由于它们是分类特征并且没有排序(这意味着 1 大于 0 实际上不是正确的解释),该算法需要避免比较两个值的大小,而更多地关注于创建相等的规则。
默认情况下,XGBoost 将这些变量视为有序的数值变量,我们不希望这样。相反,如果我们可以为每个分类值创建虚拟值(一键编码),那么 XGboost 将能够正确地完成它的工作。但是对于更大的数据集,这是一个问题,因为编码需要更长的时间。
另一方面, LightGBM 接受一个参数来检查哪一列是分类列,并通过相等拆分来轻松处理这个问题。然而,H2O 库提供了 XGBoost 的实现,它支持分类特性的本地处理。
处理缺失值
这两种算法都通过将缺失值分配到每次分割中损失最少的一边来处理缺失值。
特征重要性方法
增益:
- 数据集中的每个要素在帮助构建精确模型时都具有某种重要性/权重。
- 增益是指特定特征在特定树的上下文中的相对贡献。
- 这也可以通过模型从特征中获得的相关信息的范围来理解,以便做出更好的预测。
- 有 XGBoost 和 LightGBM 两种版本。
分割/频率/重量:
- Weight 的 split GBM 和 Frequency 或 Weight for XGBoost 方法计算特定特征在模型树的所有分割中出现的相对次数。这种方法的一个问题是,当分类特征中有大量类别时,它容易产生偏差。
- 有 XGBoost 和 LightGBM 两种版本。
覆盖范围:
- 每个要素的相对观测值数量。
- 仅在 XGBoost 中可用。
XGBoost 和 LightGBM 之间的其他主要区别
处理部件
我们想要使用的算法通常取决于我们用于运行模型的处理单元的类型。虽然 XGBoost 在 GPU 上相对比 LightGBM 慢,但它在 CPU 上实际上更快。LightGBM 要求我们单独构建 GPU 发行版,而要在 GPU 上运行 XGBoost,我们需要在初始化模型时将“gpu_hist”值传递给“tree_method”参数。
当在能够访问 GPU 和强大 CPU 的机构中工作时,我们应该选择 XGBoost,因为它比 LightGBM 更具可伸缩性。但就个人而言,我认为 LightGBM 更有意义,因为节省下来的训练时间可以用于更好的实验和特性工程。我们可以训练我们的最终模型具有模型鲁棒性。
一个框架和维护它的社区一样好。就 XGBoost 而言,它比 LightGBM 更容易使用,这完全是因为它背后强大的社区和无数有用资源的可用性。由于 LightGBM 仍然有一个较小的社区,当涉及到高级的问题和特性时,导航到解决方案变得有点困难。
证明文件
由于 XGBoost 已经存在了很长时间,并且是数据科学从业者最流行的算法之一,因此它非常容易使用,因为网上有大量关于它的文献。这可以是框架文档的形式,也可以是全球各种用户面临的错误/问题。
从高层次上看这两个产品时, LightGBM 的文档感觉非常全面。但与此同时, XGBoost 的文档给人的感觉非常结构化,在我看来,与 LightGBM 经常冗长的文档相比,它更容易阅读和理解,当然,这并不是交易破坏者,因为它们都在不断改进。
重要超参数
基于决策树的算法可能很复杂,并且容易过度拟合。根据数据可用性和各种统计指标,我们可以对数据有一个总体的了解,对我们来说,进行正确的超参数调整变得很重要。
由于超参数调优/优化本身是一个广泛的话题,在下面的小节中,我们将致力于全面了解 XGBoost 和 LightGBM 的一些重要超参数。
XGBoost 参数
以下是最重要的 XGBoost 参数:
- n_estimators【默认 100】–集合中的树的数量。较高的值意味着更多的弱学习者对最终输出有贡献,但是增加它会显著减慢训练时间。
- max_depth【默认 3】–该参数决定了算法的复杂度。分配的值越小,算法选择大多数模式的能力就越低(欠拟合)。较大的值会使模型过于复杂并挑选出不能很好概括的模式(过度拟合)。
- min_child_weight【默认 1】–我们知道,一个极深的树会因为过度拟合而产生很差的性能。min_child_weight 参数旨在通过限制树的深度来进行正则化。因此,此参数的值越高,模型过度拟合训练数据的可能性就越低。
- learning_rate/ eta【默认 0.3】–模型的学习速率与模型的精度成反比。降低学习率,虽然训练起来比较慢,但是提高了模型寻找模式并学习它们的能力。如果该值太低,则会增加模型收敛的难度。
- gamma/ min_split_loss【默认 0】–这是一个正则化参数,范围可以从 0 到无穷大。该值越高,正则化的强度就越高,过度拟合的可能性就越低(但如果太大,可能会欠拟合)。因此,该参数在所有类型的数据集之间都有所不同。
- col sample _ bytree[default 1.0]–该参数指示算法在训练期间用于一棵树的特征/预测因子总数的分数。这意味着每棵树可以使用不同的特征集进行预测,从而减少过度拟合的机会,并且还提高了训练的速度,因为不是所有的特征都在每棵树中使用。该值的范围从 0 到 1。
- 子样本[默认值 1.0]–与 colsample_bytree 类似,子样本参数指示算法在训练期间用于树的实例总数的分数。这也减少了过度适应的机会,并改善了训练时间。
点击查看更多参数。
LightGBM 参数
以下是最重要的 LightGBM 参数:
- max _ depth-与 XGBoost 类似,该参数指示树木不能生长超过指定的深度。较高的值会增加模型过度拟合的机会。
- num _ leaves—这个参数在控制树的复杂度方面非常重要。该值应该小于 2^(max_depth ),因为对于给定数量的叶子,逐叶树比深度树更深。因此,较高的值会导致过度拟合。
- min _ data _ in _ leaf-该参数用于控制过拟合。较高的值可以阻止树长得太深,但也会导致算法学习得更少(欠拟合)。根据 LightGBM 的官方文档,作为一种最佳实践,它应该设置为数百或数千。
- feature _ fraction—类似于 XGBoost 中的 colsample_bytree
- bagging _ fraction—类似于 XGBoost 中的子样本
点击查看更多参数。
模型性能和训练时间之间的权衡
当使用机器学习模型时,实验阶段涉及的一个重要方面是训练复杂模型的资源的基线要求。虽然有些人可能可以使用一些很棒的硬件,但人们通常对他们可以使用的东西有所限制。
让我们快速虚拟数据集,样本大小从 1,000 一直到 20,000 个样本。我们将从每个虚拟数据集抽取 20%的测试规模来衡量模型性能。对于每一次具有 1000 个样本的不同样本大小的迭代,我们想要检查与 LightGBM 分类器相比,XGBoost 分类器训练所花费的时间。
import neptune.new as neptune
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import make_classification
import time
from tqdm.notebook import tqdm
run = neptune.init(
project="common/xgboost-integration",
api_token="ANONYMOUS",
name="xgb-train",
tags=["xgb-integration", "train"],
)
min_samples = 1000
max_samples = 20000
step = 1000
for sample_size in tqdm(range(int(min_samples/0.8),
int(max_samples/0.8),
step)):
xgb_dummy = XGBClassifier(seed=47)
lgbm_dummy = LGBMClassifier(random_sate=47)
run['metrics/comparison/sample_size'].log(sample_size)
dummy = make_classification(n_samples=sample_size)
X_train, X_test, y_train, y_test = train_test_split(dummy[0],
dummy[1],
test_size=0.2,
stratify=dummy[1])
start = time.time()
xgb_dummy.fit(X_train, y_train)
end = time.time()
run['metrics/comparison/xgb_runtime'].log(end-start)
run['metrics/comparison/xbg_accuracy'].log(
accuracy_score(y_test, xgb_dummy.predict(X_test)),
step=sample_size)
start = time.time()
lgbm_dummy.fit(X_train, y_train)
end = time.time()
run['metrics/comparison/lgbm_runtime'].log(end-start)
run['metrics/comparison/lgbm_accuracy'].log(
accuracy_score(y_test, lgbm_dummy.predict(X_test)),
step=sample_size)
run.stop()
我们能够记录每个样本大小的运行时间和准确性指标,Neptune 会自动生成图表以供参考。要运行代码,可以参考这个 Google Colab 笔记本。
海王星仪表板是一种简单的方法,可以将我们项目的所有结果结合起来,最终进行比较研究。出于这篇博客的目的,我比较了这两种算法的运行时间以及它们各自的性能。
Comparing XGBoost runtime against LightGBM’s runtime | Dashboard
从图中我们可以看到 XGBoost 的训练时间随着样本量的增加几乎呈线性增加。另一方面, LightGBM 所需的训练时间只是其竞争者的一小部分。有意思!
但是各自的模特表演呢?让我们检查在所有这些不同的样本量下,两个模型之间的准确度分数之间的差距。
Comparing XGoost’s model performance against LightGBM’s model performance | Dashboard
从上面的图表中,我们看到了一个非常令人惊讶的结果。两种模型的准确度分数是一致的。结果表明,LightGBM 不仅速度更快,而且在模型性能方面也没有太大的妥协。那么这是否意味着我们可以抛弃 XGBoost 而使用 LightGBM 呢?
这一切都归结于硬件资源和带宽的可用性来解决问题。虽然 LightGBM 与 XGBoost 相比,在一段时间内提供了良好的性能,但是它仍然需要改进的是文档和社区力量。此外,如果硬件可用,因为 XGBoost 的伸缩性更好,如前所述,我们可以使用 LightGBM 进行训练,了解所需的参数,并将最终模型训练为 XGBoost 模型。
摘要
梯度增强决策树是机器学习算法中最受欢迎的选择之一。基于 GBDTs 的 XGBoost 和 LightGBM 在企业应用和数据科学竞赛中都取得了巨大的成功。
以下是我们比较的要点:
- 在 XGBoost 中,树是沿深度方向生长的,而在 LightGBM 中,树是沿叶方向生长的,这是两个框架的根本区别。
- XGBoost 有大量的用户支持,这些用户以文档和问题解决方案的形式提供了丰富的文献。而 LightGBM 还没有达到这样的文档级别。
- 这两种算法在模型性能方面表现相似,但 LightGBM 训练只需 XGBoost 所需时间的一小部分。
- LightGBM 中的快速训练使其成为机器学习实验的首选。
- XGBoost 需要大量资源来训练大量数据,这使得它成为大多数企业的一个可访问选项,而 LightGBM 是轻量级的,可以在中等硬件上使用。
- LightGBM 提供了传递被视为类别的特性名称的选项,并通过相等分割来轻松处理这个问题。
- H2O 的 XGBoost 实现也提供了 XGBoost 原始库还没有提供的上述特性。
- 超参数调整在这两种算法中都非常重要。
这两种算法都在输出模型性能方面设定了黄金标准,完全由用户根据分类特征的性质和数据的大小进行选择。
参考
- https://xgboost.readthedocs.io/en/stable/
- https://lightgbm.readthedocs.io/en/latest/
- https://docs . Neptune . ai/integrations-and-supported-tools/model-training/light GBM
- https://docs . Neptune . ai/integrations-and-supported-tools/model-training/XG boost
- https://docs . Neptune . ai/you-should-know/what-can-you-log-and-display