杜克大学-DataOps-笔记-全-

杜克大学 DataOps 笔记(全)

001:机器学习系统中的数据投毒

在本节课中,我们将要学习机器学习系统中一种特定的安全威胁——数据投毒。我们将探讨其攻击向量、潜在影响以及关键的缓解策略。

概述

数据投毒是一种安全威胁,攻击者通过向训练数据中注入恶意样本,来破坏机器学习模型的性能或行为。这种攻击可能来自外部,也可能来自组织内部。本节我们将重点分析由内部人员发起的两种数据投毒攻击场景。

内部威胁与数据投毒

上一节我们介绍了数据投毒的基本概念,本节中我们来看看两种具体的内部攻击向量。

攻击向量一:利用企业系统漏洞

第一种攻击向量涉及利用企业自有系统的已知漏洞。例如,攻击者可能知道某种特定类型的图片会导致Google Drive等服务离线。

以下是这种攻击可能发生的步骤:

  1. 企业内部人员蓄意将一个被禁止的图片上传至公司的Google Drive。
  2. 该图片触发系统漏洞,导致整个公司的Google Drive服务离线。
  3. 公司需要花费时间联系Google并解释情况以恢复服务。
  4. 这实质上构成了一次针对公司的持续性拒绝服务攻击。

这种攻击方式相当隐蔽,其可行性取决于员工在组织内拥有的权限。攻击者甚至可能使用难以被识别为违规内容的图片,例如一张一战时期的图片。

攻击向量二:污染训练数据

第二种攻击向量是内部人员秘密地向训练数据中“播种”恶意样本。这些样本被设计用来触发某种被禁止的攻击模式。

以下是这种攻击可能发生的步骤:

  1. 攻击者将一个特定文件植入客户系统中。
  2. 该系统使用被污染的数据进行训练。
  3. 最终训练出的多分类模型会“看到”实际上并不存在的模式,本质上植入了一个虚假的“违规”标志。
  4. 由于内部人员蓄意破坏,目标组织可能因此持续遭受拒绝服务攻击。

缓解策略

在了解了上述两种攻击方式后,我们来看看如何缓解这些威胁。

以下是关键的缓解措施:

  • 定期审计:对数据和系统访问进行定期审查,及时发现异常。
  • 实施最小权限原则:确保员工只拥有完成工作所必需的最低权限,避免过度授权。

这些并非理论上的攻击。随着机器学习和数据应用的普及,将数据投毒视为对许多组织的真实威胁至关重要。

总结

本节课中我们一起学习了机器学习系统中的数据投毒威胁。我们分析了两种由内部人员实施的攻击向量:一是利用企业系统漏洞发起拒绝服务攻击;二是通过污染训练数据来破坏模型。最后,我们探讨了通过定期审计和贯彻最小权限原则来缓解这些风险的重要性。

002:MLOps关键组件是什么

在本节课中,我们将探讨构成现代机器学习运维(MLOps)生态系统的关键组件。我们将了解云服务商提供的核心基础设施、工具和服务,以及如何根据需求选择通用服务或专业解决方案。

云环境下的MLOps全景图

进行机器学习运维时,了解所有关键要素至关重要。即使不使用云服务商提供的完整MLOps平台,也很可能用到云环境中的某些服务。让我们来看看一些可用的核心组件。

核心基础设施组件

以下是构成MLOps基础的核心云服务。

弹性存储系统

弹性存储系统允许你根据需求扩展存储容量。这包括对象存储,以及使用文件系统的挂载存储。目前一个新兴趋势是,许多云提供商提供整个集群都可以读写、无需依赖Hadoop或Spark等系统的挂载点。这一趋势带来了近乎无限的磁盘存储访问能力。

弹性计算系统

弹性计算系统同样可以根据你的需求进行扩展。这包括CPU、GPU,甚至允许你在TPU等专用芯片上运行TensorFlow推理的ASIC。

无服务器与容器化托管服务

建立在上述计算和存储基础之上的是无服务器和容器化托管服务。这是云提供商利用网络效应提供的服务,例如AWS App Runner、AWS Lambda或Google Cloud Functions。

集成开发工具与SDK

云服务商提供了紧密集成的工具和软件开发工具包(SDK)。

这些工具通常以云Shell或基于云的开发环境(如AWS Cloud9、Azure Cloud Shell、Google Cloud Shell)的形式提供。它们与供应商平台深度集成,使你能够利用云计算快速构建应用。

开发体验正日益以开发者为中心。例如,在AWS、Azure或GCP上,你可以找到云Shell和类似Visual Studio的云端集成开发环境。

数据与机器学习专用服务

随着工作重心转向数据和机器学习,你会发现每个供应商都提供了相应的工具。

存储查询工具与仪表板

每个主流云服务商都提供了针对其存储系统的查询工具和可视化仪表板。

  • Amazon Athena:允许你对对象存储执行SQL查询。
  • Google BigQuery:允许你对其分布式存储系统执行SQL查询。

机器学习与MLOps平台

进入机器学习阶段后,你会看到基于Jupyter Notebook的平台和专门的MLOps平台。

几乎所有云提供商都提供了集成了实验跟踪、模型注册、特征存储和模型推理等功能的MLOps平台。虽然这些平台功能全面,但有时可能无法完全满足特定需求。

第三方专业解决方案

正因为云平台的原生服务可能无法满足所有需求,市场上也涌现了许多第三方专业解决方案。你可以将这些云核心能力视为基础构建块,而第三方供应商则在此基础上提供更专业的服务。

以下是主要的第三方解决方案类别:

  • DataOps平台:例如Databricks或Snowflake,专注于数据工程和数据分析流水线。
  • 专用MLOps平台:提供更灵活或更强大的机器学习生命周期管理工具。
  • 专用数据库:如图数据库或时序数据库,用于处理特定类型的数据。
  • 监控与可观测性工具:例如Datadog或New Relic,用于监控系统性能和健康状况。

这些第三方供应商不仅能够紧密融入云环境,还能帮助你超越单一云平台的能力,构建更专业、更定制化的解决方案。

总结

本节课中,我们一起学习了现代MLOps生态系统的关键组件。我们了解到,MLOps不仅依赖于云服务商提供的弹性计算、存储、无服务器服务和集成开发工具等核心基础设施,还涵盖了从数据查询到机器学习平台的全套服务。同时,第三方专业解决方案在特定领域提供了更深度的功能。因此,在规划MLOps时,需要全面了解整个生态系统,明智地选择哪些需求可以使用通用的云服务来满足,哪些则需要投资于能带来更高投资回报率的专业供应商服务。

003:MLOps成熟度模型考量 🧭

在本节课中,我们将要学习MLOps成熟度模型的概念。我们将了解AWS、Microsoft和Google这三大云服务商如何定义和划分MLOps的不同成熟阶段,并理解自动化在其中的核心作用。

概述

所有主要的MLOps领域供应商都提出了MLOps成熟度模型的概念。其核心含义是,从最初级、手动且容易出错、难以将模型投入生产的阶段,到高度自动化、具备下一代特性的成熟系统,中间存在多个不同的演进阶段。接下来,我们将深入探讨这些不同供应商的MLOps成熟度模型是如何进行比较的。

AWS的MLOps成熟度模型

首先,我们来看AWS平台。让我们了解一下他们对MLOps成熟度的看法。

在将模型投入生产或实现运营化方面,你拥有的能力越多,投入生产的模型就越多,迭代速度就越快,组织的成熟度也就越高。

以下是AWS定义的几个关键阶段:

  • 实验能力:初期必须具备实验能力。如果无法进行实验,将任何东西投入生产都会非常困难。
  • 可重复性:下一步是实现可重复性。你是否能够标准化你的代码和资源?是否确保有一个可以实际部署解决方案的平台?这是进入下一级别的关键。
  • 可靠性:在可靠性方面,你需要进行测试。你能否测试生产环境的能力?是否监控数据漂移和新版本?例如,你能否拥有多个隔离的账户,如生产账户、预发布账户和开发账户?
  • 可扩展性:在最后的成熟阶段,你拥有可扩展性。你能够将许多不同的机器学习解决方案模板化并投入生产,而不仅仅是一个。你拥有一个可以反复重复使用的可扩展系统。

Microsoft的MLOps成熟度模型

现在,让我们继续看Microsoft。Microsoft同样拥有成熟度模型的概念。

他们将第一阶段视为“无MLOps”,其特点是部署困难、团队割裂、系统是黑盒且无法知晓其是否有效。

以下是Microsoft定义的成熟阶段:

  • 阶段1:无MLOps:如上所述,这是最基础的阶段。
  • 阶段2:具备部分DevOps:一些组织处于较好的位置,他们至少拥有DevOps,但由于缺乏机器学习的关键能力(如特征存储和数据漂移检测),发布过程仍然痛苦。
  • 阶段3:自动化训练:整个流程能够自动化完成。例如,在检测到数据漂移时可以自动重新训练模型。
  • 阶段4:自动化模型部署:发布变得简单。可以轻松地拥有训练环境、测试环境和生产环境。
  • 阶段5:全自动化CI/CD:一切完全自动化,没有停机时间,可以持续创建新模型。

AWS和Microsoft模型中的关键点都在于自动化因素。

Google的MLOps成熟度模型

现在,让我们来看看Google的观点。

Google认为,MLOps Level 0是一个手动过程。许多团队拥有数据科学家和ML研究员,但你可以看到机器学习和运维之间是分离的,所有事情完全手动。

以下是Google定义的成熟阶段:

  • Level 0:手动流程:机器学习与运维分离,所有步骤均为手动。
  • Level 1:管道自动化:此阶段的目标是持续训练模型。因为实现了部分自动化(例如,检测到数据漂移、拥有特征存储),你能够在适当时机自动训练模型。
  • Level 2:CI/CD管道自动化:最后的阶段是,你不仅拥有自动化的模型训练,你的持续集成和持续交付系统还能够完整地部署系统,正确地进行打包,从而实现100%的端到端自动化。

总结

本节课中,我们一起学习了三大云服务商(AWS、Microsoft和Google)的MLOps成熟度模型。尽管各家的具体阶段划分和命名有所不同,但其核心理念高度一致:即通过自动化深度集成,实现系统的持续部署,并最终培养一种生产优先的思维模式。从手动、孤立的起点,到实现端到端的自动化CI/CD管道,是MLOps成熟度演进的核心路径。

004:什么是持续集成 🚀

在本节课中,我们将要学习DevOps的核心概念之一——持续集成。我们将从搭建一个本地开发环境开始,逐步创建一个包含测试、代码检查和格式化的Python项目脚手架,并最终将其与GitHub Actions构建系统集成,实现自动化的持续集成流程。

开发环境搭建 💻

上一节我们介绍了持续集成的核心思想,本节中我们来看看如何搭建一个可靠且可复现的开发环境。

DevOps的一个核心概念是能够自动测试你的代码。这是一个反馈循环,即持续集成。持续集成的本质是能够知道你的代码是否正常工作。一旦你的代码在开发环境中正常工作,关键就在于能否将其复制到云端或生产环境。

为了实现这一点,你需要具备几个条件。首先,你需要能够在生产环境中进行复制。这意味着你可能需要使用基础设施即代码来定义基于云的环境,使其与你的开发环境相似。其次,你需要某种形式的测试,这就是之前提到的持续集成组件。最后,在部署方面,你需要将所有部分整合起来,并将代码部署到该环境中。这就是所谓的持续交付。

一旦建立了持续交付,你就能够将这些更改复制到任意数量的环境中。这就是DevOps的力量,也是测试的力量。测试是持续交付的强制性组成部分,因为你不会希望将错误的代码复制到生产环境并导致服务中断。这就是我们关心测试的本质:首先让代码在本地工作,然后能够将其复制到基于云的环境中。

我认为首先要做的是让本地开发环境先运行起来。确保我们能够真正让任何东西工作。

我将切换话题,讨论几种不同的开发环境。大多数人可能从GitHub或GitLab开始。GitHub可能是最受欢迎的,我认为这是一个开始思考项目结构的好地方。我喜欢使用基于云的开发环境,因为这样可以轻松获得所有合适的工具。我认为现在大多数开发者最好在基于云的开发环境中进行开发。

其中之一是GitHub Codespaces。这是GitHub的一个功能,与其他基于云的开发环境(如AWS Cloud9)非常相似。我将在这里创建一个新的代码空间。

它的优点是,如果你出于某种原因真的想在本地工作,你甚至可以在本地的VS Code桌面版中使用它。但我喜欢这些环境,因为它让云本身承担所有繁重的工作。我不必担心我的环境。现在,它对我来说是完全安全的。它已经配置好,加载了扩展,基本上为我测试代码做好了准备。

在这样一个新环境中,我要做的第一件事是创建一个Python虚拟环境。原因是Python是一种解释型语言,Python需要能够将所有包放在一个目录中以确保可靠性。它附带了一个叫做venv的工具。

如果我们输入python -m venv --help,它会显示在这个环境中可以做的所有不同事情,包括创建虚拟环境。这个虚拟环境工具有很多功能,但我们将保持简单,只创建一个新的。

一个好的惯例是这样做:python -m venv ~/.venv。这样做的原因是它不会被意外地推送到你的GitHub仓库中。如果把它放在主目录的一个隐藏目录里,这是一个很好的地方,可以避免干扰。

创建完成后,要激活它,我只需要输入source ~/.venv/bin/activate。现在,如果我输入which python,可以看到我引用的是这个Python。所以,对于任何Python项目,第一步在我看来就是获取一个基于云的开发环境。如果你在AWS上,使用Cloud9;如果你在GitHub上,可以使用GitHub Codespaces;GCP有Cloud Shell;Azure有Cloud Shell环境。它们都非常相似。

现在我已经设置好了。一个缺点是,如果我在这里打开一个新的终端,虚拟环境就消失了,这有点烦人。我们如何解决这个问题?幸运的是,我们可以很容易地解决,因为我可以编辑我的.bashrc文件,这是这个环境的配置文件。我认为对于这些基于云的开发环境来说,如果你要将其用于一个项目,并且项目与环境是一对一的关系,为什么不让它每次打开新shell时都自动激活呢?

我将输入vim ~/.bashrc,然后按Shift+G跳到文件底部,在这里添加一个小注释,说明我想激活我的虚拟环境。然后我只需放入那个命令。现在如果我们打开一个新的终端,虚拟环境就自动激活了。我认为这是一个很巧妙的小技巧,可以为你节省很多麻烦。

现在我们有了环境,状态良好,可以打开新的shell,这很好。我要做的第一件事是创建一个项目的脚手架。

创建项目脚手架 🏗️

上一节我们成功搭建了开发环境,本节中我们来创建一个标准化的项目脚手架。

对我来说,一个测试项目脚手架的最低要求首先是Makefile。我喜欢使用Makefile,因为它可以为我保存很多复杂的命令。这将是我在项目中可以反复引用的东西,甚至可以像食谱一样不断积累。

接下来我要创建的是一个requirements.txt文件。这将是一个我可以引用我想要安装的包的地方。这真的是我最初需要的两个文件。然后我们也许可以创建一个测试文件和一个应用文件。让我们称第一个文件为hello.py,第二个文件为test_hello.py。这是一个非常标准的过程,我参与的大多数项目都使用类似的结构。

现在,首先要做的是,这些文件都是空的,touch命令的作用就是创建空文件,它是幂等的,意味着如果我反复运行touch命令,如果文件已经创建,它不会做任何不同的事情。这是一个很简洁的命令,可以为你创建空文件。

我将打开这个Makefile,需要在里面放入一些不同的组件。为了做到这一点,我可以去看看我之前设置的另一个项目,参考一下。我有一个叫做pytest的项目。注意,我过去已经创建了一个Makefile。让我们看看这个,看看是否能得到一些启发。

很好,我有一个安装部分,一个测试部分,一个格式化部分,一个代码检查部分,然后还有一个同时运行所有这些的东西。我们可能可以直接复制这个。让我们用它作为我们的脚手架。我回到代码空间,直接粘贴进去。这就是创建一次脚手架的好处,你几乎可以一遍又一遍地使用它。

现在让我们看看这个Makefile是如何工作的。首先,我们会看到,如果我输入make,然后输入install,它会自动补全。如果我输入make加空格加Tab,它实际上会显示所有不同的选项。这就是make另一个非常酷的部分,它几乎能自动给我一个帮助菜单。这就是为什么我认为Makefile对于Python开发者来说真的非常酷。如果你不使用Makefile,开始将它们集成到项目中是值得的,可以节省你很多时间。

现在我们可以看看requirements.txt文件,我们需要安装一些能帮助我们的包。首先,我认为我们要安装的一个包显然是测试库pytest

首先,我们放入pytest。让我们看看它是如何工作的。记住,这真的很简单。我总是先检查确保Python打包工具pip没有新版本。然后我输入pip install -r requirements.txt。让我们运行这个:make install。完美。

现在我已经设置好了,我已经加载了pytest。我如何测试pytest是否加载了呢?我可以直接输入pytest --help。你可以看到它确实在运行。我已经加载了pytest,它是一个非常复杂的工具,可以做很多事情。很多测试工具都非常复杂,我现在可以查看所有我可以用pytest做的事情。

对于我刚开始一个项目时,很可能还会开始使用其他一些东西。比如我喜欢用pylint进行代码检查,还有flake8作为替代。还有black工具,它是一个格式化工具。然后我还放入了pytest-cov,这是一个覆盖工具,显示我们代码的覆盖报告,比如有多少代码被实际测试了。这可能是一个很好的开始,我认为这可能是一个很好的组合。

我可以再次利用Makefile的力量,简单地再次输入make installmake install

这里有趣的是,安装是持续集成的一个重要组成部分,这可能并不直观,但确实如此。当我们稍后为GitHub Actions设置构建系统时,我们要做的一件事就是实际测试包的安装,因为这是现实世界的情况。你想确保你的代码实际上是可以安装的。

现在我们几乎一切都设置好了,我们有能力运行东西。也许我们可以安装另一个我喜欢用来调试或尝试东西的工具,那就是ipython

我认为这会是另一个。让我们来做这个,我会告诉你为什么我喜欢安装ipython。当我调试代码或尝试东西时,能够从交互式提示符导入我的模块或任何东西,然后尝试它,这实际上非常简洁。例如,如果我要测试我的代码,我可能会先尝试我写的模块。

让我们输入more hello.py,然后做一些非常简单的事情,比如说hi。现在我这里有了一段代码。那么我如何在ipython中使用这个呢?我只需输入ipython,然后输入from hello import。看,它会为我自动补全,这真的很棒。然后我甚至可以在写第一个测试之前尝试我的代码。我可以看看这个做了什么,如果我调用它,它会做什么。它返回hi。我甚至可以尝试我可能在pytest中写的测试。

pytest使用assert,所以我可以在这里输入asserthi等于more_hello。这本质上就像是在原型化我的单元测试。哦,太好了,这很简单,很酷。所以ipython是一个很好的工具,我认为它被严重低估了。

很好。我们这里有一个测试文件,这很好。让我们继续在pytest中写我们的第一个测试。幸运的是,用pytest写测试非常简单,这就是为什么这么多人喜欢它。这个工具很复杂,但在pytest中写测试却简单得离谱。

我们记得我们这里有一个test_hello.py。我们需要做的就是基本上做和我在ipython终端里一样的事情。事实上,我可以直接看下面的ipython终端,本质上那就是我需要的所有代码。我要输入from hello import more_hello

现在我只写一个assert。测试就是这样工作的。我要写def test_more_hello,我喜欢用模块函数的名字来命名测试。然后我就做同样的事情,我基本上可以剪切粘贴下面我做的事情,然后粘贴进去。

我们可以在这里写assert hi == more_hello()。现在让我们做一个测试。再次看看我们的Makefile。注意我是如何测试的:我说python -m pytest,并给它几个选项,比如让它更详细,这些标志的作用就是这样,然后我就这样运行这个文件。所以如果我们运行这个,我可以说make test。我喜欢在这里做make test的原因,你可以看到它通过了,是因为它更简单,输入代码更少,一遍又一遍地输入命令很烦人。

你会发现,除非你在pytest中做一些非常棘手的事情,否则只需将其放入Makefile的测试块中,就能节省你很多时间。

现在让我们看看如果测试失败会发生什么。那是成功的,但让我们做一个失败的测试,说test_more_hello_2。显然它只返回hi,如果我们说别的呢,比如bye?我们可以在这里输入more_hello,它会自动补全。如果我再运行make test,我们会得到一个失败。非常直观地用pytest写测试。看,它给了我们一个报告,说系统有50%通过了,我们有一个失败,我们可以在这里看到,它说看,你说函数应该返回bye,但实际上它返回了hi,我们有问题。

好吧,现在也许我接下来要做的是回到我的代码,说哦,是的,我还没写这个函数。让我们写一个函数,说more_goodbye。然后,我们说return "bye"。然后如果我们回到测试文件,我可以直接导入那个文件。我们可以这样做。more_goodbye。然后我可以改变这个。改成test_more_goodbye。像那样改变。完美。现在如果我再次运行make test,我们得到了两个通过的测试。所以从某种意义上说,它非常直观,因为它给了你这个输出,说,哎呀,我们这里有问题,让我们修复它。

很好,我们掌握了pytest的基础。我个人认为让格式化和代码检查工作起来也很好。我会称之为最佳实践清单。让我们再次检查代码检查是否工作。如果我们用pylint进行代码检查,注意我在这里做的是说pylint,我禁用了另外两种类型的警告,我相信这是配置中推荐的。所以我只想看到警告和错误。就我而言,这些是我最关心的事情。所以我要继续检查这个文件。我要再次输入make lint,因为我想让我输入的内容简洁。make lint很好。

现在什么能让我们测试这个,看看如果代码不好会发生什么?一个简单的方法是,如果我说var = 1,我创建了一个变量,然后在里面,我说var = var,做一些无意义的事情。看,如果我做make test,测试仍然通过。所以它在语法上仍然是有效的,它仍然有效,只是没有真正做任何事情,这是一种糟糕的编码技巧。你不想把一个变量重新赋值给自己。所以如果我做make lint,现在它会说,嘿,看这个,你不能这样做,你应该小心你正在把变量赋值给它自己,这是一个警告。代码仍然有效,这不是一个错误。它也会捕获错误。让我们在这里放一个注释,说“这是产生警告的无意义代码”。

所以我相信这对于像Python这样的语言,甚至编译语言来说,捕获警告也是非常关键的。为什么不听编译器的呢?我认为这是一个好主意。

但现在让我们制造真正糟糕的语法。如果我在这里,我也可以说,f =,然后留空。像这样,这是坏掉的代码,这段代码不会执行。另一件很酷的事情是,如果我们做make lint,它实际上会显示无效语法。所以它在这里失败了,说,看,你的代码甚至无法运行。我甚至无法得到警告,因为它甚至无法运行,它直接告诉我们了。它说第12行。这就是pytest真正强大的地方之一。抱歉,是pylint。它和pytest配合得很好,它们是互补的,或者flake8也是。所以它捕获了额外一层的东西,这些只是有帮助的。你想知道这些事情,尤其是当你在一个团队项目中工作时。

好的,很好,这个工作了。让我们继续,再次运行make test,确保它工作。很好,我们要运行make lint,确保它工作。太棒了。然后真正获得初始反馈循环的另一个组成部分就是去格式化,除非你想再次检查这是如何工作的。在这个里面,我喜欢格式化工具的地方是,它还能解决你团队中的问题。当你在公司里和一些人一起工作时,一个人想这样做,另一个人想那样做,这可能会很烦人。如果你使用像这样的格式化工具,就像看,格式化工具这么说,所以让我们保持简单,继续使用这个。如果我输入make format,它只是清理代码,让它变得更好一点。所以我认为这样做也是一个好主意。如果你愿意,你实际上可以把所有这些放在一起,你可以按照你喜欢的顺序链接它们。所以我认为这是一个相当好的顺序,我推荐这个顺序,基本上就是在你将代码签入到GitHub之前,为什么不直接做make all呢?安装你的代码,确保你拥有所有最新版本,你也可以固定需求,我们实际上会这样做,然后测试你的代码并格式化你的代码。

让我们继续做这个,输入pip freeze。如果我们输入pip freeze,也许把它管道到less,它会显示当前安装的所有版本。我们可以继续做这个,我们可以把它们换掉。我不喜欢直接剪切粘贴这个,因为这样可能会把我不需要的东西放进去。所以我认为在这里对我的选择更小心一点更好。我可以说pytestpytest-cov。很好,让我们把它们放进去。像这样,这会告诉这个仓库,你正在使用我安装的这个版本的包。这对于测试来说又很好,因为我可以测试我的代码的一个非常特定的版本。然后我们可以回到这里,也可以放入这个版本。

太棒了。我们也有我们的包安装了,这很好。现在我可以做make all。让我们继续做make all,再次检查一切是否正常。它会安装我的软件,检查我的软件,测试我的软件,格式化。我认为这是一个开始你的项目的好方法,在我看来,强烈推荐。

集成持续集成流程 🔄

上一节我们完成了本地项目的脚手架和测试,本节中我们将把代码推送到远程仓库,并集成GitHub Actions以实现自动化持续集成。

让我们进入下一步,推送这个代码。我要输入git status,然后输入git add .。然后我要输入git commit -m "adding initial layout"。完美。现在我要推送这个代码。很好。

现在我已经在这里建立了这个初始结构,我们现在可以开始看下一个层次,那就是,如果我想使用一个不同的环境,而不仅仅是这个环境,例如,假设你的公司使用AWS或GCP或Azure,你该怎么做?有几件事我推荐,一是如果我们回到这个图,记住想法是你在本地测试,你的代码工作得很好,但你也希望有能力部署到其他环境。所以这就是构建系统发挥作用的地方,构建系统基本上将是守门员,允许你在使用之前再次检查一切是否正常。

因为我们还没有设置构建系统,在我们解决这个问题之前,先不要进入云环境。

我要做的是转到GitHub。我要回到我们的仓库,然后设置这个。让我们继续,称这个为pytestpytest技巧和提示。

现在我要进入这个叫做“Actions”的部分,这将是GitHub Actions构建系统。构建系统只是运行你的代码,并允许你对其进行测试和部署,这真的是它的本质。GitHub Actions是较新的一个,集成得非常好,我个人是它的忠实粉丝,我认为它很棒。关于GitHub Actions,有几点要指出。

这些工作流允许你做诸如使用Anaconda之类的事情,这里有一个如何使用Makefile的例子,我刚刚展示给你,还有如何发布Python包。所以如果你想成为一个开源软件开发人员,你可以这样做。你也可以使用其他流行的服务部署你的代码,比如Azure ACR、ECS、GKE。所有这些都是使用它的好例子。此外,还有一些更抽象的例子,比如让我们做一个标签器,或者让我们给某人分配任务。有很多很酷的东西。我认为一个好的起点是自己设置工作流,它基本上给你一个非常粗略的结构,你可以用来尝试东西。

既然我以前做过这个,我要做的是,实际上打开一个新标签页,再次复制一个我以前的版本。我有一个GitHub Actions的例子。我有一个之前做过的,看看布局,是.github/workflows,然后有一个YAML文件。你可以在这里看到一个非常非常简单的使用GitHub Actions的Python应用测试。我们要说在推送时,我们将运行这些步骤。我们甚至可以说是什么操作系统,在这种情况下是Ubuntu最新版。我们甚至可以指定Python的版本。然后我可以告诉它做我刚刚在本地做的事情。这真的就是全部,只是做同样的事情,但在云端的某个地方运行,并确保在我进入下一步之前一切都经过验证。让我们继续尝试这个,这看起来正是我想要的。

让我们复制这个。然后我将把它放入这个文件。事实上,我们甚至可以称这个为testing,或者CI,测试持续集成。然后我们可以直接点击开始。这很酷,一旦你点击这里的开始,它就会开始运行我们的任务。我可以看到它在运行。所以它将执行所有步骤,它将首先安装,然后检查,然后测试,然后格式化我们的代码。

很好,这看起来很不错。到目前为止,一切顺利。好的,看起来我们状态良好。我们让一切都在运行,它甚至在这里显示了每个步骤,这对我们所有的代码都很好。然后点击这个小菜单,说“创建状态徽章”,然后复制这个,这不是一个坏主意。

然后我们可以回到我们的项目。就是这个项目。

然后转到README.md文件。也许把它放在顶部。我们可以有我们的测试徽章。所以我们状态很好。我认为我们唯一没做的,我们可以很容易地做到。就是我没有,我要输入git pull,这样我就能得到我刚才做的所有东西。

但我们也没有做测试覆盖标志。为了做到这一点,我们只需要稍微调整一下。我们只需要做,我相信我们可以查一下,实际上,这就是我通常解决问题的方式,我直接说,pytest-cov。它在哪里,如何在命令中使用它?你只需要说。就是这样,这就是我需要做的。所以我要做类似的事情,回到这个仓库,我们只是添加一个小标志。我们只是说,在这种情况下我想覆盖什么?我只有一个叫做hello.py的文件,一个非常简单的项目。让我们继续做这个。再次运行make test

让我们看看是否能得到一个覆盖报告,make test。现在我们有了一个覆盖报告,我们有100%的测试覆盖率,这并不奇怪,这是一段非常简单的代码。输入git statusgit add Makefile。好的,让我们提交这个,添加覆盖报告。

总结 📝

在本节课中,我们一起学习了持续集成的核心概念与实践流程。我们从理解持续集成和持续交付的基本定义开始,认识到自动化测试和可重复部署的重要性。接着,我们动手搭建了一个基于云的开发环境(GitHub Codespaces),并创建了一个标准化的Python项目脚手架,其中包含了:

  • Makefile:用于封装复杂的安装、测试、代码检查和格式化命令。
  • 虚拟环境:确保项目依赖的隔离性和可复现性。
  • 测试框架(pytest):编写和运行单元测试。
  • 代码检查工具(pylint):确保代码质量。
  • 代码格式化工具(black):统一代码风格。

最后,我们将本地验证成功的项目与GitHub Actions集成,实现了自动化的工作流。该工作流会在代码推送时自动在云端运行安装、代码检查、测试和格式化步骤,并通过状态徽章直观展示构建结果。这构成了一个完整的、可扩展的持续集成基础,为后续向生产环境的持续交付打下了坚实的基础。

005:什么是持续交付 🚀

在本节课中,我们将学习持续交付的核心概念。我们将通过一个使用现代云原生工具的持续交付工作流程,来理解如何自动化地将代码变更安全、可靠地部署到多个环境。


上一节我们介绍了持续交付的基本理念,本节中我们来看看一个具体的工作流程示例。

工作流程通常始于开发环境。开发人员经常使用基于云的环境,例如 AWS 的 Cloud9 或 Azure 平台的 GitHub Codespaces。使用这些云原生环境的原因是,它们提供了与后续生产环境一致的开发工具链。

因此,你拥有一个与生产环境高度相似的一对一开发环境。

在构建应用时,你不仅会推送软件代码,还会推送“基础设施即代码”。基础设施即代码允许你定义在云环境或 Kubernetes 环境中运行的每一个细节。

请注意,当你推送变更时,构建系统将自动执行以下操作:测试你的代码、合并代码。随后,这个构建版本会自动进入“资源调配”阶段。

基础设施即代码的强大之处在于它是幂等的。

这意味着它只在必要时才做出更改,并且始终确保环境处于预期的相同状态。

例如,如果你最初创建了基础设施,在进行第二次构建时,它不会再次创建基础设施,因为它会检测到(比如这里的 S3 存储桶)已经存在,因此无需重复操作。

同样地,如果你修改了基础设施即代码的配置,做了一个小改动,系统会检测到差异并为你创建一个新的存储桶。

最后,如果需要清理资源,使用基础设施即代码可以轻松完成。

以下是你可以执行的几种强大操作:

  • 删除操作:清理不再需要的资源。
  • 创建新环境:你可以选择不删除,而是基于代码和基础设施配置创建一个新的“预发布”环境。这个环境用于进行负载测试。
  • 创建生产环境:同样地,你可以再次复制代码和基础设施配置,以创建一个“生产”环境。

这种使用代码来定义系统、并进行幂等变更的理念,是持续交付的重要组成部分。它使你能够持续地将变更推送到新环境。

这并不意味着无需人工干预就能直接推送到生产环境,但它确实允许你向多个环境进行自动化推送。这正是持续交付的关键概念。


本节课中我们一起学习了持续交付的工作流程。我们了解到,通过结合云原生开发环境和“基础设施即代码”的幂等性,可以实现代码的自动化测试、构建以及向多个环境(如预发布、生产)的安全、可靠部署。这是实现高效、可控软件交付的核心。

006:什么是特征存储 🗂️

在本节课中,我们将要学习特征存储的核心概念。我们将探讨特征存储与数据仓库的区别,并理解它在机器学习工作流中的关键作用。

概述

特征存储是机器学习基础设施中的一个关键组件,它负责存储和管理用于模型训练和预测的高质量特征数据。理解它与数据湖、数据仓库的关系,对于构建高效的机器学习系统至关重要。

数据湖、数据仓库与特征存储

上一节我们介绍了机器学习运维的宏观概念,本节中我们来看看特征存储的具体定位。数据湖、数据仓库和特征存储具有不同的特点。

我们可以从数据质量的角度来看这张图。数据湖可能是流式数据、批处理数据、非结构化数据和结构化数据的混合体。因此,你需要做大量工作来清理这些数据。

在这个具体问题中,你可以做什么?你可以从数据湖中提取原始数据,进行特征工程,并将高质量、可缓存、可复用的特征组合起来,放入特征存储中。这些特征随后将用于训练模型、为预测客户端提供服务,并且整个过程会经过审计,还可能开发出自动相关性分析等功能。所有这些都构成了特征存储的组成部分。

所以,特征存储本质上是对数据湖中内容的精炼,目的是让机器学习系统能够高质量地访问那些用于训练模型的特征。

另一种不同的资源是数据仓库。它的理念更侧重于报告、仪表盘和商业智能分析。

无论是特征存储还是数据仓库,你都可以看到它们处理的是高质量数据。一个关键区别在于,商业智能分析主要基于数据仓库,而人工智能/机器学习则主要基于特征存储。

特征存储和数据仓库之间不一定有严格或绝对的界限,它们可能存在一些重叠。但核心思想是,你将那些未清理、非结构化的低质量数据,通过ETL管道和特征工程管道等自动化工具,转化为这些高质量的资源,从而为你的组织创造更多价值。

核心概念总结

以下是特征存储的几个核心要点:

  • 数据来源:特征存储的数据通常来源于需要大量清理工作的数据湖
  • 核心功能:它通过特征工程流程,生产出高质量、可缓存、可复用的特征。
  • 服务对象:这些特征服务于模型训练在线预测
  • 附加价值:特征存储支持审计,并有助于发现特征的自动相关性
  • 与数据仓库对比:数据仓库更侧重于商业智能和报告,而特征存储专为AI/ML工作流设计。
  • 共同目标:两者都是将低质量原始数据转化为高质量、结构化数据的关键环节,旨在提升数据价值。

总结

本节课中我们一起学习了特征存储。我们明确了特征存储作为数据湖中原始数据的“精炼厂”角色,它产出专供机器学习使用的高质量特征。同时,我们将其与服务于商业智能的数据仓库进行了对比,理解了它们在数据流水线中各自不可替代的价值。掌握特征存储的概念,是构建可维护、高效机器学习系统的基石。

007:什么是数据漂移 📊

在本节课中,我们将要学习机器学习中的一个核心挑战:数据漂移。我们将通过一个生动的比喻来理解其概念、成因以及应对策略。

概述

数据漂移是指模型在生产环境中运行时,其输入数据的统计属性随时间推移而发生变化,导致模型性能下降的现象。理解数据漂移对于维护机器学习系统的长期有效性至关重要。

核心概念:一个生动的比喻

上一节我们介绍了数据漂移的重要性,本节中我们来看看一个经典的比喻,它清晰地阐释了数据漂移的核心问题。

这是一个来自现实世界的绝佳例子,说明了数据漂移带来的问题之一。这个例子源于纳西姆·塔勒布,他是《黑天鹅》及其他概率论相关书籍的作者。

他在书中给出的一个例子是关于这个概念的:想象你从一个容器中不断取出球。每个新取出的球都能让你更了解红球与黑球的出现频率。在这种情况下,我们看到事物是静态的。因此,你获得的信息越多,情况就越好。

但在现实世界中,由于数据是动态变化的,你并不一定能总是获得对世界真实状态的准确反映。他提出的一个例子是:想象同样的场景,但容器底部有一个活动面板,里面有一个小孩在不断地向活动面板里填充新球。这可能会破坏你的认知,即使你从容器中取出的球越来越多,实际上也并未给你带来更多信息,因为黑球与红球的分布一直在变化。

所以,这确实是数据漂移的核心思想:如果数据不断变化,你可能并不拥有你认为自己所拥有的信息。这就是为什么在许多场景下,持续重新训练模型是应对这种不断变化的底层数据结构的最佳方案。

关键要点与应对策略

以下是关于数据漂移的几个关键要点:

  • 静态与动态的差异:在静态环境中,更多的数据样本(n)会带来更准确的估计。公式可以表示为:估计准确度 ∝ √n。但在动态变化(数据漂移)的环境中,这个关系不成立。
  • 分布变化是核心:数据漂移的本质是底层数据概率分布 P(X)P(Y|X) 发生了变化。
  • 持续监控与再训练:应对数据漂移的标准做法是建立监控系统,当检测到显著漂移时,触发模型的再训练流程。伪代码如下:
    if detect_data_drift(current_data, training_data):
        retrain_model(new_training_data)
        deploy_new_model()
    

总结

本节课中我们一起学习了数据漂移的概念。我们通过“取球”的比喻理解了,在数据动态变化的世界里,简单地收集更多数据并不总能改善我们的模型,因为数据的统计特性本身可能已经改变。因此,在机器学习运维中,建立对数据漂移的持续监控和模型更新机制,是保证系统长期健康运行的关键。

008:微服务运维化

在本节课中,我们将学习如何将一个微服务投入生产环境,即“运维化”。我们将探讨微服务的核心概念、其优势,以及如何通过持续交付流程和基础设施即代码来自动化部署与管理。

微服务的核心概念

上一节我们介绍了机器学习运维的宏观流程,本节中我们来看看一个具体的实现单元:微服务。微服务本质上是一段可独立部署和运行的业务逻辑代码。

其核心优势在于其可复用的特性。你可以将这段逻辑转化为多种形式,例如:

  • 一个命令行工具。
  • 一个可供其他程序调用的库。
  • 一个独立的微服务。
  • 一个Docker容器。

因此,微服务就像一个被“运维化”的函数,它被封装并赋予了新的形态。

持续交付与自动化部署

当我们通过Git管理微服务代码后,其优势便开始显现。代码提交后,会触发持续交付系统中的构建服务器(Build Server)执行一系列自动化步骤。

以下是构建服务器典型的处理流程:

  1. 代码检查:进行代码质量分析。
  2. 测试:运行单元测试、集成测试等。
  3. 编译:将源代码编译成可执行文件或包。
  4. 容器化:将应用打包成Docker镜像。
  5. 推送至仓库:将镜像推送到容器镜像仓库(如Docker Hub)。
  6. 部署:通过基础设施即代码工具(如Terraform、Ansible)将服务部署到目标环境。

灵活的多环境管理

通过结合基础设施即代码容器化技术,我们可以轻松创建和管理任意数量的环境。例如:

  • 开发环境
  • 测试环境
  • 预发布环境
  • 生产环境
  • 负载测试环境

系统可以根据服务被部署到的不同环境,自动执行相应的操作。例如,在预发布环境中,我们通常需要进行性能验证。

预发布环境的监控与验证

在预发布环境中,微服务会暴露健康指标,例如:

  • CPU 使用率
  • 内存 使用量
  • 请求延迟

这些指标会被监控系统(如Prometheus或AWS CloudWatch)收集。性能验证的目的,就是确认服务在实际运行中的表现符合预期。这确保了变更在进入生产环境前是稳定可靠的。

一旦预发布环境的验证获得批准,只需将代码合并到生产分支并推送,即可自动、安全地部署到生产环境。

总结

本节课中我们一起学习了微服务的运维化。微服务最简明的解释就是一段被投入生产运行的逻辑。我们看到了如何利用Git、持续交付、容器化和基础设施即代码,将这段逻辑自动化地构建、测试、监控并部署到多种环境中,从而实现高效、可靠的软件交付。

009:微服务持续集成

概述

在本节课中,我们将学习如何为微服务项目建立一个持续集成生态系统。我们将从项目结构开始,了解如何通过本地和自动化流程来测试、检查代码格式和运行代码,确保每次代码提交都保持高质量。


项目结构与核心概念

首先,我们来看一个为持续集成和后续持续交付设置好的项目结构。一个配置得当的项目是成功的第一步。

以下是此类项目的关键组成部分:

  1. Github工作流目录:此目录包含构建系统的配置文件。在本例中,我们使用Github Actions,但你也可以使用Jenkins、AWS Code Build等其他系统。
  2. 主配置文件:通常是 .github/workflows/main.yml 文件,它定义了在每次代码推送时自动执行的操作序列。
  3. Makefile:这是一个核心文件,它包含了一系列“配方”,用于在本地或构建服务器上执行标准化命令,如安装依赖、代码检查、测试和格式化。
  4. 源代码与测试文件:包含项目的主代码文件以及对应的单元测试文件。
  5. 依赖管理文件:例如 requirements.txt,它固定了项目依赖包的版本,确保开发环境与构建环境的一致性。
  6. README文件:提供项目说明,通常包含构建状态徽章。

这种结构的核心优势在于,开发者可以在本地使用 make 命令执行所有质量检查,而构建服务器(机器人)会在代码推送后自动重复这些步骤,确保持续的质量保障。


实践:在Github项目中工作

上一节我们介绍了项目结构,本节中我们来看看它在Github项目中的实际运作。

我们进入一个基于云的开发环境(Github Codespaces)来查看和操作这个项目。在这里,我们可以运行命令并观察当代码出现问题时,系统如何快速检测到失败。

在终端中,我们运行 make all 命令。这个命令会依次执行:

  • make install:安装项目依赖。
  • make lint:运行代码检查工具。
  • make test:运行单元测试。
  • make format:格式化代码。

如果所有步骤都通过,我们会收到一切正常的反馈。现在,我们故意在代码中引入一个错误,例如将一个变量赋值给它自身(这是一个无操作且可能导致问题的代码)。当我们再次运行 make lint 时,代码检查工具会立即捕获这个“错误”或“警告”。

接着,我们将这个有问题的代码推送到Git仓库。


自动化构建与修复流程

当我们推送代码后,Github Actions构建服务器(机器人)会自动开始工作。它会拉取最新代码,在一个干净的Ubuntu虚拟环境中,按照 main.yml 的指示,依次执行 make installmake lintmake testmake format

由于我们推送的代码存在代码检查问题,构建流程会在 make lint 这一步失败,并在Github上明确标记此次构建为失败状态。

修复问题非常简单。我们甚至不需要打开本地开发环境,可以直接在Github的网页界面上编辑有问题的文件,删除多余或错误的代码行。提交这次修复后,构建服务器会再次启动。这次,所有步骤(安装、检查、测试、格式化)都将顺利通过,构建状态恢复为成功。

这个过程展示了持续集成的核心价值:它是一个自动化的质量守门员,持续地清理和检查代码,确保只有符合标准的代码才能被集成。


总结

本节课中,我们一起学习了为微服务建立持续集成系统的关键步骤。我们了解了标准的项目结构,其核心是一个能统一执行安装、代码检查、测试和格式化的 Makefile。我们看到了如何在本地使用这些命令,以及如何通过 Github Actions 配置自动化构建服务器,使其在每次代码推送时自动执行相同的质量检查流程。这种实践能显著提升代码质量和开发效率,是软件工程,特别是Python微服务开发中的推荐做法。

010:端到端MLOps - Hugging Face Spaces实践 🚀

在本节课中,我们将学习如何构建一个端到端的机器学习运维(MLOps)工作流。我们将使用Hugging Face平台上的预训练模型,通过GitHub Actions实现自动化部署,最终在Hugging Face Spaces上创建一个可运行的文本摘要应用。


概述

我们将分步完成以下任务:首先在Hugging Face上创建账户和访问令牌;接着在GitHub Codespaces中开发一个基于Gradio的简单应用;然后配置GitHub Actions工作流,实现代码的自动部署;最后验证部署的应用功能。整个过程将展示如何将机器学习模型快速、自动化地投入生产环境。


准备工作

在开始构建应用之前,我们需要完成一些基础配置。这包括在Hugging Face上创建账户和访问令牌,以及在GitHub上创建代码仓库和开发环境。

1. 创建Hugging Face账户与访问令牌

首先,访问Hugging Face官网并创建一个账户。登录后,进入个人设置页面,生成一个具有读写权限的访问令牌。这个令牌将用于后续的自动化部署。

操作步骤:

  1. 登录Hugging Face。
  2. 点击右上角个人头像,进入“Settings”。
  3. 在左侧菜单选择“Access Tokens”。
  4. 点击“New token”,为其命名(例如 github-actions-deploy),并选择“Write”权限。
  5. 复制生成的令牌字符串,妥善保存。

2. 创建GitHub仓库与Codespaces环境

接下来,我们将在GitHub上创建一个新的代码仓库,并利用GitHub Codespaces功能开启一个云端开发环境。Codespaces允许我们选择配置强大的虚拟机,非常适合机器学习项目的开发。

操作步骤:

  1. 在GitHub上点击“New repository”创建新仓库,命名为 hugging-face-demo-2
  2. 初始化时,可以添加一个README文件、.gitignore(选择Python模板)和许可证(如Creative Commons)。
  3. 仓库创建后,点击“Code”按钮,选择“Create codespace on main”。
  4. 在Codespaces配置中,选择一台性能较强的机器(例如16核CPU、32GB内存),然后启动环境。

项目开发

现在,我们已经在云端开发环境中准备就绪。本节将搭建项目的基本结构,并编写核心的应用代码。

1. 搭建项目脚手架

一个清晰的项目结构有助于管理和维护代码。我们首先创建虚拟环境,并初始化项目所需的文件。

以下是需要创建的核心文件列表:

  • requirements.txt: 列出项目依赖的Python包。
  • app.py: 应用的主程序文件。
  • Makefile: 用于定义常用的项目命令,简化工作流程。
  • .bashrc 修改:确保每次打开终端时自动激活虚拟环境。

在终端中执行以下命令来创建这些文件:

python -m venv .venv
echo "source ~/.venv/bin/activate" >> ~/.bashrc
source ~/.bashrc
touch requirements.txt app.py Makefile

2. 编写应用代码

我们的应用将使用Hugging Face transformers库加载一个预训练的文本摘要模型,并使用gradio库构建一个简单的Web界面。

核心逻辑在 app.py 文件中实现,主要步骤如下:

  1. 从Hugging Face模型库加载预训练的文本摘要模型和分词器。
  2. 定义一个predict函数,该函数接收输入文本,使用模型进行摘要生成,并返回结果。
  3. 使用Gradio的Interface类快速创建包含输入文本框和输出区域的Web界面。

以下是 app.py 的示例代码框架:

import gradio as gr
from transformers import pipeline

# 加载预训练的文本摘要模型
summarizer = pipeline("summarization", model="facebook/bart-large-cnn")

def predict(input_text):
    # 使用模型生成摘要
    summary = summarizer(input_text, max_length=130, min_length=30, do_sample=False)
    return summary[0]['summary_text']

# 创建Gradio界面
demo = gr.Interface(
    fn=predict,
    inputs=gr.Textbox(lines=10, placeholder="请输入需要摘要的文本..."),
    outputs="text",
    title="文本摘要演示"
)

demo.launch()

3. 定义项目依赖与命令

为了确保环境一致性,我们需要在requirements.txt中明确列出所有依赖包。同时,Makefile可以帮助我们标准化安装和运行命令。

requirements.txt 文件内容示例:

gradio
transformers
torch  # 或 tensorflow,根据模型需求选择

Makefile 文件内容示例:

install:
	pip install -r requirements.txt

run:
	python app.py

在终端中运行 make install 即可安装所有依赖。


自动化部署

开发并测试好本地应用后,下一步是实现自动化部署。我们将使用GitHub Actions,在代码推送到仓库时,自动将应用部署到Hugging Face Spaces。

1. 配置GitHub Secrets

为了安全地在GitHub Actions工作流中使用Hugging Face令牌,我们需要将其设置为仓库的加密Secret。

操作步骤:

  1. 进入你的GitHub仓库页面。
  2. 点击“Settings” -> “Secrets and variables” -> “Actions”。
  3. 点击“New repository secret”。
  4. 名称填写 HF_TOKEN,值粘贴之前复制的Hugging Face访问令牌。
  5. 点击“Add secret”。

2. 创建GitHub Actions工作流

GitHub Actions工作流由YAML文件定义。我们需要在仓库的 .github/workflows/ 目录下创建一个文件,例如 deploy.yml

该工作流的主要步骤是:

  1. 在代码发生推送(如到main分支)时触发。
  2. 使用 actions/checkout 动作检出代码。
  3. 使用 huggingface/huggingface_hub 动作,借助我们配置的 HF_TOKEN,将代码推送到指定的Hugging Face Space。

以下是 deploy.yml 的示例内容:

name: Deploy to Hugging Face Space
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Push to Hugging Face
        uses: huggingface/huggingface_hub@v3
        with:
          hf_token: ${{ secrets.HF_TOKEN }}
          git_user: "GitHub Action"
          git_email: "action@github.com"
          # 修改为你的Hugging Face用户名和Space名称
          space: "your-hf-username/your-space-name"
          # 设置推送方式为强制推送,以同步GitHub仓库的更改
          force: true

创建并提交这个工作流文件后,后续任何对main分支的推送都会触发自动部署。


验证与总结

完成以上所有步骤后,整个MLOps流水线就已经搭建完毕。现在,让我们来验证成果并进行总结。

1. 验证部署结果

部署成功后,你可以访问你的Hugging Face Space页面(格式通常为 https://huggingface.co/spaces/your-username/your-space-name)。

在Space页面上,你应该能看到与本地开发时一样的Gradio界面。尝试输入一段长文本,点击提交,应用应该能返回一个连贯的摘要。这证明你的模型已经成功部署并运行在云端。

同时,在GitHub仓库的“Actions”标签页下,你可以看到每次部署的工作流运行记录,绿色对勾表示部署成功。

2. 课程总结

在本节课中,我们一起学习并实践了一个完整的端到端MLOps工作流:

  1. 环境与资源准备:我们在Hugging Face创建了账户和访问令牌,在GitHub创建了仓库并利用Codespaces搭建了开发环境。
  2. 应用开发:我们构建了一个基于Hugging Face模型和Gradio库的文本摘要应用,并定义了项目依赖。
  3. 自动化部署:我们通过配置GitHub Secrets和编写GitHub Actions工作流,实现了代码变更到Hugging Face Spaces的自动部署。
  4. 成果验证:我们最终验证了部署的应用可以正常运行。

这个流程的核心价值在于自动化可重复性。它展示了如何将机器学习项目的开发、测试和部署环节串联起来,减少手动操作,提高迭代效率,是MLOps理念的一个具体实践。你可以将此模式扩展到其他类型的模型和更复杂的应用场景中。

011:使用FastAPI与AWS App Runner部署微服务示例

在本节课中,我们将学习如何将一个使用FastAPI框架构建的简单微服务,部署到AWS的App Runner托管服务上。整个过程将涵盖从本地开发、测试到云端部署的完整流程。


上一节我们介绍了微服务部署的基本概念,本节中我们来看看一个具体的实践示例。我使用了一个名为NOAAgi-fastAPI的代码仓库,它基于FastAPI框架。FastAPI是一个流行的Python Web框架,它支持类型注解、内置了Swagger API文档,并且非常简单易用。

以下是FastAPI的一些关键特性:

  • 支持Python类型提示。
  • 自动生成交互式API文档(Swagger UI)。
  • 高性能。
  • 易于学习和使用。

我将从一个简单的开发环境开始。我选择使用AWS Cloud9,因为它非常适合在AWS云平台上部署微服务。我们最终将使用AWS App Runner,这是AWS提供的一个用于部署和托管微服务的新兴框架。

App Runner的一个优点是管理方便。你可以看到我这里已经运行着多个应用程序。现在,让我们开始操作,先看看这个开发环境。

我的Cloud9环境已经设置好。我创建了一个Python虚拟环境,你可以在这里看到它的引用。我喜欢为我的项目建立一个标准的脚手架结构。让我看看这个Makefile,我定义了installtestformatlint等命令。我认为这是一个很好的实践。

此外,我还使用了GitHub Actions来自动化测试我的代码,这被称为持续集成。我强烈建议你也这样做。你可以在NOAAgi-fastAPI仓库中查看具体配置。

接下来,我要运行这个微服务。我们先看看代码。首先,从fastapi导入FastAPI。我定义了一个/hello路由,它会返回“Hello Duke”。这是我正在杜克大学讲授的云计算课程的内容。然后,我定义了一个/add端点,它接收两个数字,将它们相加并返回总和。最后,应用在端口8080上启动,监听外部接口。

运行它非常简单。进入微服务目录,输入python main.py。看,它运行起来了。现在,我可以在一个新终端中,使用curl命令测试刚刚在输出中看到的地址。在基于终端的环境里,这是一个很有用的技巧。

我们测试/hello端点,成功了。然后测试/add端点,输入2和2,也成功了。

现在,我已经让服务在本地运行起来了,如何将它部署到AWS App Runner环境中呢?幸运的是,这个过程非常直接。

我将创建一个新的服务。按照仓库文档的说明,我选择“源代码仓库”作为来源。然后,我选择NOAAgi-fastAPI这个仓库。稍等片刻让它加载。

找到我的fastapi仓库并选中它,将其作为部署的源代码。这里有几个选项,其中“自动部署”是一个好主意,这被称为持续交付,可以自动将代码推送到生产或原型环境。但为了演示清晰,我暂时选择“手动部署”。

运行时选择Python 3。构建命令很简单:pip install -r requirements.txt,因为我已经准备好了依赖文件。启动命令是python main.py,这和我在Cloud9环境中做的完全一样。

点击“下一步”,为服务命名,例如“microservice-2”。然后继续点击“下一步”并选择“创建和部署”。整个过程非常直观。

现在,部署开始了。由于我之前已经操作过,知道这大约需要5分钟才能完成。我先回到另一个已经运行中的微服务实例。如果我点击它的默认域名,会得到一个完全加密的URL,这很不错。

同样很棒的是,我可以在URL后加上/docs路径。FastAPI内置了Swagger文档,我可以在这里直接测试API。点击“Try it out”,输入两个数字(比如2和2),然后执行。它会给出对应的curl命令、请求URL和响应详情等非常有用的信息。这对于构建数据工程或机器学习API非常方便。同样,我也可以直接测试/hello路由。

本节课中我们一起学习了如何使用FastAPI快速构建一个微服务,并通过AWS App Runner将其部署到云端。我们涵盖了从本地开发测试、项目结构配置到云端服务创建和访问的完整步骤。这是一个将机器学习模型或数据处理功能快速发布为API服务的有效方法。

012:Flask应用示例 🍇

在本节课中,我们将学习如何使用Flask框架构建一个简单的微服务应用。这个应用的核心功能是随机生成一种水果名称,并通过网页展示。我们将从项目结构开始,逐步讲解代码实现、本地测试,并最终了解如何将其集成到持续集成(CI)环境中。


项目结构 📁

首先,我们需要为项目建立一个清晰的结构。一个良好的结构有助于代码管理和自动化流程。以下是本项目包含的核心文件:

  • app.py: 这是应用的主文件,包含了Flask应用的核心逻辑。
  • requirements.txt: 列出了项目运行所依赖的Python包。
  • test_app.py: 包含了用于测试应用功能的单元测试。
  • Makefile: 一个自动化脚本,用于执行安装、代码检查、测试和格式化等任务。
  • build system configuration file: 用于配置持续集成/持续部署(CI/CD)环境的文件,例如GitHub Actions的配置文件。

这些文件共同构成了一个既适合本地开发,也适合在持续集成环境中运行的项目基础。


核心代码解析 🧑‍💻

上一节我们介绍了项目的整体结构,本节中我们来看看核心代码是如何实现的。让我们从app.py文件开始。

应用逻辑 (app.py)

app.py文件包含了Flask应用的所有后端逻辑。其核心功能是定义一个函数来随机选择一种水果,并设置一个Web路由来展示这个结果。

import random
from flask import Flask, render_template

app = Flask(__name__)

def random_fruit():
    """
    这个函数从预定义的列表中随机返回一种水果。
    """
    fruits = ['Apple', 'Cherry', 'Orange']
    return random.choice(fruits)

@app.route("/")
def home():
    """
    这是应用的主页路由。
    它调用random_fruit函数,并将结果传递给HTML模板进行渲染。
    """
    fruit = random_fruit()
    return render_template("index.html", fruit=fruit)

代码解析:

  1. random_fruit()函数从一个包含['Apple', 'Cherry', 'Orange']的列表中随机选取一项。
  2. @app.route(“/”)装饰器将home()函数绑定到应用的根URL(即主页)。
  3. render_template函数用于渲染一个名为index.html的模板,并将随机生成的水果变量fruit传递给它。

前端模板 (index.html)

为了在网页上显示结果,我们需要一个HTML模板。这个模板位于templates/index.html

<!DOCTYPE html>
<html>
<head>
    <title>Random Fruit Generator</title>
</head>
<body>
    <h1>Random Fruit: {{ fruit }}</h1>
    <p>Refresh the page for more random fruit.</p>
</body>
</html>

模板解析:

  • 这是一个标准的HTML文件。
  • 关键部分在于{{ fruit }},这是Jinja2模板语法。Flask会用从home()函数传递过来的fruit变量的实际值(如“Apple”)替换这个占位符。

本地开发与测试 🔧

我们已经构建了应用的核心部分,接下来需要确保它能正确运行并且代码质量过关。这可以通过本地自动化工具链来完成。

使用Makefile自动化任务

Makefile定义了一系列命令,可以简化开发流程。以下是其内容:

install:
    pip install --upgrade pip &&\
        pip install -r requirements.txt

lint:
    pylint --disable=R,C app.py test_app.py

test:
    python -m pytest -vv test_app.py

format:
    black *.py

all: install lint test format

这个文件定义了四个任务:

  • make install: 安装项目依赖。
  • make lint: 使用pylint进行代码风格和错误检查。
  • make test: 运行test_app.py中的单元测试。
  • make format: 使用black工具自动格式化Python代码。
  • make all: 按顺序执行以上所有任务。

运行本地CI流程

在终端中,只需运行一个命令即可执行完整的本地持续集成流程:

make all

执行后,你会看到终端依次进行依赖安装、代码检查、运行测试和代码格式化。这能确保你的代码在提交前是干净且功能正常的。

单元测试 (test_app.py)

测试是保障代码质量的关键。test_app.py文件包含了对random_fruit函数的简单测试。

import app

def test_random_fruit():
    """
    测试random_fruit函数返回的值是否在预期的水果列表中。
    """
    fruit = app.random_fruit()
    assert fruit in ['Apple', 'Cherry', 'Orange']

这个测试会调用random_fruit()函数,并断言其返回值是‘Apple’‘Cherry’‘Orange’中的一个。make test命令会运行这个测试。

启动应用

完成检查和测试后,就可以运行应用了:

python app.py

应用启动后,你可以在浏览器中访问它(在GitHub Codespaces等开发环境中,通常会提供预览功能)。每次刷新页面,都会看到随机显示的不同水果名称。


集成到持续集成(CI)环境 🚀

前面的步骤都是在本地完成的。为了在团队协作或自动化部署中保持代码质量,我们需要将这套流程集成到CI环境中,例如GitHub Actions。

CI配置文件

项目中的构建系统配置文件(如.github/workflows/python-app.yml)定义了在代码推送或拉取请求时自动执行的任务。其内容通常与Makefile中的all目标一致:

name: Python Application CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Run Make All
      run: make all

这个配置告诉GitHub Actions:每当有代码推送(push)或拉取请求(pull_request)时,在一个Ubuntu系统上执行make all命令。

CI流程的优势

一旦配置好,CI流程将自动运行:

  1. 当你向代码仓库推送更改时,GitHub Actions会自动启动一个任务。
  2. 该任务会拉取你的代码,并依次执行make installmake lintmake testmake format
  3. 你可以通过GitHub的界面查看任务运行结果。如果任何一步失败(例如测试未通过),你会立即收到通知。

这种自动化测试确保了代码库的稳定性和一致性,是实施MLOps和DevOps实践的重要基础。


总结 📝

本节课中,我们一起学习了一个完整的Flask微服务示例。我们从搭建项目结构开始,编写了生成随机水果的后端逻辑和前端模板。接着,我们利用Makefile实现了本地开发任务的自动化,包括依赖管理、代码检查、测试和格式化。最后,我们探讨了如何将这套本地流程通过配置文件集成到GitHub Actions中,实现自动化的持续集成。

这个示例虽然简单,但它清晰地展示了一个可测试、可维护且适合自动化部署的微服务应具备的基本要素和开发工作流。掌握这些是构建更复杂机器学习运维(MLOps)管道的第一步。

013:构建Golang-GCP-App-Engine微服务 🚀

概述

在本节课中,我们将学习如何在Google Cloud Platform的App Engine环境中,构建并部署一个简单的Golang微服务。我们将从创建项目结构开始,编写代码,最终完成部署和日志查看。


在Google Cloud Shell环境中操作

我们当前位于Google Cloud Shell环境中。从这里开始,我们将构建一个App Engine应用程序。

需要了解的一点是,你可以通过输入 gcloud app 命令来获取关于App Engine环境的更多信息。输入 help 会显示你可以执行的不同操作选项,例如部署或查看版本等。你可以在这里查看所有可执行的操作。

我已经在此处为App Engine创建好了环境。


创建Go项目结构

接下来,我需要创建一个Go项目结构。首先,我将创建这个结构。

输入命令 mkdir go-app

接下来,查看这个目录内部,确认它是空的。然后,我需要创建一个 app.yaml 文件。

app.yaml 文件是App Engine应用程序的配置文件。我们只需要在其中指定运行时环境。这里我们设置运行时为 go115。当然,你也可以选择其他运行时,但这只是一个非常简单的初始配置。

完成这个 go-app 目录的创建后,我们需要将 app.yaml 文件移入其中。同时,我们还需要创建项目结构。让我们快速进入这个目录以便操作。

输入命令 cd go-app


创建主Go文件

现在,我们可以开始创建 main.go 文件。

main.go 文件的开头,我们需要声明包名。输入 package main

我们还需要导入一些必要的包。输入 import 语句,并格式化代码。需要导入的包包括 lognet/httpos

接下来,我们需要编写索引处理器。这里我会粘贴一段简单的代码。这段代码的功能是处理一个返回“Hello World GCP certification”的请求。

然后,我们需要注册这个处理器,将其放在代码的合适位置。

至此,一个简单的微服务代码就完成了。


部署微服务

为了部署这个简单的微服务,我们只需要输入命令 gcloud app deploy

输入命令后,系统会询问是否确认部署。我们选择“是”继续。

部署过程会将我们的应用直接移动到App Engine中。稍等片刻,部署就会完成。

现在,应用已经部署成功。


浏览和查看应用

一个简单的浏览方法是输入命令 gcloud app browse。如果当前环境无法直接启动浏览器,该命令会提供应用的URL。

访问该URL,我们将看到“Hello world GCP certification”的响应。

另一个有用的功能是实时查看日志,这在开发应用时非常方便。我们可以通过命令 gcloud app logs tail 来跟踪日志。

反复访问应用URL,可以在日志中看到相应的网络请求记录。这对于调试和监控应用行为非常有帮助。


管理和监控应用

现在,我们进入了App Engine的管理界面。在这里,你可以看到所有的网络请求,因为我再次执行了 gcloud app logs tail 命令。

如果我想要重新部署或进行更改,过程同样简单。只需在对源代码进行任何修改后,再次运行 gcloud app deploy 命令即可。

我也可以进入控制台查看仪表板,观察不同的图表和信息,例如计费状态、负载状态、每分钟请求数、服务器错误等。这里提供了大量有用的信息。

此外,我还可以查看版本信息,了解流量是如何分配到不同版本上的。

总而言之,使用App Engine构建微服务是一个非常直接和简单的过程。


总结

本节课中,我们一起学习了如何在Google Cloud Platform的App Engine上构建和部署一个Golang微服务。我们从创建项目结构和配置文件开始,编写了处理HTTP请求的Go代码,然后使用 gcloud 命令行工具完成了部署。最后,我们还探讨了如何浏览应用、查看实时日志以及利用控制台进行应用监控和管理。整个过程展示了利用GCP托管服务快速搭建和运维微服务的便捷性。

014:Makefile入门

概述

在本节课中,我们将要学习如何创建和使用一个名为 Makefile 的文件。Makefile 是一个用于自动化执行一系列命令的工具,它可以帮助我们封装复杂的构建步骤,使项目管理和部署变得更加简单和一致。

什么是Makefile?

Makefile 是一个包含了一系列规则的文件,这些规则定义了如何编译和构建项目。它通常用于自动化软件构建过程,但也可以用于执行任何你希望自动化的任务序列。

检查Make命令

首先,我们需要确认 make 命令是否已经安装在你的计算机上。你可以在终端中输入以下命令来检查:

which make

如果 make 已经安装,终端会显示其安装路径,例如 /usr/bin/makemake 命令在大多数基于Unix的系统(如macOS和Linux)上都是预装的,或者可以很容易地安装。

创建Makefile

接下来,我们将创建一个空的 Makefile。请注意,文件名必须精确地命名为 Makefile,区分大小写。我们可以使用 touch 命令来创建这个文件:

touch Makefile

执行此命令后,你会在当前目录下看到一个名为 Makefile 的新文件。

编写第一个Make规则

现在,让我们打开 Makefile 并添加我们的第一个规则。规则的基本格式是:

目标: 依赖
    命令

例如,我们可以创建一个名为 hello 的目标,它执行一个简单的 echo 命令:

hello:
    echo "This is my first make command."

保存文件后,在终端中运行 make hello 命令,你将看到输出的文本。

添加更多规则

Makefile 的强大之处在于你可以定义多个规则来组织不同的任务。例如,我们可以添加一个 install 规则,用于安装项目依赖。

以下是添加 install 规则的示例:

install:
    # 这里将来可以替换为 pip install 等安装命令
    echo "This will later be a pip install command."

保存后,运行 make install 即可执行该规则下的命令。

使用Makefile管理项目

一旦你的 Makefile 设置完成,你可以将其添加到版本控制系统中,以便与团队成员共享。以下是常用的Git命令:

git add Makefile
git commit -m "Adding a Makefile"
git push

这样,你就为项目设置了一个基础的自动化构建脚本,可以在后续开发中不断扩展和完善。

总结

本节课中我们一起学习了 Makefile 的基础知识。我们了解了如何检查 make 命令、创建 Makefile 文件、编写简单的规则以及如何运行这些规则。Makefile 是一个强大的工具,能够帮助我们自动化重复性任务,提高开发效率。在后续的课程中,我们将基于此基础,探索更复杂的构建和部署自动化流程。

015:Python项目中最重要的三个文件 📁

在本节课中,我们将学习Python项目中至关重要的三个文件:MakefileDockerfilerequirements.txt。理解并正确使用这些文件,是构建可维护、可重复和可部署的现代Python项目的基础。


概述

一个组织良好的Python项目离不开核心的配置文件。它们分别负责自动化任务、定义运行环境和锁定依赖版本,共同构成了项目工程化的基石。


Makefile:项目自动化脚本 📜

首先,我们来看Makefile。这个文件至关重要,因为它允许你自动化诸如安装、测试、部署等步骤。你可以把它想象成一套烹饪食谱。在家做饭时,你不需要每次都去查看每一种食材;同样,使用Makefile可以让你无需反复查找和输入复杂的命令,从而简化开发流程。

Makefile通过定义一系列“目标”(targets)和对应的命令来工作。以下是一个简单的示例:

install:
    pip install -r requirements.txt

test:
    pytest

format:
    black .

在上面的例子中,运行make install会自动执行安装依赖的命令,make test会运行测试,make format会格式化代码。这自动化了所有复杂的步骤,开发者无需记忆具体的命令。


Dockerfile:定义运行时环境 🐳

上一节我们介绍了用于自动化的Makefile,本节中我们来看看DockerfileDockerfile之所以关键,是因为它定义了应用程序的运行时环境。在2022年及以后,项目几乎不可能不使用Dockerfile。它已成为必备项,这种运行时打包技术对于容器化部署至关重要。

确保你的项目中包含Dockerfile,这样你就可以将应用容器化并部署。一个典型的Dockerfile会从基础镜像开始,设置工作目录,复制代码,安装依赖,并指定启动命令。

以下是一个基于Python的Dockerfile示例:

# 使用官方Python 3.8镜像作为基础
FROM public.ecr.aws/lambda/python:3.8

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/5d82beaacb76ea836f465674d19e1260_4.png)

# 设置工作目录
WORKDIR /var/task

# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install -r requirements.txt

# 复制应用程序代码
COPY app.py .

# 设置容器启动时执行的命令
CMD ["app.handler"]

这个文件允许你精确地控制应用运行所需的环境,确保开发、测试和生产环境的一致性。


requirements.txt:管理Python依赖 🔒

接下来,我们讨论requirements.txt文件。这个文件用于记录项目的Python包依赖。它的重要性在于允许你“锁定”版本号。

这意味着,即使其他人在四年后克隆你的项目,他们也不需要去猜测你当时使用的是哪个版本的包。这极大地实现了流程的自动化。你可以使用pip freeze命令来生成当前环境的依赖列表。

以下是requirements.txt文件内容的示例:

fastapi==0.68.0
uvicorn==0.15.0
pydantic==1.8.0

在快速开发阶段,你可能不需要严格锁定每个版本。但一旦准备将项目投入生产,就应该固定这些依赖的版本,以确保稳定性。


实战项目解析

让我们结合一个名为“NOAAgi fast API”的项目来具体看看这三个文件是如何协同工作的。这个项目包含了我们提到的三个最重要的文件。

  • Makefile:该项目的Makefile包含了make install(安装依赖)、make test(运行测试)和make format(格式化代码)等命令。它自动化了所有复杂步骤。
  • requirements.txt:该文件列出了项目所需的包。在生产部署前,会固定这些包的版本号。
  • Dockerfile:这个Dockerfile基于AWS Lambda的Python 3.8镜像,通过一系列命令设置运行时环境,最终将应用容器化。开发者只需运行docker build .docker run即可构建和运行容器,并可以将其推送到源代码仓库或Amazon的容器仓库。

为项目设置持续集成(CI)也变得非常简单,因为这些文件提供了标准化的构建和测试入口。


总结

本节课中,我们一起学习了构成Python项目基石的三个核心文件:

  1. Makefile:用于自动化常见开发任务,如安装、测试和格式化。
  2. Dockerfile:用于定义和打包应用程序的运行时环境,实现容器化部署。
  3. requirements.txt:用于精确管理并锁定项目所依赖的Python包版本。

掌握并熟练运用这三个文件,能够显著提升项目的可维护性、可重复性以及部署的便捷性,是迈向专业机器学习运维和软件开发的重要一步。

016:数据科学实战-第一天 🚀

在本节课中,我们将学习作为一名数据科学家,在入职第一天应该如何开展工作。我们将涵盖从创建结构化笔记本、进行数据分析,到设置自动化测试管道的完整工作流程。

结构化你的工作 📁

上一节我们介绍了课程概述,本节中我们来看看如何构建一个清晰的数据科学项目结构。我发现许多数据科学项目的结构有待改进。一个良好的结构至关重要。

以下是构建项目结构的四个核心部分:

  1. 数据获取:首先,你需要获取数据。
  2. 探索性数据分析:接下来,分析数据。了解数据情况,绘制散点图,找出突出点,判断数据是否充足。
  3. 建模:然后,进行建模。机器学习就是从数据中学习,进行数值或分类预测。
  4. 结论:最后,得出结论。结论必须包含强有力的建议,并且有数据支撑。

我建议从使用CoLab或Jupyter笔记本开始。首先为笔记本命名,然后创建文本单元格来构建层级结构。

例如,使用Markdown标题创建结构:

## 数据获取
## 探索性数据分析
## 建模
## 结论

这种结构允许你折叠章节,并通过侧边栏目录快速导航,对于管理大型项目非常有用。

利用现代开发工具 🛠️

上一节我们介绍了项目结构,本节中我们来看看可以使用的强大工具。对于学生和初学者,GitHub Codespaces是一个理想的选择。

GitHub Codespaces能为你自动设置一个功能强大的免费开发环境。你无需担心本地配置问题,可以直接在云端获得一个完整的、预配置好的环境,甚至可以使用高达32核的机器进行重型计算。

另一个重要工具是Google Colab。它有三个版本:

  • 免费版:提供GPU访问,可进行深度学习。
  • 专业版:提供高端GPU。
  • 专业增强版:支持后台持续训练任务。

对于学生,免费版或专业版通常已足够。在Colab中创建笔记本后,你可以通过“保存副本到GitHub”功能,轻松将笔记本与GitHub仓库同步。这确保了项目的可复现性,他人只需点击链接即可运行你的代码。

实战数据分析 🔍

上一节我们介绍了工具,本节中我们通过一个真实的数据分析案例来实践。我们将使用一个分析新冠疫情数据的笔记本。

首先,确保数据可复现。使用pandas直接从URL读取CSV数据,例如:

import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-states.csv')

加载数据后,使用df.shape查看数据维度(行数与列数),使用df.describe()获取基本的统计描述。这是了解数据全貌的第一步。

在探索性数据分析阶段,可以自由尝试。例如,使用seaborn库绘制散点图,观察病例数与死亡数的关系:

import seaborn as sns
sns.scatterplot(data=df, x='cases', y='deaths')

通过排序和筛选,可以找出死亡数最高的州,并尝试将疫情数据与其他数据集(如各州糖摄入量、选举数据)合并,以探索更多相关性。使用pd.concat合并数据框,使用pd.get_dummies进行独热编码。

分析完成后,可以将处理好的数据框导出为CSV文件:

df.to_csv('processed_data.csv')

在Colab中,你可以从文件侧边栏轻松下载该文件。

实现自动化测试与集成 ⚙️

上一节我们完成了数据分析,本节中我们来看看如何确保项目的健壮性和专业性。最佳实践是为你的笔记本设置持续集成管道。

首先,在项目根目录创建requirements.txt文件列出依赖,并创建Makefile来定义自动化命令。例如,Makefile可以包含安装依赖和测试笔记本的命令。

核心是使用nbval插件来测试笔记本。nbval会执行笔记本中的每个代码单元格,确保没有错误。一个简单的测试脚本如下:

import sys
import os
import subprocess

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/0c600e7b694888fe3d43b47092387f1d_62.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/0c600e7b694888fe3d43b47092387f1d_64.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/0c600e7b694888fe3d43b47092387f1d_66.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/0c600e7b694888fe3d43b47092387f1d_68.png)

# 要测试的笔记本路径
notebook_path = ‘你的笔记本.ipynb’

# 使用pytest和nbval运行测试
cmd = f‘pytest — nbval {notebook_path} — disable-warnings’
subprocess.run(cmd, shell=True, check=True)

然后,你可以配置GitHub Actions。在仓库的.github/workflows/目录下创建一个YAML文件(例如ci.yml),定义在每次代码推送时自动运行make test命令的工作流程。

这样,每次你更新笔记本并推送到GitHub,系统都会自动测试整个笔记本的有效性。这向协作者展示了你的专业性和对代码质量的重视,是机器学习运维中的重要实践。

总结 📝

本节课中我们一起学习了数据科学家第一天工作的完整流程。我们从建立清晰的项目结构(获取、分析、建模、结论)开始,探索了GitHub Codespaces和Google Colab等强大工具,并进行了实际的数据分析演练。最后,我们通过设置基于nbval和GitHub Actions的持续集成管道,确保了项目的可复现性和专业性。这套流程结合了良好的实践与自动化,能为你的数据科学工作打下坚实的基础。

017:使用Google Colab进行数据科学项目 📓

在本节课中,我们将学习如何使用Google Colab笔记本进行数据科学项目和作品集项目。Colab是一个基于云的免费Jupyter笔记本环境,特别适合机器学习、数据分析和协作。

概述

Google Colab提供了一个便捷的平台来编写和执行Python代码,无需进行复杂的本地环境配置。它支持GPU加速,并能轻松与GitHub和Google Drive集成,便于项目管理和分享。

创建与设置新笔记本

上一节我们介绍了Colab的基本概念,本节中我们来看看如何创建和设置一个新的笔记本。

首先,访问Colab后,你会看到默认的欢迎界面,其中包含一些使用说明。

要创建一个新笔记本,请点击菜单栏的 文件 -> 新建笔记本。系统会创建一个空白的笔记本模板。

创建后,有两件重要的事情需要注意:

  1. 你可以为笔记本命名。点击顶部的默认名称(如“未命名的笔记本”),将其修改为与项目相关的名称,例如 你的数据科学项目。这有助于他人理解笔记本的内容。
  2. 运行时 菜单中,你可以更改运行时类型。如果你使用的是Colab Pro版本,可以选择性能更强的GPU,也可以选择TPU。这对于需要大量计算资源的任务非常有用。

构建清晰的项目结构

一个结构清晰的笔记本能让你的项目逻辑更分明,也便于他人阅读。我特别向学生和数据科学专业人士推荐创建层次结构。

以下是我推荐的项目结构,你可以通过创建多个代码单元格并添加标题来实现:

# 数据获取
# 你的数据加载和初步处理代码在这里

# 探索性数据分析 (EDA)
# 你的数据可视化和分析代码在这里

# 建模
# 你的模型训练和评估代码在这里

# 结论
# 你的总结和结论在这里

通过这种方式,你可以将不同阶段的代码组织起来。Colab会自动为这些标题生成目录,你可以在左侧边栏中轻松导航。当代码块较多时,你还可以折叠每个部分,使界面保持整洁。

保存与分享项目

构建好项目后,下一步就是保存和分享。Colab提供了几种强大的分享方式。

保存到GitHub

最直接的方法之一是将笔记本保存到GitHub,这对于创建作品集或团队协作非常有效。

操作步骤如下:

  1. 在GitHub上为你正在进行的作品集项目创建一个新的代码仓库,例如命名为 data-science-portfolio
  2. 在Colab中,点击 文件 -> 在GitHub中保存副本
  3. 在弹出的窗口中,选择你刚刚创建的仓库,然后点击确定。

这样,你的笔记本就会保存到GitHub仓库中,并生成一个公开的Colab链接。其他人可以通过这个链接直接打开并运行你的代码。

通过Google Drive分享

另一种强大的方式是使用Google Drive的分享功能。

操作步骤如下:

  1. 点击Colab界面右上角的 分享 按钮。
  2. 在分享设置中,将权限修改为 “知道链接的任何人” 并设置为 “查看者”“编辑者”
  3. 复制生成的链接。
  4. 你可以将这个链接放入项目的README文件中,或直接分享给他人。

这种方式的好处是,任何人无需登录即可访问笔记本,非常适合进行演示或代码共读。

查看一个完整项目示例

为了更直观地理解,让我们来看一个更复杂的数据科学项目示例。假设我们有一个分析《纽约时报》数据的项目。

打开该项目的Colab链接后,你会注意到清晰的结构:

  • 数据获取:这部分代码读取一个CSV格式的《纽约时报》数据集。
  • 探索性数据分析:对数据进行可视化和初步统计。
  • 建模:基于数据训练机器学习模型。
  • 结论:总结分析结果和模型表现。

这个示例展示了如何使项目具备100%的可复现性,并确保其易于导航和理解。关键在于将数据、代码和逻辑清晰地组织在一起。

总结

本节课中我们一起学习了使用Google Colab进行数据科学项目的核心工作流。我们涵盖了从创建和设置新笔记本、构建清晰的项目层次结构,到通过GitHub和Google Drive保存与分享项目的完整过程。记住,无论是学生、数据科学专业人士还是任何希望分享成果的人,遵循清晰的结构和利用便捷的分享功能,都能让你的项目更加专业和高效。

018:贪心算法与旅行商问题

在本节课中,我们将要学习两种经典的算法思想:贪心算法和旅行商问题。我们将通过构建自动找零系统和旅行路线规划工具这两个具体项目,来理解这些算法的核心概念和实际应用。课程将全程使用Python,并借助GitHub Copilot等AI辅助工具来加速开发。


贪心算法:构建自动找零系统

上一节我们介绍了本课程的目标,本节中我们来看看第一个核心概念:贪心算法。贪心算法的核心思想是,在每一步选择中都采取当前状态下最好最优的选择,从而希望导致结果是全局最好或最优的。

一个经典的例子是自动售货机的找零系统。我们的目标是:给定一个找零金额,系统应返回硬币数量最少的组合。在美国,常用的硬币面额有:25美分、10美分、5美分和1美分。

贪心算法的策略很直接:总是优先使用最大面额的硬币,直到剩余金额小于该面额,然后转向次大的面额,依此类推。

以下是实现该算法的核心代码:

def greedy_coin(change):
    coins = [0.25, 0.10, 0.05, 0.01]  # 硬币面额
    coin_dict = {coin: 0 for coin in coins}  # 初始化硬币计数字典

    for coin in coins:
        while change >= coin:
            change -= coin
            coin_dict[coin] += 1

    # 输出结果
    for coin, count in coin_dict.items():
        if count > 0:
            print(f"{count} 个 {int(coin*100)} 美分硬币")
    return coin_dict

为了使这个算法更实用,我们使用 click 库将其包装成一个命令行工具。这样,我们既可以在终端直接使用,也可以将其作为模块导入到其他Python项目中。

# 在命令行中使用
$ ./greedy_coin 0.99
你的找零 0.99 美元需要:
3 个 25 美分硬币
2 个 10 美分硬币
4 个 1 美分硬币

通过这个例子,我们看到了贪心算法如何通过一系列局部最优选择,快速得到一个可行的解决方案。然而,贪心算法并不总能得到全局最优解,但在像找零这样的特定问题上,它非常有效。


旅行商问题:寻找最短旅行路线

上一节我们介绍了贪心算法解决确定性问题,本节中我们来看看一个更复杂的优化问题:旅行商问题。这是一个NP难问题,目标是为一位“旅行推销员”找到一条访问一系列城市并返回起点的最短可能路线

由于城市数量增加时,可能的路线组合会爆炸式增长,我们无法穷举所有解。因此,我们需要借助启发式算法来寻找一个“足够好”的近似解。

我们将采用一种结合了随机化贪心策略的算法:

  1. 随机选择一个起始城市
  2. 从当前城市出发,贪心地选择距离最近且未访问过的城市作为下一站。
  3. 重复步骤2,直到所有城市都被访问。
  4. 计算总旅行距离。
  5. 将上述过程运行多次(例如1000次),最后选择总距离最短的那条路线作为我们的解决方案。

为了模拟真实场景,我们使用真实美国城市的经纬度数据。这里会用到 geopy 库来计算城市间的地理距离。

以下是算法核心部分的简化代码:

import random
from geopy.distance import geodesic

def calculate_distance(city1, city2):
    """计算两个城市间的距离(英里)"""
    return geodesic(city1.coords, city2.coords).miles

def tsp_random_greedy(cities_list, num_simulations=100):
    best_distance = float('inf')
    best_route = []

    for _ in range(num_simulations):
        # 1. 随机打乱城市顺序作为新的起点
        random.shuffle(cities_list)
        route = [cities_list[0]]
        unvisited = set(cities_list[1:])
        total_distance = 0

        # 2. 贪心选择下一个最近城市
        while unvisited:
            current_city = route[-1]
            # 找到未访问城市中距离当前城市最近的
            next_city = min(unvisited, key=lambda city: calculate_distance(current_city, city))
            route.append(next_city)
            unvisited.remove(next_city)
            total_distance += calculate_distance(current_city, next_city)

        # 3. 返回起点
        total_distance += calculate_distance(route[-1], route[0])

        # 4. 更新最佳结果
        if total_distance < best_distance:
            best_distance = total_distance
            best_route = route

    return best_distance, best_route

同样,我们也将这个解决方案构建成一个强大的命令行工具。用户可以指定任意城市列表和模拟运行次数。

# 使用内置的美国城市列表运行100次模拟
$ ./tsp_solver simulate --count 100

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/1b4182f62d7dd2b9e2351b522514d295_19.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/1b4182f62d7dd2b9e2351b522514d295_21.png)

# 使用自定义城市列表运行50次模拟
$ ./tsp_solver custom Boston "New York" Chicago "Los Angeles" --count 50

通过多次随机模拟,我们能够以较高的概率找到一个非常接近最优解的旅行路线。这种方法在无法求得精确解的实际问题中非常有用。


开发技巧:AI辅助与工程化实践

在构建上述项目的过程中,我们实践了一些重要的现代开发技巧:

  1. 使用GitHub Copilot辅助编程:我们演示了如何用自然语言提示Copilot生成函数、命令行工具甚至测试代码,极大提升了开发效率。
  2. 创建可复用的开发环境:通过 Dockerfiledevcontainer.json 配置Codespaces,确保任何协作者都能获得完全一致的开发环境。
  3. 编写可组合的代码:将核心算法逻辑与命令行接口分离,使得同一个函数既能被终端调用,也能轻松集成到Web服务或其他系统中。
  4. 实施代码质量检查:使用 black 自动格式化代码,使用 pylint 进行静态检查,并使用 pytest 编写自动化测试,确保代码的健壮性。


总结

本节课中我们一起学习了:

  • 贪心算法的核心思想及其在自动找零问题上的应用。我们了解到贪心算法通过局部最优选择来构建解,简单高效,但适用范围有限。
  • 旅行商问题的复杂性以及如何用随机化贪心算法这种启发式方法寻找近似最优解。我们构建了一个可以处理真实地理数据的实用路线规划工具。
  • 如何利用AI辅助工具(如GitHub Copilot)工程化实践(如容器化、代码格式化、测试) 来高质量、高效率地完成算法项目的开发。

通过这两个从简单到复杂的项目,我们不仅理解了算法思想,更掌握了将其转化为实际可用工具的技能。在接下来的课程中,我们将探索更多有趣的启发式和元启发式算法。

019:仿真与实验追踪对比 🔄

在本节课中,我们将探讨机器学习运维中一个核心概念:实验追踪。我们会发现,它与我们熟悉的“仿真”概念有许多相似之处。通过对比仿真与实验追踪,我们可以更好地理解如何将仿真中的思想应用到机器学习模型的开发与优化流程中。

仿真与实验追踪的相似性

上一节我们介绍了机器学习运维的宏观概念,本节中我们来看看实验追踪与仿真的具体联系。

仿真与机器学习实验追踪存在许多相似之处。如果我们观察一个仿真问题,例如旅行商问题,其核心思想是多次运行(例如,一个贪婪随机起点算法)以求解最短路径。其目标是找到访问所有城市所需的最短旅行距离。公式可以表示为:

minimize(total_distance)

同样,对于轮盘赌游戏,如果你想最大化收益,可以创建大量仿真来观察是否存在从轮盘赌中获得高收益的方法。众所周知,这没有最优解,但你可以通过仿真自行验证。扑克游戏也是如此,你可以构建自己的扑克仿真来最大化收益。或者,如果你在考虑加入一家初创公司,可以观察风险投资组合如何通过最小化风险来最大化收益。这就是他们投资100家公司,并将所有风险转移给初创公司员工的原因。

现在,观察机器学习运维中的实验追踪,这是一个非常相似的过程。你需要审视大量实验,目标是在一系列不同实验中最小化误差,或针对某个指标进行优化。你可能需要进行大量的超参数调优,并找出最佳的调优任务。因此,经典的仿真与MLOps实验追踪有许多共同点。

仿真实例分析

以下是几个具体的仿真示例,帮助我们理解其运作模式。

轮盘赌仿真

第一个示例是轮盘赌仿真。这是一个有趣的例子。如果我想仿真轮盘赌运行10000次,每次我都押注黑色,会发生什么?这实际上是模拟大数定律的一种方式,你可以看到事实上你并没有很高的获胜几率。

如果我们运行这段代码,可以看到我每次下注1美元,选择黑色,并运行成千上万次仿真。我可以可视化发生的一切,结果是我们看到收益为负。它显示了黑色、红色和绿色出现的次数。如果我再次运行仿真,由于大数定律,我同样会得到负收益。长期来看,在简单的轮盘赌中我会输钱。

现在,快速查看一下轮盘赌仿真的代码。其基本要点是:我使用pandas和click库,首先构建一个轮盘。然后,我定义了旋转轮盘、仿真轮盘、生成报告的函数。我计算整个仿真过程中的收益,处理红、黑、绿等结果,打印信息,最后将其构建成一个命令行工具。这就是微型仿真的基本原理。

扑克仿真

如果我想运行另一种仿真,我们也可以进行扑克仿真。运行扑克仿真时,它会询问下注金额。例如,下注1美元并玩5轮。每次它都会显示手牌、我是否获胜。最后,它会说基于我的下注,期望收益是4美元,但我实际赢了100美元。这是模拟你以特定方式玩一手牌的不同结果的绝佳方法。

同样,快速查看代码,它会遵循与之前相同的模式:构建我要仿真的“世界”(本例中是扑克牌堆),编写一些辅助代码来处理发牌等操作,选择特定的手牌以便我知道在与哪些牌对赌,构建其他功能,然后进行显示和评估,最后执行仿真。

风险投资仿真

我还有一个有趣的仿真示例:模拟成为一名风险投资家的体验。运行这个仿真时,可以看到我获得了20%或80%的投资回报率。它显示累计投资额(例如500万)和最终支出(例如28.85亿),并展示了对这100家公司投资后各自所占的股权百分比。在这个特定仿真中,结果很好。

那么,如果我模拟大量不同的初创公司员工(风险被转移给了他们,且他们无法利用众多公司进行风险分散)会怎样?你可以看到,在这种场景下,初创公司成功的概率一遍又一遍地只有2%。

从仿真到MLOps实验追踪

这引出了一个重要的观点:通过进行仿真,你能够真正弄清楚你想要构建什么,并针对某个目标进行最小化或最大化。

在实践中,这意味着如果我转到Databricks平台,查看一个正在进行的实验追踪任务,我可以看到不同实验之间的差异。我会仔细查看我想要达成的指标,这些指标会显示在实验追踪面板中。

总而言之,实验追踪的概念与你实际进行机器学习运维时的许多操作非常相似。通过进行仿真,你能够真正地将工作流程从仿真风格转向MLOps风格。

020:聚类算法在机器学习与AI中的实践 🧠

在本节课中,我们将要学习K均值聚类算法。我们将从理论开始,了解它是什么以及需要掌握的技术,然后深入到算法本身,学习如何编写代码。接着,我们将探讨如何在生产环境中实现它,并学习如何通过并行计算来扩展性能,以获得更高的算法效率。


机器学习概述

在深入K均值聚类之前,有必要先了解什么是机器学习、它为何有用,以及如何用它来解决问题。首先,我们可以从描述机器学习能做什么以及它究竟是什么开始。

机器学习主要分为两个领域:监督式机器学习无监督式机器学习

监督式机器学习

在监督式学习中,我们拥有历史数据。这些数据可以是任何带有标签的信息,一个很好的例子是股票价格。在股票价格数据中,我们可能有日期作为一个字段,实际价格作为另一个字段。在这种场景下,你会从过去的正确答案中学习,然后生成某种预测

监督式机器学习的核心思想是,你能够处理那些带有标签且具有正确值的数据。一旦你拥有了这两样东西,你就能为未来创建一个预测模型。这种机器学习被广泛使用,例如我们最近看到的房地产公司Zillow的房屋翻新问题。他们训练模型来确定购买房屋的价格,然后为房屋定价,这就是监督式学习的一个例子。

无监督式机器学习

无监督式机器学习是一种非常不同的形式,因为你不知道标签是什么。这使得它成为一种不同的技术,因为你试图发现标签。通过发现标签,你可以找出新的事物。一旦你能够发现这些新事物,你就可以用这种特定技术来解决一些问题。

你会在很多场景中看到无监督式机器学习,例如发现事物之间的关系。比如,你可以有一类花费很多钱的客户(一个集群),另一类只花费很少钱的客户(另一个集群)。因此,人们会大量使用这些聚类算法来发现关于其业务的新信息。特别是,无监督式机器学习可以成为商业分析和数据挖掘的绝佳技术。


聚类分析简介

接下来,我们来看看一个具体的项目示例,以更好地理解聚类分析。

在聚类分析中,主要需要注意的是,它是一种无监督式机器学习,并且是一种距离相似性/相异性函数。其核心思想是让你找出不同事物之间的关系。它有一个用于评估聚类的损失函数,以及一个用于优化损失函数的算法

目标是在数据中发现自然的分组。由于你通常不知道正确的分组是什么,这正是它的强大之处。一个组内的样本应该比不同组内的样本更相似,这是其背后的关键直觉。

以下是关于距离度量的关键点:

  • 距离度量:例如欧几里得距离,用于在多维空间中找出所有属性都非常相似的点。
  • 标准化:几乎所有机器学习都需要某种形式的标准化。原因在于,标准化有助于让每个特征或维度对聚类产生同等的影响。例如,如果一个数据集的一列单位是英里,另一列是英寸,它们是不同的维度或度量,可能无法同等工作。标准化(例如将所有值缩放到0到1之间)可以让你在进行距离测量时更好地看到数据中的趋势。
  • Python实现:你可以使用Python中的scikit-learn库方便地进行标准化和聚类。


K均值聚类详解

K均值是最流行的聚类形式之一,同样是一种无监督机器学习技术。在使用K均值时,有几种诊断工具可以帮助你评估模型。

以下是几种关键的诊断工具:

  • 肘部法则图:用于确定最佳的聚类数量(K值)。图中“肘部”拐点对应的K值通常是较好的选择。
  • 轮廓分析:用于评估聚类的密度和分离度。理想的聚类,其轮廓系数应超过图中的平均线。
  • 簇间距离图:在二维空间中展示聚类中心的位置,并保持它们与其他中心的距离关系,有助于可视化聚类的分离情况。

这些诊断工具并非完美,但它们可以帮助你在对数据一无所知时,做出关于聚类数量的选择。


性能优化:并行处理

进行无监督机器学习(如K均值)时,一个需要注意的问题是它可能计算量非常大。随着数据量增长,磁盘I/O和CPU都会成为性能瓶颈。

例如,连续运行25个K均值聚类操作可能会花费相当长的时间(例如23秒)。对于大型数据集,时间会更长。

为了提高性能,你可以使用并行处理来同时运行多个K均值聚类任务。在Python中,可以利用multiprocessing模块来实现这一点。该模块可以创建多个进程,每个进程在独立的CPU核心上执行聚类任务,从而显著缩短总体运行时间,尤其是在拥有多核处理器的高性能计算环境中。

通过并行化,你可以高效地处理大量数据集,进行探索性分析,以发现聚类操作可能揭示的新信息。


总结

本节课中,我们一起学习了K均值聚类算法。我们从机器学习的宏观分类(监督式与无监督式)入手,明确了聚类属于无监督学习的范畴。接着,我们深入探讨了聚类分析的核心概念,包括距离度量和数据标准化的重要性。

我们详细介绍了K均值算法,并学习了如何使用肘部法则图、轮廓分析和簇间距离图等工具来诊断和优化聚类效果。最后,我们探讨了在面对大规模数据时,如何通过Python的multiprocessing模块实现并行计算,以显著提升K均值聚类的处理性能。

掌握从理论到实现,再到性能优化的完整流程,将帮助你在实际的生产环境中有效地应用K均值聚类来解决业务问题。

021:云开发者工作空间优势 🚀

在本节课中,我们将探讨一个在现代软件开发、数据工程和机器学习领域日益重要的趋势:云开发者工作空间。我们将了解其核心优势,并与传统的本地开发环境进行对比,帮助你理解为何向云端迁移是未来的发展方向。

传统本地环境的局限性 💻

上一节我们介绍了机器学习运维的多种工具,本节中我们来看看开发环境本身。首先,让我们审视一下传统的笔记本电脑或工作站开发环境。

这种环境存在几个关键问题:

  • 环境非确定性:没有标准化的、可复现的环境。可能安装了你不想要的软件包,导致依赖冲突。
  • 资源成本高昂:获取高性能GPU和大容量固态硬盘的成本很高。
  • 与部署环境脱节:如果你的应用最终部署在云端,那么本地开发环境与生产环境存在差异,可能导致“在我机器上能运行”的问题。

虽然可以通过容器技术(如Docker)在一定程度上解决环境一致性问题,但这增加了配置和管理的复杂性。

云开发者工作空间的兴起 ☁️

现在,让我们将目光转向云端。云服务商提供了多种基于浏览器的集成开发环境,它们正在改变开发者的工作方式。

以下是主流的云开发环境分类及其特点:

1. 集成开发环境
这类环境提供了完整的代码编辑、调试和项目管理功能,更适用于软件工程和MLOps工作流。

  • GitHub Codespaces:深度集成GitHub Actions(CI/CD系统)和GitHub Copilot(AI编程助手),是与GitHub生态结合最紧密的环境之一。
  • AWS Cloud9:提供基于角色的权限管理,无需在代码中硬编码API密钥,并与AWS Lambda、S3等服务深度集成,便于构建无服务器应用。
  • GCP Cloud IDE 与 Azure Cloud IDE:谷歌云和微软Azure也提供了各自功能类似的云端编辑器。

2. 云端Shell终端
这是更轻量级的命令行环境,适合执行快速任务或管理操作。

  • AWS CloudShell / GCP Cloud Shell / Azure Cloud Shell:各云厂商均提供了内嵌在控制台中的Shell环境,预装了SDK和工具,并可在Bash、Zsh或PowerShell之间切换。

3. 笔记本友好型环境
这类环境专为数据科学和交互式编程设计,核心是Jupyter Notebook。

  • Google Colab Notebooks:提供免费的GPU资源运行Jupyter兼容的笔记本,并有Pro版本提供更强大的功能。
  • AWS SageMaker Studio Lab:由AWS平台提供的免费服务,允许用户使用GPU运行Jupyter笔记本。

核心优势与未来展望 ⚡

综合来看,云开发者工作空间代表了明确的演进方向。它们提供的是强大的、可随时创建与销毁的、预配置好的环境

其核心优势可以用一个简单的概念概括:同地协作。你的开发环境与你的数据及计算资源位于同一云端区域。

考虑这个场景:当你在咖啡馆需要处理TB级的数据时,如果数据在云端,而你的开发环境也在同一云端,你就可以直接高效地进行计算,无需在本地和云端之间来回传输数据。

因此,未来的趋势是充分利用云开发者工作空间优势。它通过提供一致的环境、集成的工具链、按需可扩展的资源以及与云服务的无缝连接,极大地提升了开发、数据科学和机器学习工程的效率与协作能力。

本节课中我们一起学习了云开发者工作空间相较于传统本地环境的巨大优势,了解了不同类型的云端开发环境及其适用场景。拥抱云端开发环境,是迈向更高效、更协作的现代技术工作流程的关键一步。

022:GitHub生态系统关键组件 🛠️

在本节课中,我们将学习如何利用GitHub生态系统来构建和部署机器学习项目。我们将重点介绍四个核心组件:Codespaces、GPU访问、Copilot AI编程助手以及GitHub Actions。这些工具共同构成了一个强大、可复现且高效的现代开发环境。


构建可复现的开发环境 🔄

上一节我们介绍了GitHub生态系统的整体价值,本节中我们来看看如何实现开发环境的可复现性。这对于团队协作和课堂教学至关重要。

通过Codespaces环境,你可以获得极高的可复现性。这意味着团队中的其他成员或课堂上的其他学生,都能访问与你完全相同的开发环境。

以下是Codespaces实现可复现性的三个关键方面:

  • 云端开发环境:它是一个基于云的工作空间,内置了容器镜像。这个镜像可以是Ubuntu镜像、微软创建的镜像,或任何与Docker兼容的镜像。
  • 自定义配置:你可以通过 .devcontainer 配置文件,自定义这个环境以满足你的特定需求。
  • 计算与存储:你可以配置Codespaces使用GPU、多核机器或高内存机器。这非常宝贵,因为你可以在与生产环境相似的环境中进行测试和构建。

利用GPU加速机器学习任务 ⚡

现在,我们已经有了一个可复现的环境,接下来看看如何利用GPU的强大算力来加速我们的工作。

访问GPU允许你执行多种高级机器学习任务。例如,你可以深入使用Hugging Face——预训练模型的领先提供商之一。你可以下载其预训练模型,并在你的设备上直接进行微调,而无需购买昂贵的独立GPU。

以下是利用GPU可以进行的几项核心工作:

  • 使用预训练模型:Hugging Face与PyTorch配合非常紧密。你可以访问PyTorch,也可以使用TensorFlow。
  • 构建深度学习模型:你可以从头开始构建自己的深度学习模型。
  • 底层GPU编程:你甚至可以深入到更底层的NVIDIA CUDA SDK,构建直接应用于GPU的函数。

借助AI编程助手提升效率 🤖

在拥有了强大的计算环境后,我们还需要高效的开发工具。Copilot AI编程助手正是为此而生。

Copilot AI编程助手是一种获取代码建议、直接向项目中添加细节的方式。通过Copilot整合项目中的所有信息,你可以请求Pylint进行代码检查、使用Pytest进行测试,或用IPython执行代码,从而形成一个持续改进的良性循环。这可以带来数倍的开发速度提升。


实现持续集成与持续交付 🚀

最后,当我们完成了代码开发,就需要一个可靠的部署流程。GitHub Actions的持续集成和持续交付功能完美地解决了这个问题。

它允许你在Codespace环境中,执行 make installmake testmake deploy 等步骤(定义在你的Makefile中)。然后,通过GitHub Actions将这些步骤集成到CI/CD流程中。例如,它可以触发将镜像推送到Amazon的容器注册表,进而触发平台即服务(如App Runner)来部署你的应用。

这样,你就拥有了在完全相同的环境中开发和最终部署所需的所有工具,为实现持续集成和持续交付的最佳实践提供了平滑的过渡。


总结 📝

本节课中,我们一起学习了GitHub生态系统中四个关键组件如何协同工作,为机器学习运维提供强大支持:

  1. Codespaces 提供了可复现的云端开发环境
  2. GPU访问 赋能了高性能的模型训练与推理
  3. Copilot AI助手 显著提升了代码开发与调试的效率
  4. GitHub Actions 实现了从代码到部署的自动化CI/CD流水线

掌握这些工具,你将能更高效、更协作地构建和部署机器学习应用。

023:使用GitHub模板创建项目脚手架

在本节课中,我们将学习如何利用GitHub的模板功能,快速创建一个标准化的机器学习项目仓库。我们将基于一个现有模板创建新仓库,并将其自定义为适合团队或课程使用的模板。


概述

GitHub模板仓库功能允许用户基于一个预定义的项目结构快速创建新仓库。这能确保团队或课程中的所有项目都遵循一致的目录结构、配置文件和开发环境设置,从而提高协作效率和项目启动速度。

上一节我们介绍了开发容器和代码空间的基本概念,本节中我们来看看如何利用GitHub模板来标准化项目初始化流程。

创建基于模板的新仓库

首先,我们需要找到一个合适的模板作为起点。这里以微软的“Codespaces Tea Template Pi”公共模板为例。

以下是创建基于模板的新仓库的步骤:

  1. 在模板仓库页面,点击 “Use this template” 按钮。
  2. 选择目标账户或组织。
  3. 为新仓库命名,例如 mlops-template
  4. 选择仓库可见性(公开或私有)。
  5. 选择是否包含模板的所有分支(通常只包含 main 分支即可)。

通过以上步骤,模板中的所有文件将被复制到新创建的仓库中。

自定义模板内容

创建模板仓库后,我们通常需要根据特定需求对其进行自定义。一个常见的做法是添加 Makefile 来简化常用命令。

例如,我们可以直接在GitHub界面上创建一个新的 Makefile

install:
    pip install -r requirements.txt

test:
    pytest

format:
    black .
    isort .

此外,我们也可以修改 .devcontainer 目录下的配置文件,以定制开发容器的环境,例如预装特定的工具或库。

将仓库发布为模板

为了使自定义的仓库结构能够被他人复用,我们需要将其设置为模板仓库。

以下是具体操作:

  1. 进入新仓库的 “Settings” 页面。
  2. 向下滚动找到 “Template repository” 选项。
  3. 勾选复选框,将其设置为模板仓库。

设置完成后,该仓库的页面将显示“Template”标签。团队成员或学生现在可以通过点击 “Use this template” 按钮,基于此标准化结构快速创建自己的项目仓库。

总结

本节课中我们一起学习了GitHub模板仓库的完整使用流程。我们首先基于一个公共模板创建了新仓库,然后通过添加 Makefile 等方式对其进行了自定义,最后将该仓库发布为团队可复用的模板。利用此功能,可以确保项目结构的一致性,显著提升团队协作和项目初始化的效率。

更多详细信息,可以参考GitHub官方文档“Creating a template repository”。

024:GitHub Codespaces 演示 🚀

在本节课中,我们将学习如何使用 GitHub Codespaces 来定制一个公开的仓库模板,以满足个人或团队特定的开发环境需求。我们将涵盖从创建 Codespace、选择硬件配置、使用预构建容器,到安装扩展和自定义开发环境的完整流程。


概述

GitHub Codespaces 提供了一个完全配置的云端开发环境。本节演示将展示如何从一个公共模板仓库开始,通过 Codespaces 快速启动一个开发环境,并对其进行个性化定制,例如安装扩展、修改配置文件,最终生成一个可供他人使用的增强版模板。


启动与配置 Codespace

首先,我拥有一个作为公共模板的仓库。该仓库内部包含一些配置项,例如用于配置 Codespaces 的开发容器配置文件,以及一些 GitHub Actions 工作流。

为了满足我的特定需求并修改此模板,以便其他人能从中获得更多功能,我将使用 Codespaces。

我们进入 Codespaces 界面,选择“在云中编辑”。默认情况下,我可以选择默认配置。此外,在配置菜单中,我实际上可以从多种机器类型中进行选择。选择取决于我的任务性质。

例如,如果我教授需要多核处理的概念课程,我会选择 16 核的机器。如果我要进行 GPU 相关的工作,例如微调一个 Hugging Face 模型,我则会选择 GPU 机型。

现在,我们选择这个 GPU 机型,然后点击“创建 Codespace”。


加速启动:预构建容器

启动过程需要一些时间。我们可以通过使用预构建容器功能来加速这一过程,这是一个非常实用的小功能。

一旦 Codespace 启动,我可以展示如何返回设置。在 Codespaces 设置中,我可以选择使用预构建配置选项。

我将启用此选项。它的作用是允许环境自动为我们构建。我可以选择主分支,并设置每次推送代码时都重新构建此 Codespace。

创建此选项后,未来的启动速度将显著提升。


环境初始化与连接

当 Codespace 启动时,我们可以看到它正在执行各种操作来配置开发环境。

一旦开发环境设置完成,我就可以开始定制模板了。这个过程只需要片刻。

关于这个特定环境,需要注意的一点是,我也可以通过进入 Codespaces 的开发容器环境并修改 devcontainer.json 文件来自行调整它,而这正是我接下来要做的。

我们可以看到容器已启动,现在正在连接,稍等片刻即可准备就绪。


个性化环境设置

连接成功后,我首先喜欢配置的是 Codespace 的设置。我会进入颜色主题设置,将其更改为“Colorblind Beta”主题。这个主题对比度高,且具有良好的可访问性。

让我们进行更改,并适当调大字体。

此外,我注意到已经有人为我构建了这个开发容器,这很不错。它基于 Bullseye 系统,并安装了一些软件。

但我希望在其中添加更多内容,进行一些个性化定制。


安装扩展

接下来,我将安装一些扩展。我转到环境中的扩展面板。

首先,我会安装 Codium。我选择安装 Nightly 版本,以获取最新功能。

其次,我喜欢安装 GitHub Copilot Labs 扩展,它可以帮助进行代码翻译等功能。

安装后,我可以右键点击这些扩展,选择“添加到开发容器”。这样做的优点是,将来当我把这个环境提供给其他人时,他们也能直接获得这些功能。


自定义 Makefile

另一个我喜欢做的定制是修改 Makefile,并在其中添加一些配置安装步骤,同时为 Makefile 安装一个语法扩展。

我们右键点击 Makefile,选择“添加到开发容器”。

现在所有设置都已完成,最后一步是回到我的文件,打开 Makefile,并粘贴一些预设内容进去。

我们可以粘贴内容,并组合成一个小模板。例如,我们可以添加一个 deploy 目标,并可能为使用者添加一些注释说明。

这样,我就可以为他们提供关于如何安装软件、测试软件、格式化代码以及检查项目链接的建议。所有这些都封装在一个模板化的环境中。


验证环境功能

此外,如果我们运行 htop 命令,可以看到这个环境确实拥有高内存配置。

如果我们输入 nvidia-smi 查询命令,也可以查看 GPU 是否正在运行。

至此,所有必需的配置都已完成。


保存与共享定制

最后一步是保存我们的更改。我们运行 git status 查看更改。

然后,我们将修改添加到 Git 暂存区:

git add .devcontainer
git add Makefile

现在,其他人就可以使用这个经过修复和增强的模板了。


总结

本节课中,我们一起学习了如何利用 GitHub Codespaces 快速定制一个开发环境模板。我们从选择硬件配置、启用预构建加速,到安装个性化扩展、修改核心配置文件,最终保存并分享了我们的定制成果。这个过程展示了如何高效地创建可复现、可共享且功能强大的云端开发环境。

025:GPU与Code Whisperer工具 🚀

在本节课中,我们将学习如何在基于GPU的Codespace环境中,利用NVIDIA监控工具和Whisper等工具进行高效的GPU计算与资源管理。


上一节我们介绍了机器学习运维中的部署与监控概念。本节中,我们来看看如何在具体的开发环境中利用GPU资源。

这里有一个NVIDIA监控工具,它允许我查看此处NVIDIA GPU的完整利用率。

你可以在此看到CUDA驱动版本是11.7,GPU使用率为43%。在另一个终端中,我正在运行Whisper,它能够利用Codespace上的GPU。同时,得益于Codespace提供的存储空间,我也能够转录非常大的文件。

因此,对于使用基于GPU实例的数据科学和机器学习学生来说,这确实是一个进行GPU相关工作的绝佳环境。

我们还可以切换到这里,查看每个进程的详情。我们可以看到,事实上我不仅能够充分利用GPU。

我还能够使用这台六核机器,并利用这些重型GPU机器上可用的一些大内存资源。

你可以看到有110 GB可用内存。这意味着我实际上可以再启动几个转录任务,使用OpenAI的Whisper。

监控我的资源,然后之后当我想做其他工作时,例如文本摘要或在转录数据上运行其他Hugging Face预训练模型。

一切都可以顺利进行。


本节课中我们一起学习了如何在Codespace环境中使用NVIDIA工具监控GPU资源,并利用Whisper等工具执行高效的转录任务。我们了解到,这种环境为数据科学和机器学习工作提供了强大的计算能力和灵活性,便于后续进行更复杂的模型处理。

026:Hugging Face微调实践

在本节课中,我们将学习如何使用流行的模型托管服务Hugging Face,并实践对预训练模型进行微调的核心流程。

概述

Hugging Face是一个提供模型、数据集和协作空间的平台。它拥有超过75,000个且数量持续增长的预训练模型,覆盖了文本摘要、分类、问答等多种任务。用户可以直接在线体验这些模型,也可以下载它们,在自己的环境中针对特定需求进行微调。本节我们将重点介绍微调的实践过程。

Hugging Face核心功能

Hugging Face主要提供三大核心功能:模型数据集空间

  • 模型:这里托管了大量预训练模型。用户可以根据任务类型(如摘要、分类)浏览和选择模型,并在线进行测试。
  • 数据集:平台提供了丰富的数据集,可用于模型训练和评估。
  • 空间:允许用户创建和分享基于模型的演示应用。

例如,如果我们进入“摘要”任务区,选择Google的Pegasus模型,就可以直接输入文本并查看其摘要效果。这项服务被广泛用于实验和生产环境。

微调预训练模型实践

上一节我们介绍了Hugging Face的平台功能,本节中我们来看看如何具体微调一个预训练模型。核心概念是:下载一个预训练模型,然后使用你自己的数据对其进行调整,以适应特定任务。

Hugging Face提供了详细的教程来指导这一过程。通常,你可以从平台下载一个数据集,然后在启用了GPU的GitHub Codespace环境中进行模型微调。

以下是一个微调示例代码的关键步骤:

# 导入必要的库
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from datasets import load_dataset, load_metric
  1. 加载数据集:使用 load_dataset 函数加载Hugging Face上或本地的数据集。
  2. 预处理与分词:定义一个函数,使用 AutoTokenizer 对数据集进行分词处理。
  3. 加载预训练模型:使用 AutoModelForSequenceClassification 加载一个基础预训练模型。
  4. 定义评估指标:例如,构建一个计算准确率的函数。
  5. 执行训练:配置训练参数后,调用 trainer.train() 方法开始微调过程。

执行训练时,计算环境至关重要。在启用GPU的情况下,训练速度会显著快于仅使用CPU。你可以使用 nvidia-smi 命令来监控GPU的使用情况,例如在一次微调任务中,GPU利用率可能达到94%。

总结

本节课中我们一起学习了Hugging Face平台的核心功能,并实践了对预训练模型进行微调的完整流程。我们了解到,通过下载模型和数据集,并在配备GPU的计算环境中运行训练代码,可以相对直接地完成模型定制,从而将其适配到特定的业务场景中。

027:GitHub Copilot 演示 🚀

在本节课中,我们将学习如何使用 GitHub Copilot 来辅助编程。我们将探索其代码翻译功能,并体验如何通过自然语言提示与 Copilot 进行“结对编程”,快速生成和修改代码。

启用 GitHub Copilot

首先,我进入了一个已启用 Copilot 功能的代码仓库。要使用 Copilot,需要安装相应的扩展。

在 VS Code 的扩展面板中,我们可以找到两个相关扩展:GitHub CopilotGitHub Copilot Labs。后者提供了一些实验性功能,例如代码翻译。我已经安装了最新版本,接下来我们将尝试这两个扩展。

使用 Copilot Labs 翻译代码

上一节我们介绍了如何启用 Copilot,本节中我们来看看如何使用 Copilot Labs 的代码翻译功能。这个功能可以帮助我们将一种编程语言的代码转换成另一种语言。

以下是开始操作的步骤:

  1. 点击 Copilot Labs 面板中的 “Translate code” 功能。
  2. 在代码编辑器中选中想要翻译的代码片段。
  3. 在翻译面板中选择目标语言,即可看到翻译后的代码。

为了演示,我创建了一个名为 loops 的文件,并从另一个仓库复制了一段 Bash 脚本代码粘贴进去。

#!/bin/bash
fruits=("apple" "banana" "cherry")
for fruit in "${fruits[@]}"
do
    echo "I love eating healthy snacks like this $fruit"
done

这段代码可以正常运行。现在,如果我想理解这段代码在 Python 中如何实现,我可以使用翻译功能。

在 Copilot Labs 中,选择将代码翻译成 Python。这是一个很好的学习新语言的方式,尤其当你已经熟悉另一种语言时,它能让你快速上手。

我创建了一个 translate_copilot 目录来存放翻译后的代码,并将 loops 文件移入。然后,在该目录下创建一个 Python 文件 py_loops.py。Copilot 给出了翻译建议,生成如下代码:

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(f"I love eating healthy snacks like this {fruit}")

运行 python py_loops.py,我们得到了相同的输出。这确实是一种非常高效的学习方法。

我们不仅可以翻译成 Python,还可以快速尝试其他语言。例如,将同一段 Bash 代码翻译成 Ruby

fruits = ["apple", "banana", "cherry"]
fruits.each do |fruit|
  puts "I love eating healthy snacks like this #{fruit}"
end

整个过程非常直观,在不同语言间进行翻译的体验很棒。

与 Copilot 结对编程

在体验了代码翻译后,接下来我们看看如何通过与 Copilot 进行“结对编程”来构建更复杂的工作流。其核心思想是将 Copilot 视为另一位开发伙伴。

我创建了一个名为 ai_pair 的目录,并在其中创建一个 calc 文件。我们将通过编写提示(Prompt)来引导 Copilot 帮助我们生成代码。

首先,在文件顶部,我通过注释描述了模块的用途,这有助于 Copilot 理解我们的意图:

# This module is used to create calculation functions such as addition, subtraction.

然后,我添加了 #!/usr/bin/env python3 这一行,表明这最终将是一个可执行脚本。Copilot 非常智能,它已经能推测出我想要做什么。这类似于向另一位人类开发者描述需求。

基于这个提示,Copilot 开始生成加法函数 add 的框架。接着,我继续引导它生成减法函数 subtract

为了将这个模块变成一个命令行工具,我进一步提示它:“This module will also be invoked as a command script, using click.” 并添加 import click

现在,我需要构建一个 Click 命令组。我只需告诉 Copilot:“build a click group”,它就会为我生成所有样板代码,甚至帮我写出建议的命令结构。

import click

@click.group()
def calculator():
    """Calculator App."""
    pass

@calculator.command()
@click.argument(‘a‘, type=int)
@click.argument(‘b‘, type=int)
def add(a, b):
    """Add two numbers."""
    result = a + b
    click.echo(f"The sum is {result}")

@calculator.command()
@click.argument(‘a‘, type=int)
@click.argument(‘b‘, type=int)
def subtract(a, b):
    """Subtract two numbers."""
    result = a - b
    click.echo(f"The difference is {result}")

if __name__ == ‘__main__‘:
    calculator()

代码生成后,我可以通过命令行来调用它。运行 python calc.py --help 可以看到帮助信息。测试加法 python calc.py add 2 2 和减法 python calc.py subtract 5 3,一切工作正常。

如果想让输出更美观,我可以继续提示 Copilot。例如,我说:“invoke the add function with colored output from click.” Copilot 便理解了意图,并修改代码使用 click.style 来输出彩色文本。

@calculator.command()
@click.argument(‘a‘, type=int)
@click.argument(‘b‘, type=int)
def add(a, b):
    """Add two numbers."""
    result = a + b
    click.echo(click.style(f"The sum is {result}", fg=‘green‘))

通过这种温和提示的方式,让 Copilot 为我们构建代码,可以非常快速地完成大量样板代码的编写,这个计算器工具就是一个很好的例子。

总结

本节课中我们一起学习了 GitHub Copilot 的两个强大应用。首先,我们利用 Copilot Labs 的代码翻译功能,轻松地在 Bash、Python 和 Ruby 等语言间转换代码,这为学习新语言提供了极大便利。接着,我们体验了与 Copilot 进行 “结对编程”,通过编写清晰的注释和提示,引导它帮助我们生成完整的命令行工具代码,包括使用 Click 库和添加彩色输出等进阶功能。这展示了 Copilot 如何显著提升开发效率,尤其是在处理重复性样板代码时。

028:GitHub Actions 实战指南 🚀

在本节课中,我们将学习如何在实际项目中启用和使用 GitHub Actions,了解其核心概念,并通过一个具体的例子来观察自动化工作流的运行过程。

概述

GitHub Actions 是一个强大的持续集成和持续交付平台,允许你自动化软件工作流程。本节我们将通过一个已启用 Actions 的项目,学习其配置文件结构、如何与本地开发流程对应,以及如何触发和监控自动化构建。

项目结构与配置文件

让我们先来看一个已启用 GitHub Actions 的项目。任何配置了 Actions 的项目都会在 .github/workflows/ 目录下包含一个或多个 YAML 配置文件。

在这个目录中,可以看到我定义了一个在 ubuntu-latest 环境上运行的作业。它也可以运行在我选择的、受 GitHub Actions 支持的任何容器上,甚至是我自定义的容器或开发环境中。

在作业内部,我为每个步骤定义了名称。例如:

- name: Install and Lint
  run: make install-lint
- name: Lint
  run: make lint
- name: Test
  run: make test
- name: Format
  run: make format

链接 Makefile 实现本地与云端一致

现在,让我们看看与上述 Actions 配置对应的 Makefile 文件。

你可以看到,这里定义了我构建过程中的每一个步骤。这种将 Makefile 直接链接到 GitHub Actions 配置文件的方法非常棒,因为你无需思考在云端运行什么命令,只需运行与本地相同的命令即可。

例如,如果我想在本地运行 make format,它会格式化我项目中的所有代码。同样,如果我想运行 make lint,它会检查项目中所有代码的规范性。当这些命令在 GitHub Actions 环境中运行时,会发生完全相同的事情。

这样设计的核心理念是:保持本地开发与云端自动化流程的一致性

创建工作流与使用模板

如果我们回到 GitHub 界面,可以通过点击 “Actions” 来创建一个新的工作流。

系统会提供几个不同的选项。一种是自己从头开始设置,它会提供一个模板。这对于初学者来说是一个不错的起点,你可以直接在模板中填入任何你想运行的命令,甚至是运行我们刚才提到的构建脚本。

不过,我认为使用 Makefile 是更好的方法,因为它能确保与你本地或 GitHub Codespace 中的操作保持一致。

另一个需要注意的地方是,GitHub 提供了许多建议的示例工作流供你参考。例如,“发布 Python 包”的示例。

查看这些示例是如何实际工作的,能为你提供许多关于最佳实践的良好指导。因此,GitHub Actions 是一个可用于部署等众多场景的绝佳服务,这也是它在 DevOps 中如此强大的原因。

实战:触发与观察工作流运行

接下来,让我们实际操作并观察它的工作过程。假设我想测试项目中发生的一些更改。

我可以先使用 git stash 将当前的修改暂存起来。然后,我可以在某个脚本中进行一个小修改。

修改完成后,我可以使用 git status 查看状态,并将这些更改提交。

当我添加(git add)并提交(git commit)这些更改后,例如提交信息为 “Kicking off build”,它会立即触发一个新的 GitHub Actions 构建任务。

这就是 GitHub Actions 的便利之处:我可以逐步查看我在 YAML 文件中定义的每个步骤的执行情况。

推荐的部署流程

虽然具体测试内容取决于每个用户的需求,但我推荐在部署流程中按顺序执行以下步骤:

  1. make install - 安装依赖
  2. make lint - 代码规范性检查
  3. make test - 运行测试
  4. make deploy - 执行部署

最后一步可以将应用推送到生产环境。GitHub Actions 确实是构建非常专业的 DevOps 工作流的核心。

总结

本节课中,我们一起学习了 GitHub Actions 的核心应用。我们了解了其配置文件(YAML)的结构,探讨了通过 Makefile 保持本地与云端命令一致性的最佳实践,并实际操作了如何通过代码提交触发自动化工作流。GitHub Actions 通过提供丰富的模板和强大的自定义能力,成为实现高效、专业 DevOps 流程的关键工具。

029:使用Step-Functions构建DataOps管道 🚀

在本节课中,我们将学习如何使用AWS Lambda函数和AWS Step Functions来构建一个简单的数据处理管道。我们将从编写一个基础的Lambda函数开始,然后将其与另一个函数串联起来,最终在Step Functions中创建一个可视化的工作流。整个过程将展示如何用少量代码实现强大的自动化流程。


创建第一个Lambda函数 🛠️

首先,我们需要创建一个AWS Lambda函数。Lambda函数的核心概念非常简单:它接收一个输入(事件),执行一些工作,然后返回一个输出。如果你会写Python函数,你就会写Lambda函数。

以下是创建Lambda函数的步骤:

  1. 在AWS控制台中找到并进入Lambda服务。
  2. 点击“创建函数”。
  3. 选择“从头开始创作”。
  4. 为运行时选择“Python 3.9”。
  5. 将函数命名为“random_fruit”。
  6. 保持其他默认设置,然后点击“创建函数”。

创建完成后,你会看到一个代码编辑器。系统已经提供了一个基本的函数结构,其中lambda_handler是入口点,event参数就是函数的输入。

现在,让我们编写函数逻辑。我们将创建一个函数,根据输入的水果名称返回不同的消息。

def lambda_handler(event, context):
    # 从输入事件中获取‘fruit’字段的值
    fruit = event.get('fruit', '')

    # 判断水果类型并返回相应消息
    if fruit == 'cherry':
        return {
            'statusCode': 200,
            'body': f'I love {fruit}.'
        }
    else:
        return {
            'statusCode': 200,
            'body': f'No thanks, I don\'t like {fruit}.'
        }

编写完代码后,点击“部署”按钮保存。为了测试函数,我们需要创建一个测试事件。

  1. 点击“测试”选项卡。
  2. 点击“创建新事件”。
  3. 将事件命名为“cherry_test”。
  4. 在事件JSON中,输入:{"fruit": "cherry"}
  5. 点击“保存”,然后点击“测试”。

如果一切正常,你将看到返回结果:{"statusCode": 200, "body": "I love cherry."}。你可以再创建一个名为“pear_test”的测试事件,输入{"fruit": "pear"},测试会返回"No thanks, I don't like pear."

这个“输入-处理-输出”的模式是软件工程和分布式计算的基础。接下来,我们将创建第二个函数,并将其与第一个函数串联起来。


创建第二个Lambda函数:厨师处理 🧑‍🍳

上一节我们创建了一个处理水果偏好的函数。本节中,我们将创建第二个函数,它根据第一个函数的输出结果来决定制作什么餐点。

这个新函数将扮演“厨师”的角色。它的逻辑是:如果收到的消息中包含“love”这个词,就决定做沙拉;否则,就决定做烧烤。

以下是创建第二个函数的步骤:

  1. 返回Lambda服务主页,再次点击“创建函数”。
  2. 同样选择“从头开始创作”和“Python 3.9”运行时。
  3. 将函数命名为“chef”。
  4. 点击“创建函数”。

在新函数的代码编辑器中,输入以下逻辑:

def lambda_handler(event, context):
    # 从上一个函数的输出中获取消息体
    # 注意:Step Functions中,上一个状态的输出会成为下一个状态的输入
    previous_output = event
    # 通常输出在‘body’字段中,但我们需要根据实际结构调整
    message_body = previous_output.get('body', '')

    # 判断并决定餐点
    if 'love' in message_body:
        meal = 'salad'
    else:
        meal = 'barbecue'

    return {
        'statusCode': 200,
        'body': f'Let\'s make a {meal}.'
    }

部署这个函数后,我们也需要测试它。由于这个函数的输入是第一个函数的输出,我们的测试事件需要模拟这种结构。

  1. 点击“测试”选项卡,创建一个新事件。
  2. 命名为“salad_test”。
  3. 输入模拟第一个函数成功响应的JSON:{"statusCode": 200, "body": "I love cherry."}
  4. 保存并测试,应该返回"Let‘s make a salad."
  5. 再创建一个名为“barbecue_test”的事件,输入{"statusCode": 200, "body": "No thanks, I don‘t like pear."}进行测试,应返回"Let‘s make a barbecue."

现在,我们有了两个可以独立工作的函数。它们遵循相同的模式:接收输入,进行处理,产生输出。这种模块化设计是构建复杂管道的关键。接下来,我们将使用AWS Step Functions把这两个函数像链条一样连接起来。


使用Step Functions构建工作流 ⛓️

我们已经有了两个独立的Lambda函数。本节中,我们将使用AWS Step Functions服务将它们组合成一个有序的工作流。Step Functions允许你以可视化的方式设计和管理多个AWS服务之间的工作流程,本质上是一种低代码/无代码的编排工具。

以下是构建工作流的步骤:

  1. 在AWS控制台中,找到并进入“Step Functions”服务。
  2. 点击“创建状态机”。
  3. 选择“使用可视化设计器编写工作流”,然后点击“下一步”。
  4. 你将会看到一个画布。从左侧的“操作”面板中,拖拽一个“Lambda:调用函数”的节点到画布上。
  5. 点击这个节点进行配置:
    • 在“API参数”下的“函数名称”中,选择我们之前创建的random_fruit函数。
    • “有效负载”选择“状态输入”,这意味着工作流启动时传入的数据会直接作为这个Lambda函数的输入。
  6. 从第一个节点的右侧拉出一条线,再拖拽第二个“Lambda:调用函数”节点到画布上,与第一个节点连接。
  7. 配置第二个节点:
    • 在“函数名称”中,选择我们创建的chef函数。
    • “有效负载”同样选择“状态输入”。在Step Functions中,上一个节点的输出会自动成为下一个节点的输入。

现在,你的工作流看起来应该是:Start -> random_fruit Lambda -> chef Lambda -> End

  1. 点击“下一步”,为这个状态机命名,例如“Meal_Generator”。
  2. 权限设置保持默认(Step Functions会自动创建一个具有必要权限的执行角色)。
  3. 点击“创建状态机”。

状态机创建成功后,我们就可以执行它了。这就像运行一个程序。

  1. 在新创建的状态机详情页,点击“开始执行”。
  2. 在输入框中,提供启动工作流所需的数据。例如,输入:{"fruit": "pear"}
  3. 点击“开始执行”。

执行开始后,你可以直观地看到流程的进行。每个步骤(状态)会高亮显示。执行完成后,你可以查看每个步骤的详细输入和输出。

  • 第一步 (random_fruit) 的输入是 {"fruit": "pear"},输出是 {"statusCode": 200, "body": "No thanks, I don‘t like pear."}
  • 这个输出自动成为第二步 (chef) 的输入。chef函数处理后会输出 {"statusCode": 200, "body": "Let‘s make a barbecue."}

整个工作流的最终输出就是最后一个步骤的结果。通过这种方式,我们成功地将两个独立的函数串联成了一个自动化的数据处理管道。


总结 📝

本节课中,我们一起学习了如何使用AWS的核心服务构建一个简单的DataOps管道。

  1. 我们首先创建了AWS Lambda函数,它遵循“事件输入、执行工作、返回结果”的基本模式。我们编写了一个判断水果喜好的函数。
  2. 接着,我们创建了第二个Lambda函数作为“厨师”,它根据第一个函数的结果决定制作什么餐点。这展示了函数的模块化可重用性
  3. 最后,我们使用AWS Step Functions将这两个函数可视化的连接起来,创建了一个完整的工作流。Step Functions负责管理状态、传递数据和处理错误,使我们能够以低代码的方式构建复杂的管道。

这个“链式”处理的概念非常强大,它不仅存在于AWS中,也同样是Linux命令行工具(如通过管道符 | 连接 grep, sort, awk)和现代CI/CD工具的核心思想。通过将小型、专注的任务(函数)组合起来,你可以构建出灵活、强大且易于维护的自动化系统。

030:查询Databricks管道

在本节课中,我们将学习如何从外部环境(如GitHub Codespaces)连接并查询Azure Databricks。我们将配置必要的认证信息,使用Databricks CLI和Python SDK来管理集群、文件系统并执行SQL查询。


概述与准备工作

上一节我们介绍了Databricks的基本概念。本节中,我们来看看如何从本地开发环境远程连接和操作Databricks。

首先,需要在Azure Databricks中启动一个计算集群,并获取连接所需的关键信息。

步骤:

  1. 登录Azure门户并启动你的Databricks工作区。
  2. 导航到“计算”页面,启动一个集群(例如单节点集群)。
  3. 集群启动后,在“高级选项”中获取 服务器主机名HTTP路径
  4. 在用户设置中生成一个 访问令牌(Token)

这些信息是建立远程连接的基础。


配置GitHub Codespaces环境

为了在Codespaces中连接Databricks,我们需要将连接信息设置为仓库机密(Secrets)。这样可以在代码中安全地使用这些凭证。

以下是需要设置的机密变量列表:

  • DATABRICKS_HOST: 你的Databricks工作区主机名。
  • DATABRICKS_HTTP_PATH: 集群的HTTP路径。
  • DATABRICKS_SERVER_HOSTNAME: 服务器主机名。
  • DATABRICKS_TOKEN: 你的个人访问令牌。

配置完成后,启动Codespaces环境,它将自动加载这些机密。


验证连接:使用Databricks CLI

环境启动后,首先使用Databricks命令行工具验证连接是否成功。

打开终端,运行以下命令列出所有集群:

databricks clusters list

如果连接正常,终端将显示当前工作区中所有集群的状态信息。

接下来,可以尝试与Databricks文件系统交互:

databricks fs ls

此命令会列出根目录下的文件,确认你已具备访问数据存储的权限。


使用Python SDK进行管理操作

除了CLI,我们还可以使用Python SDK(databricks-sdk)以编程方式管理Databricks。这更适合集成到自动化脚本或应用程序中。

首先,确保已安装必要的Python包。在requirements.txt文件中应包含:

databricks-sdk

以下是一个Python函数示例,用于列出所有集群:

from databricks.sdk import WorkspaceClient
import os

def list_clusters():
    # 从环境变量读取认证信息
    host = os.getenv('DATABRICKS_HOST')
    token = os.getenv('DATABRICKS_TOKEN')
    
    # 创建客户端
    w = WorkspaceClient(host=host, token=token)
    
    # 列出集群并返回
    clusters_list = w.clusters.list()
    return clusters_list

if __name__ == "__main__":
    clusters = list_clusters()
    for c in clusters:
        print(f"Cluster: {c.cluster_name}, State: {c.state}")

你可以将此逻辑封装成库,并构建自定义的命令行工具。


执行SQL查询

对于数据查询任务,我们需要使用databricks-sql-connector库来直接执行SQL语句。

首先,安装连接器:

pip install databricks-sql-connector

以下代码展示了如何连接到Databricks并执行查询:

from databricks import sql
import os

def query_databricks(sql_query):
    connection = sql.connect(
        server_hostname=os.getenv('DATABRICKS_SERVER_HOSTNAME'),
        http_path=os.getenv('DATABRICKS_HTTP_PATH'),
        access_token=os.getenv('DATABRICKS_TOKEN')
    )
    
    cursor = connection.cursor()
    cursor.execute(sql_query)
    result = cursor.fetchall()
    
    cursor.close()
    connection.close()
    return result

# 示例:查询一个表
results = query_databricks("SELECT * FROM default.diamonds LIMIT 10")
for row in results:
    print(row)

你可以基于此函数构建灵活的命令行工具,接受动态SQL语句作为输入参数。


总结

本节课中我们一起学习了如何搭建从GitHub Codespaces到Azure Databricks的远程连接。我们涵盖了从配置认证机密、使用CLI进行基础验证,到利用Python SDK进行集群管理和执行SQL查询的完整流程。

掌握这些技能后,你可以将Databricks视为一个强大的远程数据与计算引擎,在熟悉的本地或云端开发环境中进行数据工程和机器学习任务开发。

031:在AWS上构建数据摄取管道

在本节课中,我们将学习如何在AWS云平台上构建数据摄取与处理管道。我们将重点介绍两种核心的托管服务:AWS Batch和AWS Step Functions,并解释它们如何简化复杂任务的编排与执行。

概述

AWS的数据摄取和处理管道通过使用托管服务来解决复杂问题。这意味着AWS负责管理底层的基础设施,如服务器、网络和扩展,而开发者可以专注于业务逻辑的实现。接下来,我们将深入探讨两种关键服务。

AWS Batch:托管批处理作业服务

上一节我们了解了AWS托管服务的优势,本节中我们来看看AWS Batch。AWS Batch将解决周期性作业的许多复杂部分整合在一起。

其工作流程如下:

  1. 触发器:作业可以由定时器、代码调用或其他事件触发。
  2. 创建作业:触发器激活后,会创建一个新的作业。
  3. 作业队列:新作业被放入作业队列中。队列中可以容纳成千上万个作业。
  4. 作业处理:作业根据您为AWS Batch设置的并发进程数进行处理。例如,您可以启动200个不同的容器(例如,全部配备GPU)来并行处理作业。

AWS Batch用途广泛,尤其适用于机器学习任务,例如基于组织内的事件计划对Hugging Face模型进行GPU微调。

AWS Step Functions:无服务器工作流编排

了解了批处理作业后,我们再来看看事件驱动的流程编排。AWS Step Functions是另一种无服务器技术,同样由AWS托管。

以下是其典型工作流程:

  1. 事件触发:流程可由API调用或数据到达某处等事件触发。
  2. 串联Lambda函数:您可以串联多个AWS Lambda函数。
  3. 负载处理:每个Lambda函数接收一个负载(payload),并执行其中定义的处理逻辑。
  4. 输出结果:在管道的最终阶段,您将获得处理结果。

AWS Step Functions的突出优势在于其强大的内置编排能力。您可以查看日志、监控各步骤耗时,而无需自行构建整个编排生态系统。该服务已为您构建好,您只需组合业务逻辑即可。

总结

本节课中我们一起学习了在AWS上构建数据摄取管道的两种核心方法。我们介绍了AWS Batch,它擅长管理大规模的周期性批处理作业,特别适合机器学习中的模型微调等任务。接着,我们探讨了AWS Step Functions,它是一种强大的无服务器工作流编排服务,能够以可视化的方式轻松串联和监控多个处理步骤。利用这些托管服务,开发者可以更高效地构建可靠、可扩展的数据处理管道。

032:AWS Step Functions 实践 🚀

在本节课中,我们将学习如何使用 AWS Step Functions 来编排和协调多个 AWS Lambda 函数,从而构建一个简单的数据处理工作流。我们将通过一个“Marco Polo”的示例,直观地理解 Step Functions 的工作原理和优势。


AWS Step Functions 非常适合用于编排任务,特别是协调 AWS 中许多不同的组件。你可以直观地设计一系列决策步骤,将其放入一个管道中运行,并获得出色的执行过程监控。

一个很好的入门方法是点击“入门指南”。它会提供一个“Hello World”示例。在这个示例中,你可以看到它实际上就是一段 JSON 代码。在这段代码内部,你可以看到不同的“状态”。

它从一个“Pass”状态开始。然后执行“Hello World”示例,等待三秒钟,执行“Hello World”操作,最后进入结束状态。如果我们直接运行这个示例,过程非常直观。我们可以创建状态机并运行它。它会详细展示每一步将要发生什么。运行完成后,结果会直接打印在这里。Step Functions 的优势就在于它提供了这种出色的执行过程监控。

在演示中看到这一点很好,但如果我们想自己动手从头构建一些东西呢?我们可以编排自己的 Lambda 函数来构建一个管道。


上一节我们了解了 Step Functions 的基本概念,本节中我们来看看如何构建一个自定义的工作流。我们将创建两个 Lambda 函数,并用 Step Functions 将它们连接起来。

首先,我将从 AWS Lambda 开始。我将创建一个函数,命名为 premarco。我选择 Python 作为运行时环境。

这个函数的功能是:接收一个包含 name 字段的负载(payload)。如果 name 的值是 “Marco”,则返回 “Polo”;否则返回 “No”。

以下是该函数的代码:

def lambda_handler(event, context):
    if event.get('name') == 'Marco':
        return {'name': 'Polo'}
    else:
        return {'name': 'No'}

接下来,我们可以配置一个测试事件。我将创建一个名为 “Marco” 的测试事件,其负载为 {"name": "Marco"}。保存并部署这个函数,然后进行测试。测试结果显示返回了 {"name": "Polo"},功能正常。

现在,让我们构建第二个 Lambda 函数,命名为 postmarco。同样使用 Python 运行时。

这个函数的功能是:检查负载中的 name 字段。如果值是 “Polo”,则返回一条祝贺信息;否则返回一条鼓励信息。

以下是该函数的代码:

def lambda_handler(event, context):
    if event.get('name') == 'Polo':
        return {'message': 'Great job!'}
    else:
        return {'message': 'Keep trying!'}

同样,我们部署这个函数并进行测试。为了确保两个函数能协同工作,我们需要调整 premarco 函数的返回格式,使其与 postmarco 的预期输入格式匹配。我们已经在上面的代码中完成了这一点,即返回一个包含 name 键的字典。

现在,两个 Lambda 函数都已准备就绪。


现在,我们可以转到 AWS Step Functions 控制台,将这两个状态(函数)连接起来。

我们将创建一个新的状态机,并选择“可视化设计”。

以下是构建流程的步骤:

  1. 添加第一个状态:从左侧拖拽一个“Lambda 调用”状态到画布上。我们将其命名为 “Invoke Premarco”,描述为“处理 Marco Polo 消息的第一步”。在配置中,选择我们之前创建的 premarco 函数。
  2. 添加第二个状态:再拖拽一个“Lambda 调用”状态到画布上,放在第一个状态之后。将其命名为 “Invoke Postmarco”,并选择 postmarco 函数。
  3. 连接状态:Step Functions 会自动将第一个状态的输出作为第二个状态的输入。

创建完成后,我们将状态机命名为 “PrePostMarcoPipeline” 并保存。


现在,让我们来执行这个工作流,看看它是如何运作的。

我们将启动一个新的执行。需要为工作流提供初始输入。我们创建两个测试执行:

  • 测试一:输入 "Marco"
    • 执行负载:{"name": "Marco"}
    • 点击“开始执行”。我们可以观察执行过程。premarco 函数接收输入 {"name": "Marco"},输出 {"name": "Polo"}。这个输出自动传递给 postmarco 函数,postmarco 接收 {"name": "Polo"},最终输出 {"message": "Great job!"}。执行成功。
  • 测试二:输入 "Bob"
    • 执行负载:{"name": "Bob"}
    • 再次启动执行。premarco 函数接收 {"name": "Bob"},输出 {"name": "No"}postmarco 函数接收 {"name": "No"},最终输出 {"message": "Keep trying!"}

通过 Step Functions 的可视化界面,我们可以清晰地看到每个步骤的输入和输出,这正是其强大的监控和调试能力。


本节课中我们一起学习了 AWS Step Functions 的核心用法。我们首先了解了 Step Functions 用于工作流编排和监控的价值。然后,我们通过一个“Marco Polo”的实践示例,逐步创建了两个 Lambda 函数,并使用 Step Functions 将它们串联成一个完整的工作流。最后,我们通过不同的输入测试了工作流的执行,并观察了其可视化的执行详情。

通过这种“Marco Polo”式的简单练习,你可以快速上手 Step Functions。一旦掌握了基本概念,你就可以利用它来构建更复杂的数据摄入和处理工作流,协调更多的 AWS 服务。

机器学习运维:33:AWS传输中数据转换 🔄

在本节课中,我们将学习如何在AWS平台上进行传输中的数据转换。AWS Glue提供了一个绝佳的示例,我们将通过一个具体的架构图来理解其工作原理。


上一节我们介绍了数据转换的概念,本节中我们来看看AWS Glue如何实现一个无服务器的ETL(提取、转换、加载)流程。

首先,整个流程由一个定时器触发一个Glue作业。AWS Glue是一个无服务器的ETL系统。这意味着你可以将其指向多个数据源。

以下是Glue处理数据的基本步骤:

  1. 提取:从指定的数据源(如S3中的大型CSV文件或外部PostgreSQL数据库)读取数据。
  2. 转换:根据定义的业务逻辑对数据进行清洗、整合与转换。
  3. 加载:将处理后的数据输出到另一个目标位置,例如一个新的S3存储桶。

这样,你就创建了一个可重用的ETL操作。由于外部数据源(如供应商更新的数据库)可能持续变化,这个定期触发的作业会不断生成数据的新版本,并将其放入新的存储桶中。


此外,Glue还有一个非常实用的功能:它可以为处理后的数据创建数据目录和元数据记录。

这意味着,之后你的数据科学家无需将S3中的所有数据都下载出来,就可以直接使用Athena查询这个目录。他们可以运行无服务器查询,进行数据可视化和初步分析,其组合公式可以表示为:

数据分析 = Athena查询 + Glue数据目录

这种由Glue在你的生态系统内部提供的无服务器能力带来了很多好处。我们刚才探讨的这种特定架构是一个非常常见且适用的模式,对于许多组织来说,它既易于理解也便于维护。


本节课中我们一起学习了AWS Glue在传输中进行数据转换的核心机制。我们了解了其如何通过定时触发、无服务器ETL作业来处理多源数据,并利用数据目录功能使处理后的数据易于查询与分析。这种架构模式结合了Glue与Athena,为组织提供了一种高效、可维护的数据处理解决方案。

034:AWS Batch 入门教程 🚀

在本节课中,我们将学习如何使用 AWS Batch 服务在云端运行计算任务。AWS Batch 是一个用于解决基本云端运行问题的优秀技术。我们将通过一个简单的“Hello World”示例,逐步了解其核心组件和配置流程。

概述

AWS Batch 服务允许您轻松地在 AWS 云上运行批处理作业,而无需管理底层基础设施。其架构清晰,包含计算环境、作业队列、作业定义和作业本身。接下来,我们将通过实际操作演示如何配置并运行您的第一个 AWS Batch 作业。

核心组件与配置流程

上一节我们介绍了 AWS Batch 的基本概念,本节中我们来看看其具体的配置步骤。整个过程通过一个向导完成,步骤简洁明了。

以下是配置 AWS Batch 作业的主要步骤:

  1. 创建计算环境:这是运行作业的基础设施。您可以选择在 Fargate 上运行(无需管理服务器),或使用虚拟机(按需或 Spot 实例)。对于 Fargate,您还可以选择 Fargate Spot 以获得高达 70% 的折扣,这对于运行大量作业非常划算。在虚拟机模式下,您可以调整所需的虚拟 CPU 数量,并指定作业运行的 VPC 网络。

  2. 创建作业队列:作业队列用于存放等待处理的任务。您可以创建多个队列来管理不同优先级或类型的作业。

  3. 创建作业定义:作业定义是作业的蓝图,它指定了运行作业所需的容器镜像、命令、CPU 和内存资源等。您可以在此处使用自定义镜像,例如包含特定库(如 Hugging Face 库)的镜像。作业启动时执行的命令也在这里定义。

  4. 创建并提交作业:最后,基于已定义的作业定义,向指定的作业队列提交一个具体的作业实例并运行它。

详细配置说明

现在,让我们深入了解每个配置环节的细节。

计算环境配置

在配置计算环境时,您需要做出几个关键选择。首先是选择运行平台:FargateEC2(虚拟机)。

  • Fargate:这是一个无服务器选项,AWS 会为您管理所有后端服务器。这大大简化了运维工作。
  • Fargate Spot:在 Fargate 基础上,使用闲置容量,成本更低,适合可中断的任务。
  • EC2:提供对底层虚拟机的更多控制,可以选择按需实例或更便宜的 Spot 实例。在此模式下,您可以精确指定虚拟 CPU 的数量和作业运行的 VPC 网络。

作业定义配置

作业定义是核心配置部分,它告诉 AWS Batch 如何运行您的任务。

  • 容器镜像:您需要指定一个 Docker 镜像。可以使用公共镜像,但更常见的做法是构建并推送自己的自定义镜像,其中包含任务所需的所有依赖项(例如,特定的 Python 库)。
  • 执行命令:这是容器启动后运行的命令。例如,一个简单的 echo “Hello World” && date 命令。您也可以通过编写代码来动态插入命令。
  • 资源分配:您需要为容器预留一定数量的虚拟 CPU 和内存。
  • 高级配置:您还可以进行更高级的配置,例如挂载存储卷、配置日志记录选项等,这些功能使得 AWS Batch 能够处理复杂的容器化任务。

运行示例作业

遵循上述步骤完成配置后,向导会汇总所有信息。确认无误后,即可提交并运行作业。系统会处理作业的调度、执行,并在完成后提供结果信息。

总结

本节课中我们一起学习了 AWS Batch 服务。我们了解了其用于在云端运行批处理作业的简洁架构,包括计算环境、作业队列、作业定义和作业。通过一个分步演示,我们掌握了如何配置这些组件,特别是如何选择计算环境类型(Fargate 或 EC2)以及如何定义作业的容器镜像和启动命令。AWS Batch 提供了一种直接且有用的方式,让初学者也能轻松开始在云端运行计算任务。

035:AWS无服务器数据工程管道 🚀

在本节课中,我们将学习如何在AWS平台上使用无服务器技术快速构建一个数据工程管道。我们将通过一个具体的例子,了解如何利用AWS的各项服务,从数据读取、处理到最终存储和可视化的完整流程。


在AWS平台上快速开发应用程序的一个强大方法是使用无服务器技术。

例如,在这个场景中,我们有一个无服务器数据工程管道,它能非常快速地完成多种不同的任务。

上一节我们介绍了无服务器技术的概念,本节中我们来看看这个管道的具体构成。

以下是该数据管道的核心流程:

  1. 流程始于一个CloudWatch定时器。它触发从DynamoDB表中读取数据的操作。
  2. DynamoDB表是一个键值存储,其中包含关于警察、警察局以及不同执法相关的元数据信息。
  3. 读取的数据随后被放入一个SQS(简单队列服务)系统中。
  4. 一旦数据进入SQS,它会自动触发一个Lambda函数。
  5. 该Lambda函数使用AWS的Comprehend服务(一项情感分析API)来处理来自这些报告的信息。
  6. 处理后的数据最终被放入S3存储桶中,之后可以用于可视化或生成报告,例如一份关于美国各地社区与警察部门互动情况的季度报告。

现在,让我们详细查看一下其中的代码实现。

以下是Lambda函数处理数据的一个示例代码片段:

import boto3
import uuid

# 创建DynamoDB资源客户端
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('YourTableName')

def lambda_handler(event, context):
    # 生成全局唯一ID
    unique_id = str(uuid.uuid4())
    
    # 从数据库获取一条记录(示例)
    response = table.get_item(Key={'id': 'some_id'})
    item = response.get('Item')
    
    # 动态添加额外的元数据
    if item:
        item['region'] = 'Northeast'  # 添加区域属性
        item['interaction_type'] = 'Community Outreach'  # 添加互动类型
        # 可以根据需要添加更多属性,如部门、时间戳等
    
    # 后续可以将处理后的item发送到SQS或进行其他处理
    # ... (此处省略了发送到SQS或调用Comprehend的代码)
    
    return {
        'statusCode': 200,
        'body': 'Processing complete'
    }

在这段代码中,你会创建一个全局唯一ID,并从数据库中获取一条记录。然后,你可以动态地为其分配额外的元数据。

例如,如果你想添加关于特定区域、特定部门或互动类型的属性,所有这些都可以在运行时完成,因为它是一个无模式数据库。

因此,利用无服务器技术快速移动的能力,加上无模式数据库的特性,创造了像这个AI数据工程管道这样的新可能性。


本节课中我们一起学习了如何利用AWS的无服务器服务(如CloudWatch、DynamoDB、SQS、Lambda、Comprehend和S3)构建一个高效、可扩展的数据处理管道。这种架构避免了管理服务器的复杂性,允许开发者专注于业务逻辑,并能根据需求自动扩展,是实现快速数据工程和机器学习的强大模式。

036:从零构建Python函数 🚀

在本课程中,我们将学习如何从零开始构建一个Python函数,并将其逐步发展为一个完整的、可部署的微服务。我们将涵盖从基础语句、项目结构、命令行工具到容器化和云端部署的完整流程。


1:从零开始:Python基础语句与环境搭建 🏁

上一节我们介绍了课程目标,本节中我们来看看如何搭建开发环境并编写最基础的Python语句。

概述

我们将从最基础的“Hello World”开始,学习Python的核心语句、变量和数据结构,并搭建一个交互式的开发环境。

搭建开发环境

首先,创建一个GitHub仓库来管理我们的代码。推荐使用基于浏览器的开发环境,如Google Colab或GitHub Codespaces,它们提供了交互式学习和软件工程开发两种模式。

  • Colab/Jupyter Notebook:适合交互式学习和记笔记,像处理文档一样处理代码。
  • GitHub Codespaces/VS Code:适合构建结构化的软件工程项目。

编写基础语句

以下是Python中最核心的几个概念:

  1. 打印语句:使用 print() 函数输出信息。

    print("Hello World")
    
  2. 变量:用于存储数据。

    x = 1
    y = 2
    print(x + y)  # 输出:3
    

  1. 数据结构 - 列表:用于存储一系列有序的元素。
    my_list = [1, 2, 3]
    print(my_list[0])  # 输出:1 (索引从0开始)
    

  1. 数据结构 - 字典:用于存储键值对,是Python中最灵活的数据结构之一。

    my_dict = {1: "one", 2: "two"}
    print(my_dict.keys())   # 输出:dict_keys([1, 2])
    print(my_dict.values()) # 输出:dict_values(['one', 'two'])
    
  2. 循环控制:用于遍历数据结构中的元素。

    # 遍历字典
    for key, value in my_dict.items():
        print(f"This is my key: {key}")
        print(f"This is my value: {value}")
    
    # 遍历列表
    for item in my_list:
        print(f"This is the value in the list: {item}")
    

总结:掌握了打印、变量、列表、字典和循环,你就拥有了用Python进行基础编程和数据处理的能力。这是构建更复杂功能(如函数)的基石。


2:构建项目:从脚本到可测试的工程结构 🏗️

上一节我们学习了基础语句,本节中我们来看看如何将这些代码组织成一个结构化的、可测试的软件工程项目。

概述

我们将学习如何将零散的脚本转化为一个拥有标准目录结构、自动化测试和代码质量检查的专业项目。

创建Python脚本

首先,将代码写入 .py 文件,形成可执行的脚本。

  • hello.py:一个简单的Hello World脚本。

    print("Hello World")
    

    运行方式:python hello.py

  • my_statements.py:一个更复杂的脚本,包含列表、字典和循环。

    my_list = ["apple", "cherry", "lemon"]
    my_dict = {"drink": "coffee", "milk": "whole milk"}
    
    for item in my_list:
        print(f"My favorite thing to eat is {item}")
    
    for _, value in my_dict.items():
        print(f"My favorite thing to drink is {value}")
    

搭建项目脚手架

为了确保代码的可重复性和可维护性,需要为项目创建标准结构。以下是三个核心文件:

  1. Makefile:用于定义常用的自动化命令(如安装、测试、代码检查)。
    install:
        pip install --upgrade pip
        pip install -r requirements.txt
    
    lint:
        pylint --disable=C0114,C0116 *.py
    
    test:
        python -m pytest -v
    
    all: install lint test
    
    运行命令示例make all 会依次执行安装、代码检查和测试。

  1. requirements.txt:列出项目依赖的第三方库。
    pylint
    pytest
    black
    

  1. 测试文件:用于编写单元测试,确保代码逻辑正确。
    • test_hello.py:测试 hello.py 中的函数。
      from hello import add
      
      def test_add():
          assert 2 == add(1, 1)
      

使用虚拟环境

为了避免不同项目间的依赖冲突,强烈建议使用Python虚拟环境。

# 创建虚拟环境
python3 -m venv .venv
# 激活虚拟环境 (Linux/Mac)
source .venv/bin/activate
# 激活后,安装的包将仅限于此项目

集成持续集成

使用GitHub Actions可以自动化运行测试和代码检查。每次代码推送后,GitHub会自动运行 make all 命令,并通过状态徽章直观展示项目健康度。

总结:通过创建 Makefilerequirements.txt 和测试文件,我们建立了一个专业的项目结构。这就像为代码建立了“退休账户”,现在的投入(编写测试和配置)将在未来长期受益,使协作、维护和部署变得异常轻松。


3:核心构建块:深入理解Python函数 ⚙️

上一节我们建立了项目结构,本节中我们来看看Python编程的核心——函数。

概述

函数是Python中最重要的构建块。理解函数是将代码逻辑模块化、实现代码复用和构建复杂应用(如命令行工具、Web服务)的关键。

函数的多种形式

函数可以有多种形式,从简单到复杂:

  1. 最简单的函数:什么都不做。
    def simple():
        pass
    

  1. 无参数函数:执行一些操作,但不返回数据。

    def simple2():
        print("simple")
    simple2()  # 调用函数
    
  2. 最实用的函数模式:接收输入,进行处理,并返回输出。这是构建更高级应用的基础模式。

    def worker(fruit):
        statement = f"My favorite meal is chicken and {fruit}"
        meals = {"dinner": statement}
        return meals
    
    def human(food):
        consume = food["dinner"]
        return consume
    
    # 使用函数
    meal = worker("apple")
    print(f"I want my meal, it will be {human(meal)}")
    

    模式解析

    • worker 函数接收参数,处理业务逻辑,将结果放入数据结构(字典)并返回。
    • human 函数接收 worker 的返回结果,进行进一步处理。
    • 这种“输入-处理-输出”并传递给下一个函数的模式,在构建命令行工具、Web API和数据处理流水线时极为常见。

构建一个实际函数:维基百科摘要抓取器

让我们构建一个更有用的函数,它调用维基百科API获取页面摘要。

  1. 添加依赖:在 requirements.txt 中加入 wikipedia 库并安装 (make install)。
  2. 探索API:使用 ipython 交互环境快速了解库的用法。
    import wikipedia
    print(wikipedia.summary("Microsoft", sentences=1))
    
  3. 编写函数:创建 wikibot.py,将逻辑封装成函数。
    import wikipedia
    
    def scrape(name="Microsoft", length=1):
        """从维基百科抓取摘要"""
        result = wikipedia.summary(name, sentences=length)
        return result
    
    if __name__ == "__main__":
        # 当直接运行脚本时执行
        print(scrape("Facebook"))
    
  4. 为函数编写测试:创建 test_wikibot.py 确保函数逻辑正确。
    from wikibot import scrape
    
    def test_scrape():
        result = scrape("Microsoft")
        assert "Microsoft" in result
    

总结:函数是封装逻辑、实现代码复用的单元。掌握“接收参数-处理-返回结果”这一核心模式,是构建命令行工具、Web服务乃至机器学习流水线的第一步。我们已将维基百科抓取逻辑成功封装为一个可测试的函数。


4:功能扩展:将函数转化为命令行工具 🛠️

上一节我们创建了可复用的函数,本节中我们来看看如何为其添加命令行界面,使其成为易用的工具。

概述

我们将使用两个流行的库——ClickFire,为我们的函数快速创建功能强大且用户友好的命令行界面。

使用 Click 创建命令行工具

Click 库通过装饰器让定义命令行参数变得非常简单。

  1. 安装依赖:将 click 加入 requirements.txt 并安装。
  2. 改造 wikibot.py:添加Click命令行接口。
    import click
    import wikipedia
    
    def scrape(name, length):
        result = wikipedia.summary(name, sentences=length)
        return result
    
    @click.command()
    @click.option("--name", prompt="Wikipedia page to scrape", help="The web page we want to scrape.")
    @click.option("--length", default=1, help="Length of the output from Wikipedia.")
    def cli(name, length):
        """一个简单的维基百科摘要抓取工具"""
        result = scrape(name, length)
        click.echo(click.style(result, fg="green"))  # 用绿色输出结果
    
    if __name__ == "__main__":
        cli()
    
  3. 使用工具
    # 查看帮助
    python wikibot.py --help
    # 运行工具
    python wikibot.py --name Microsoft --length 2
    

使用 Fire 自动生成命令行工具

Fire 库是Google开发的,可以自动将任何Python对象(函数、类等)转化为CLI,几乎无需额外代码。

  1. 安装依赖:将 fire 加入 requirements.txt
  2. 创建 fire_cli.py
    import fire
    from my_lib.bot import scrape  # 从我们的库中导入函数
    
    if __name__ == "__main__":
        fire.Fire(scrape)  # 关键的一行:让Fire接管scrape函数
    
  3. 使用工具
    # 自动生成帮助信息
    python fire_cli.py --help
    # 运行工具
    python fire_cli.py --name Microsoft --length 1
    
    Fire 会自动解析 scrape 函数的参数 (name, length) 并将其转化为命令行选项。

为命令行工具添加测试

使用 click.testing 可以为Click应用编写自动化测试。

from click.testing import CliRunner
from wikibot import cli

def test_cli():
    runner = CliRunner()
    result = runner.invoke(cli, ["--name", "Microsoft"])
    assert result.exit_code == 0
    assert "Microsoft" in result.output

总结:通过 ClickFire,我们可以轻松地将一个纯Python函数转化为功能完整的命令行工具。Click 提供了更多自定义和控制选项,而 Fire 则以极简的代码实现了自动化CLI生成。这极大地提升了函数的可用性和可交互性。


5:服务化:将函数部署为Web微服务 🌐

上一节我们创建了命令行工具,本节中我们来看看如何将同样的函数逻辑包装成一个可通过HTTP访问的Web API。

概述

我们将使用 FastAPI 框架快速构建一个RESTful API,它能够提供与命令行工具相同的功能,并通过Swagger UI自动生成交互式文档。

构建FastAPI应用

  1. 安装依赖:将 fastapi, uvicorn, pydantic 加入 requirements.txt 并安装。
  2. 创建主应用文件 main.py
    from fastapi import FastAPI
    from pydantic import BaseModel
    from my_lib.bot import scrape  # 导入我们自己的函数
    
    # 定义请求体的数据模型
    class Wiki(BaseModel):
        name: str
    
    # 创建FastAPI实例
    app = FastAPI()
    
    # 定义一个根路径端点,用于健康检查
    @app.get("/")
    def read_root():
        return {"Hello": "Functions"}
    
    # 定义核心的API端点
    @app.post("/wiki/")
    def scrape_story(wiki: Wiki):
        """接收一个包含页面名称的JSON,返回维基百科摘要"""
        result = scrape(wiki.name)
        payload = {"wiki_page": wiki.name, "scraped_result": result}
        return payload
    
  3. 运行服务
    uvicorn main:app --reload --host 0.0.0.0 --port 8080
    
    • main:app:指定应用对象。
    • --reload:开发模式,代码修改后自动重启。
    • --host 0.0.0.0:允许外部访问。
    • --port 8080:指定服务端口。

测试API

启动服务后,打开浏览器访问:

  • http://localhost:8080/:返回 {"Hello": "Functions"}
  • http://localhost:8080/docs:自动生成的Swagger交互式文档。你可以在这里直接测试 /wiki/ 端点,无需编写任何客户端代码。

使用cURL测试API

也可以通过命令行工具如 cURL 进行测试:

curl -X POST "http://localhost:8080/wiki/" \
     -H "Content-Type: application/json" \
     -d '{"name":"Microsoft"}'

总结:使用 FastAPI,我们只需极少的代码就将一个本地函数变成了一个可通过网络调用的Web服务。自动生成的API文档极大地简化了前后端协作。现在,我们的函数逻辑可以通过命令行和HTTP两种方式被调用,适用性大大增强。


6:容器化与部署:迈向生产环境 🐳

上一节我们创建了Web服务,本节中我们来看看如何将其打包成容器,并部署到云平台,实现持续交付。

概述

容器化将应用及其所有依赖打包成一个标准单元,确保环境一致性。我们将使用Docker构建镜像,并部署到AWS的托管服务上。

使用Docker容器化应用

  1. 创建 Dockerfile
    # 使用轻量级的Python镜像
    FROM python:3.9-slim
    # 设置工作目录
    WORKDIR /app
    # 复制依赖文件并安装
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    # 复制应用代码和自定义库
    COPY main.py .
    COPY my_lib ./my_lib
    # 声明容器运行时暴露的端口
    EXPOSE 8080
    # 启动命令
    CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
    
  2. 构建Docker镜像
    docker build -t wiki-service .
    
  3. 本地运行容器
    docker run -p 8080:8080 wiki-service
    
    访问 http://localhost:8080/docs 确认服务在容器内运行正常。

推送到容器仓库

为了在云上部署,需要将镜像推送到一个容器仓库(如AWS ECR)。

  1. 在AWS ECR控制台创建一个新的仓库(例如 wiki-repo)。
  2. 按照ECR提供的指引,在本地终端执行登录、打标签和推送命令:
    # 1. 登录到ECR
    aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com
    # 2. 为本地镜像打上ECR仓库的标签
    docker tag wiki-service:latest <account-id>.dkr.ecr.<region>.amazonaws.com/wiki-repo:latest
    # 3. 推送镜像到ECR
    docker push <account-id>.dkr.ecr.<region>.amazonaws.com/wiki-repo:latest
    

部署到AWS App Runner

AWS App Runner是一项完全托管的服务,可以自动从容器仓库部署Web服务。

  1. 在App Runner控制台点击“创建服务”。
  2. 选择“容器仓库”,并浏览选择我们刚刚推送的 wiki-repo 镜像。
  3. 配置服务名称(如 function-as-a-service),其他设置可保持默认。
  4. 点击“创建并部署”。App Runner会自动完成以下步骤:
    • 从ECR拉取镜像。
    • 配置网络和负载均衡。
    • 运行健康检查。
    • 提供一个可访问的HTTPS端点。

部署完成后,App Runner会提供一个URL(如 https://xxx.us-east-1.awsapprunner.com)。访问此URL的 /docs 路径,即可使用运行在AWS云上的微服务。更重要的是,App Runner设置了自动部署流水线,以后每次向ECR推送新的镜像标签,服务都会自动更新。

总结:通过Docker容器化和AWS App Runner,我们实现了从代码到生产部署的自动化流水线。这个过程展示了现代软件交付的核心:一次构建,随处运行。我们从一个简单的Python函数开始,最终获得了一个高可用、可自动扩展、持续交付的云原生微服务。


课程总结 🎉

在本课程中,我们一起完成了一次完整的Python函数演进之旅:

  1. 奠基:从“Hello World”和基础数据结构开始,掌握了Python的核心语法。
  2. 工程化:建立了标准的项目结构,引入了代码检查、格式化、单元测试和持续集成,使项目变得专业且可靠。
  3. 抽象核心:深入理解了函数作为代码构建块的重要性,并封装了可重用的业务逻辑。
  4. 多样化接口:为同一个函数逻辑添加了命令行界面(使用Click和Fire),大大提升了工具的易用性。
  5. 服务化:使用FastAPI将函数快速转变为拥有自动文档的Web API,使其可通过网络调用。
  6. 产品化:通过Docker容器化应用,并利用AWS ECR和App Runner将其部署到云端,实现了完整的持续交付流水线。

这条学习路径的核心思想是:从简单开始,迭代演进。你不需要一开始就设计一个庞大的系统。从一个能工作的简单函数出发,逐步添加项目结构、测试、不同的接口和部署策略,最终就能构建出健壮、可维护的生产级应用。希望本教程为你提供了从“写代码”到“交付产品”的清晰路线图。

037:使用Python Fire构建NLP项目

在本节课中,我们将学习如何通过构建函数化的逻辑,并使用Python Fire库将其快速转化为命令行工具,从而创建一个完整的自然语言处理项目。我们将涵盖从逻辑设计、库构建、工具封装到自动化测试和持续集成的全过程。

从函数化逻辑开始

上一节我们介绍了项目构建的基本思想。本节中,我们来看看如何将核心逻辑封装在函数中。

将逻辑封装在函数中的核心思想是:我们需要将处理逻辑放在函数内部。这样,一段包含特定逻辑的代码可以被映射到多种不同的应用场景中。

我认为一个很好的例子是进行自然语言处理。因此,这里的逻辑将是NLP处理。一旦我们拥有了这个逻辑,我们可以将其映射到多种形式。

以下是几种主要的映射方式:

  • 映射到命令行工具。这可能是最简单的方式之一。
  • 映射到iPython交互式环境。
  • 映射到Web框架。
  • 如果需要,还可以将该逻辑映射到AWS或GCP等云平台的云函数中。

这就是我们接下来要搭建的项目基本框架。

搭建项目结构

接下来,我将回到Github Codespaces,开始构建一个项目结构。

首先,我需要导入一个名为TextBlob的库。这是一个用于简化文本处理的库,非常适合用来构建演示项目。

以下是一个使用TextBlob的示例。让我们导入这个库。

我将把textblob添加到requirements.txt文件中。由于我已经通过Makefile设置了项目结构,安装变得非常简单。我只需要运行make install命令。

现在安装完成了。测试它也很容易,因为我还有iPython环境。如果我想尝试一个想法,可以参考文档,然后直接在iPython中测试。

例如,我可以这样做:

from textblob import TextBlob

现在我需要创建一些文本。让我们用一种高效且富有创意的方式来解决这个问题:使用一个名为wikipedia的库来自动抓取文本。这样我们就不需要手动输入任何内容。

我先运行make install来安装wikipedia库。然后,我们获取一些文本并了解如何构建文本。

在iPython中:

import wikipedia

我们可以使用wikipedia.summary函数。让我们搜索“Golden State Warriors”。

golden_state_warriors_text = wikipedia.summary("Golden State Warriors")

这样我们就获得了一些可以免费使用的文本。现在,我们可以用TextBlob来处理它。

回到文档,我们创建一个TextBlob对象:

blob = TextBlob(golden_state_warriors_text)

现在,blob对象有许多可用的方法,包括情感分析:

blob.sentiment

我们还可以获取词性标签:

blob.tags

哦,它提示我们需要下载语料库。这没问题,我们可以把它也加入到Makefile中,使其更容易执行。在iPython中,我们可以使用感叹号来运行任何shell命令。

现在再次运行blob.tags,看,它成功了。它能够自动为我们抓取一堆标签,这真的很棒。

还能做什么呢?可以提取名词短语:

blob.noun_phrases

它能够从文本中提取出许多不同的短语。这是一个很酷的小库。

构建可复用的逻辑库

我已经有了一些可以工作的东西,现在让我们构建处理所有这些事情的逻辑。为此,我首先创建一个库。如果你开始构建一些可复用的东西,构建一个库总是一个好主意。

首先创建一个名为nlp_logic的目录,然后在里面创建一个空文件__init__.py,这告诉Python这是一个包。

现在我们可以开始在里面构建代码了。创建一个文件叫core_nlp.py

我可以开始构建内容了。我们可以回到iPython,并“窃取”一些我们已经尝试过的想法。例如,我们导入了TextBlobwikipedia,使用了noun_phrases等方法。

我们可以构建几个函数。

第一步,创建一个函数来获取维基百科摘要文本。我们可以构建三个函数。

第一个函数,我们称之为search_wikipedia,它接收一个名称参数,并返回wikipedia.search(name)的结果。我们可以在里面添加一点调试逻辑。

第二个函数,summarize_wikipedia,也接收名称参数。它的逻辑是打印“Finding summary for {name}”,然后返回wikipedia.summary(name)

第三个函数,get_text_blob,接收文本参数,返回一个TextBlob对象。这样我们可以用它做很多事情。

最后,我们可以构建一个整合一切的主函数get_phrases。它接收名称参数,封装了所有操作。它的逻辑是:首先获取摘要文本,然后创建TextBlob对象,最后返回名词短语列表。

这样我们就得到了一些不错的逻辑,允许我们做各种有趣的事情。

在iPython中交互式测试

iPython的酷之处在于,它允许我们在深入构建实际应用之前,先玩转所有这些代码。这就是函数化编程的力量。

我要做的是从我们的库中导入模块:

from nlp_logic import core_nlp

理论上,我现在只需要将“Golden State Warriors”传入get_phrases函数,它就会一次性包装所有操作。

但这里我遇到了一个拼写错误和一个小bug。通过iPython,我可以一步一步地调试,重现函数内部的逻辑,直到找到问题所在。

最终,我成功运行了:

from nlp_logic.core_nlp import get_phrases
phrases = get_phrases("Golden State Warriors")

在我看来,这种首先使用iPython完全在函数中构建逻辑的编码方式非常强大,因为一些棘手的细节和bug在玩转iPython的过程中就已经被解决了,而且我现在对我写的代码非常熟悉。

使用Python Fire构建命令行工具

现在我可以构建一个工具了。首先要构建的是一个命令行工具。同样,我需要使用一个库。事实上,构建命令行工具最简单的方法可能就是使用Python Fire。

Python Fire是一个来自Google的库,用于创建命令行工具,其简单程度令人惊讶。

你需要做的就是import fire,然后构建命令行工具。基本上,你只需要几行代码。

我创建一个新文件wiki_phrases.py。我想导入之前构建的逻辑,也就是core_nlp库中的get_phrases函数,它为我们完成了所有工作。

接下来,关于Python Fire令人惊叹的一点是:我甚至不需要在里面放太多代码。我基本上只需要导入逻辑和fire,然后调用fire.Fire(get_phrases)。这可能是世界上最简单的命令行工具了。

我还需要添加shebang行并将其设为可执行的Python工具。

现在运行它。哦,我需要先安装fire,运行make install

现在,如果我运行python wiki_phrases.py --help,看,它给了我所有帮助信息。我几乎什么都没做,因为它从文档字符串中获取了信息。实际上我只添加了几行代码。

现在,我们可以这样使用它:
python wiki_phrases.py --name="Golden State Warriors"

它会去维基百科获取摘要,然后找出短语。如果你首先在函数中构建逻辑,然后使用像Python Fire这样的工具将该函数转化为命令行工具,其强大程度令人震惊。

完善项目:代码质量与自动化测试

为了让项目更专业,我们应该构建一个DevOps结构,包括代码检查、测试等。

首先,我构建一个测试文件test_core_nlp.py。为了进行测试,我需要添加一些其他库:pytestpytest-cov(用于测试覆盖率)、pylint(用于语法检查)和python-black(用于代码格式化)。这些都是我喜欢使用的库。

我要确保Makefile中包含所有这些步骤。让我们添加一个format步骤,使用black格式化所有Python文件。

运行make install获取所有库,然后运行make format。很好,它清理了我们的代码。

同样,我们运行make lint来检查代码。太好了,10分满分。

接下来我们需要构建一个测试结构。我们关心的是测试wiki_phrasesnlp_logic库。我们告诉pytest查看测试文件test_core_nlp.py

现在运行测试,它会显示没有测试或0%的覆盖率。所以我需要添加一些测试。

打开测试文件。我会导入core_nlp模块中的所有相关函数。然后,至少先创建一个测试。我们可以做一个简单的功能测试。例如,断言从get_phrases("Golden State Warriors")返回的结果中包含“Golden State”。这是一个可以接受的功能测试。

现在我们有了测试。运行make test。我们遇到了一个导入错误,因为我可能导入方式不对。修复它,然后再次运行测试。

现在,仅从这一个功能测试,我们就获得了88%的测试覆盖率。

配置持续集成

现在让我们提交代码。然后使用Github Actions来设置持续集成,这非常容易做到。

我们可以设置一个工作流。我通常有一些之前构建的Github Actions作为模板。这个Yaml文件将自动测试我们的项目。

我们需要确保构建系统测试的Python版本与我们项目中使用的版本一致。检查一下,我们使用的是Python 3.10.x,所以在工作流文件中指定3.10。

工作流将依次执行:安装依赖、代码检查、运行测试、代码格式化。

提交这个工作流文件,然后推送到仓库。在Github Actions页面,我们可以看到构建过程。它可能会因为Python具体版本号而报错,根据提示修改即可。

构建成功运行:安装依赖、代码检查、运行测试、格式化。一切顺利。

现在我们可以创建一个状态徽章,将其添加到项目的README中,让项目看起来更专业、更酷。

总结

本节课中,我们一起学习了如何从零开始构建一个完整的NLP项目。我们首先将核心NLP逻辑封装在函数中,并在iPython交互环境中进行测试和调试。接着,我们利用Python Fire库,以极少的代码将函数快速转化为功能强大的命令行工具。然后,我们通过引入pytest、pylint和black等工具,为项目添加了自动化测试、代码检查和格式化功能,提升了代码质量。最后,我们配置了Github Actions工作流,实现了项目的持续集成,确保每次代码变更都能自动通过测试和质量检查。这个过程展示了函数化设计、快速原型开发与现代DevOps实践相结合的高效工作流程。

038:扩展Google Cloud Functions 🚀

在本节课中,我们将学习如何使用Google Cloud Functions快速构建和部署无服务器函数。我们将从创建一个简单的“Hello World”函数开始,逐步深入到更复杂的示例,例如翻译维基百科页面和计算找零。通过本教程,你将掌握使用Google Cloud Functions进行快速原型设计和数据工程任务的核心技能。

创建第一个函数

首先,我们访问Google Cloud Platform并搜索“Cloud Functions”。进入服务后,点击“创建函数”。

在创建函数的对话框中,我们需要配置几个关键参数:

  • 函数名称:例如,命名为“hello”。
  • 区域:选择一个离你近的区域。
  • 触发器:选择“HTTP触发器”,这将允许我们通过URL(如使用curl或Postman)来调用函数。为了方便快速测试,我们勾选“允许未经身份验证的调用”。
  • 运行时:选择“Python 3.9”。

创建函数时,默认会使用内联代码编辑器,并提供一个简单的“Hello World”示例代码。该函数接收一个请求,并尝试解析其中的message字段,如果解析失败或未提供,则默认返回“Hello World!”。

以下是示例代码:

def hello_world(request):
    request_json = request.get_json()
    if request_json and 'message' in request_json:
        return request_json['message']
    return 'Hello World!'

配置完成后,点击“部署”。部署过程通常需要一两分钟。

测试与调用函数

函数部署完成后,我们可以对其进行测试。

在函数详情页,切换到“测试”标签页。这里,我们可以模拟一个HTTP请求来触发函数。例如,我们可以输入一个JSON负载:

{
  "message": "你好,世界"
}

点击“测试函数”后,我们会看到函数的响应结果。对于上述负载,响应应为“你好,世界”。

除了在控制台测试,我们也可以通过命令行工具gcloud来调用函数,这对于自动化脚本或CI/CD流程非常有用。命令格式如下:

gcloud functions call hello --data '{"message":"你好,世界"}'

构建复杂函数:翻译维基百科

上一节我们创建了一个基础函数,本节中我们来看看如何构建一个更实用的函数:自动翻译维基百科摘要。

我们创建一个名为“translate_wikipedia”的新函数。这个函数需要用到两个第三方库:wikipedia用于获取维基百科内容,google-cloud-translate用于调用Google翻译API。

因此,我们需要在“requirements.txt”文件中声明这些依赖:

wikipedia
google-cloud-translate

函数的Python代码主要逻辑如下:

  1. 从请求中解析出目标实体(如“Facebook”)、要获取的句子数量以及目标语言(如“Spanish”)。
  2. 使用wikipedia库获取指定实体的维基百科摘要。
  3. 使用google-cloud-translate库将摘要翻译成目标语言。
  4. 返回翻译后的文本。

部署此函数后,我们可以通过发送如下JSON负载来测试它:

{
  "entity": "Facebook",
  "sentences": 20,
  "language": "Spanish"
}

函数将返回Facebook维基百科页面前20句话的西班牙语翻译。这展示了如何快速组合不同服务(网络爬取和NLP)来构建有价值的应用。

另一个示例:找零计算器

为了进一步巩固理解,我们再构建一个函数:找零计算器。

创建一个名为“change_machine”的新函数。这个函数不需要外部库,仅使用Python标准库。其功能是:接收一个金额(美元),计算并返回需要多少枚25美分(quarter)、10美分(dime)、5美分(nickel)和1美分(penny)的硬币来凑成这个金额,并优先使用大面额硬币(贪心算法)。

以下是核心的找零计算逻辑:

def make_change(amount):
    # 将美元转换为美分
    cents = int(amount * 100)
    coins = [25, 10, 5, 1]
    result = {}
    for coin in coins:
        count, cents = divmod(cents, coin)
        if count:
            result[f‘{coin}_cents’] = count
    return result

函数主体会从请求中提取amount字段,调用make_change函数,并返回结果字典。

部署后,我们可以通过控制台或gcloud命令进行测试:

gcloud functions call change_machine --data '{"amount": 1.34}'

这将返回类似{"25_cents": 5, "10_cents": 0, "5_cents": 1, "1_cents": 4}的结果,表示1.34美元需要5个25美分、1个5美分和4个1美分。

总结

本节课中我们一起学习了Google Cloud Functions的核心用法。我们从创建一个简单的“Hello World”函数开始,学习了如何配置、部署和测试。接着,我们探索了如何构建更复杂的函数,包括集成第三方库(如翻译维基百科)和实现具体业务逻辑(如找零计算)。通过gcloud命令行工具,我们还掌握了如何以编程方式调用这些函数。Google Cloud Functions作为一种无服务器解决方案,能够让你快速将想法转化为可部署的生产服务,是进行数据工程和快速原型设计的强大工具。

039:使用 Google Cloud Functions

概述

在本节课中,我们将学习 Google Cloud Functions 的架构、创建流程以及如何测试函数。我们将通过一个简单的“Marco Polo”示例,演示如何用 Python 和 Go 语言编写并部署云函数。

Google Cloud Functions 架构简介

首先,我们来看看 Google Cloud Functions 的架构。这是理解 Google Cloud 平台计算工作原理的最佳方式之一。

第一步是事件触发器。这意味着在触发器系统内部,你可以监听诸如存储事件(例如将图像或文本文件放入存储桶)、发布/订阅消息流,或者简单的 HTTP 调用。这些事件都可以触发云函数的执行。

Google Cloud Functions 的优势在于它支持多种现代编程语言,如 Go、Python、C#、Ruby、Node.js 等,并且易于通过命令行或 HTTP 进行测试。

创建云函数

上一节我们介绍了架构,本节中我们来看看如何在 Google Cloud 控制台创建一个云函数。

首先,进入 Google Cloud Functions 界面,选择“创建云函数”。你会看到有第一代和第二代两种版本。第二代提供了更多触发器和功能,但目前仍处于初步阶段。本教程将使用第一代。

以下是创建函数的主要步骤:

  1. 为函数命名:例如,可以命名为 hello-world
  2. 选择触发器类型:对于初学者,从 HTTP 触发器开始是个好选择。你也可以配置其他触发器,如 Pub/Sub、Cloud Storage 或 Firestore。
  3. 设置身份验证:一个良好的默认设置是要求对调用进行身份验证,除非你明确要创建一个公开的 API。
  4. 选择运行时环境:接下来,选择你希望使用的编程语言。平台提供了丰富的选项,包括 .NET、Go、Java、PHP、Python、Ruby 等。我们选择 Python 3.11。
  5. 管理依赖和代码:所有语言的云函数都提供了依赖包管理功能。你只需在此处列出依赖项,平台会自动安装。代码入口点处的函数名(例如 hello_world)需要与你在第一步中指定的函数名匹配。

编写函数代码

现在,让我们编写一个比简单“Hello World”更高级一点的函数。我们将创建一个函数,它接收一个包含 name 字段的 JSON 请求体。如果 name 是“Marco”(不区分大小写),则返回“Polo”;否则返回“I don‘t know you”。

以下是 Python 版本的示例代码:

def hello_world(request):
    request_json = request.get_json()
    if request_json and 'name' in request_json:
        name = request_json['name']
        if name.lower() == 'marco':
            return 'Polo'
        else:
            return "I don't know you"
    else:
        return 'Please provide a name in the JSON payload.'

编写完代码后,点击“部署”按钮即可发布函数。

测试云函数

部署完成后,我们可以测试函数。进入函数详情页,选择“测试”标签页。

平台提供了两种测试方式:

  1. 在界面内直接测试:你可以在提供的文本框中输入 JSON 负载进行测试。例如,输入 {"name": "Marco"},点击“测试函数”,应返回“Polo”。输入 {"name": "Bob"},则应返回“I don‘t know you”。
  2. 在 Cloud Shell 中测试:你也可以选择在 Cloud Shell 中使用 curl 命令进行测试,平台会生成相应的命令供你使用。

使用 Go 语言示例

为了展示多语言支持,我们再看一个 Go 语言的相同功能实现。

以下是 Go 版本的示例代码:

package p

import (
    "encoding/json"
    "fmt"
    "net/http"
)

// NameStruct 定义了期望的JSON结构
type NameStruct struct {
    Name string `json:"name"`
}

// HelloWorld 是云函数的入口点
func HelloWorld(w http.ResponseWriter, r *http.Request) {
    var d NameStruct

    if err := json.NewDecoder(r.Body).Decode(&d); err != nil {
        fmt.Fprint(w, "Error decoding JSON")
        return
    }

    if d.Name == "Marco" {
        fmt.Fprint(w, "Polo")
    } else {
        fmt.Fprint(w, "I need another name")
    }
}

测试过程与 Python 版本类似。在测试界面输入 {"name": "Marco"},函数将返回“Polo”。

其他功能与管理

除了编写和测试,Google Cloud Functions 控制台还提供了其他实用功能:

  • 监控指标:你可以查看每秒调用次数等指标。
  • 编辑与重新部署:如需修改代码,可以点击“编辑”,调整后重新部署即可。
  • 查看日志:日志页面对于调试和查看函数调用历史非常有帮助。

这构成了一个完整的、基于事件的轻量级计算环境。

总结

本节课中,我们一起学习了 Google Cloud Functions 的核心概念。我们了解了其基于事件触发的架构,逐步完成了创建、编写(使用 Python 和 Go)、部署和测试一个云函数的全过程。我们还看到了平台提供的监控、日志和编辑等管理功能。Google Cloud Functions 提供了一个支持多语言、易于测试的完整无服务器计算环境。

040:使用GitHub Actions部署Rust Azure函数 🚀

在本节课中,我们将学习如何使用GitHub Actions自动化部署一个用Rust编写的Azure函数。我们将涵盖从创建Azure函数应用、配置Rust项目,到设置GitHub Actions工作流进行自动化构建和部署的完整流程。


创建Azure函数应用

上一节我们介绍了课程背景,本节中我们来看看如何开始创建Azure函数应用。

首先,需要登录到Azure门户。在门户中,可以搜索或直接选择“函数应用”来创建新资源。

以下是创建新函数应用的步骤列表:

  1. 选择正确的订阅。
  2. 创建或选择一个资源组。建议创建一个名称有意义的新资源组,例如 demo-rust-func
  3. 为函数应用命名。此名称在 azurewebsites.net 域中必须是全局唯一的。
  4. 在“运行时堆栈”中选择“自定义处理程序”,因为Rust没有Azure函数的原生支持。
  5. 选择“Linux”作为操作系统。
  6. 选择“消费(无服务器)”作为托管计划,这是默认且经济的选项。
  7. 最后,检查所有配置并点击“创建”。

部署过程需要一些时间来完成初始化。


配置Rust Azure函数项目

创建好函数应用容器后,我们需要准备实际的函数代码。虽然可以通过Visual Studio Code的Azure Functions扩展生成项目文件,但这里我们直接查看一个已生成的项目结构。

一个典型的Rust Azure函数项目包含以下关键文件:

  • host.json: 函数应用的配置文件。
  • local.settings.json: 本地开发设置文件(通常不提交到仓库)。
  • Cargo.toml: Rust项目的清单文件,必须包含一个关键配置。

Cargo.toml 文件中,必须添加以下构建目标配置,以确保编译出的二进制文件能在Azure Functions环境中运行:

[package]
name = "your_function_name"

[[bin]]
name = "handler"
path = "src/main.rs"

# 关键配置:指定目标平台
[target.x86_64-unknown-linux-musl]

设置GitHub Actions工作流

现在,我们将配置GitHub Actions来自动化构建和部署流程。工作流定义在一个YAML文件中(例如 .github/workflows/deploy.yml)。

工作流的核心步骤如下:

  1. 安装Rust和musl工具链:这是编译适用于Linux环境的静态链接二进制文件所必需的。
  2. 添加目标平台:执行 rustup target add x86_64-unknown-linux-musl
  3. 构建Release版本:使用指定的musl目标进行编译:cargo build --release --target x86_64-unknown-linux-musl
  4. 复制处理程序二进制文件:将编译好的二进制文件复制到项目根目录,因为 host.json 中配置的 executablePath 指向它。
  5. 登录Azure:使用Azure凭据进行身份验证。
  6. 部署到Azure Functions:使用 Azure/functions-action 等官方Action完成部署。

为了让GitHub Actions能访问你的Azure订阅,需要创建一个服务主体(Service Principal)并将其凭据存储为仓库的Secret。


创建Azure服务主体

服务主体是自动化脚本访问Azure资源的身份凭证。可以通过Azure Cloud Shell或本地已安装的Azure CLI来创建。

运行以下命令创建服务主体:

az ad sp create-for-rbac \
  --name "github-actions-<your-unique-name>" \
  --role contributor \
  --scopes /subscriptions/<your-subscription-id>/resourceGroups/<your-resource-group-name>

命令执行后会输出一个包含 appIdpasswordtenant 等信息的JSON对象。你需要将这个完整的JSON对象保存为GitHub仓库的Secret,名称设为 AZURE_CREDENTIALS


检查Rust函数代码

我们的示例函数是一个HTTP触发器,它接收一个JSON请求,计算输入文本的哈希值并返回。

函数的主要逻辑在 src/main.rs 中,关键点包括:

  • 使用 actix-web 框架处理HTTP请求。
  • 路由被映射到 /api/tokenize 路径(Azure Functions要求API路径以 /api 开头)。
  • 函数需要绑定到由Azure运行时注入的环境变量 FUNCTIONS_CUSTOMHANDLER_PORT 指定的端口。

触发部署并验证

配置完成后,可以在GitHub仓库的“Actions”标签页中找到我们定义的工作流(例如“Demo Functions Actions”)。由于工作流中配置了 workflow_dispatch,你可以手动点击“Run workflow”按钮来触发部署。

部署完成后,回到Azure门户,在对应的函数应用中,你应该能看到名为“token”的新函数。你可以通过其提供的URL端点来测试函数。

使用 curl 命令测试部署的函数:

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"text": "Your input string here"}' \
  https://<your-function-app-name>.azurewebsites.net/api/tokenize

如果一切正常,你将收到一个计算出的哈希值作为响应。


总结

本节课中我们一起学习了使用GitHub Actions部署Rust Azure函数的完整流程。我们首先在Azure门户创建了函数应用,然后配置了Rust项目以兼容Azure环境。接着,我们设置了GitHub Actions工作流,通过自动化步骤完成代码的构建和部署,其中关键环节是创建并使用Azure服务主体进行安全认证。最后,我们触发了部署并验证了函数可以正常运行。这套流程实现了MLOps中持续集成和持续部署(CI/CD)的核心实践,能够高效、可靠地将机器学习模型或应用部署到生产环境。

041:容器化微服务 🐳

在本节课中,我们将学习如何将机器学习应用构建为容器化的微服务,并探讨其部署到主流云平台的流程。

概述

我们将介绍一个容器化机器学习微服务的架构思路。该流程始于本地开发环境,最终通过持续交付部署到云平台。

开发环境

首先,我们需要一个开发环境。这可以是安装了Bash的Linux系统。

在具体实践中,我们可以通过命令行工具与Linux Bash交互。我们也可以使用容器技术,在Linux Bash环境中运行。此外,基于云的环境也是一个选择。

以下是几种常见的开发环境选项:

  • AWS Cloud9
  • GitHub Codespaces

这些环境都适合用来构建我们的容器镜像。

部署与云平台

上一节我们介绍了开发环境,本节中我们来看看如何将构建好的容器部署到生产环境。

当容器准备就绪后,可以将其集成到云服务商的微服务框架中进行部署。这通常通过容器注册表完成,我们需要在那里注册自己的容器镜像。

随后,通过一个持续交付流程,将应用部署到云平台提供的“平台即服务”产品上。

以下是几个主流的云平台部署服务:

  • AWS App Runner:这是一个对微服务友好的框架。它允许你通过AWS CodeBuild这样的构建系统,或通过你自己的构建系统(如GitHub Actions),自动部署容器。
  • GCP Cloud Run:谷歌云提供的类似容器化部署服务。
  • Azure App Services:Azure也提供了支持容器化工作流的类似服务。

集成MLOps平台

除了直接部署,我们还可以增加一个步骤:与MLOps平台集成。

这意味着,你可以通过API调用部署模型,然后调用部署在某处的推理端点。这个部署目标会利用MLOps平台来处理你的API请求。

此外,你的微服务可能需要与实验跟踪服务交互。例如,你可以有一个内部工具,它使用实验跟踪服务,查看具有最佳指标的最新模型版本,并自动选择该模型与“平台即服务”产品进行交互。

核心优势与总结

这种工作流的关键在于,容器化技术让一切成为可能

通过将运行时环境与代码一起打包,容器使你能够实现这种高效的、基于微服务的持续交付。

如果你打算构建微服务,AWS App Runner、GCP Cloud Run和Azure App Services这三个平台是极佳的起点。

本节课中,我们一起学习了容器化机器学习微服务的完整流程:从本地或云端开发环境构建容器,到通过容器注册表和持续交付流程部署到云平台,最后探讨了与MLOps平台集成以增强模型管理能力的可能性。容器化是实现高效、可移植微服务部署的核心。

042:容器化持续交付 🚀

在本节课中,我们将学习如何利用容器技术,结合AWS Cloud9、ECR、App Runner和CodeBuild等服务,构建一个完整的容器化持续交付生态系统。


概述

上一节我们介绍了机器学习运维的基本概念。本节中,我们来看看如何将容器化与AWS平台上的服务结合,实现从代码开发到自动部署的持续交付流程。我们将通过一个简单的FastAPI微服务项目来演示整个过程。


容器化持续交付架构

让我们深入了解在AWS平台上使用容器进行持续交付的架构。

整个流程可以从AWS Cloud9开始。你可以在Cloud9中开发项目,并在本地构建容器镜像,从而建立一个快速的反馈循环。例如,你可以使用 docker build 命令进行构建。

一旦构建完成,你可以将镜像推送到Amazon ECR(弹性容器注册表)中。

镜像推送到ECR后,你可以直接将其部署到AWS App Runner服务上。

另一种更符合持续构建流程的方法是:首先对代码进行测试,然后配置AWS CodeBuild服务。CodeBuild会自动重新构建容器镜像,并将新的镜像变更推送到ECR。

在现实世界的生产环境中,构建系统(如CodeBuild)很可能是负责测试、构建项目并推送镜像到ECR的核心组件。随后,ECR中的镜像更新会自动触发App Runner进行部署。


项目实践:构建与部署

接下来,让我们动手构建并部署这个项目。

这是一个非常简单的微服务,功能是将两个数字相加。项目内部包含一个Dockerfile,这将使我们能够利用AWS上的高级服务。

首先,我们需要将代码克隆到本地。我已经配置好了SSH密钥,所以克隆过程会更快一些。

git clone <repository-url>

克隆完成后,进入项目目录。接下来,我通常会创建一个Python虚拟环境。

python -m venv ~/.venv
source ~/.venv/bin/activate

为了方便,我将激活命令添加到了我的 .bashrc 文件中,这样每次打开新终端时都会自动激活虚拟环境。

echo "source ~/.venv/bin/activate" >> ~/.bashrc

然后,安装项目所需的依赖包。

pip install -r requirements.txt

安装完成后,最好先在本地运行应用程序以确保一切正常。

python main.py

服务启动后,可以在另一个终端中使用 curl 命令进行测试。

curl "http://localhost:8000/add?x=3&y=3"

如果返回结果 6,说明本地服务运行成功。


推送镜像到Amazon ECR

现在,我们来看看如何将本地构建的容器镜像推送到Amazon ECR。

这个过程相当直接。首先,你需要在ECR控制台创建一个新的存储库。

以下是创建存储库的步骤:

  1. 进入ECR控制台。
  2. 点击“创建存储库”。
  3. 为存储库命名,例如 fastapi-cd
  4. 可以启用镜像扫描功能以检查安全漏洞。
  5. 点击“创建”。

存储库创建完成后,点击进入该仓库,查看“推送命令”。这些命令提供了从Cloud9环境进行身份验证和推送所需的所有步骤。

你需要依次执行以下命令:

  1. 使用AWS CLI进行身份验证。
  2. 在本地构建Docker镜像。
  3. 为镜像打上符合ECR仓库地址的标签。
  4. 将镜像推送到ECR。

我使用了一台配置很高的机器(16核CPU,64GB内存),这能显著加快容器构建和推送的速度。


使用AWS App Runner进行部署

将镜像成功推送到ECR后,下一步就是使用AWS App Runner来部署这个容器。

App Runner的优势在于它能直接监听ECR仓库中的特定容器镜像,并在镜像更新时自动部署新版本。

以下是部署步骤:

  1. 进入AWS App Runner控制台。
  2. 点击“创建服务”。
  3. 选择“容器注册表”作为源,并选择“私有注册表”。
  4. 浏览并选择我们刚刚创建的ECR仓库(例如 fastapi-cd)。
  5. 在部署设置中,选择“自动部署”。这样,每次向该ECR仓库推送新的镜像时,App Runner都会自动拉取并部署新版本。
  6. 为服务创建一个新的IAM角色,或使用现有角色。
  7. 配置服务名称(例如 fastapi-container)和其他设置,大部分可以保持默认。
  8. 点击“创建并部署”。

服务创建后,需要一些时间来初始化。在等待期间,我们可以探讨如何利用AWS CodeBuild将流程自动化到更高水平。


使用AWS CodeBuild实现自动化

在真实的生产环境中,下一步通常是集成AWS CodeBuild来实现完全自动化的构建和推送。

CodeBuild可以监控你的源代码仓库(如GitHub),每当代码发生变更时,自动执行预设的构建流程,并将新构建的容器镜像推送到ECR。

以下是配置CodeBuild的大致思路:

  1. 在CodeBuild控制台创建新的构建项目。
  2. 将源代码源设置为你的GitHub仓库,并进行授权。
  3. 在构建规范中,插入构建命令。这些命令与我们之前手动执行的命令类似,包括:
    • 安装依赖
    • 运行测试
    • 构建Docker镜像
    • 将镜像推送到ECR
  4. 配置构建触发器,例如在每次向主分支推送代码时自动运行。

通过这样的设置,你就建立了一个完整的持续交付流水线:代码变更 -> 自动构建与测试 -> 自动推送镜像到ECR -> 自动触发App Runner部署。


总结

本节课中,我们一起学习了如何构建一个基于容器的持续交付生态系统。

我们利用AWS Cloud9进行开发,使用Docker进行容器化,通过Amazon ECR管理容器镜像,并借助AWS App Runner实现无缝的容器部署。此外,我们还探讨了如何使用AWS CodeBuild将整个构建和推送过程自动化。

总而言之,AWS ECR + App Runner + CodeBuild 的组合为构建容器化应用的持续交付流程提供了一个强大且高效的解决方案。它结合了容器化的灵活性与云服务的自动化能力,是现代化软件部署的理想场景。

043:容器化机器学习 🐳

在本节课中,我们将学习如何将机器学习模型容器化,并利用AWS服务将其部署为可扩展的微服务。我们将通过两个具体示例,演示从构建Docker镜像到使用AWS App Runner进行持续部署的完整流程。


概述

容器化是MLOps中的关键环节,它将模型、代码和依赖项打包成一个标准化的单元,确保环境一致性并简化部署。本节我们将实践如何将两个不同的机器学习项目(一个身高体重预测模型和一个虚假新闻检测模型)容器化,并部署到云端。


容器化流程详解

上一节我们介绍了模型训练和微服务的基本概念,本节中我们来看看如何将它们打包并部署。

第一步:准备容器注册表

首先,我们需要一个地方来存储构建好的容器镜像。我们将使用AWS的弹性容器注册表。

以下是创建ECR仓库的步骤:

  1. 登录AWS管理控制台,导航到ECR服务。
  2. 点击“创建仓库”。
  3. 为第一个模型(身高体重预测)的仓库命名为 mlops-cookbook
  4. 创建完成后,ECR会提供用于推送镜像的docker push命令,复制并保存这些命令备用。

第二步:构建并测试第一个微服务

现在,我们回到Cloud9开发环境,开始构建第一个容器。

首先,我们需要登录到ECR。使用之前复制的登录命令:

aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account-id>.dkr.ecr.<region>.amazonaws.com

接着,在包含Dockerfileapp.py的项目目录中,构建Docker镜像:

docker build -t mlops-cookbook .

在推送之前,最好先在本地测试微服务是否运行正常。我们可以运行容器并进行预测:

# 运行容器
docker run -p 8080:8080 <image-id>
# 在另一个终端中,使用curl或自定义CLI工具测试端点
./utils_cli predict --host http://localhost:8080/predict --height 70

第三步:推送镜像并部署到AWS App Runner

确认本地运行无误后,我们将镜像推送到ECR仓库。

使用ECR提供的命令进行标记和推送:

docker tag mlops-cookbook:latest <account-id>.dkr.ecr.<region>.amazonaws.com/mlops-cookbook:latest
docker push <account-id>.dkr.ecr.<region>.amazonaws.com/mlops-cookbook:latest

镜像推送成功后,即可在AWS App Runner中创建服务。

  1. 在AWS控制台导航到App Runner服务。
  2. 点击“创建服务”,选择“容器注册表”作为来源。
  3. 选择我们刚刚推送镜像的ECR仓库(mlops-cookbook)。
  4. 配置服务名称、访问角色等(均可使用默认设置),并确保启用“持续部署”。这样,每当ECR中有新的镜像版本时,App Runner会自动部署更新。
  5. 创建服务后,App Runner会提供一个可访问的HTTPS端点。

第四步:构建并部署第二个复杂模型

为了展示流程的通用性,我们重复上述步骤,部署第二个项目——一个基于FastAPI的虚假新闻检测模型。

首先,为这个项目在ECR中创建另一个仓库,例如 fastapi-mlops

这个项目的Dockerfile略有不同,它使用了AWS Lambda的基础镜像,但核心步骤一致:

FROM public.ecr.aws/lambda/python:3.8
COPY ./app /var/task
COPY ./requirements.txt /var/task
RUN pip install -r requirements.txt
CMD ["app.handler"]

同样地,在项目目录中构建、标记并推送镜像:

docker build -t fastapi-mlops .
docker tag fastapi-mlops:latest <account-id>.dkr.ecr.<region>.amazonaws.com/fastapi-mlops:latest
docker push <account-id>.dkr.ecr.<region>.amazonaws.com/fastapi-mlops:latest

然后,在App Runner中创建第二个服务,指向 fastapi-mlops 仓库。部署完成后,我们可以通过其提供的Swagger UI文档页面(通常在/docs路径)来交互式地测试这个虚假新闻检测API。


核心架构与不同来源的模型

通过以上实践,我们构建了一个灵活的MLOps部署架构。其核心流程可以概括为:无论模型来自何处,最终都被封装进容器,推送到注册表,并由托管服务(如App Runner)部署为微服务

模型的来源可以多种多样,主要分为以下四种方式:

以下是不同模型来源的对比:

  • 下载预训练模型:从模型中心(如TensorFlow Hub、Hugging Face)直接下载现成模型,进行微调或不微调直接使用。这是快速启动项目的方式。
  • 使用自动化机器学习平台:利用Databricks、Amazon SageMaker、Azure ML等平台的AutoML功能自动生成模型。
  • 从零开始自行构建:这是最传统的方式,完全由数据科学家手动设计、训练和调优模型。
  • 调用第三方API端点:直接消费已有的模型服务,无需自己托管模型。这更偏向于集成而非部署。

关键点在于:一旦我们建立了从“容器注册表”到“微服务部署”的自动化流水线,那么更新模型就变得非常简单。只需要触发新的构建,将新版本的容器镜像推送到注册表,部署就会自动完成。


总结

本节课中我们一起学习了机器学习模型容器化的完整流程。我们掌握了如何将不同的ML项目打包成Docker镜像,推送到AWS ECR,并利用AWS App Runner配置持续部署,最终将模型发布为可扩展的线上API服务。这套方法的核心优势在于将模型部署流程标准化和自动化,无论模型来源如何,都能通过一致的容器化路径实现高效、可靠的运维。

044:容器化端到端机器学习 🚀

在本节课中,我们将学习如何利用容器化技术实现机器学习模型的持续交付。我们将剖析一个典型的工作流程,并解释为何容器技术非常适合传统机器学习和大语言模型。

概述 📋

容器化持续交付系统旨在减少构建和部署机器学习应用时的摩擦。通过将代码、运行时环境和模型依赖打包进容器,可以实现自动化的构建、测试和部署流程。接下来,我们将详细拆解这个工作流程中的关键组件。

工作流程详解 🔄

上一节我们介绍了容器化持续交付的概念,本节中我们来看看其具体的工作流程是如何运作的。

源代码控制

工作流程始于源代码控制系统,例如 GitHub。以下是源代码控制系统中包含的核心内容:

  • 应用代码:实现具体功能的代码,例如一个使用大语言模型的微服务。
  • Dockerfile:一个定义文件,用于精确描述运行时环境和所构建微服务的每一个方面。

代码配置完成后,会被推送到源代码控制系统中。

自动化构建

当变更被推送到源代码控制系统时,构建系统会自动触发后续流程。以下是构建系统执行的关键步骤:

  1. 链接模型:模型可以是一个存放在模型注册表或专用模型服务系统中的小模型,也可以是一个存放在对象存储等存储系统中的大语言模型。
  2. 构建容器镜像:构建系统会创建一个容器镜像,该镜像包含了调用模型所需的确切运行时环境。
  3. 推送至容器仓库:构建完成的容器镜像被推送到云平台的容器仓库中。

部署与调用

容器镜像准备就绪后,即可进行部署。GPU 服务端点会引用这个容器镜像并启动服务。以下是调用流程:

  1. 客户端(例如,在 VS Code 中使用 Hugging Face 的 StarCoder)向 GPU 服务端点发起请求。
  2. GPU 服务端点加载容器镜像,该镜像内嵌了确切的运行时环境,并包含对大语言模型存储位置的引用。
  3. 端点处理请求(例如,“编写一个将两个数字相加的 Python 函数”)并返回结果给客户端代码编辑器。

这种设计的优势在于各个组件相互独立,但在构建时又能链接在一起。运行时环境被封装在容器镜像内,模型则通过存储系统引用,从而消除了脆弱的依赖关系。

总结 🎯

本节课中我们一起学习了容器化持续交付系统如何为机器学习模型部署提供高效、可靠的解决方案。通过将代码、环境和模型依赖容器化,并结合自动化构建流程,可以实现从代码提交到服务部署的无缝衔接。这种方法不仅减少了手动配置的复杂性,也保证了环境的一致性,适用于从传统机器学习模型到现代大语言模型的各种场景。

045:构建Distroless容器 🐳

在本节课中,我们将学习如何为一个真实的Rust项目构建一个极简的Docker容器。我们将使用“Distroless”镜像技术,它能显著减小容器体积,从而加快部署速度、简化回滚流程并提升实验效率。

概述

我们将为一个Rust编写的API服务构建容器。该服务接受文本输入,并使用来自Hugging Face的预训练分词器(Tokenizer)进行处理。核心目标不是深入理解应用代码,而是掌握如何使用Distroless镜像来创建一个体积极小、仅包含运行所需必要组件的安全容器。

项目代码解析

首先,让我们浏览一下项目代码,理解其基本结构。

我们有一个通用的API函数,它接收两个字符串参数:预训练分词器的名称和需要分词的文本。函数定义如下:

fn tokenize(pretrained_model: String, text: String) -> Vec<String> {
    // ... 分词逻辑
}

在Web服务器部分,我们使用Actix-web框架。应用会绑定到所有网络接口的8000端口,并提供一个/tokens/{pretrained_model}端点来接收POST请求。请求体是一个包含text字段的JSON对象。

这些实现细节并非本节重点。我们的核心是探索如何利用Distroless来容器化这个应用。

构建Distroless容器镜像

上一节我们介绍了项目背景,本节中我们来看看构建容器的核心——Dockerfile。通过一些调整,你可以将这里的技术应用到自己的项目中。

以下是完整的Dockerfile内容及分步解析:

# 第一阶段:构建(Builder)
FROM rust:1.67-buster AS builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release

# 第二阶段:运行(Distroless)
FROM gcr.io/distroless/cc-debian11
COPY --from=builder /usr/src/app/target/release/rust-tokens-api /usr/local/bin/rust-tokenizer-api
CMD ["/usr/local/bin/rust-tokenizer-api"]

第一阶段:构建阶段

  1. 设置构建环境:我们使用rust:1.67-buster作为基础镜像,并将其命名为builder阶段。buster是Debian的版本代号。
  2. 设置工作目录与复制代码:将工作目录切换到/usr/src/app,并将项目所有文件复制进去。
  3. 编译项目:执行cargo build --release命令来生成优化的可执行文件。

到目前为止,这些步骤与常规的Docker镜像构建流程一致。

第二阶段:运行阶段(Distroless魔法)

这里是实现容器精简的关键,仅用三行代码完成。

  1. 使用Distroless基础镜像:我们使用gcr.io/distroless/cc-debian11作为运行环境。这个镜像来自Google容器仓库,它只包含运行C/C++/Rust等编译型语言程序所必需的最少库文件,没有shell、包管理器等任何多余工具。
  2. 复制可执行文件:从之前的builder阶段中,将编译好的二进制文件rust-tokens-api复制到Distroless镜像的/usr/local/bin/路径下,并重命名为rust-tokenizer-api
  3. 设置启动命令:指定容器启动时运行的命令就是刚才复制的二进制文件。

Rust的优势在此凸显:它能编译成独立的静态二进制文件,不依赖复杂的系统环境,因此可以轻松放入极简的Distroless镜像中运行。

构建与运行容器

现在,让我们在终端中实际构建并运行这个容器。

首先,执行构建命令。这可能需要几分钟时间,具体取决于你的网络速度。

docker build -t rust-local-distroless .

构建完成后,查看生成的镜像列表:

docker images | grep rust-local-distroless

你会看到一个惊人的结果:镜像体积大约只有36MB。这与动辄数百MB甚至上GB的包含完整操作系统的传统镜像形成了鲜明对比。

接下来,运行这个容器,并将容器的8000端口映射到本机的8000端口:

docker run -p 8000:8000 rust-local-distroless

容器启动后,我们可以测试API。打开另一个终端,发送一个POST请求。例如,我们使用bert-base-uncased这个分词器来处理文本“Hello, world!”。

curl -X POST http://localhost:8000/tokens/bert-base-uncased \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello, world!"}'

服务器将返回分词后的结果,例如 ["hello", ",", "world", "!"]。你可以尝试更换请求路径中的分词器名称(如bert-base-cased)来处理不同的模型。

总结

本节课中我们一起学习了Distroless容器构建技术。我们通过一个两阶段构建的Dockerfile,首先在完整的Rust环境中编译应用,然后将得到的独立二进制文件复制到极度精简的Distroless镜像中。

这种方法的核心优势在于:

  • 极小的镜像体积(本例中仅36MB),节省存储和网络传输开销。
  • 更高的安全性:由于镜像中不包含Shell等多余工具,攻击面大大减小。
  • 更快的部署与启动:小体积镜像拉取和启动速度更快。

只需对Dockerfile进行一些简单的修改,你就可以为自己的Rust应用(或其他编译型语言应用)构建出轻量、安全且高效的容器镜像,从而获得更快的部署速度、更轻松的滚动更新以及更高效的应用实验能力。

046:使用AI编写AI代码 🚀

在本节课中,我们将探讨一个现代AI编程工作流,其核心是“AI创建AI来与AI对话”。我们将了解如何利用基于云的开发环境和AI编程工具来加速机器学习解决方案的开发。


概述

现代AI编程工作流的核心是利用AI工具来辅助甚至生成代码,从而更快地构建AI解决方案。本节将介绍如何通过配置云开发环境,并集成像Github Copilot这样的AI编程工具来实现这一流程。

工作流详解

上一节我们介绍了现代AI编程的概念,本节中我们来看看这个具体的工作流是如何构建和运作的。

首先,我们可以从Github Codespaces开始。这是一个基于云的开发环境。你可以通过自定义的Docker文件和开发容器配置文件来配置它,使其专门为AI编程和机器学习编程进行优化。其中一个关键优化是支持使用GPU。

在构建这个环境时,你可以做的一件事就是与Github Copilot进行交互。那么,它是什么呢?

Github Copilot是一个AI结对编程工具,它与OpenAI Codex进行通信。Codex是一个经过预训练的模型,旨在帮助你自动补全代码。它足够智能,能够为你提供代码建议。

当你使用Copilot时,发生的情况是,你也可以通过它与云服务的SDK进行通信。例如,你可以构建一个新的系统来转录代码,或者构建与AWS中S3生态系统交互的功能。

这意味着你正在使用AI进行元编程。实际上,你正在使用一个经过预训练、旨在帮助创建AI解决方案的AI。这正是现代AI程序或工作流的本质:AI本身成为一个赋能者,使你能够更快地编写代码、使用更高级的工作流,并在机器学习领域以更快的速度进行开发。

因此,在构建解决方案时,考虑如何使用Github Copilot或AWS CodeWhisperer这类AI工具是非常重要的。

以下是构建此工作流的关键步骤列表:

  1. 设置云开发环境:使用Github Codespaces,并通过Dockerfile和devcontainer.json文件进行定制化配置,以支持GPU加速。
  2. 集成AI编程助手:在开发环境中启用并配置Github Copilot,使其能够与你的代码编辑器交互。
  3. 利用预训练模型:Copilot后台连接的OpenAI Codex模型会分析你的代码上下文,并提供代码补全和建议。
  4. 连接云服务SDK:通过AI助手生成的代码或建议,快速集成例如AWS S3、Azure ML等云服务的功能。
  5. 实现元编程循环:使用AI生成的代码来构建更复杂的AI或机器学习流水线,形成“AI创建AI”的增强循环。

总结

本节课中,我们一起学习了现代AI编程工作流“使用AI编写AI代码”。我们了解到,通过结合云原生开发环境(如Github Codespaces)和智能编程助手(如Github Copilot),开发者可以显著提升在机器学习领域的开发效率。这种以AI赋能AI开发的方式,是当前MLOps实践中的一个重要趋势。

047:通过Copilot学习Python-DevOps关键技能 🚀

在本节课中,我们将学习如何从零开始构建一个完整的Python项目,涵盖从环境配置、库开发、命令行工具、Web微服务到云端部署的全过程。我们将利用GitHub Copilot等现代工具来加速开发,并实践DevOps中的持续集成与持续交付理念。

概述

Python函数是许多有趣任务的核心,它可以被视为一个中心枢纽,连接着库开发、GPU编程、数据科学、微服务、命令行工具和事件驱动编程等多个领域。本节课的目标是掌握围绕Python函数构建复杂系统的关键技能。

第一步:配置开发环境 ⚙️

上一节我们概述了Python函数的中心地位,本节中我们来看看如何搭建一个高效的开发环境。

一个配置良好的环境是快速开发的基础。我们将使用基于云的开发环境来确保一致性和可复现性。

以下是配置环境的核心步骤:

  1. 配置GitHub Codespaces(或等效环境):我们选择GitHub Codespaces作为开发环境。它可以提供强大的计算资源(如16核CPU、32GB内存),甚至支持NVIDIA GPU,非常适合需要处理复杂任务的项目。
  2. 创建项目脚手架:初始化项目结构,包括必要的配置文件。
    • Makefile:用于定义常见的开发命令(如安装、测试、格式化)。
    • requirements.txt:列出项目依赖的Python包。
    • README.md:项目说明文档。
  3. (可选)设置虚拟环境:即使在容器化环境中,使用虚拟环境也能进一步隔离依赖,减少潜在的冲突。可以通过在.bashrc中配置来自动激活。
  4. (可选)在requirements.txt之外单独安装IPython:IPython是一个强大的交互式Python shell,非常适合快速测试和调试。将其独立安装可以避免将其打包到最终部署中。

完成这些步骤后,我们就拥有了一个可以立即开始编码的基础项目结构。

第二步:掌握交互式调试 🐛

现在我们已经搭建好了项目脚手架,接下来需要掌握如何高效地测试和调试代码。交互式工具是关键。

利用IPython和IPDB(IPython调试器)可以极大地提升原型设计和调试效率。

以下是使用交互式工具的方法:

  • 使用IPython进行快速实验:在IPython终端中,你可以像使用计算器一样执行Python语句,测试变量赋值、类型检查以及快速构建和测试函数。who命令可以显示当前内存中加载的所有对象,有助于理解代码状态。
  • 使用IPDB进行脚本调试:在Python脚本中,你可以通过import ipdb; ipdb.set_trace()设置断点。当脚本运行到该行时,会进入一个交互式调试会话,允许你逐行执行代码、检查变量值,就像在IPython中一样。

掌握这些工具能让你在遇到问题时快速定位和解决。

第三步:构建库、CLI工具与测试 🧱

有了调试能力,我们就可以开始构建项目的核心逻辑了。最佳实践是先构建库,再基于库创建命令行工具,并同时编写测试。

将核心逻辑封装在库中,然后通过命令行工具进行调用和测试,这是一种高效且可维护的开发模式。

以下是构建库和CLI的流程:

  1. 创建库结构:在项目下创建mylib/目录,并添加__init__.py文件,使其成为一个Python包。
  2. 使用Copilot编写库代码:在库模块(如mylib/calc.py)中,通过编写清晰的注释(提示)来引导Copilot生成函数代码,例如计算器功能(加、减、乘、除、乘方)。
  3. 创建命令行工具:使用click库创建CLI。Copilot可以根据库中的函数和注释,快速生成对应的click命令和参数解析逻辑。
  4. 编写并运行测试:为库函数和CLI命令编写单元测试和集成测试。Copilot同样可以辅助生成测试用例。使用pytest运行测试,确保代码质量。

通过这个流程,我们得到了一个经过测试的、功能完整的库及其对应的命令行接口。

第四步:构建Web微服务 🌐

库和CLI工具在本地运行良好,接下来我们需要将其能力通过Web API暴露出来,构建一个微服务。

使用FastAPI框架,我们可以轻松地将库中的函数转换为RESTful API端点。

以下是构建微服务的步骤:

  1. 创建主应用文件:创建main.py,导入FastAPI和我们的库(如mylib.logistics)。
  2. 定义API端点:为库中的功能创建对应的HTTP端点(如GET /citiesPOST /distancePOST /travel_time)。Copilot可以帮助生成端点函数和Pydantic模型。
  3. 运行和测试API:在开发环境中运行服务,并通过FastAPI自动生成的交互式文档(/docs)来测试各个端点。
  4. 编写Web服务测试:使用TestClient为API端点编写测试,确保HTTP层面的功能正确。

现在,我们的逻辑不仅可以通过库和CLI访问,还可以通过网络API提供服务。

第五步:容器化与云端部署 ☁️

为了使微服务能够在生产环境中运行,我们需要将其容器化并部署到云平台。

我们将使用Docker进行容器化,并部署到AWS的托管服务上。

以下是部署流程:

  1. 创建Dockerfile:定义构建容器镜像的步骤,包括基础镜像、依赖安装和启动命令。
  2. 构建和本地测试镜像:使用docker build构建镜像,并用docker run在本地运行测试,确保容器内应用正常工作。
  3. 推送镜像到容器仓库:将构建好的镜像推送到AWS Elastic Container Registry (ECR)。
  4. 使用AWS App Runner部署服务:在AWS控制台创建App Runner服务,选择来自ECR的容器镜像,配置端口和资源,即可完成部署。App Runner会自动处理负载均衡、扩缩容和HTTPS。
  5. 设置持续交付:通过AWS CodeBuild配置构建项目,监听GitHub仓库的变更。每当代码更新时,CodeBuild会自动执行构建、测试、打包和部署到ECR的流程,从而实现持续交付。

至此,我们实现了一个从代码提交到服务自动更新的完整CI/CD流水线。

总结

本节课中我们一起学习了如何以Python函数为核心,从零开始构建一个完整的应用。我们涵盖了环境配置、交互式调试、库开发、命令行工具构建、Web微服务创建,以及最终的容器化与云端部署。整个过程充分利用了GitHub Copilot等现代AI辅助编程工具和云原生服务,展示了高效、现代的DevOps开发流程。通过这个实践,你不仅掌握了Python编程的关键技能,也了解了如何将代码转化为可运维的生产级服务。

048:Amazon CodeWhisperer 与 GitHub Copilot 对比 🆚

在本节课中,我们将对比两款流行的AI结对编程工具:Amazon CodeWhisperer 和 GitHub Copilot。我们将通过实际操作,展示它们如何帮助开发者编写代码,并分析各自的优缺点。

概述

我们将首先介绍GitHub Copilot,展示其核心功能。接着,我们将切换到Amazon CodeWhisperer,进行类似的任务演示。通过对比,我们可以了解两者在代码生成速度、准确性、集成体验等方面的差异。

GitHub Copilot 演示

上一节我们介绍了课程目标,本节中我们来看看GitHub Copilot的实际表现。我使用一个预配置了GPU的MLOps代码空间环境,它启动迅速且已安装好所有必要的扩展。

代码生成示例

以下是使用Copilot生成简单Python代码的步骤。

首先,我创建一个目录并编写一个注释来描述需求。

# 构建一个随机水果列表

Copilot会根据注释自动生成代码建议。

fruit = ['apple', 'banana', 'cherry', 'date', 'elderberry']

代码重构与格式化

使用AI工具时,配合传统开发工具(如代码格式化器和linter)非常重要。这能确保生成的代码既智能又整洁。

我使用一个名为refactor的工具来格式化和整理代码。

make refactor

构建复杂循环

接下来,我指导Copilot构建一个更复杂的循环。

# 构建一个for循环,打印出列表中每个水果及其序号,格式为“序号: 水果名”

Copilot生成了以下代码:

for i, f in enumerate(fruit):
    print(f"{i}: {f}")

代码解释与翻译

Copilot Labs 提供了代码解释和翻译功能。我可以选中一段代码,让它解释其功能,或尝试将其翻译成其他语言(如Shell或Ruby)。虽然翻译功能目前处于测试阶段,结果可能不完美,但展示了其潜力。

切换到 Amazon CodeWhisperer

上一节我们体验了Copilot的流畅性,本节中我们来看看AWS的解决方案。我将在AWS Cloud9环境中使用CodeWhisperer。

环境设置

我创建了一个新的Cloud9环境。与GitHub Codespaces可以预构建环境不同,Cloud9需要手动进行一些设置,例如配置SSH密钥以克隆代码仓库。

启用 CodeWhisperer

Cloud9与AWS服务深度集成。我可以在IDE中直接启用CodeWhisperer预览版。

编写AWS工具代码

让我们测试CodeWhisperer在AWS相关任务上的能力。我创建一个工具来列出S3存储桶。

首先,我创建一个Python文件并写下初始注释。

#!/usr/bin/env python
# 构建一个函数,返回我账户中的所有S3存储桶

CodeWhisperer 开始给出建议,首先导入了boto3库。

import boto3
def list_s3_buckets():
    s3 = boto3.client('s3')
    response = s3.list_buckets()
    return [bucket['Name'] for bucket in response['Buckets']]

处理格式问题

我注意到CodeWhisperer生成的代码有时存在缩进问题。和之前一样,我使用refactor工具(结合Black和Pylint)来自动修复格式。

make refactor

构建计算器应用

为了进行更公平的对比,我尝试用CodeWhisperer构建一个与之前类似的计算器命令行工具。

代码生成质量很高,但建议的弹出速度感觉比Copilot慢一些。有时需要等待或使用Tab键来触发建议。

并排对比

上一节我们分别尝试了两个工具,本节中我们将它们放在一起直接对比。我同时在Copilot代码空间和CodeWhisperer Cloud9环境中构建相同的“S3存储桶文件计数”工具。

Copilot 实现体验

在Copilot中,我描述了需求:

# 构建一个使用click的命令行工具,用于统计AWS账户中所有存储桶的文件数量。

Copilot的反应非常迅速,几乎能预测我的想法。它快速生成了使用boto3click的完整代码框架,包括列出存储桶、统计文件数和组织命令行组的逻辑。整个流程感觉非常自然、快速。

CodeWhisperer 实现体验

在CodeWhisperer中,我进行相同的尝试。它生成的代码质量也很高,结构清晰。然而,其建议速度明显较慢,并且偶尔会出现恼人的缩进错误,需要手动或通过格式化工具纠正。我需要更主动地引导代码生成过程。

总结与对比分析

本节课中我们一起学习并对比了GitHub Copilot和Amazon CodeWhisperer。

GitHub Copilot 的优势:

  • 响应速度极快,感觉像是与思维同步。
  • 交互非常直观,代码补全流畅自然。
  • 与开发流程集成度好,能快速理解上下文并生成复杂代码。

Amazon CodeWhisperer 的优势:

  • 生成的代码质量高,尤其针对AWS相关服务,代码通常很整洁。
  • 与AWS Cloud9环境深度集成,对于AWS开发者非常方便。
  • 作为AWS生态的一部分,对于主要使用AWS服务的团队有天然优势。

CodeWhisperer 需要改进的方面:

  • 建议响应速度有待提升。
  • 代码缩进/空格问题需要修复。
  • 整体流畅度和“智能感”暂不如Copilot。

总体而言

  • Copilot 提供了更优的整体开发者体验,感觉更像一个高效的结对编程伙伴。
  • CodeWhisperer 是一个非常有潜力的工具,特别是在AWS环境中。它已经比没有AI辅助要好得多,并且随着迭代一定会不断改进。
  • 对于Cloud9用户来说,CodeWhisperer是一个必用的增强工具。如果AWS能进一步优化Cloud9的启动速度(例如引入预构建环境功能),体验会更上一层楼。

两款工具都是强大的“生产力增强剂”,选择哪一个可能取决于你主要的工作环境(GitHub vs. AWS)以及对速度与深度集成的不同侧重。

049:启用AI工作流 🚀

在本节课中,我们将学习如何整合多种现成的AI工具来构建一个支持AI的自动化工作流。我们将通过一个具体的例子,了解如何将视频转录、文本摘要、关键词提取等任务串联起来,形成一个高效的自动化管道。

概述

上一节我们讨论了机器学习运维的基础设施。本节中,我们来看看如何利用现成的AI服务来构建自动化工作流。我们将以一个内容发布商的案例,展示从原始视频到最终发布的全流程自动化。

AI工具整合示例

以下是一个内容发布商可以构建的自动化工作流示例。该流程展示了如何将多个独立的AI工具串联起来,完成从视频处理到内容发布的系列任务。

工作流步骤详解

以下是该自动化工作流的具体步骤:

  1. 视频转录:发布商首先获取一个YouTube视频,并自动将其转录为英文文本
  2. 内容摘要与标题生成:随后,他们可以使用Hugging Face的模型来总结转录文本自动生成一个标题
  3. 段落摘要:他们还可以利用Hugging Face为文本的特定段落生成摘要。
  4. 关键词提取:为了获取内容的关键信息,他们可以使用Hugging Face的零样本分类工具,或是像Yaake这样的工具,来提取关键词和关键段落
  5. 自动化构建:发布商可以利用这些现成的AI工具,构建起整套自动化流程
  6. 内容存储:生成的内容(如标题、摘要)可以被放入Google Drive目录,或自动上传到其他存储系统。
  7. 流程迭代:这可以作为他们自动化管道的第一个版本。后续,他们可以在此基础上增加这些AI工具的更多功能

工作流的扩展可能性

初始流程建立后,还可以进行多方面的功能扩展,使自动化更加强大和全面。

  1. 多语言转录:他们可以将视频转录成10种最流行的语言,以扩大受众范围。
  2. 个性化推荐:他们还可以利用自然语言处理技术构建自己的推荐引擎。例如,通过分析视频内容,为用户推荐其他相关视频
  3. 内容打包与发布:最后,他们可以通过编程方式,将所有这些生成的内容(标题、摘要、视频链接)打包成完整的发布物料
  4. 自动更新:进而,可以通过编程方式自动将这些内容更新到YouTube或其他平台。

总结

本节课中,我们一起学习了如何构建一个启用AI的自动化工作流。通过整合如OpenAI或Hugging Face这样的预训练模型,许多复杂的处理能力被封装在后台。正如本例所示,当你将这些工具组合在一起时,你会发现AI真正实现了自动化,并且这些工具之间具有非常好的互补性。这种模块化的方法让即使是不精通底层算法的开发者,也能快速构建出强大的AI应用。

050:使用Bash在AWS CloudShell中快速原型化AI API

概述

在本节课中,我们将学习如何利用AWS CloudShell中的Bash环境,快速原型化和探索AI API。我们将使用AWS Comprehend服务,从维基百科获取数据,进行情感分析和实体提取,并通过Bash管道处理数据,从而快速验证想法,为后续的正式开发奠定基础。

使用AWS CloudShell和Bash进行AI API原型设计

很多时候,开发者容易陷入使用Python、C#或Ruby等语言开发API的细节中,在尚未完全理解需求前就深陷复杂的代码。

使用AWS CloudShell的一个优势是,可以利用Bash构建初始原型,以交互方式探索想法并快速尝试。我们将使用AWS CloudShell调用AWS Comprehend服务,从维基百科拉取数据,进行情感分析和实体提取,然后通过Bash管道处理,快速发现有趣的信息。之后,你可以基于在Bash中构建的原型来决定下一步的开发内容。

开始使用AWS AI服务

AWS提供了从高级文本分析、自动化代码审查、聊天机器人到预测和文档分析等各种AI服务。

我喜欢从CloudShell开始探索。CloudShell的优势在于可以快速尝试和原型化想法。如果你想查看一些完整的示例,可以访问AWS Comprehend的示例页面。现在,让我们开始实际操作。

首先,输入aws comprehend命令。通过输入help可以查看该服务能做什么。它会显示可用的子命令,例如批量检测主要语言、分类文档等。要使用这些功能,只需在命令中放入相应的子命令即可。

初步尝试情感分析

首先,我们将尝试情感分析。我们可以粘贴一整段文档内容进行测试。注意,粘贴时系统会提示安全粘贴,命令中的换行符使得每个选项单独成行,这有助于构建更复杂、更易读的命令。

以下是命令示例:

aws comprehend detect-sentiment \
    --language-code "en" \
    --text "I love C#"

这个命令会分析文本“I love C#”的情感是消极、积极还是中性。

执行后,结果显示情感为“积极”。这非常直接。如果你想进行AI工作,甚至无需深入编程语言,就可以从这里开始尝试。

处理更复杂的文本输入

这里有两个微妙的问题需要解决。第一个是如何将更复杂的文本(例如来自网站或其他数据源)输入到命令中。第二个问题是,一次可以输入多少文本。

通过输入aws comprehend并利用其良好的Tab自动补全功能,可以方便地探索。输入help可以查看所有参数的描述,例如可以更改文本输入、语言代码等。

但需要注意,从这个特定工具传入的每个字符串必须少于5000字节。如果你要传入大量文本,必须注意这一点。

从网络获取文本数据

接下来,我们将解决如何获取文本的问题。我们将安装一个名为links的工具。这是一个在20世纪80年代末和90年代初许多人用来浏览互联网的工具。它也可以用于数据科学。

我们将使用一段代码片段来演示其功能。代码使用links命令并加上-dump参数,将网页文本内容输出到Bash的标准输出。我们首先浏览目标网页,这是关于阿尔伯特·爱因斯坦的维基百科页面。

我们可以使用links命令将内容通过管道传递给less命令进行浏览。即使不做数据科学,了解可以从终端使用links浏览维基百科也是很有用的。

处理文本长度限制

接下来,我们想知道获取的内容有多少行和多少字节。wc(word count)命令可以帮助我们。输入wc -c可以查看字节数。

结果显示有超过432,000字节,远超过AWS Comprehend工具5000字节的限制。因此,我们需要创建一个变量来精确提取5000字节的文本。

我们可以构建一个命令行工具来提取5000字节。使用相同的links -dump命令,结合head -c命令,可以提取指定数量的字节。

将文本存入变量并与AWS Comprehend集成

现在我们已经能获取文本,接下来是如何将其用于之前的AWS Comprehend命令。查看之前的命令,发现它使用--text参数,这有点复杂,因为我们无法直接通过管道输入。我们需要将内容赋值给一个变量。

在Bash中,这很简单。我们只需将命令用反引号或$()括起来,然后将输出赋值给一个变量,例如text=$(...)

现在,如果我们输入echo $text,就可以看到文本已存储在变量中。但这里我们不需要单词计数,而是需要原始文本。因此,我们调整命令,使用head -c 5000来获取原始文本。

执行情感分析

现在我们已经将文本存储在变量中,接下来可以将其用于更复杂的AWS Comprehend命令。我们只需构建命令,将--text参数的值设置为我们的变量。

执行命令后,我们可以看到对爱因斯坦维基百科文章的情感分析结果。总体而言,文章的情感偏向中性,但也有相当一部分(约三分之一)内容表现出非常积极的情感。作为一个历史人物,爱因斯坦受到高度评价,从数据科学的角度看,这很有趣。

进阶:实体提取与处理

除了情感分析,我们还能做什么?另一个有趣的功能是实体提取。

这次我们使用detect-entities子命令,并指定输出格式为文本。这样我们就可以利用Bash的能力来处理输出结果。

输出显示了从文本中提取的关键实体,如“Wikipedia”、“Albert Einstein”、“German”等。如果我们只查看前25个条目,可以看到更多实体。这些都是从文本中提取的关键项目。

构建Bash数据处理管道

如果我们能获取实体列,并统计每个实体出现的次数,这将是一种更强大的方式,可以让我们更深入地了解维基百科文章的内容,以便进行进一步研究或用其他语言构建应用。

为了实现这个目标,我们将构建一个更复杂的Bash管道命令。首先进行实体提取,传入语言代码和文本。然后进入Bash管道处理:首先获取实体所在的列;接着清理数据,只保留字母字符并转换为小写,同时移除换行符;然后对结果进行排序;排序后,使用uniq -c统计每个实体出现的次数;接着按第一列(计数)进行反向排序;最后,只查看前几个最重要的实体。

运行这个管道命令后,我们得到了预期的结果:它显示了最重要的实体及其出现次数。例如,关于爱因斯坦的文章中,“Einstein”一词出现频率很高,“University”、“German”、“Empire”、“Albert”、“Kingdom”、“Zuric”等也频繁出现。这些信息对于进一步的数据科学研究可能非常有用。

总结

本节课中,我们一起学习了如何利用AWS CloudShell和Bash快速原型化AI API。我们使用AWS Comprehend服务对网络文本进行了情感分析和实体提取,并构建了Bash管道来处理和分析结果。这种方法证明,你并非必须使用Python、C#或R等语言才能进行复杂的数据科学探索。结合CloudShell和Bash,你可以非常快速地使用AI API原型化解决方案,验证想法,为后续开发提供清晰的思路。

051:使用迁移学习

概述

在本节课中,我们将要学习迁移学习的优势,以及它为何与传统监督式学习不同。我们将探讨迁移学习如何解决数据与计算资源的挑战,并介绍如何利用预训练模型进行微调,以高效地应用于新领域。


迁移学习的优势

上一节我们介绍了机器学习运维的宏观概念,本节中我们来看看迁移学习的具体优势。

传统监督式机器学习面临诸多问题,这些问题主要围绕数据展开。你是否拥有处理数据的能力?你是否拥有数据以及计算资源?你是否能够访问计算资源,并利用这些资源处理任务?

如果我们观察一个特定的新闻数据问题,你需要使用历史模型对其进行训练,然后整理出一个能够总结数据的预测结果。同样地,你需要选取另一个独立的数据集,进行总结并创建预测。因此,在自然语言处理领域,使用传统监督式机器学习进行训练需要大量的计算资源和存储资源。

迁移学习的优势之一在于,你可以采用在其他领域训练好的模型。例如,一个在新闻数据上训练的模型。我们可以保留其主体部分,初始化一个新模型,该模型将使用一个文学数据集进行微调。接着,我们通过移除其头部并进行调整,针对包含文学信息的新数据进行实际微调。这将为我们提供一种更高效的预测方法。

因此,这里的区别在于,微调允许你利用由专家开发、并消耗了大量计算和存储资源的成果,然后在你自己的资源上对其进行微调。


微调实践与平台

以下是迁移学习微调过程的关键实践平台。

Hugging Face 是进行微调过程的主要平台之一。它允许你在另一个领域高效地进行基于模型的高质量训练。实际上,未来我们将在市场上看到迁移学习的更多优势。事实上,你可以自己进行迁移学习,并将微调后的模型推送到 Hugging Face 上。


总结

本节课中我们一起学习了迁移学习的核心优势。我们了解到,与传统监督学习相比,迁移学习通过复用预训练模型,显著降低了对数据量和计算资源的需求。微调使我们能够站在“巨人肩膀上”,利用现有高质量模型快速适应新任务。Hugging Face 等平台为这一过程提供了强大支持。掌握迁移学习是高效构建机器学习应用的关键技能。

052:通过Streamlit集成OpenAI技术 🚀

在本节课中,我们将学习如何将OpenAI的API功能集成到一个Web应用中。我们将使用Streamlit框架快速构建一个交互式界面,并重构代码以创建可复用的库。整个过程将涵盖环境设置、代码重构、测试编写以及Web应用开发。


概述

我们将从一个现有的命令行工具开始,将其核心逻辑提取到一个独立的库中。然后,我们将利用这个库,构建一个能够根据自然语言描述生成代码的Streamlit Web应用。课程将展示如何设置开发环境、确保代码质量,并快速迭代开发。


环境设置与代码重构

上一节我们运行了一个基于OpenAI的问答命令行工具。本节中,我们来看看如何优化项目结构,为后续开发打下基础。

首先,我们需要确保开发环境配置正确,包括设置GitHub Actions工作流和开发容器。

以下是设置持续集成工作流的步骤:

  1. 进入项目的“Actions”标签页。
  2. 选择“Set up a workflow yourself”。
  3. 粘贴预先准备好的工作流配置代码,用于代码格式化和测试。

同时,我们通过命令 Shift + Command + P 并选择“Add Development Container Configuration Files”来配置开发容器,确保环境一致性。

接下来,我们重构项目,将核心功能移入库中以提高代码复用性。

我们创建一个库文件 oa_lib/solutions.py,并将命令行工具中的 submit_question 函数逻辑移动至此。

# oa_lib/solutions.py
import openai
import os

def submit_question(question: str) -> str:
    """向OpenAI API提交问题并返回答案。"""
    openai.api_key = os.getenv("OPENAI_API_KEY")
    response = openai.Completion.create(
        engine="text-davinci-003",
        prompt=question,
        max_tokens=150
    )
    return response.choices[0].text.strip()

原命令行工具则简化为导入并使用库函数。

# question_answer_cli.py
import click
from oa_lib import solutions

@click.command()
@click.argument('question')
def main(question):
    """一个简单的问答CLI工具。"""
    answer = solutions.submit_question(question)
    click.echo(f"答案: {answer}")

if __name__ == '__main__':
    main()

运行 make lintmake test 来确保代码质量,解决所有格式和逻辑错误。


扩展库功能:代码生成

现在我们已经有了一个基础的库,本节中我们来看看如何为其添加新的功能,例如将自然语言描述转换为代码。

我们参考OpenAI的文档,使用 code-davinci-002 模型来实现代码生成功能。在 oa_lib/solutions.py 中添加一个新函数。

# oa_lib/solutions.py
def create_code(text: str, language: str) -> str:
    """根据文本描述和指定语言生成代码。"""
    openai.api_key = os.getenv("OPENAI_API_KEY")
    prompt = f"# 语言: {language}\n# 描述: {text}\n# 代码:\n"
    response = openai.Completion.create(
        engine="code-davinci-002",
        prompt=prompt,
        max_tokens=256
    )
    return response.choices[0].text.strip()

为了快速测试这个新功能,我们创建一个命令行工具 mk_code.py

# mk_code.py
import click
from oa_lib import solutions

@click.command()
@click.option('--language', '-l', default='Python', help='目标编程语言,例如 Python, JavaScript')
@click.argument('text')
def main(text, language):
    """根据描述生成代码示例。"""
    code = solutions.create_code(text, language)
    click.echo(f"生成的 {language} 代码:\n{code}")

if __name__ == '__main__':
    main()

运行工具进行测试:

./mk_code.py -l Python “计算两个数字的和”

构建Streamlit Web应用

有了功能完善的库之后,本节我们将利用它快速构建一个交互式的Web应用。

我们创建一个新的Streamlit应用文件 code_gen_web_app.py。其核心是提供一个文本输入框供用户描述需求,并选择一个目标语言,然后调用我们的库来生成并显示代码。

# code_gen_web_app.py
import streamlit as st
from oa_lib import solutions

st.title('OpenAI 代码生成器 🧑‍💻')
st.write('输入您的需求,选择语言,即可自动生成代码。')

# 用户输入
user_input = st.text_area("描述您想要的功能:", "例如:创建一个函数,计算列表的平均值")
language = st.selectbox("选择编程语言:", ["Python", "JavaScript", "SQL", "Java"])

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/4453d35498bdfd5cfb13d03c5fdc52e2_36.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/4453d35498bdfd5cfb13d03c5fdc52e2_37.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/4453d35498bdfd5cfb13d03c5fdc52e2_39.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/4453d35498bdfd5cfb13d03c5fdc52e2_41.png)

if st.button('生成代码'):
    with st.spinner('正在生成代码,请稍候...'):
        try:
            generated_code = solutions.create_code(user_input, language)
            st.code(generated_code, language=language.lower())
        except Exception as e:
            st.error(f"生成代码时出错: {e}")

运行Streamlit应用:

streamlit run code_gen_web_app.py --server.enableCORS false

请注意,--server.enableCORS false 参数可能在某些开发环境下需要,以解决应用加载问题。

应用启动后,在浏览器中打开提供的本地地址,即可使用代码生成器。


总结

本节课中我们一起学习了如何将OpenAI API集成到实际项目中。我们从重构代码、创建可复用库开始,然后扩展了代码生成功能,并最终使用Streamlit框架构建了一个直观的Web应用程序。这个过程展示了如何系统化地开发AI应用,并强调了代码质量、环境配置和快速原型开发的重要性。

053:Python转Rust入门 🦀

概述

在本节课中,我们将探讨为什么Rust语言对于Python开发者而言是一个值得学习的强大工具。我们将从Rust的设计理念、核心优势以及它如何与现代开发实践(如AI辅助编程)结合等方面进行介绍,帮助你理解从Python转向Rust的价值和路径。

为什么选择Rust?

我是Noah Gift,一位O‘Reilly的常驻作者,撰写过多本技术书籍。我在杜克大学教授云计算、数据工程和机器学习运维课程。我的研究重点是如何让机器学习运维、DevOps和云计算尽可能高效和富有成效。因此,制作这个从Python转向Rust的系列教程既有趣又富有意义。

本系列将基于我当前正在进行的工作,展示Rust的一些能力。首先,让我从宏观上阐述为什么我认为Rust是未来,以及为什么如果你是Python程序员,至少应该尝试一下它。

Rust的核心优势

Rust作为一门现代语言,拥有多项显著优势。以下是其核心特点的详细说明。

1. 现代化的设计

Rust的一大优势在于其诞生时间较晚。与那些已存在数十年的语言不同,Rust能够汲取其他语言的最佳实践。其中,包管理可能是Rust的头号优势。当你使用基于cargo的系统时,会立刻感受到它的强大、实用和令人耳目一新。如果你曾为Python或其他语言的包管理而苦恼,那么使用Rust的包管理会让你感到得心应手。

2. 卓越的性能与能效

在性能方面,Rust达到了C++级别的速度。在能效方面,同样具备C++级别的能源效率。因此,如果你确实需要充分利用成本节约和能源效率,Rust将是你的绝佳选择。

3. 强大的并发支持

Python由于全局解释器锁(GIL)的历史遗留问题,无法进行充分利用所有核心的多线程编程。这对Python程序员来说是一个挑战,因为线程化编程可以更高效地利用内存。而在Rust中,你只需几行代码,就可以在线程池中启动多个线程。同时,编译器会保护你免受多线程编程中可能出现的许多问题。

4. 内存安全与系统级安全

这引出了下一点:安全性。Rust是最安全、最安全的语言之一。它被设计为一门系统编程语言,因此在网络安全方面的许多安全特性都内置于语言本身。这就是为什么Linux内核开始采用Rust,谷歌也在采用Rust。在2023年及以后,你将会看到Rust被广泛采用。

5. 便捷的二进制分发

最后一点,Rust的另一个巨大优势在于分发。如果你有一个Python脚本,想交给非技术人员(比如你的祖父母)运行,即使他们有一点技术背景,运行你的脚本也可能遇到困难。而对于Rust,默认情况下,一旦你编译了包,就可以将生成的二进制可执行文件放在某个目录中,他们可以直接运行它。因此,Rust的二进制可执行文件交付方式是一个巨大的优势,我认为许多人都会利用这一点。

6. AI辅助开发的新时代

最后要提到的是,我们正处在一个使用AI辅助的新时代。特别是GitHub Copilot,它为本课程所重点介绍,为代码开发增添了一种惊人的方式。你从Python中已经掌握的代码检查、格式化和测试等所有技能,都可以直接通过Copilot来加速掌握Rust。这也是我将在本课程中演示的内容之一。

总结

总而言之,即使你对Rust感到有些畏惧,或者觉得其语法有点陌生,我将会逐步引导你如何成为一名Rust程序员。掌握这项技能,能将你公司、组织或个人业余项目的水平提升一个档次。

好的,让我们开始吧。

054:Rust讲义笔记介绍 🦀

在本节课中,我们将介绍一份用于本课程的Rust学习笔记(Rustbook),并概述其内容结构、核心学习方法以及如何利用现代开发工具链快速上手Rust,特别是用于构建命令行工具和云服务。

概述:Rustbook简介

这里有一份使用Markdown编写的Rust学习笔记,名为“Rustbook”。我使用它来记录本课程中将要讲解的许多讲座内容。

你可以通过Github上的URL rustt tutorial 查看这份笔记。笔记包含前言、第一章、第二章等内容。如果我们查看开头部分,可以看到前言,其中介绍了我的背景——我在构建系统方面拥有丰富经验,还有一些额外内容。

第一章内容预览

上一节我们介绍了Rustbook的整体情况,本节中我们来看看第一章的简要内容。在后续课程中,我们会深入细节。但在最开始,核心思想是:你可以通过这些演示了解研究生课程的部分教学内容,并最终学会如何使用Rust技术构建自己的项目组合。

我认为有几个有趣的点值得指出。当你开始学习时,2023年结合提示工程的现代编程工作流是一个巨大的改变,尤其是在MLOps和云计算领域使用Rust。

以下是其基本工作流程:

  1. 从Github的项目模板开始(我后续会分享我的仓库模板)。
  2. 使用Codespaces配置一个已预装Rust的优质开发环境。
  3. 创建你的项目。
  4. 通过在Rust代码中添加注释来“播种”想法,AI工具会据此给出建议。
  5. 接着,你可以构建你的命令行工具。

这种 “格式化 -> 检查 -> 编译 -> 运行” 的循环有助于控制提示工程,并真正发挥其能力来构建你想要的工具。

因此,秘诀在于 传统工具 + Copilot这类新型AI编程工具

实战示例:构建命令行工具

以上介绍了现代Rust开发流程,本节我们通过一个具体例子来看看如何实践。这里有一个很好的入门项目示例:我想运行一个“Marco Polo”命令行工具。

我们可以通过运行 cargo 命令来创建并运行一个能实现此功能的项目:我输入单词“Marco”,它会返回单词“Polo”。

相关代码非常简单。如果你熟悉Python,除了 pub 关键字表示此函数对另一个模块公开,以及必须声明类型(Python中类型注解是可选的)之外,没有太大区别。

以下是一个直观的代码格式示例:

if name == "Marco" {
    return "Polo";
}

在主函数中,我们使用了一个命令行参数解析库,它在很多方面类似于Python的argparse库,用来解析参数。

因此,开始构建命令行工具非常简单。我的建议就是:着手构建命令行工具。你可以参考这份教程,我也会带你逐步学习。

后续章节与高级应用

我们刚刚探讨了如何入门构建基础工具,接下来简要谈谈其他章节的内容。随着本系列课程的进展,会有更多内容加入。我希望能尽快分享这些信息,因此目前以草稿形式呈现。

通常,在这里向下滚动,你还可以学习构建AWS无服务器工具。这是一个演示如何在AWS内部部署Lambda函数的例子,实际上相当简单。

这里又是一个“Marco Polo” Lambda函数的示例。如果滚动到页面底部,你还可以看到一个与AWS交互的无服务器工具。再次强调,代码量不大,非常直观。如果你是Python程序员,不必担心,你会很快适应这项技术。

总结

本节课中我们一起学习了为本课程准备的Rustbook笔记。我们概述了其结构,介绍了结合AI提示工程的现代Rust开发工作流,并通过“Marco Polo”示例演示了如何快速构建命令行工具和云函数。请随时查看这份资料,本系列内容会频繁更新。我非常期待教授这些材料。

055:为AWS Cloud9配置Rust环境 🦀

在本节课中,我们将学习如何在AWS Cloud9环境中配置Rust编程语言。我们将通过对比Python环境的设置流程,来展示Rust工具链的简洁与高效。


概述

我们将使用rustup工具来安装Rust。rustup是Rust语言的官方安装器,它提供了一种极其简单的方式来设置开发环境。整个过程通常只需一行命令。本节将演示在AWS Cloud9中创建新环境、安装Rust、初始化项目,并介绍如何利用Makefile来统一开发工作流。

环境创建与Python设置对比

首先,我们在AWS Cloud9中创建一个新的环境。对于习惯使用Python的开发者来说,这个过程很熟悉。为了进行对比,我们先看看在Python环境中通常需要做哪些设置。

以下是典型的Python环境设置步骤:

  1. 创建虚拟环境:使用Python内置的venv模块来隔离项目依赖。
    python3 -m venv ~/.venv
    
  2. 激活虚拟环境:需要手动激活环境,并通常需要将其添加到shell配置文件中以便新终端自动激活。
    source ~/.venv/bin/activate
    
  3. 管理依赖:需要手动创建requirements.txt文件来列出项目依赖,然后使用pip进行安装。
    pip install -r requirements.txt
    

这个过程虽然可行,但步骤较多,且每次新建项目都需要重复操作。

使用Rustup安装Rust

现在,让我们看看Rust的安装过程。相比之下,它要直接得多。

我们只需在终端中运行以下命令:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

或者直接使用:

rustup

(假设rustup安装脚本已下载)

执行后,rustup会自动完成以下工作:

  • 安装最新稳定版的Rust编译器(rustc)。
  • 安装Rust的包管理器和构建工具cargo
  • 安装rustfmt(代码格式化工具)、clippy(代码lint工具)和rust-docs(文档工具)。
  • 自动将cargo等工具的路径添加到用户的~/.bashrc文件中,无需手动配置。

安装完成后,创建一个新的Rust项目非常简单:

cargo new hello

这个命令会生成一个完整的项目结构,包括Cargo.toml文件(用于管理依赖和元数据)和src/main.rs文件(包含一个“Hello, world!”示例程序)。从项目伊始,你就拥有了一个成熟的构建和包管理系统。

使用Makefile统一工作流

为了进一步提升开发体验,尤其是在使用多种语言时保持工作流一致,我们可以引入一个Makefile。

以下是一个示例Makefile的内容,它定义了一些常用任务:

.PHONY: help format lint test run release
help:
	@echo "可用命令:"
	@echo "  make format    # 格式化代码"
	@echo "  make lint      # 运行clippy进行代码检查"
	@echo "  make test      # 运行测试"
	@echo "  make run       # 编译并运行项目"
	@echo "  make release   # 构建发布版本"

format:
	cargo fmt

lint:
	cargo clippy

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/ed4ac675204814f45db8a1d46b241d4d_9.png)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/ed4ac675204814f45db8a1d46b241d4d_10.png)

test:
	cargo test

run:
	cargo run

release:
	cargo build --release

将这个Makefile放入你的项目根目录后,你就可以使用统一的命令来执行各种操作:

  • make run:编译并运行项目。
  • make format:使用rustfmt自动格式化代码。
  • make lint:使用clippy进行静态分析,检查代码中的常见问题或可改进之处。
  • make test:运行项目中的单元测试。
  • make release:构建优化后的发布版本。

这种统一的方式使得在不同项目间切换时更加得心应手。

总结

本节课中,我们一起学习了在AWS Cloud9中配置Rust开发环境。通过rustup,Rust的安装过程变得非常简洁,一键即可获得完整的工具链。cargo工具在项目创建之初就提供了依赖管理、构建、测试等一体化支持,体现了“生产就绪”的设计理念。最后,通过引入Makefile,我们能够建立一套统一、高效的开发工作流。对于许多MLOps或工程项目而言,Rust因其出色的性能、安全性和现代化的工具链,正成为一个非常有吸引力的Python替代选择。

056:使用GitHub Copilot辅助Rust编程

概述

在本节课中,我们将学习如何利用GitHub生态系统(包括GitHub Copilot、Visual Studio Code和GitHub Codespaces)来辅助Rust编程。我们将探讨如何将Python程序员的知识迁移到Rust,并利用现代工具链实现更高效的开发流程。

开始使用GitHub生态系统进行Rust开发

上一节我们介绍了课程背景,本节中我们来看看如何开始使用GitHub生态系统进行Rust开发。

我认为这是成为一名软件工程师更令人兴奋的方式之一。这就是在GitHub生态系统中使用Copilot。不仅仅是单独使用Copilot,而是与Visual Studio Code、GitHub Codespaces和GitHub一起使用。这些工具的结合可以让你提升水平。在我刚开始使用Python的时候,感觉非常棒。我进入Python世界,觉得可以做很多事情,快速编写脚本代码,速度快如闪电,这很神奇。当你使用Copilot升级到像Rust这样更强大的语言时,那种感觉和最初的Python体验一样。但区别在于,你拥有一种现代语言和一个现代打包系统。你的能源效率提高了50倍,计算性能至少提高了25倍。由于它是一种内存效率很高的语言,内存使用也更优。

在安全性方面,你通过编译器构建了一个非常安全、并发的程序,并且从网络安全的角度来看也是安全的。因此,有所有这些很棒的优势。所以真正的问题是,使用Copilot配合一个稍微复杂一点的语言(Rust)是否值得付出代价。答案是值得的,因为你可以利用作为Python程序员已有的知识,将其应用到Rust中,从而提升你公司的水平。我认为这将成为2023年的一项新兴技能。Python程序员不必抛弃他们所学的一切,他们可以运用我将要展示的技巧来应用这些知识。

使用GitHub Codespaces模板创建Rust项目

上一节我们讨论了使用Rust和Copilot的优势,本节中我们来看看如何使用GitHub Codespaces模板创建Rust项目。

让我们看一下这里使用GitHub生态系统的Rust新项目模板。这确实是神奇之处,这就是为什么Copilot能让你提升现有Python程序员水平的原因。如果你想进入下一个级别,我强烈推荐GitHub Codespaces加上Copilot加上Visual Studio Code。这是秘诀。如果我们浏览这里,我们会看到一个Dockerfile,它配置了我的环境,包含了我需要的所有东西。我们还在devcontainer中配置了功能,例如Copilot。此外,这意味着我可以在任何时候用新项目启动它。所以这里的秘诀就是,我只需要说,嘿,我要使用这个,我想自动测试我的代码,一切都为我设置好了。让我们使用这个模板,创建一个新的仓库,在这里选择额外的选项,并挑选一台性能强大的机器,以便编译我的代码。

配置开发环境与验证

上一节我们创建了项目模板,本节中我们来看看如何配置开发环境并进行验证。

我们在这个环境中。让我们检查一下一切是否正常。我们可以做的一件事是查看这里的Makefile,这在项目初期是一个好主意。如果我输入make rust-version,好处是它会告诉我所有美好的东西,比如Rust的版本等等。这是免费的,这是与Python的一大区别,你不需要做任何事情,它已经准备好了。所以如果我想创建一个新项目,我该怎么做?我只需输入cargo new hello_marco。让我们构建一个Marco Polo应用程序。如果我浏览这里,看,我有一个打包系统已经为我设置好了。所以我需要在这里放入我关心的依赖项。我要做的是在这里放入一个命令行工具库,叫做Clap,这是一个非常流行的库。然后由我决定结构。

如果你是Python程序员,我建议你浏览这里,进入src目录。首先进入目录,然后touch src并创建一个lib.rs。这是我喜欢放置逻辑的地方。在这里,我们也可以通过使用Copilot构建一些惊人的东西。这确实让我们能够利用从Python带来的技能。我们可以首先在这里创建一个注释,说,一个Marco Polo游戏。

利用Copilot编写Rust逻辑

上一节我们设置了项目结构,本节中我们来看看如何利用Copilot编写Rust逻辑。

然后由我来创建正确的提示。所以我要做的是,我会说,如果给出的名字是“Marco”,程序用“Polo”回应。否则,我们会说“你叫什么名字?”。这看起来很不错,对吧?所以它就像一个真人。我们只需要正确地提示它。然后我还会在这里添加一些额外的提示。这又取决于我们,真的去引导它,对吧?所以我们想做一些事情。只要我们一路帮助它,它就会给你一个好的回应。在这种情况下,我们说pub fn,所以将这个暴露给我的主模块,我将用于命令行工具。然后看看其余的代码,它实际上非常直观。我们这里有一个字符串用于名字,我们对字符串做一些处理,然后返回一个字符串,非常非常直观。

现在让我们进入main.rs。这里的技巧是,很多时候所有的命令行工具库或样板代码。所以很多时候,如果我正在构建一些东西,我会从其他程序中剪切粘贴,以再次帮助我们的提示。所以我要在这里放入一些东西,一个命令行工具来玩Marco Polo游戏。这都只是样板代码。这里的要点是,你将一个子命令映射到你在库中创建的函数。这几乎与Python相同,除了我获得了25倍更好的性能。我可以部署二进制文件,以及其他很酷的东西。

完善代码与处理依赖

上一节我们生成了初始代码,本节中我们来看看如何完善代码并处理依赖关系。

一旦我完成了这个,我可以再看看,好的,我想传递一个名字进去,然后会发生的是,我只需让Copilot为我完成其余的工作。看看它会做什么,它说,在这种情况下,有一件事它搞错了。所以现在我们看到它已经能够生成一个合理的建议。但这并不完美,对吧?我想稍微调整一下。所以我要做的是,我不让它在这里打印名字,这不是我真正想做的,对吧?我想发送“Marco Polo”。我要做的是,我会按Tab键,然后说let result =。然后我会引导它注意到我有一个可以在模块中使用的命名空间。这是当你刚开始使用Rust时可能会让你有点困惑的事情之一,比如,嘿,等等,这是什么?这个命名空间是什么?实际上,这是Cargo.toml文件里的内容,对吧?是这个名字。所以你必须将其映射为相同的名字。现在,我可以做的是,我可以说make format,看看如果我格式化我的代码会发生什么,它是否会清理一下代码。这做了什么?它说“fail to use unresolved crate”。嗯,在这种情况下,它应该是已解析的,因为那实际上是……哦,实际上crate名称不正确。linter告诉了我正确的事情。所以我们必须将其改为hello_marco。我们必须说hello_marco。怎么样?好了。所以这就是类比工具的地方,Cargo系统以及Copilot一起工作。格式化工具、linter或所有这些东西一起工作。然后我只需不断迭代以获得解决方案。看,如果linter通过了,我们就处于很好的状态。

编译与运行程序

上一节我们解决了代码问题,本节中我们来看看如何编译和运行我们的Rust程序。

现在我可以使用最后一部分,也就是我可以实际运行cargo来执行它。这很像从Python解释器运行东西。我只需输入cargo run --。如果我们在这里使用双破折号,它会将一些命令传递回我们的程序。现在它将首次编译它。Rust编译器非常棒,因为它做了所有这些非常酷的事情来使你的程序安全且快速。我们可以看到它工作了。现在我可以输入play,我们可以输入Marco,然后它会返回。实际上,出现了意外的参数play,因为我们需要做--name。好了,polo。如果我输入Bob,它会说“你叫什么名字?”,对吧?这是一个很好的反馈循环。再看看这里的target目录。如果我浏览这里,我说target/debug,然后输入./hello_marco。看这里,实际上,我得到了那个可执行文件。所以在我看来,这比常规Python是一个巨大的胜利,因为这个快速的反馈循环,使用Copilot提升水平的能力,以及利用这个现有工具链获得反馈循环。所以这是Copilot提供的新结对编程工具的一个新兴特性。

总结

本节课中我们一起学习了如何利用GitHub Copilot、Visual Studio Code和GitHub Codespaces组成的生态系统来辅助Rust编程。我们看到了如何将Python开发经验迁移到Rust,通过Copilot生成代码、利用Cargo工具链管理依赖和构建,并最终编译运行一个简单的命令行程序。这种组合提供了高效的开发反馈循环,并能让开发者享受到Rust语言在性能、安全性和能效方面的优势。

057:使用Rust包管理进行Web开发 🚀

在本节课中,我们将学习如何从Python包管理系统升级,转而使用Rust的Cargo包管理器和Crate生态系统来构建一个高性能的Web微服务。我们将创建一个简单的计算器服务,并体验Rust在开发效率和部署便捷性上的优势。

从Python包管理升级到Cargo

上一节我们介绍了Python的包管理系统。本节中,我们来看看Rust的Cargo系统。Python的打包方式有很多种,这继承了Perl的特点,但Rust的Cargo和Crate系统在许多方面更简单。使用Rust生态系统,你可以快速开始构建Web微服务、K均值工具、集成Hugging Face模型、使用PyTorch和GPU等。这些功能在Rust生态中都可实现,且方式通常比Python更简单。

我们将使用世界上速度最快的Web框架之一。具体哪个框架最快可能每周都在变化,但这并不重要。关键在于,我们将看到安装它、用Rust构建微服务、运行甚至部署都是非常简单的,因为二进制文件会为我们自动生成。

探索Crate生态系统

对于任何要使用的库,一个常见困扰是安装路径是否友好,或者安装过程是否会非常困难。幸运的是,借助Rust的Crate系统,你可以访问社区Crate注册中心。这里可以看到可用Crate(即包)数量的巨大增长,以及惊人的下载量。

以下是一些关于不同语言库增长趋势的研究发现:

  • Python显然经历了指数级增长。
  • Ruby的增长实际上是对数级的,可能即将进入稳定状态或衰退。
  • 相比之下,Cargo可能正处于大规模指数增长曲线的早期阶段。可以说,Rust生态系统的指数增长甚至比Python的还要快。

选择Web框架

如果你想构建微服务,首先要做的是寻找一个Web框架。在Crate注册中心,你可以查看不同的Web框架。一个实用的方法是关注近期下载量。例如,actix-web框架拥有巨大的下载量。它的描述是“一个强大、实用、快速的Rust框架”。最棒的是,你只需复制配置,就可以将其轻松集成到你的项目中。

查看它的“Hello World”示例,会发现它非常简单,看起来就像Flask或FastAPI。现在,让我们回到GitHub Codespaces,快速启动一个微服务。

构建计算器微服务

我们将构建一个基于Web服务的计算器,这是一个很好的入门方式。

首先,使用以下命令创建一个新的Rust项目:

cargo new calc

这会生成一个Cargo.toml文件。接下来,我们需要将actix-web的依赖项添加到这个文件中。只需从Crate页面复制依赖信息并粘贴进去即可。这个生态系统会自动显示所有内容的版本信息。

现在,我们几乎准备好了。接下来,需要创建一个库文件。

创建库函数

我们将在src/lib.rs文件中构建计算器函数。目标是公开这些函数,以便后续的Web服务可以调用。

以下是核心的计算函数定义:

pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

pub fn subtract(a: i32, b: i32) -> i32 {
    a - b
}

pub fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

pub fn divide(a: i32, b: i32) -> i32 {
    a / b // 注意:实际应用中需处理除零错误
}

代码非常直观:使用pub关键字将函数公开,指定函数名、输入参数及其类型,以及返回值类型。这几乎和Python一样清晰,只是语法略有不同。

创建主Web服务

现在,我们将在src/main.rs文件中编排所有库代码,创建微服务。

首先,引入必要的依赖和定义路由:

use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use calc::*; // 引入我们编写的计算器库

#[get("/")]
async fn home() -> impl Responder {
    HttpResponse::Ok().body("Calculator Microservice")
}

#[get("/add/{a}/{b}")]
async fn add(info: web::Path<(i32, i32)>) -> impl Responder {
    let result = add(info.0, info.1);
    HttpResponse::Ok().body(format!("{}", result))
}

// 类似地,可以定义 subtract, multiply, divide 路由
// ...

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(home)
            .service(add)
            // 注册其他服务...
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}

在这段代码中,我们定义了一个主页路由和加法路由。加法路由从URL路径中提取两个参数,调用库中的add函数,并返回结果。我们可以按照相同模式轻松添加减、乘、除的路由。

最后,在main函数中,我们配置服务器在0.0.0.0:8080上运行,并注册定义好的服务。

运行与测试

代码编写完成后,可以使用cargo run命令运行。如果项目配置了Makefile,也可以使用make run

如果一切顺利,服务将在Github Codespaces的预览中启动。你可以通过访问相应的URL(例如 /add/2/2)来测试功能。如果返回结果4,说明服务运行成功。

使用Rust的一个巨大优势是,一旦代码通过编译,你就可以对其正确性抱有很高的信心。

部署的便捷性

部署过程本质上已经为我们完成了。构建过程会生成一个二进制文件。这种生产优先的思维模式非常有用。你只需要将生成的二进制文件放到服务器上,设置好路由,就可以运行了。

总结

本节课中,我们一起学习了如何使用Rust的Cargo包管理器来升级我们的开发体验。我们探索了蓬勃发展的Crate生态系统,选择了actix-web这一高性能Web框架,并逐步构建、测试并准备部署了一个简单的计算器微服务。整个过程展示了Rust在代码安全性、开发效率和部署简便性上的强大优势,特别是在与Python的Web生态系统对比时,这无疑是一次显著的升级。

058:Rust与Python能效对比 🚀

在本节课中,我们将探讨一个常被忽视但至关重要的主题:编程语言的选择对计算能效的影响。我们将通过具体的研究数据,对比Python与Rust(或C语言)在能耗、计算时间和内存使用方面的表现,并讨论这对于机器学习运维和可持续性发展的意义。


概述

从Python转向Rust时,一个常见的误解是:“Python已经能用了,我不想改变现状,继续用我高效的语言就好。”本节将展示一个具体用例,说明为何许多有识之士应考虑Python语言的能效问题。我们将讨论两项研究:一项是关于不同语言的能耗与时间对比,另一项是关于计算性能的对比。你会发现,在许多场景下,尤其是处理繁重计算负载时,使用Python可能缺乏充分的理由。


编程语言的能效排名 📊

首先,我们来看一篇关于按能效对编程语言进行排名的论文。这项研究从能量角度比较了不同编程语言的效率。

如果我们直接关注核心结论,可以看到两种能效最高的语言是C和Rust。在针对不同操作进行全局结果标准化后,它们基本等效。从计算时间来看,C和Rust的差异也微乎其微。

那么,这与世界上最流行的语言Python相比如何呢?实际上,Ruby、Python和Perl在能耗和使用时间上都非常接近。基本上,Python消耗的能量是Rust的约70倍。在等效的解释型语言中,Python的能效表现也类似。


计算时间与内存使用对比

在计算时间方面,用Python完成某项任务所需的时间大约是Rust的70倍。在内存使用上,Python也存在一些问题。与Rust相比,Python的内存使用量大约是两倍。这还未涉及多线程编程,由于全局解释器锁的存在,Python无法跨多个核心执行多线程,人们通常使用内存密集型操作的多进程方式。

简而言之,如果你关心能耗和计算时间,Python在这两方面的表现都是最差的语言之一。从可持续性发展的角度来看,如果你的组织能轻松切换到Rust,这值得考虑。


计算性能的深度分析 ⚡

接下来,我们深入探讨计算性能的另一个研究。最近,谷歌的David Patterson博士在一次演讲中提到了一个关于矩阵乘法加速的幻灯片。

他提到,根据你编写代码的方式和具体任务,矩阵乘法在优化后可比原生Python代码快上62,000倍。这表明,就计算性能而言,Python并非理想的选择。人们应该考虑替代方案,并评估自身或组织是否有能力采用像Rust这样的语言。

借助Copilot等工具,提升到Rust这类语言的编程水平并非难事。观察语法可以发现,Rust与Python的差异并不大。深入考虑加速和能效,不仅可能对你的预算产生积极影响(例如为云服务节省50-70倍的计算成本),还能体现你对组织可持续性目标的深思熟虑。


总结

本节课我们一起学习了Python与Rust在能效和计算性能上的显著差异。关键点在于:

  1. Python的能耗约为Rust的70倍
  2. Python的计算时间也约为Rust的70倍
  3. 在内存使用和多线程支持上,Python存在固有局限。
  4. 通过优化或切换语言,计算任务可能获得数万倍的性能提升

在机器学习运维中,选择高效的语言不仅关乎成本和性能,更是践行可持续计算的重要一步。希望本节能帮助你更明智地评估和选择适合项目的编程语言。

059:Rust与Python在MLOps中的对比 🦀🐍

在本节课中,我们将探讨在机器学习运维领域采用系统编程思维的重要性,并深入对比两种编程语言——Python和Rust——在解决MLOps核心问题时的不同表现。我们将从性能、效率、部署和语言设计哲学等多个维度进行分析。

概述:系统编程思维与MLOps

上一节我们介绍了MLOps的核心理念。本节中,我们来看看为何需要以“生产优先”的思维来对待机器学习运维。在我看来,MLOps首先是一个系统编程问题。

系统编程通常涉及对性能要求极高的底层操作。例如,Linux操作系统管理笔记本电脑的睡眠与唤醒,就是一种经典的、对性能和能效要求严苛的系统编程。同理,在机器学习运维中,性能同样至关重要。训练模型意味着处理海量数据集并调动庞大的计算资源,我们必须从中榨取尽可能高的效率。如果你的方法效率低下,导致成本比竞争对手高出数十倍,这将会带来严重的问题。

正是在这种对极致性能的追求下,像Rust这样的现代系统编程语言开始展现出其价值。

创新者的窘境与语言选择

在深入技术对比前,我们可以借助“创新者的窘境”这一概念来理解技术演进。克莱顿·克里斯坦森在其著作中指出,成功的公司往往因过于倾听现有客户的需求,而忽视了拥有颠覆性技术的新兴竞争者。

Python无疑取得了巨大的成功。它是目前采用最广泛的编程语言,这一点无可争议。然而,正如创新者的窘境所预示的,我们正看到一些新的颠覆性技术出现。固守“我们是第一”的心态,并非为手头问题寻找最佳解决方案的正确方式。

Python在API文档、代码可读性以及快速完成非计算密集型任务(如文件读写、文本处理)方面表现卓越,是理想的解决方案。但当我们讨论之前提到的系统编程问题时,情况就不同了。

Rust与Python核心特性对比

以下是Rust与Python在多个关键维度的详细对比,这些维度对于MLOps至关重要。

能效与性能

  • Python:在相对能效排名中,Python是能耗最高的语言之一。
  • Rust:近期研究表明,Rust是能效最高的语言之一。

在计算速度方面:

  • Python:是计算速度最慢的语言之一,研究表明其速度可比Rust慢高达70倍
  • Rust:是现有性能最高效的语言之一。

部署与打包

  • Python:没有“二进制部署”的概念,这不是其设计目标。标准库“内置电池”,但打包方案众多且不统一(如virtualenv、Pip、Conda、Poetry等)。
  • Rust:默认支持二进制部署。打包方案是内置且唯一的(cargo)。

开发工具与线程安全

  • Python:解释器适合快速验证想法,但未内置代码格式化工具、Linter或编译器。这些需要额外安装。
  • Rust:默认安装即包含所有这些提升软件工程生产力的工具(rustfmt, clippy, 编译器)。

在并发编程方面:

  • Python:由于历史设计妥协(全局解释器锁GIL),难以充分利用多核CPU进行高效的多线程编程。
  • Rust:编译器能帮助开发者编写安全的并发代码,可以轻松利用所有CPU核心,这对于现代多核机器至关重要。

内存效率与语言安全性

  • Python:内存效率相对较低。使用多进程可改善,但开销较大。类型安全是“后加”的特性,需借助额外工具(如mypy),并非语言原生设计。
  • Rust:内存效率至少是Python的两倍以上。语言从设计之初就以安全为核心,拥有强大的类型系统和所有权模型,能有效防止内存泄漏和数据竞争。

现实场景与应用

理解了这些特性差异后,让我们看一个MLOps中的具体场景。假设你的任务是:将一个Hugging Face预训练模型与一个命令行工具打包,构建一个高性能二进制文件,用于遍历数以百万计的文档并以最低成本进行摘要生成。

这对于Python而言并非最优解,因为Python并非为高效的多线程和系统级资源管理而设计。而Rust则是完成此类任务的理想选择。

此外,一个判断是否为系统编程的简单方法是:看它是否用于开发操作系统内核。Linux内核的开发并未使用Python,但正在引入Rust。这从侧面印证了Rust在系统编程领域的定位。

总结与展望

本节课中,我们一起学习了以系统编程视角看待MLOps的重要性,并详细对比了Python和Rust两种语言。

需要明确的是,这并不意味着Python是一个“差”的语言。恰恰相反,Python是一个取得了惊人成功的杰出语言。然而,过去的成功并不总能预测未来的成功。在MLOps这个对性能、能效和部署有严苛要求的领域,开发者时间比计算时间更宝贵的观点,在多核机器和MLOps时代之前或许成立,但今天已非如此。可持续性(包括计算效率和能源效率)变得非常重要。

Rust作为一种现代语言,正是为可持续的高性能系统编程而设计。因此,我相信对于MLOps中的许多核心挑战,Rust是正确的语言选择。它代表了应对当前及未来机器学习运维规模化挑战的一种颠覆性思路。

060:使用GitHub Actions实现Rust持续集成 🚀

在本节课中,我们将学习如何为一个Rust项目设置GitHub Actions持续集成(CI)流程。我们将从创建项目模板开始,逐步配置自动化测试、代码格式化和代码检查,最终实现一个完整的CI工作流。


创建新项目与仓库

首先,我们需要创建一个新的项目模板,用于设置GitHub Actions的持续集成。GitHub Actions是一种自动化测试和部署代码的方式。

以下是创建新仓库的步骤:

  1. 使用提供的模板创建一个新的代码仓库。
  2. 将仓库命名为 github-actions-rust-example
  3. 在描述中注明“构建和测试一个Rust项目”。

从一开始就为新项目设置持续集成,是DevOps的最佳实践。这有助于更快地构建微服务,因为持续集成提供了一个质量控制流程,可以持续改进代码质量。

接下来,我将创建一个新的GitHub Codespace环境。Rust编译能从强大的机器中受益,因此我将使用一台16核的机器,以便编译过程能快速进行。这个环境将为我设置一个基于Rust的开发环境,允许我在其中构建代码,并允许我推送更改以测试GitHub Actions工作流。


在Codespace中初始化项目

现在,我们位于GitHub Codespace环境中。通过输入 which cargo 命令,可以确认Cargo(Rust的包管理器)已经准备就绪。

以下是初始化Rust项目的步骤:

  1. 使用 cargo new test_rust 命令创建一个名为“test_rust”的新项目。
  2. 使用 touch src/lib.rs 命令创建库文件。
  3. 使用 mkdir -p tests 命令创建测试目录。
  4. 使用 touch tests/test_lib.rs 命令在测试目录中创建测试文件。

项目结构搭建完成后,接下来需要添加一些代码。我将从另一个项目中复制代码并粘贴进来。

  • 将主程序代码粘贴到 src/main.rs 文件中。
  • 将库函数代码粘贴到 src/lib.rs 文件中。
  • 将测试代码粘贴到 tests/test_lib.rs 文件中。

粘贴完成后,需要对代码进行一些小的调整。例如,将测试模块的名称从 unit_test 改为 test_rust。Rust语言的一个优点是它优秀的工具链支持,我们可以使用查找替换功能轻松完成这个修改。


配置Makefile与本地验证

因为我们有一个Makefile,所以可以运行不同的命令来管理项目。

以下是Makefile支持的命令及其作用:

  • make format:格式化所有代码。
  • make lint:运行代码检查,确保代码符合规范。
  • make test:运行所有测试用例。

在本地运行 make lintmake test 后,确认所有检查都通过,测试也全部成功。这验证了我们的代码在本地是健康的。

现在,最关键的一步是验证我们的GitHub Actions工作流能否成功运行。工作流配置文件(位于 .github/workflows/ 目录下)定义了CI流程,它将在Ubuntu系统上运行,拉取Rust工具链,并依次执行 make lintmake formatmake test 等命令。

由于我们已经在本地测试了这些步骤,因此可以确信它们在CI环境中也能正常工作。我们注意到工作流中有一个 make format-check 步骤,但我们的Makefile中没有定义它。因此,我们可以稍作调整,将其改为 make format


提交代码并触发CI流程

所有配置修改完成后,需要将更改提交到仓库以触发GitHub Actions。

以下是提交代码的步骤:

  1. 运行 git status 查看更改。
  2. 使用 git add .githubgit add * 等命令添加所有更改的文件。
  3. 运行 git commit -m “Ready for continuous integration” 提交更改。

提交完成后,推送操作会自动触发GitHub Actions工作流。我们可以转到仓库的“Actions”标签页查看运行情况。


查看与分析CI结果

在“Actions”页面,我们可以看到由刚才的提交触发的工作流正在运行。系统将逐步验证所有配置的步骤。

GitHub Actions的一个优点是每个步骤都是独立且清晰的。我们可以看到以下步骤:

  • 构建二进制发布版:此步骤目前不是我们关注的重点。
  • 代码检查(Linting):显示成功。
  • 代码格式化(Formatting):显示成功。
  • 测试(Testing):显示成功。

所有核心步骤(代码检查、格式化、测试)都显示为成功状态。我们还可以为这个成功的工作流创建一个状态徽章(Status Badge)。这是一个很好的实践,可以直观地向所有人展示项目代码的质量状态。

我们可以复制徽章的Markdown代码,并将其添加到项目的README文件中,例如:

# GitHub Actions Rust CI 示例
这是一个使用GitHub Actions测试Rust代码的CI流水线示例。
[![CI Status](https://github.com/your-username/repo-name/actions/workflows/rust.yml/badge.svg)](https://github.com/your-username/repo-name/actions)


总结:持续集成的核心

本节课中,我们一起学习了为Rust项目设置GitHub Actions持续集成的完整流程。

持续集成的核心在于:

  1. 本地开发与验证:在本地编写代码,并使用Makefile等工具运行测试、格式化和检查,确保代码质量。
  2. 自动化流程:将本地验证的步骤(通过 make all 可以一次性运行)配置到自动化构建系统(如GitHub Actions)中,确保每次代码提交都能自动执行这些质量关卡。
  3. 状态可视化:通过状态徽章公开分享构建状态,向协作者和用户表明代码处于高质量且可用的状态。

这是DevOps实践中持续集成(Continuous Integration) 的基础组成部分。建立好这个基础后,你就可以在此基础上进一步实现持续交付(Continuous Delivery),自动化地将代码部署到生产环境。整个设置过程是直接且高效的。

061:Rust单元测试演示 🦀

在本节课中,我们将学习如何为一个Rust项目构建单元测试。我们将从创建一个新项目开始,逐步构建一个包含数学运算的库,并为其编写测试。最后,我们将使用Makefile来组织构建和测试流程,实现可重复的自动化。

项目初始化与结构搭建

首先,我们需要创建一个新的Rust项目。在终端中执行以下命令:

cargo new trust
cd trust

初始项目只包含一个 main.rs 文件。为了组织代码,我们需要为测试和库代码创建专门的结构。

以下是创建项目结构的步骤:

  1. 创建一个名为 tests 的目录来存放测试文件。
  2. tests 目录下创建一个空的测试文件 test_lib.rs
  3. src 目录下创建库文件 lib.rs

创建完成后,项目结构应如下所示:

trust/
├── Cargo.toml
├── src/
│   ├── lib.rs
│   └── main.rs
└── tests/
    └── test_lib.rs

编写库函数

上一节我们搭建了项目结构,本节中我们来看看如何编写核心的库函数。我们将创建一个简单的计算器库,包含加、减、乘、除四个基本函数。

打开 src/lib.rs 文件,并添加以下代码:

pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

pub fn subtract(a: i32, b: i32) -> i32 {
    a - b
}

pub fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

pub fn divide(a: i32, b: i32) -> i32 {
    a / b
}

编写单元测试

现在库函数已经就绪,接下来我们为它们编写单元测试。单元测试能帮助我们验证代码逻辑是否正确,并确保后续修改不会引入错误。

打开 tests/test_lib.rs 文件。首先,我们需要导入要测试的库模块。

use trust::{add, subtract, multiply, divide};

#[test]
fn test_add() {
    assert_eq!(add(2, 2), 4);
}

#[test]
fn test_subtract() {
    assert_eq!(subtract(5, 3), 2);
}

#[test]
fn test_multiply() {
    assert_eq!(multiply(3, 4), 12);
}

#[test]
fn test_divide() {
    assert_eq!(divide(10, 2), 5);
}

使用Makefile实现自动化

手动运行测试和检查代码格式虽然可行,但为了构建可重复的自动化流程,使用Makefile是一个好方法。Makefile可以将编译、测试、代码检查等步骤封装起来。

在项目根目录创建一个 Makefile 文件,内容如下:

.PHONY: all test lint format run clean

all: lint test

test:
	cargo test

lint:
	cargo clippy -- -D warnings

format:
	cargo fmt --all -- --check

run:
	cargo run

clean:
	cargo clean

这个Makefile定义了以下几个命令:

  • make test: 运行所有单元测试。
  • make lint: 使用Clippy进行代码静态分析,检查潜在问题。
  • make format: 检查代码格式是否符合rustfmt标准。
  • make run: 编译并运行主程序。
  • make all: 依次执行代码格式检查、静态分析和测试,这是提交代码前的完整检查流程。
  • make clean: 清理编译产物。

现在,你可以通过简单的命令来执行整个质量保证流程。例如,运行 make all 会依次进行代码格式化检查、静态分析和单元测试。

集成与运行主程序

最后,让我们修改 src/main.rs 文件,使其调用我们编写的库函数,从而验证整个项目的集成情况。

src/main.rs 的内容替换为以下代码:

use trust::{add, subtract, multiply, divide};

fn main() {
    println!("2 + 3 = {}", add(2, 3));
    println!("5 - 2 = {}", subtract(5, 2));
    println!("3 * 4 = {}", multiply(3, 4));
    println!("8 / 2 = {}", divide(8, 2));
}

现在,你可以使用 cargo runmake run 来运行程序,并看到计算结果输出。

总结

本节课中我们一起学习了如何为一个Rust项目构建完整的单元测试流程。我们从创建项目结构开始,编写了包含基本数学运算的库函数,并为每个函数编写了对应的单元测试。通过引入Makefile,我们将测试、代码检查和格式化等步骤自动化,形成了一个可靠且可重复的质量保证流程。这种模式是构建稳健软件的基础,可以轻松集成到持续集成/持续部署(CI/CD)系统中,例如GitHub Actions,为后续的微服务开发和持续交付奠定坚实基础。

062:使用Rust构建去重工具

在本节课中,我们将学习如何使用Rust编程语言构建一个高性能、内存效率高的数据去重工具。我们将探讨Rust在数据工程领域的优势,并逐步解析一个实际项目的结构与核心代码。

概述

数据工程是典型的系统编程问题,而Rust是一门系统编程语言。与脚本语言相比,Rust能够构建出多线程、高效、低内存占用且可移植的响应式工具。本节课将通过构建一个文件去重工具,展示Rust在构建高性能数据工程工具方面的能力。

Rust在数据工程中的优势

上一节我们介绍了Rust作为系统编程语言的定位,本节中我们来看看它具体为何适合数据工程任务。

Rust相比Python等脚本语言的关键优势在于能够构建高性能工具。在处理例如PB级文件服务器或Amazon EFS等场景时,高效利用内存和高性能代码至关重要。Rust的代码执行速度可比Python快70倍,并且由于线程间共享内存,其内存占用极低。

我们的目标是:在20核的Mac上运行时,能够充分利用所有核心,而非仅使用一个核心来回切换。同时,工具应具备进度条显示功能,能够分发可移植的二进制文件,并且速度极快、效率极高,从而构建出高性能的数据工程工具。

项目结构与开发流程

了解了目标后,我们来看看如何组织一个典型的Rust数据工程项目。

以下是构建此类高性能二进制文件并分发给他人使用的推荐项目结构:

  • 开发容器:配置开发容器,便于与他人共享项目并确保一致的测试环境。
  • Makefile自动化:使用Makefile集成常用命令。
    • make lint:在每次代码变更后运行代码检查。
    • make release:构建高性能的发布版本二进制文件,便于分发给他人。
    • make format:确保代码格式正确。
    • make test:运行测试,确保不引入业务逻辑问题。
  • 项目文档:在项目中提供相关链接和说明。这种模式相比Python有巨大优势,因为Python无法直接分发二进制文件,必须提供详细的软件安装说明。

代码解析:核心库

现在,让我们深入代码,看看这个去重工具是如何实现的。我们首先分析核心逻辑所在的库文件。

我倾向于将主要逻辑放在库(lib)中,然后通过命令行工具来调用它。这种模式非常适合数据工程。

Cargo.toml文件中,我们定义了项目依赖,包括用于开发和生产环境的配置、命令行参数解析、目录遍历、校验和计算、高效线程池以及与线程池交互的进度条。这个模式对于构建其他工具也非常有用。

以下是库文件中的核心函数:

遍历目录:该函数接受一个路径字符串,并返回一个文件路径的向量(Vec<String>)。其代码与Python实现差异不大。

pub fn walk_directory(path: &str) -> Result<Vec<String>, Box<dyn Error>> {
    // ... 遍历目录并收集文件路径 ...
}

模式匹配:用于根据模式过滤文件。代码量很少,同样与Python类似。

pub fn filter_files_by_pattern(files: Vec<String>, pattern: &str) -> Vec<String> {
    // ... 使用通配符模式匹配过滤文件 ...
}

计算校验和:这个函数稍复杂一些。它计算文件的校验和,同时集成了进度条来显示处理进度。最后,将所有结果放入一个字典(HashMap)中返回。

pub fn calculate_checksums(files: Vec<String>, progress_bar: &ProgressBar) -> Result<HashMap<String, Vec<String>>, Box<dyn Error>> {
    // ... 多线程计算文件校验和,并更新进度条 ...
}

查找重复项:最后,我们检查上述返回的字典,如果同一个校验和对应多个文件,则将其报告为重复项。这就是最终的输出结果。

pub fn find_duplicates(checksums: HashMap<String, Vec<String>>) -> Vec<Vec<String>> {
    // ... 筛选出校验和出现次数大于1的文件组 ...
}

代码解析:主程序与执行

核心逻辑封装好后,我们来看看主程序如何将它们组织起来并执行。

在主文件(main.rs)中,开头有一些样板代码。重要的是命令映射部分:

  1. 定义命令:我们定义了search(搜索)、ddupe(去重)、count(计数)等命令。
  2. 映射执行逻辑:在这里,我们将这些命令映射到对应的库函数上。例如,ddupe命令就精确地映射到了我们刚才在库中看到的去重逻辑。

这种模式使得构建极其强大且内存高效的工具变得非常可行。

总结

本节课中我们一起学习了如何使用Rust构建一个高性能的文件去重工具。我们探讨了Rust在数据工程中相比脚本语言的优势,包括其高性能、低内存占用和强大的并发能力。我们分析了一个实际项目的结构,包括开发容器、Makefile自动化的最佳实践,并逐步解析了从目录遍历、文件过滤、校验和计算到重复项查找的核心代码逻辑。最后,我们看到了如何通过主程序将各个模块组织成一个完整的命令行工具。总而言之,使用Rust构建高性能的数据工程工具是直接且高效的,希望你能尝试实践。

063:Rust与Hugging Face零样本分类 🚀

在本节课中,我们将学习如何利用Rust语言和Hugging Face生态系统构建一个高性能的机器学习运维应用。具体来说,我们将创建一个歌词分析器,它能从文件中读取歌词,使用零样本分类模型进行分析,并将结果存入SQLite数据库。我们将看到Rust如何以其卓越的性能和“生产优先”的特性,成为MLOps的理想选择。


为什么选择Rust进行MLOps?⚡

上一节我们介绍了课程目标,本节中我们来看看为什么Rust是机器学习运维的绝佳语言。

机器学习运维的核心是将模型从开发环境部署到生产环境。许多人认为Python是机器学习的主导语言,但Rust在这方面展现出巨大潜力。

Rust是进行机器学习运维的优秀候选语言,因为它为许多常用操作提供了绑定。例如,PyTorch可以非常方便地与GPU协同工作。事实上,Rust在许多操作上的速度平均可以达到Python的70倍

Rust的另一个优势是其二进制可移植性。从项目伊始,Rust就秉持“生产优先”的理念。你可以将一个模型打包成二进制文件,然后直接部署到生产环境。这与Python常说的“生产优先”不同,Rust在模型和二进制可移植性上提供了更实际的解决方案。

对于像Hugging Face这样的应用,使用Rust的优势在于:能耗更低计算时间更短,并且可以利用多线程编程充分发挥所有核心的性能。如果你需要分析数百万首歌曲并进行摘要或零样本分类,就应该使用高性能语言,而不是有史以来最慢的语言之一。

因此,Rust是高性能MLOps的绝佳工具。接下来,我将展示如何结合Hugging Face来实现。


项目架构概述 🏗️

上一节我们探讨了Rust的优势,本节中我们来看看一个具体的生产系统架构示例。

假设我是一家音乐公司,文件存储系统中有数百万首歌曲。我想使用现代大语言模型来分类我的唱片收藏,以便从中获利或用于推荐引擎。

以下是该系统可能的架构:

首先,需要一个SQL数据库,其中包含一些零样本分类的候选类别。例如:摇滚、流行、嘻哈、乡村、拉丁等。你可以在这里放入任何想要的类别,核心思想是拥有一些初始分类。

接下来,需要以尽可能快和高效的方式转录那数百万首歌曲。你肯定不希望花费数百万美元进行转录。这正是基于Rust的方法大显身手的地方。Rust在多线程代码方面性能卓越,如果你想爬取文件系统、查看所有不同的歌曲,然后以极高的内存和计算效率转录它们,这就是正确的方法。

获得转录文本后,可以再次将其传入Rust的Hugging Face绑定库进行零样本分类。最终,可以将分类结果存回SQL数据库。这是一个非常真实的生产系统。也许已经有人这么做了,但我们将亲手构建它。


开始构建:环境与依赖设置 🛠️

上一节我们规划了系统架构,本节中我们开始动手搭建开发环境并初始化项目。

我们将借助Copilot和Cargo生态系统的力量来加速开发。第一步是在GitHub中构建,使用强大的Codespace实例,并遵循“提示 -> 代码生成 -> 格式化 -> 检查 -> 测试 -> 运行 -> 部署”的工作流,Copilot将在“提示”环节协助我们。

首先,让我们查看Rust的相关库。rust-bert库提供了即用的NLP流水线和语言模型。需要指出的是,有人认为Rust缺乏MLOps库,但这并不正确。rust-bert库允许你使用PyTorch,同时rust-tokenizers提供了预处理功能。rust-tokenizers的第一句话就是:“得益于Rust实现,速度极快”。正因为性能优势,Rust在Hugging Face中被大量使用,这是关键的MLOps能力。

同样,查看rust-bert的示例,你会发现它的语法非常简洁,在很多方面看起来就像Python。我们只需要复制代码就可以开始。

现在,我们在新目录中构建项目。打开一个Codespace环境,然后创建新项目:

cargo new sqlite_hf
cd sqlite_hf

接下来,我们需要配置Cargo.toml文件以添加依赖。以下是所需的依赖项:

[dependencies]
rust-bert = "0.21.0"
tokio = { version = "1.0", features = ["full"] }
rusqlite = "0.30.0"
anyhow = "1.0"

然后,创建必要的项目文件结构:

touch src/lib.rs
touch lyrics.txt

lyrics.txt中,我们可以粘贴一些喜欢的歌曲歌词,作为我们分析的测试数据。


核心代码实现:数据库与歌词处理 📝

上一节我们设置了项目基础,本节中我们开始编写核心功能代码:初始化数据库和读取歌词。

首先,在lib.rs中开发我们的库代码。提示词在借助Copilot开发时非常关键。我们的第一个提示可以是:“使用Hugging Face库分析歌曲歌词,并将其放入SQLite数据库”。

为了演示方便,我将直接导入已知有用的库。首先,创建第一个零样本分类的候选类别。以下代码演示了如何在内存中创建SQLite数据库并插入候选类别(在实际世界中,我们会持久化到磁盘):

use rusqlite::{Connection, Result};

pub fn initialize_database() -> Result<Connection> {
    let conn = Connection::open_in_memory()?; // 实际应用应持久化
    conn.execute(
        "CREATE TABLE IF NOT EXISTS zero_shot_candidates (
            id INTEGER PRIMARY KEY,
            category TEXT NOT NULL UNIQUE
        )",
        [],
    )?;

    let categories = vec!["rock", "pop", "hip hop", "country", "latin"];
    for category in categories {
        conn.execute(
            "INSERT OR IGNORE INTO zero_shot_candidates (category) VALUES (?)",
            &[&category],
        )?;
    }
    Ok(conn)
}

查询SQLite数据库在Rust中非常简单,代码看起来很像Python:

pub fn get_all_candidates(conn: &Connection) -> Result<Vec<String>> {
    let mut stmt = conn.prepare("SELECT category FROM zero_shot_candidates")?;
    let category_iter = stmt.query_map([], |row| row.get(0))?;

    let mut categories = Vec::new();
    for category in category_iter {
        categories.push(category?);
    }
    Ok(categories)
}

接下来,我们需要从文件中读取歌词。以下函数从指定文件路径读取歌词,并返回一个字符串向量:

use std::fs;
use anyhow::Result as AnyResult;

pub fn read_lyrics_from_file(file_path: &str) -> AnyResult<Vec<String>> {
    let contents = fs::read_to_string(file_path)?;
    // 假设每行歌词是一个条目,或根据实际情况分割
    let lines: Vec<String> = contents.lines().map(String::from).collect();
    Ok(lines)
}

关于Rust的一个有趣之处是let关键字用于创建不可变变量。这是一个安全机制,能使你的代码更加健壮。


集成Hugging Face进行零样本分类 🤖

上一节我们处理了数据和数据库,本节中我们集成Hugging Face模型来完成核心的零样本分类任务。

现在,我们可以使用Hugging Face生态系统来构建分类功能。我们将创建一个函数,接收歌词字符串向量(对于Python用户来说,这就像一个可变列表)并进行分类。

以下是使用rust-bert进行零样本分类的示例代码框架:

use rust_bert::pipelines::zero_shot_classification::ZeroShotClassificationModel;
use anyhow::Result as AnyResult;

pub fn classify_lyrics(lyrics: Vec<String>, candidates: Vec<String>) -> AnyResult<Vec<String>> {
    // 创建零样本分类模型(首次运行会下载模型)
    let model = ZeroShotClassificationModel::new(Default::default())?;

    // 假设我们将所有歌词连接成一个文本进行分析
    // 实际应用中可能需要更精细的处理,如分句或分段
    let combined_text = lyrics.join(" ");

    // 执行零样本分类
    let output = model.predict(
        vec![combined_text],   // 输入文本
        candidates,            // 候选标签
        None,                  // 假设使用默认的假设模板
        1,                     // 每个输入返回的标签数量
    )?;

    // 处理结果,这里简单返回第一个(也是唯一一个)输入的顶级标签
    let result_labels: Vec<String> = output[0]
        .iter()
        .map(|classification| classification.text.clone())
        .collect();

    Ok(result_labels)
}

最后,我们可以在main.rs中组合所有这些功能:

use sqlite_hf::{initialize_database, get_all_candidates, read_lyrics_from_file, classify_lyrics};
use anyhow::Result;

#[tokio::main]
async fn main() -> Result<()> {
    // 1. 初始化数据库并获取候选类别
    let conn = initialize_database()?;
    let candidates = get_all_candidates(&conn)?;
    println!("候选分类: {:?}", candidates);

    // 2. 从文件读取歌词
    let lyrics = read_lyrics_from_file("lyrics.txt")?;
    println!("已读取 {} 行歌词。", lyrics.len());

    // 3. 使用Hugging Face模型分类歌词
    let classification_results = classify_lyrics(lyrics, candidates)?;
    println!("分类结果: {:?}", classification_results);

    // 4. (可选)将结果存回数据库...
    // ...

    Ok(())
}

我们可以运行cargo run来构建和测试,或者运行cargo make(如果配置了)来执行更完整的检查流程。


总结 🎯

本节课中,我们一起学习了如何利用Rust构建一个完整的MLOps应用。我们从解释Rust在性能、能效和“生产优先”理念上的优势开始,然后设计了一个用于分析海量歌曲歌词的系统架构。通过动手实践,我们逐步实现了SQLite数据库的初始化、歌词文件的读取,并最终集成了Hugging Face的零样本分类模型。

这个原型虽然简单,但展示了Rust在高性能、并发处理和资源效率方面的强大能力,使其能够轻松扩展到处理数百万用户和文档的真实生产场景。你已掌握了使用Rust进行机器学习运维的基础,可以继续探索更复杂的模型、数据库持久化或分布式处理。

064:Rust-GPU-Hugging Face 翻译器 🚀

在本节课中,我们将学习如何结合 Rust 编程语言、GPU 加速以及 Hugging Face 的预训练模型,快速构建一个高性能的批量文本翻译工具。我们将使用 GitHub Codespaces 的 GPU 环境,通过 Rust 绑定来调用 Hugging Face 的模型,实现西班牙语到英语的快速翻译。


概述与架构

上一节我们介绍了 MLOps 中的多种工具链。本节中我们来看看如何利用 Rust 的高性能特性进行机器学习推理。

使用 Rust 最强大的方式之一,是深入使用预训练模型和 GPU,构建高性能的命令行工具,以进行批量机器学习推理。我将向你展示,在启用 GPU 的 GitHub Codespaces 中,为其构建 Rust 绑定,并在几分钟内构建出一个翻译工具是多么简单。

我们即将构建的架构如下:

  1. 在 Codespaces 中启用 GPU。
  2. 使用 Hugging Face 的 Rust 绑定库。
  3. 结合两者,将一首西班牙语歌曲翻译成英语。
    整个过程仅需几秒钟,并且可以观察到 GPU 被有效利用。对于希望构建批量机器学习工具的人来说,Rust + GPU + Hugging Face 是一个理想的解决方案。

环境与依赖设置

首先,我们需要一个配置好的开发环境。以下是设置步骤:

以下是启动和验证环境的步骤:

  1. 使用一个预配置的代码仓库模板,它包含了在 Codespaces 中使用 GPU 所需的一切。
  2. 启动 Codespace 后,首先运行命令 nvidia-smi -l 1 来监控 GPU 状态。初始时 GPU 应处于空闲状态。
  3. 进入项目目录,查看代码结构。

项目代码解析

现在,让我们深入查看翻译工具的项目代码。项目主要包含库(lib)和主程序(main)两部分。

依赖配置

项目的依赖关系在 Cargo.toml 文件中定义,非常简单:

[dependencies]
rust-bert = "0.21.0"  # Hugging Face 模型的 Rust 绑定
clap = { version = "4.4", features = ["derive"] }  # 命令行参数解析
anyhow = "1.0"  # 简化错误处理

核心库函数

库文件(lib.rs)中定义了核心功能:

  1. 读取文件为字符串:一个基础函数,用于读取文件内容。
    pub fn read_file_to_string(path: &str) -> Result<String, anyhow::Error> {
        std::fs::read_to_string(path).map_err(|e| e.into())
    }
    
  2. 读取文件为文本行数组:将文件按行读取,便于批量送入翻译模型。
    pub fn read_file_to_lines(path: &str) -> Result<Vec<String>, anyhow::Error> {
        let content = read_file_to_string(path)?;
        Ok(content.lines().map(String::from).collect())
    }
    
  3. 翻译函数:这是核心函数,它创建翻译管道,指定源语言(西班牙语)和目标语言(英语),然后对输入的文本行数组进行批量翻译。
    pub fn translate_spanish_to_english(texts: Vec<String>) -> Result<Vec<String>, anyhow::Error> {
        // 创建翻译管道
        let translation_model = rust_bert::pipelines::translation::TranslationModel::new(
            rust_bert::pipelines::translation::TranslationConfig::new(
                rust_bert::pipelines::translation::Language::Spanish,
                rust_bert::pipelines::translation::Language::English,
            ),
        )?;
    
        // 执行翻译并返回结果
        let output = translation_model.translate(&texts);
        Ok(output)
    }
    

命令行界面

主程序(main.rs)使用 clap 库来构建命令行工具,将库中的函数映射为子命令:

use clap::{Parser, Subcommand};

#[derive(Parser)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// 翻译指定文件中的西班牙语文本
    Translate { path: String },
    /// 打印文件内容
    Print { path: String },
}

fn main() -> Result<(), anyhow::Error> {
    let cli = Cli::parse();
    match cli.command {
        Commands::Translate { path } => {
            let lines = mylib::read_file_to_lines(&path)?;
            let translated = mylib::translate_spanish_to_english(lines)?;
            for line in translated {
                println!("{}", line);
            }
        }
        Commands::Print { path } => {
            let content = mylib::read_file_to_string(&path)?;
            println!("{}", content);
        }
    }
    Ok(())
}

这种模式非常强大,可以轻松扩展更多功能。


运行与效果验证

一切就绪后,让我们运行这个工具并观察其性能。

以下是运行翻译和验证 GPU 使用的步骤:

  1. 首先,可以通过运行 cargo run -- --help 来查看工具的使用帮助。
  2. 在运行翻译前,在另一个终端窗口运行 nvidia-smi -l 1 以实时监控 GPU 利用率。
  3. 执行翻译命令,例如:cargo run -- translate ./lyrics.txt,其中 lyrics.txt 包含西班牙语歌词。
  4. 观察过程:翻译在几秒内完成,同时在监控终端可以看到 GPU 使用率出现峰值,证明计算任务被成功卸载到了 GPU 上。

这个实践清晰地展示了 Rust、GPU 和 Hugging Face 组合的威力:你可以构建出远超 Python 等解释型语言运行速度的批量处理工具。


总结

本节课中我们一起学习了如何搭建一个基于 Rust、GPU 和 Hugging Face 的批量文本翻译工具。我们从环境配置开始,逐步解析了项目的依赖管理、核心库函数(包括文件读取和模型调用)以及命令行接口的构建。最后,我们成功运行了工具,并验证了其利用 GPU 进行高速推理的能力。这个流程为构建高性能的批量机器学习应用提供了一个高效、可复用的模板。

065:Rust、GPU、PyTorch与Stable Diffusion实践 🚀

在本节课中,我们将学习如何利用Rust语言,结合PyTorch和Hugging Face生态,来运行高性能的Stable Diffusion图像生成模型。我们将看到Rust如何通过其出色的性能、可移植性和打包能力,为深度学习研究和应用部署提供强大支持。


深度学习与Rust的机遇

机器学习领域最令人兴奋的发展之一是深度学习。从大语言模型到使用Stable Diffusion进行文生图等,涌现了许多令人惊叹的技术。Python程序员们已经从中获得了许多乐趣。

然而,Rust语言的一个有趣之处在于,你同样可以在Rust中使用PyTorch和Hugging Face。事实上,在某些情况下,其速度至少可以快70倍。如果你关心可移植性性能,或者需要将预训练模型打包后分发给他人,Rust在许多方面是无可替代的选择。Rust可以轻松地将所有组件打包在一起,并利用Cargo等出色的工具进行管理和执行不同任务。

因此,在某种程度上,如果你想要一个高性能的深度学习研究环境,Rust是一个非常优秀的工具。


实践步骤:在Rust中运行Stable Diffusion

接下来,我们将一步步学习如何在Rust中实际使用带有PyTorch绑定的Stable Diffusion模型。我们还将演示如何调用GPU,并观察其在GitHub Codespaces环境中的使用情况。

项目与工具概览

我们使用Laurent Mazare维护的 tch-rs 包。这个包的出色之处在于它能非常好地将Rust与PyTorch绑定,包括执行GPU操作。其原理是绑定到PyTorch的C++ API。

以下是使用它的一个关键步骤:设置环境变量。例如,我设置了以下变量,从而成功启用了GPU支持:

export LIBTORCH=/path/to/libtorch
export LD_LIBRARY_PATH=${LIBTORCH}/lib:$LD_LIBRARY_PATH

通过 tch-rs,你可以训练模型,也可以使用预训练模型。我们最终的目标是运行Stable Diffusion示例来生成图像。


环境配置与代码执行

我将使用我的一个仓库模板,该模板已启用GPU支持。在Codespaces环境中,最大的收获是:通过一些设置代码,我能够将Torch CUDA的环境变量配置到bash或shell中。完成此步骤并pip install安装PyTorch后,Rust就能与Stable Diffusion协同工作了。

我们只需进入stable diffusion目录。我提前下载了所有权重数据,这是过程中比较棘手的一步。之后,便可以按照笔记执行。

现在,让我们打开一个终端,并使用以下命令实时监控GPU使用情况:

nvidia-smi -l 1

目前GPU使用率为0。


运行图像生成

接下来,我们运行以下命令来生成图像。我们将使用提示词“rusty code in the ocean”:

cargo run --example stable_diffusion -- "rusty code in the ocean"

运行后,我们将看到GPU使用率迅速上升并达到饱和状态。这个过程展示了高性能代码的魅力:我们可以利用Stable Diffusion这样的尖端库,直接与GPU通信,快速构建原型。

系统会依次构建Transformer和Autoencoder。完成后,图像文件将保存在 diffusers 目录下。例如,我们生成了名为 rusty_code_in_the_ocean.png 的图片。

我们可以轻松地修改提示词,快速生成新的图像。例如,将提示词改为“Python is so slow but rust is so fast”,然后再次运行命令,就能得到新的结果。


核心优势与总结

即使不是Rust专家,也可以像我一样,复现Stable Diffusion的示例链接,并将其作为一个原型工具来使用。这展示了利用Rust生态系统的广泛可能性。

本节课中,我们一起学习了:

  1. Rust在深度学习领域的高性能和可移植性优势。
  2. 如何通过 tch-rs 包在Rust中绑定并使用PyTorch(包括GPU支持)。
  3. 一步步配置环境并运行Stable Diffusion模型来生成图像。
  4. 观察了GPU在代码执行过程中的利用率变化。

Rust凭借其强大的性能、安全的并发模型和卓越的打包工具Cargo,为机器学习运维和高效原型开发提供了极具吸引力的选择。希望你能尝试一下这个强大的技术栈。

066:Rust与PyTorch演示 🦀🔥

在本节课中,我们将学习如何在生产环境中使用Rust语言结合PyTorch进行机器学习模型的训练与推理。我们将探讨Rust的实际应用价值,并通过具体示例展示其与GPU加速和现代部署技术的结合。


概述

很多人对在生产环境中使用Rust存在顾虑,认为它是一门较新的语言。然而,Rust自2010年诞生以来,已在诸多关键系统中得到验证。本节课旨在消除这些疑虑。我们将演示如何使用Rust的PyTorch绑定进行模型训练,并利用GPU加速。同时,我们也将介绍由AWS开发、用于支撑AWS Lambda服务的Firecracker微虚拟机技术,说明Rust如何支撑起大规模、高并发的生产级服务。


Firecracker:AWS Lambda的基石

上一节我们提到了Rust在生产环境中的可行性,本节中我们来看看一个关键例证:Firecracker。

Firecracker是一项由AWS开发的基于服务器的技术,专门用于支撑其无服务器计算服务AWS Lambda。考虑到AWS在云计算领域的领先地位,其最受欢迎的服务之一选择用Rust构建,这足以证明Rust在生产环境中的能力和可靠性。

Firecracker是一个轻量级虚拟化方案,专为无服务器计算设计。它具有以下显著优势:

  • 可以在125毫秒内启动一个微虚拟机。
  • 经过实战检验,系统开销极低。
  • 是一个开源项目。

如果我们查看其源代码架构,会发现这是一个用Rust构建的非常复杂的系统。Firecracker能够在一个实例上运行数千个多租户微虚拟机,是一种极其高效的虚拟化实现方式。这项技术非常适合用于机器学习模型的推理服务部署。


Rust PyTorch GPU绑定实战

既然我们知道了PyTorch提供了Rust绑定,并且有Firecracker这样的Rust技术栈,接下来让我们深入实际,看看如何在Rust中使用PyTorch进行GPU加速计算。

我将通过一个代码空间来演示,使用Rust PyTorch GPU绑定实际上非常简单。

以下是几个可供探索的项目示例:

  • portable-pytorch:一个致力于模型便携性的项目。
  • pytorch-mnist:一个使用Rust训练MNIST数据集的示例。

我们首先进入pytorch-gpu目录,运行一个压力测试。在终端中执行命令 cargo run --features gpu。同时,我们可以打开另一个终端,运行 nvidia-smi -l 1 来实时监控GPU利用率。

我们可以看到,GPU很快就被完全占用。这段Rust代码有效地饱和了GPU的计算能力。如果我们查看源代码,会发现实现非常简洁:

// 示例代码:在Rust中指定PyTorch张量使用GPU
let device = Device::Cuda(0);
let tensor = Tensor::randn(&[1000, 1000], (Kind::Float, device));

代码量很少,就能实现针对GPU的操作。这主要借鉴了Rust PyTorch绑定主要作者的示例。

另一个有趣的例子是训练一个完整的模型。我们进入pytorch-mnist目录。查看其源代码,主要文件是一个卷积神经网络(CNN)的实现。

在代码中,我们导入必要的绑定,设置网络结构,定义训练循环,最后构建并运行神经网络。其逻辑与Python版的PyTorch代码并无太大差异。

运行训练命令后,我们可以再次通过nvidia-smi观察到GPU被迅速占用并用于模型训练。这表明,使用Rust这种高性能系统编程语言来训练深度学习模型是完全可行且高效的。


Rust PyTorch的优势与MLOps实践

我的使用经验表明,Rust的PyTorch绑定质量非常高。此外,它还有一些额外优势:

  1. 更简单的打包:得益于Cargo包管理器,依赖管理和项目构建比Python的pip和虚拟环境更加简单和一致。安装所需工具只需利用Cargo生态系统即可。
  2. 可复现的模型:使用Rust可以更容易地创建可复现的模型构建流程。

一个与此相关的新兴趋势是模型打包与分发。人们正在认真考虑如何使用ONNX等便携式格式将模型打包,并集成到工具中分发给他人。这正是一种MLOps的核心实践:将你的模型及其运行环境一起封装,并部署到任何地方。

我强烈建议大家多关注这类演示。越多的人使用Rust这样的系统编程语言来探索机器学习示例,MLOps社区就越能从这些像“变色龙”一样灵活、可移植的工具中受益。


总结

本节课中,我们一起学习了:

  1. Rust语言在生产环境(尤其是AWS Lambda的Firecracker)中已得到大规模验证,并非“新”而“不可靠”。
  2. 通过Rust的PyTorch绑定,可以方便地进行GPU加速的模型训练与推理,代码简洁高效。
  3. 基于Cargo的打包机制和Rust的性能特性,为构建可复现、易分发的机器学习工具链提供了优秀基础。
  4. 将模型与运行环境打包分发,是现代化MLOps的重要一环,而Rust在其中大有可为。

希望本教程能帮助你打消对Rust在机器学习领域应用的疑虑,并激发你尝试将高性能系统编程与机器学习工作流相结合的兴趣。

067:构建GPU压力测试工具 🚀

在本教程中,我们将学习如何使用 Rust 语言,结合其系统编程能力和 PyTorch 绑定,构建一个能够对 CPU 和 CUDA 支持的 GPU 进行压力测试的工具。我们将利用 Rust 的 rayon 库实现多线程,以最大化 GPU 的利用率。


概述

Rust 的一个强大用途是构建能与 GPU 通信的系统工具。幸运的是,PyTorch 的 Rust 绑定工作得很好。我们将组装一个工具,它不仅可以通过 PyTorch 与 CPU 通信并使其饱和,还能与支持 CUDA 的 GPU 通信,利用 PyTorch 使其饱和。同时,我们将利用 Rust 的 rayon 库实现真正的多核并行,通过多线程向 GPU 发送数据,以进行全面的压力测试。

接下来,我们来看看构建这个压力测试工具的架构。

架构设计

让我们看看如何利用 Rust 的系统编程能力和 PyTorch 的 Rust 绑定,为支持 CUDA 的 GPU 构建压力测试工具的架构。

以下是构建此工具的关键步骤:

  1. 环境准备:首先,需要访问一个支持 CUDA 的 GPU 环境。这可以通过 GitHub Codespaces、AWS、GCP 或 Azure 实例实现。
  2. 监控配置:配置 NVIDIA SMI 监控,以便在压力测试期间观察 GPU 的利用率。
  3. 绑定集成:集成 Rust 的 PyTorch 绑定,这是与 GPU 通信的核心。
  4. 工具构建:使用 Rust 的 clap 库构建命令行工具,提供三种不同的压力测试执行方式。
  5. 测试执行
    • CPU 测试:向 CPU 设备发送数据。
    • GPU 测试:向 CUDA 设备发送数据。
    • 多线程 GPU 测试:利用 rayon 库,以多线程方式向 GPU 发送数据,进行完全的压力测试。

现在,让我们开始构建这个工具。

项目结构与依赖

首先,我们需要设置正确的 Cargo 项目结构。这是本教程的关键要点之一。

以下是我们将使用的 Cargo.toml 文件中的依赖项:

[dependencies]
clap = { version = "4", features = ["derive"] }  # 用于构建命令行界面
tch = "0.13.0"                                   # Rust 的 PyTorch 绑定
rayon = "1.8"                                    # 用于并行计算的库

我们使用了三个主要依赖:

  1. clap:用于构建命令行工具。
  2. tch:Rust 的 PyTorch 绑定。
  3. rayon:允许我们编写多线程代码。

接下来,我们遵循一个模式:库代码放在 src/lib.rs 中,而命令行工具的主逻辑放在 src/main.rs 中。

库代码实现

让我们先看看库代码。在库代码中,我们构建了几个函数,每个函数都很简单。

以下是 src/lib.rs 的核心内容:

use rayon::prelude::*;
use tch::{Device, Tensor};

/// 执行 CPU 负载测试
pub fn cpu_load_test() {
    let device = Device::Cpu;
    let data: Vec<_> = (0..1000).map(|i| i as f64).collect();
    for _ in 0..100 {
        let tensor = Tensor::of_slice(&data).to(device);
        // 执行一些计算,例如
        let _ = tensor * 2;
    }
    println!("CPU 负载测试完成。");
}

/// 执行 GPU 负载测试
pub fn gpu_load_test() {
    if let Ok(device) = Device::cuda_if_available() {
        if device.is_cuda() {
            let data: Vec<_> = (0..1000).map(|i| i as f64).collect();
            for _ in 0..100 {
                let tensor = Tensor::of_slice(&data).to(device);
                let _ = tensor * 2;
            }
            println!("GPU 负载测试完成。");
        } else {
            println!("未检测到 CUDA 设备,回退到 CPU。");
            cpu_load_test();
        }
    } else {
        println!("无法获取 CUDA 设备。");
    }
}

/// 使用多线程执行 GPU 负载测试
pub fn threaded_gpu_load_test() {
    if let Ok(device) = Device::cuda_if_available() {
        if device.is_cuda() {
            // 使用 rayon 进行并行迭代
            (0..4).into_par_iter().for_each(|_| {
                let data: Vec<_> = (0..250).map(|i| i as f64).collect(); // 分割数据
                for _ in 0..25 {
                    let tensor = Tensor::of_slice(&data).to(device);
                    let _ = tensor * 2;
                }
            });
            println!("多线程 GPU 负载测试完成。");
        } else {
            println!("未检测到 CUDA 设备。");
        }
    } else {
        println!("无法获取 CUDA 设备。");
    }
}

这段代码的关键点在于:

  • cpu_load_test 函数将向量数据发送到 CPU 设备。
  • gpu_load_test 函数将迭代目标改为 CUDA 设备。
  • threaded_gpu_load_test 函数使用 rayoninto_par_iter().for_each() 操作实现多线程,并将数据推送到 CUDA 设备。

这样,我们就有了三种完全不同的测试方式。

主程序与命令行界面

现在,我们转到 src/main.rs。这里使用了完全相同的模式,本质上是样板代码。

以下是 src/main.rs 的核心内容:

use clap::{Command, Arg, SubCommand};
use stress_tool::{cpu_load_test, gpu_load_test, threaded_gpu_load_test}; // 假设库 crate 名为 `stress_tool`

fn main() {
    let matches = Command::new("GPU 压力测试工具")
        .version("1.0")
        .author("作者")
        .about("使用 Rust 和 PyTorch 进行 CPU/GPU 压力测试")
        .subcommand(SubCommand::with_name("cpu").about("运行 CPU 压力测试"))
        .subcommand(SubCommand::with_name("gpu").about("运行 GPU 压力测试"))
        .subcommand(SubCommand::with_name("t-gpu").about("运行多线程 GPU 压力测试"))
        .get_matches();

    match matches.subcommand() {
        Some(("cpu", _)) => {
            println!("开始 CPU 压力测试...");
            cpu_load_test();
        }
        Some(("gpu", _)) => {
            println!("开始 GPU 压力测试...");
            gpu_load_test();
        }
        Some(("t-gpu", _)) => {
            println!("开始多线程 GPU 压力测试...");
            threaded_gpu_load_test();
        }
        _ => {
            // 如果没有提供子命令,显示帮助信息
            let _ = Command::new("GPU 压力测试工具")
                .subcommand(SubCommand::with_name("cpu").about("运行 CPU 压力测试"))
                .subcommand(SubCommand::with_name("gpu").about("运行 GPU 压力测试"))
                .subcommand(SubCommand::with_name("t-gpu").about("运行多线程 GPU 压力测试"))
                .print_help();
        }
    }
}

这个模式非常强大,因为你只需在库中编写几行代码,然后将这些函数映射到命令行子命令上。唯一需要注意的是确保库中的函数是 pub(公开的)。

运行与监控

现在,要运行这个工具,我们可以使用 Cargo。

首先,构建并查看帮助菜单:

cargo run -- --help

这将编译并显示帮助菜单,对应我们定义的三个命令:cpugput-gpu

进行压力测试时,有两种监控非常有帮助:

  1. CPU 监控:可以使用 htop 等工具。
  2. GPU 监控:使用 nvidia-smi 命令。

运行 CPU 测试

cargo run -- cpu

此时,工具会向 CPU 发送大量数据,你会看到 CPU 使用率饱和。而在 GPU 监控中,不会看到任何活动。这验证了代码确实在使用 CPU 设备。

运行 GPU 测试

cargo run -- gpu

现在,工具会向 GPU 发送数据。切换到 GPU 监控(如 nvidia-smi),你会看到 GPU 利用率开始上升,可能达到约 25% 的负载。同时,CPU 核心仍在被使用。

运行多线程 GPU 测试

cargo run -- t-gpu

这是使用 rayon 的代码。运行后,你会看到发送到 GPU 的负载显著增加,可能达到之前的 2 到 3 倍。同时,观察 CPU 负载,你会发现它实际上降低了。这是因为当你开始向 GPU 发送足够多的任务时,它可以有效地卸载系统上的部分计算资源。

总结

本节课中,我们一起学习了如何使用 Rust 构建一个强大的 GPU 压力测试工具。我们了解了如何利用 Rust 的系统编程特性、PyTorch 的 Rust 绑定以及 rayon 并行库,来实现对 CPU 和 CUDA GPU 的负载测试。

通过构建这样的基准测试工具,你可以真切地感受到环境中发生了什么。特别是在像使用 GPU 进行 PyTorch 训练这样的分布式计算问题中,除非进行基准测试,否则你无法真正了解其运行状况。Rust 是执行训练、推理、构建便携二进制工具的完美选择,它作为系统编程语言,是 MLOps(机器学习运维)中的理想工具。

068:在AWS Lambda中使用Rust、ONNX与EFS进行模型推理 🚀

在本节课中,我们将学习如何构建一个基于无服务器架构的机器学习推理服务。具体来说,我们将使用Rust语言、ONNX模型格式,通过AWS EFS文件系统挂载模型,并最终在AWS Lambda上部署和调用。这种组合方式能充分发挥无服务器架构免运维、易部署的优势,同时利用Rust的高性能和ONNX的模型通用性。


项目架构概述

上一节我们介绍了项目的目标,本节中我们来看看其核心架构。整个流程的目标是:使用AWS Lambda这类无服务器技术来提供模型推理服务。其优势在于无需管理基础设施,部署简单,尤其适合使用像Rust这样可以编译为单一二进制文件的高性能语言。

为了实现这一点,我们需要让Lambda函数能够访问存储在EFS文件系统中的ONNX模型文件。因此,整个架构涉及以下几个关键AWS服务的配置与联通。


第一步:设置EFS文件系统 📁

首先,我们需要创建并配置一个Amazon EFS文件系统,用于存储我们的ONNX模型。

  1. 创建EFS文件系统:在AWS控制台找到EFS服务,创建一个新的文件系统。通常使用默认配置即可。
  2. 配置安全组:这是关键且容易出错的一步。EFS文件系统关联的安全组必须开放端口5049的入站规则。这是EFS客户端(如Cloud 9或Lambda)与EFS服务通信所必需的端口。
  3. 在开发环境挂载EFS:为了将模型文件放入EFS,我们需要在一个可以访问该EFS的环境中挂载它。AWS Cloud 9是一个不错的选择。以下是挂载步骤:
    • 在EFS控制台找到你的文件系统,点击“附加”按钮。
    • 选择“使用EFS挂载助手”的选项,它会生成一个挂载命令。
    • 在你的Cloud 9实例中运行该命令,即可将EFS挂载到指定目录。

完成以上步骤后,你就可以将1个或多个ONNX模型文件复制到挂载的EFS目录中。


第二步:配置AWS Lambda函数 ⚙️

接下来,我们需要配置Lambda函数,使其能够访问上一步创建的EFS。

  1. 将Lambda接入VPC:在Lambda函数的配置中,必须将其放入一个VPC。这个VPC需要包含我们之前为EFS配置的、开放了5049端口的安全组。这样Lambda才能与EFS通信。
  2. 添加文件系统配置:在Lambda配置的“文件系统”部分,添加对EFS的访问。
    • 文件系统ID:填入你创建的EFS的ID。
    • 访问点:你需要在EFS控制台中创建一个“访问点”。创建后,将访问点ID填入此处。
    • 本地挂载路径:指定一个路径(例如/mnt/efs),Lambda函数将在运行时把EFS挂载到此路径下。

有一篇AWS官方文章《在无服务器应用程序中将Amazon EFS用于Lambda》详细介绍了这些步骤,建议参考。


第三步:开发与测试Rust Lambda函数 🦀

当基础设施就绪后,我们就可以专注于应用代码的开发了。我们使用Rust和cargo-lambda工具进行本地开发和测试。

以下是核心代码结构的解析:

// 示例:从EFS加载模型并进行推理
use onnxruntime::environment::Environment;
use std::path::Path;

fn load_model_from_efs() {
    // 模型文件路径指向EFS的挂载点
    let model_path = Path::new("/mnt/efs/models/squeezenet.onnx");
    // 使用ONNX Runtime加载模型
    // ... 后续推理代码
}

代码关键点:

  • 模型加载:代码通过指定的本地挂载路径(如/mnt/efs/models/squeezenet.onnx)从EFS读取ONNX模型文件。
  • 辅助调试函数:建议编写一个列出挂载点文件列表的函数,用于验证EFS是否成功挂载及模型文件是否存在。
  • 推理执行:使用ONNX Runtime库执行实际的模型推理并返回结果。

为了方便测试,可以创建一个Makefile

invoke:
    cargo lambda invoke --remote \
          --data-ascii '{"image_url": "https://example.com/cat.jpg"}'

这个命令会打包你的Rust代码,部署到Lambda,并发送一个测试事件来触发函数执行,从而验证整个流程。


关键要点与总结 ✅

本节课中我们一起学习了如何构建一个结合了Rust、ONNX、EFS和AWS Lambda的MLOps推理流水线。我们来回顾一下核心要点和需要牢记的步骤:

以下是成功部署此架构必须检查的清单:

  • 端口5049:确保EFS的安全组以及Lambda所在的VPC安全组都允许5049端口的通信。这是所有组件互联的基础。
  • 遵循EFS挂载指南:严格按照AWS控制台提供的EFS挂载说明进行操作。
  • 模型文件就位:将训练好的ONNX模型从开发环境复制到EFS的指定目录。
  • Lambda VPC配置:确认Lambda函数已正确配置VPC,并且该VPC能访问EFS的安全组。
  • 文件系统访问点:在EFS中创建访问点,并在Lambda配置中正确引用。

从开发体验角度,GitHub Codespaces是一个理想的开发环境,它集成了Copilot等工具,可以方便地进行代码编写和远程测试。

总而言之,Rust + ONNX + EFS + AWS Lambda 是一种新兴且强大的MLOps实践模式。它利用无服务器技术简化了运维,通过高性能语言和通用模型格式优化了推理效率,非常适合需要在生产环境中快速、高效部署机器学习模型的团队。

069:通过Cloud Shell使用Python和Rust接入GCP

在本节课中,我们将学习如何开始使用Google Cloud Platform。我们将重点介绍其免费套餐,并演示如何通过Cloud Shell环境,使用Python和Rust两种编程语言来接入和操作GCP服务。

概述:Google Cloud免费套餐

首先,我们来看一下Google Cloud的免费套餐。

如果你在Google Cloud免费套餐上启动,你可以访问20种免费产品。

你还会获得$300的免费额度,但需要在三个月内使用。免费套餐包含的部分产品有:计算引擎、云存储、BigQuery、Kubernetes、应用引擎、Cloud Run、Cloud Build、Stackdriver、Filestore、Pub/Sub、云函数、Vision AI、语音转文本、自然语言API、AutoML等。

这里确实有大量的免费服务。

启动并探索Cloud Shell

接下来,我们开始实际操作。我将进入云控制台仪表板。

你可以在这里看到所有内容的概览。首先,我们有项目信息。在项目信息中,你可以决定例如如何向项目添加人员、配置项目设置等。

此外,中间的仪表板显示了一些最近访问的服务。

你还有一个资源选项卡,可以切换查看不同的资源,例如,如果你想启动虚拟机。

右侧还有状态信息。

当你使用GCP时,这通常是你最常使用的起点。请注意,我在这里选择了一个项目。如果我想创建一个新项目,我会点击“创建新项目”。

对于初次使用Google Cloud Platform的用户,我建议启动Cloud Shell。

让我们开始操作。Cloud Shell的优势在于,你可以立即开始在这个环境中构建解决方案、尝试想法。

配置Python开发环境

我喜欢做的第一件事是创建一个Python虚拟环境,以便测试Python项目并在Cloud Shell中运行它们。我将首先执行以下命令:

python3 -m venv .venv

然后,我会把这个虚拟环境放在一个隐藏的主目录中。

创建成功。接下来,我喜欢编辑我的.bashrc文件。

在这里,我可以添加一行来激活Python虚拟环境。

source .venv/bin/activate

这是一个有用的小技巧,现在每次我打开这个环境时,都会自动激活Python虚拟环境,这解决了许多与Python相关的奇怪问题。

如果我想进入一个存放代码的仓库,例如我这里有一些Python代码,并且我不想推送更改回去,我可以直接在这个环境中进行git clone

让我们执行这个操作。输入git clone命令。

现在,我有了我的Python代码。如果我cd进入这个仓库。

我们可以看到我有一个测试文件,还有一些其他文件。

我喜欢使用Makefile,因为它允许我使用快捷命令。我们甚至可以进入编辑器查看代码,这是Google Cloud平台内部一个很好的资源。

进入这个目录,我们在这里看到一个Makefile。你可以看到我可以执行installtestformatlintcontainerrefactor等命令。这包含了在Google Cloud环境中工作时非常常见的所有操作。如果你查看教程,也会看到类似的内容。

让我们返回这里,通过执行make installmake lint来测试一下。

我们输入make install,这将根据我的requirements.txt文件安装所有包。

安装完成后,我可以对我的代码进行代码检查。这个公式实际上适用于任何语言,不仅仅是Python。

我们执行make lint。看起来我们的代码检查成功了。

你甚至可以查看这个文件,看看main函数里有什么,这是一个非常简单的应用程序。

配置Rust开发环境

现在我们已经让Python正常工作了,我们还能做什么呢?我们还可以安装Rust。

我将访问rustup.rs,复制安装命令,然后在这里粘贴执行。这将下载Rust环境,包括cargoclippy代码检查工具。

基本上,我们拥有了成为Rust开发者所需的一切。

我喜欢用Rust编程的原因之一是,根据你所做的事情,它的性能可能比Python好40倍到1000倍

因此,如果你想进行高性能计算,这通常是一个非常好的选择。安装程序已经将其添加到了我的路径中。

所以,如果我在这里,我可以实际运行cargo。我可以创建另一个“Hello World”项目。

cargo new hello

这将在这里创建一个示例目录。进入目录后,与Python不同,我不需要做任何额外的步骤,我只需直接运行cargo run

如果我们输入cargo run,它会编译并输出我们的“Hello World”。

如果我们想查看该项目的结构,可以在这里查看。你可以看到,在Cargo.toml中,这是一个非常简单的“Hello World”文件。如果我想在这里添加依赖,例如GCP SDK,我可以在这里完成。

这是一个很好的概述,展示了作为一名开发者你需要做的一些事情。我认为Python和Rust是两种非常理想的编程选择。

管理GCP虚拟机实例

我要做的最后一件事是启动一个虚拟机并查看它。哦,这里,我们看到已经启动了一个实例。

如果我想创建一个新的,我可以在这里点击“创建实例”,并启动某种类型的机器。例如,如果我想启动一个微型实例,你可以看到我将花费的成本估算会显示在这里,它是按小时计费的。

如果我想要一台非常大的机器,查看这里,在这个特定环境中,一台32核的机器需要$500。因此,确保你查看启动不同机器时的各项指标是很重要的。

由于我已经有一个正在运行的实例,我需要做的就是通过命令行来查询它。

在Google Cloud的教程中,查看如何列出机器的命令行概览是非常常见的。

我的历史命令中已经有一个相关命令。我们可以查看最近的一条命令,这也是一个获得快捷方式的好方法,就是运行history

如果我输入gcloud compute instances list

我们可以看到,我实际上可以控制它。如果我愿意,我甚至可以使用这个基础命令来启动东西。

gcloud compute instances

你还可以运行help来获取关于特定命令的更多信息。

这确实是一个面向命令行的服务。因此,如果你理解命令行,你将能很好地使用Google Cloud。

总结

本节课中,我们一起学习了如何开始使用Google Cloud Platform。我们介绍了其免费套餐,演示了如何通过Cloud Shell配置Python和Rust开发环境,并展示了如何通过命令行管理GCP资源(如虚拟机实例)。希望你能亲自尝试这些命令。

070:使用 Google Cloud Run 运行 Rust Actix 微服务 🚀

概述

在本节课中,我们将学习如何在 Google Cloud Shell 环境中安装 Rust,并创建一个简单的 Actix-web 微服务。随后,我们将把这个微服务容器化,并最终部署到 Google Cloud Run 平台,使其成为一个公开可访问的 Web 服务。


在 Cloud Shell 中安装 Rust 🛠️

首先,我们需要在 Google Cloud Shell 环境中安装 Rust 编译器。Cloud Shell 是一个临时的在线环境,非常适合快速测试和开发。

以下是安装 Rust 的步骤:

  1. 打开 Cloud Shell 终端。
  2. 运行以下命令来安装 Rust:
    curl --proto ‘=https’ --tlsv1.2 -sSf https://sh.rustup.rs | sh
    
  3. 安装完成后,需要加载 Cargo(Rust 的包管理器)的环境变量:
    source $HOME/.cargo/env
    

现在,我们可以验证 Rust 是否安装成功。让我们创建一个新的 Rust 项目并运行它。

cargo new hello
cd hello
cargo run

如果一切顺利,终端将输出 Hello, world!,这表明 Rust 环境已准备就绪。


使用 Cloud Shell 编辑器进行开发 ✍️

上一节我们介绍了如何在终端中安装 Rust,本节中我们来看看如何使用 Cloud Shell 内置的编辑器来编写和修改代码。

Cloud Shell 提供了一个基于 Web 的代码编辑器,功能比纯终端更强大。我们可以在这里编辑源代码文件。

  1. 在 Cloud Shell 界面中,点击“打开编辑器”按钮。
  2. 在左侧的文件浏览器中,导航到我们刚才创建的 hello 项目。
  3. 打开 src/main.rs 文件,将 println! 的内容修改为:
    println!(“Hello GCP from Rust!”);
    
  4. 保存文件,然后回到终端,在项目目录下再次运行 cargo run

现在,程序将输出我们自定义的问候语。为了更方便地管理项目,我们还可以创建一个 Makefile 来定义常用的命令,如格式化代码、代码检查和运行。


为 Cloud Run 准备 Rust 微服务 🌐

我们已经有了一个可以运行的 Rust 程序,但 Cloud Run 需要的是能够处理 HTTP 请求的 Web 服务。因此,我们需要将程序改造成一个 Web 微服务。

我们将使用 Actix-web 框架,它是 Rust 生态中最流行的 Web 框架之一。以下是改造步骤:

  1. 首先,我们需要修改 Cargo.toml 文件来添加依赖项。
  2. 然后,编写一个简单的 HTTP 服务器代码。

以下是 Cargo.toml 文件中需要添加的依赖项:

[dependencies]
actix-web = “4”
actix-rt = “2”
serde = { version = “1”, features = [“derive”] }
rand = “0.8”

接下来,我们替换 src/main.rs 文件的内容。以下是一个返回随机水果名称的简单 API 示例:

use actix_web::{get, App, HttpResponse, HttpServer, Responder};
use rand::seq::SliceRandom;
use serde::Serialize;

#[derive(Serialize)]
struct Fruit {
    name: String,
}

#[get(“/”)]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body(“Hello world! Random Fruit API”)
}

#[get(“/fruit”)]
async fn get_random_fruit() -> impl Responder {
    let fruits = vec![“Apple”, “Banana”, “Cherry”, “Date”, “Elderberry”];
    let fruit = fruits.choose(&mut rand::thread_rng()).unwrap();
    let response = Fruit {
        name: fruit.to_string(),
    };
    HttpResponse::Ok().json(response)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(hello)
            .service(get_random_fruit)
    })
    .bind((“0.0.0.0”, 8080))?
    .run()
    .await
}

编写完成后,使用 cargo run 命令在本地运行服务。然后,打开另一个终端标签页,使用 curl 命令测试 API:

curl http://localhost:8080/
curl http://localhost:8080/fruit

如果服务返回了问候语和随机的水果 JSON 数据,说明我们的微服务已经成功运行。


创建 Dockerfile 并本地构建镜像 🐳

上一节我们创建了一个可运行的 Web 微服务,本节中我们来看看如何将其容器化,这是部署到 Cloud Run 的关键一步。

Cloud Run 运行的是容器化应用。我们需要创建一个 Dockerfile 来定义如何构建我们的 Rust 应用镜像。

以下是一个高效的两阶段构建 Dockerfile 示例。它首先在一个完整的 Rust 镜像中编译应用,然后将编译好的二进制文件复制到一个更精简的最终镜像中,以减小镜像体积。

# 第一阶段:使用 Rust 官方镜像进行构建
FROM rust:latest as builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release

# 第二阶段:使用轻量级 Debian 镜像运行应用
FROM debian:buster-slim
RUN apt-get update && apt-get install -y extra-runtime-dependencies && rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/src/app/target/release/web-docker /usr/local/bin/web-docker
CMD [“web-docker”]

在项目根目录下创建这个 Dockerfile 后,我们可以使用 Cloud Shell 编辑器中的 Cloud Code 扩展来模拟本地构建和运行。

  1. 在编辑器中,找到 Cloud Code 面板。
  2. 选择“在本地运行 Cloud Run 应用”。
  3. 扩展会自动检测 Dockerfile 并启动一个本地 Minikube 集群来模拟 Cloud Run 环境,进行构建和部署测试。

这个过程会验证我们的容器配置是否正确,为真正的云端部署做好准备。


部署到 Google Cloud Run ☁️

经过本地测试,我们的容器镜像已经准备就绪。现在,我们可以将其部署到 Google Cloud Run,使其成为一个全球可访问的服务。

使用 Cloud Shell 编辑器中的 Cloud Code 扩展,部署过程非常简单直观:

  1. 在 Cloud Code 面板中,找到我们正在运行的服务。
  2. 点击“部署到 Cloud Run”按钮。
  3. 在弹出的配置窗口中,保持默认设置(如服务名称、区域选择“完全托管”)。
  4. 点击“部署”。

系统将开始执行以下步骤:

  • 将我们的源代码和 Dockerfile 打包。
  • 在 Google Cloud Build 服务中根据 Dockerfile 构建容器镜像。
  • 将构建好的镜像推送到 Google Container Registry。
  • 在 Cloud Run 上创建并启动一个新的服务实例,并分配一个公开的 HTTPS 网址。

部署过程可能需要几分钟,具体时间取决于代码编译和镜像上传的速度。我们可以在日志窗口中查看实时进度。

部署成功后,Cloud Code 会提供一个可点击的 URL。点击它,或在浏览器中访问该 URL,我们应该能看到 Hello world! Random Fruit API 的响应。访问 /fruit 路径则会返回随机的 JSON 格式水果数据。

总结 🎉

本节课中我们一起学习了在 Google Cloud 平台上运行 Rust 微服务的完整流程。

我们首先在 Cloud Shell 中配置了 Rust 开发环境,然后使用 Actix-web 框架创建了一个简单的 Web API。接着,我们通过编写 Dockerfile 将应用容器化,并利用 Cloud Shell 的 Cloud Code 扩展完成了本地模拟测试。最后,我们成功地将容器化应用一键部署到了 Google Cloud Run,使其成为了一个可弹性伸缩、免运维的云服务。

整个过程表明,尽管 Cloud Run 的控制台向导没有直接提供 Rust 模板,但通过标准的容器化流程,我们可以轻松地将任何语言(包括 Rust)编写的应用部署上去,享受 Serverless 带来的便利。

071:通过Google Cloud Run构建部署Rust微服务

在本节课中,我们将学习如何在Google Cloud Platform上,为Rust编写的微服务构建一个容器化部署流程,并利用Cloud Run实现服务托管。

概述

我们将从一个已构建好的Rust微服务代码仓库开始。部署完成后,服务将拥有一个Cloud Run管理界面,并能通过URL访问。其核心架构是实现一个在Google云平台上持续交付的容器化Rust微服务。

代码存放在GitHub仓库中。任何代码变更都会触发GCP Cloud Build环境,进而自动将更新部署到容器即服务(CaaS)平台Cloud Run上。Rust作为一种微服务框架,能够实现低内存、高性能的计算。我们的目标是构建一个能够随代码更新而持续推送到生产环境的流程。


开始构建

首先,我们需要打开Cloud Shell并选择打开编辑器。这个编辑器具有一些定制化功能,便于我们本地构建和测试Cloud Run微服务。

点击这里的Cloud Code图标,会看到一个Cloud Run图标。我们需要先进行一次授权。授权完成后,就可以开始创建新的应用程序了。

接下来,我们选择“创建新的Cloud Run应用”。在模板选择步骤,可以选择任意模板,因为后续我们会修改代码。这里选择Go模板作为起点。创建应用后,可以根据习惯更改编辑器的颜色主题,例如选择深色主题。然后,打开一个新的终端。

准备项目环境

环境设置完成后,我们需要清理并修改项目,使其能够运行Rust代码。

以下是需要清理的目录和文件:

  • 删除Go模板生成的目录。
  • 删除Go相关的代码文件。

清理完毕后,项目就准备就绪了。接下来,我们将把Rust应用的代码文件复制到当前仓库中。

配置Dockerfile

首先,复制Rust应用的Dockerfile代码,并将其粘贴到本仓库中。



我们将Go的Dockerfile替换为Rust的Dockerfile。这个Dockerfile定义了一个简单的构建过程:创建二进制文件,将其推入一个精简的容器,并从8080端口暴露服务。

获取并设置Rust源代码

接下来,我们需要获取Rust的源代码文件。我们将进入源代码目录,并创建lib.rsmain.rs文件。

对于Rust项目,一个简便的方法是使用cargo工具。首先检查cargo是否已安装。如果未安装,可以通过rustup工具快速安装。





rustup是用于在终端环境中安装Rust的工具,安装过程高效快捷。Rust生态系统安装完成后,我们使用cargo new命令初始化一个新项目。

执行以下命令来初始化项目结构:

source $HOME/.cargo/env
cargo new web-docker

这将在本地创建一个名为web-docker的项目结构。接着,我们在src目录下创建lib.rs文件:

touch src/lib.rs

创建好这两个文件后,我们将之前准备好的Rust应用代码复制过来。


理解应用代码

在部署前,最好先在本地测试以确保代码能正常工作。

服务器代码非常直观,包含一些导入语句和Web处理函数。例如,它定义了健康检查、版本信息、随机返回水果等端点。

lib.rs文件中的代码则负责生成随机水果的逻辑。


这是一个非常简单的REST风格应用程序。

配置项目依赖

我们还需要配置项目的依赖项,它们定义在Cargo.toml文件中。

我们将依赖项内容复制并粘贴到项目的Cargo.toml文件中。

完成此步骤后,只需在终端中运行cargo run命令。该命令会自动安装所有依赖并启动Web微服务。

本地测试与云部署

在本地测试通过后,下一步就是进行云部署。

部署过程非常直接。在编辑器中,找到Cloud Run图标,点击“上传到Cloud Run”。

系统将开始分析工作空间、构建容器化应用,并将其推送到生产环境。按照部署向导完成所有必要步骤后,服务就会部署成功。

验证部署结果

部署完成后,我们可以在Cloud Run控制台查看服务状态。服务运行后,我们可以复制其提供的URL。

打开一个新终端,使用curl命令访问该URL,可以验证服务是否正在运行。例如,访问/fruit端点,它会随机返回一个水果名称。这表明我们的容器化微服务已在生产环境成功运行。

配置持续交付

整个流程始于GitHub,代码存储在那里。当需要实现持续交付时,可以配置Cloud Build流程。Cloud Build会监听代码仓库的变更,并自动将更新部署到生产环境,从而实现持续交付。

总结

本节课我们一起学习了在Google Cloud Platform上部署Rust微服务的完整流程。我们从设置Cloud Shell环境开始,准备了Rust项目代码和Dockerfile,并在本地进行了测试。随后,我们利用Cloud Run将容器化应用部署到云端,并验证了服务的可用性。最后,我们了解了如何通过集成Cloud Build与GitHub来实现代码变更的持续自动交付。这个流程展示了构建和运维现代化、高性能微服务的一种高效方法。

072:Google App Engine的Rust监控与日志 📊

在本节课中,我们将学习如何为一个部署在Google App Engine上的Rust微服务设置和使用监控与日志功能。我们将从查看应用仪表盘开始,然后深入探索日志查询,以全面了解生产环境中的服务运行状况。

应用概览与仪表盘监控

上一节我们介绍了微服务部署的基本概念,本节中我们来看看如何监控一个已部署的应用。这里有一个使用Actix Web框架的Rust微服务。代码中包含一个路由 /fruit 和一个返回“hello world”的函数。该应用已被容器化,非常适合部署到App Engine。

如果我们访问该服务在App Engine上的部署版本,可以看到一个仪表盘,它展示了所有重要的运行摘要。

以下是仪表盘中提供的关键监控信息:

  • 请求数量:可以查看应用接收到的请求总数。
  • 计费状态:监控与使用量相关的成本。
  • 错误信息:如果存在任何错误,可以在此处查看。
  • 请求类型与延迟:可以按类型筛选请求,并查看延迟情况,例如加载延迟。
  • 流量统计:查看接收和发送的流量数据。
  • 资源利用率:监控CPU等资源的使用情况。
  • 实例信息:查看已部署的实例数量,例如当前有两个实例在运行。
  • 内存使用量:这对微服务至关重要,甚至可以基于此创建警报策略。
  • 缓存查询:仪表盘还提供了多种缓存查询数据。

如果想直接访问应用,操作很简单。我们只需访问相应URL,这里是我们的Rust微服务,调用 /fruit 端点并可以反复运行测试。因此,仅凭这个仪表盘,就能获得非常直观和全面的监控服务。

此外,我们还可以在此查看版本信息,了解当前是哪个版本在提供服务流量。在本例中,我们看到当前版本承担了100%的流量。我们甚至可以直接从这个仪表盘停止或启动服务。所以,如果你有一个容器化的Rust微服务运行在Google App Engine上,这个仪表盘堪称一站式监控管理平台。

深入日志查询与分析

除了仪表盘,另一项非常实用的功能是查看日志。我们可以进一步深入细节。其中一种方法是创建自定义查询。我们可以按资源类型进行筛选,从而清晰掌握发生的一切。我们还可以创建指标、设置警报,甚至执行SQL查询。

接下来,我将演示一个简单的操作:查询我们已知会被调用的 /fruit 这个URL。让我们运行一个查询。

查询结果显示,我们可以清楚地看到每次调用的应用延迟(以秒为单位)、项目名称以及调用发生的时间戳。如果需要,我也可以基于此创建警报,例如,如果调用次数过于频繁,可以触发相应的操作。

我们还可以切换查看不同的日志名称和严重级别。总之,结合Google App Engine的仪表盘和详细的日志浏览器,你便拥有了调试一个基于Rust的App Engine微服务所需的一切工具,足以应对生产环境中的应用调试需求。

课程总结

本节课中,我们一起学习了如何利用Google App Engine的内置工具监控和调试Rust微服务。我们首先探索了功能全面的仪表盘,它可以提供从请求、错误到资源利用率的全景视图。接着,我们深入日志系统,学习了如何执行自定义查询来追踪特定请求并分析性能数据。掌握这些监控和日志技能,是确保机器学习应用在生产环境中稳定、高效运行的关键。

073:Rust微服务负载测试 🚀

在本节课中,我们将学习如何使用Locust工具对部署在Google App Engine上的Rust微服务进行负载测试。负载测试是确保应用在生产环境中能按预期工作的重要方法,它可以模拟用户请求、检查资源使用情况并测试自动扩缩容能力。

安装与配置Locust

上一节我们介绍了负载测试的重要性,本节中我们来看看如何安装和配置测试工具Locust。

首先,我们需要安装Locust。这可以通过Python的包管理器pip轻松完成。

以下是安装步骤:

  • 在已激活的虚拟环境中,执行命令:pip install locust
  • 安装完成后,可以通过命令 which locust 来验证安装位置。

安装完成后,我们需要编写一个Locust测试文件。这个文件将定义测试场景,例如将客户端请求(GET或POST等)映射到我们服务的具体路由上。

编写Locust测试文件

现在我们已经安装了Locust,接下来需要创建测试脚本来定义要模拟的用户行为。

我们的Rust应用部署在Google App Engine上,包含多个路由。为了进行全面测试,我们将对三个路由进行负载测试:默认路由、水果数据路由和健康检查路由。

以下是我们将在Locust文件中定义的任务代码示例:

from locust import HttpUser, task, between

class QuickstartUser(HttpUser):
    wait_time = between(1, 5)

    @task(3)
    def default_route(self):
        self.client.get("/")

    @task(2)
    def fruit_route(self):
        self.client.get("/fruit")

    @task(1)
    def health_route(self):
        self.client.get("/health")

这段代码定义了一个模拟用户类,它会以不同的权重(3,2,1)随机访问三个路由,并在每次请求间等待1到5秒。

执行负载测试

准备好测试脚本后,我们就可以启动Locust并开始模拟用户负载了。

在Google Cloud环境中,我们可以方便地进行测试,因为应用已经部署好。只需在终端输入 locust 命令,它将在本地启动一个Web界面(默认端口8089)。

启动Locust后,我们需要在浏览器中访问其Web界面。首先进行一个简单的测试来验证配置是否正确。

以下是初始测试的配置步骤:

  • 在Locust Web界面中,输入目标主机的URL(即App Engine应用的地址,注意末尾不要加斜杠)。
  • 设置用户数为1,孵化率(每秒新增用户数)为1。
  • 点击“Start swarming”开始测试。

测试开始后,界面会显示实时数据,包括请求响应时间(毫秒)的最大值、最小值、平均值,以及每秒请求数。我们可以观察图表,确认请求是否按预期进行,并且没有出现失败或异常。

进行高并发负载测试

简单的验证测试通过后,我们可以增加负载,进行更有压力的并发测试,以评估应用的性能极限。

现在让我们停止当前测试,开始一个新的、负载更高的测试场景。

以下是高并发测试的配置:

  • 设置并发用户数为100。
  • 设置孵化率为25(即每秒新增25个用户,4秒内达到100用户)。
  • 再次确认目标URL正确无误。
  • 点击“Start swarming”开始高强度负载测试。

这次测试会产生显著不同的负载。我们可以看到每秒请求数大幅上升。测试结果会显示成功率、错误率以及App Engine的响应时间。一个健壮的应用应该能够优雅地处理这种工作负载,并保持较低的响应时间。我们还可以在App Engine的控制台中查看更详细的监控图表和日志,以了解应用在实时负载下的表现。

总结

本节课中我们一起学习了如何使用Locust对Google App Engine上的应用进行负载测试。我们完成了从安装Locust、编写测试脚本、执行简单验证测试到进行高并发压力测试的全过程。Locust是一个直接有效的负载测试工具,它能很好地与Google App Engine配合,帮助我们确保应用在投入生产前具备可靠的性能表现。

074:在AWS上构建容器化Rust微服务 🚀

在本节课中,我们将学习如何构建一个容器化的Rust微服务,并将其部署到AWS云平台。我们将使用Actix Web框架、Docker容器技术以及AWS App Runner服务,实现一个能够随机返回水果名称的简单REST API服务。

项目结构概述

首先,我们来看一下这个容器化Actix微服务的整体结构。这个结构与我参与的许多项目类似,包含了一些常见的配置文件。

以下是项目的主要文件:

  • Makefile:用于定义构建、格式化和运行等自动化命令。
  • Dockerfile:定义了如何构建该服务的Docker镜像。
  • Cargo.toml:Rust项目的配置文件,列出了项目依赖。
  • lib.rs:库文件,包含核心的业务逻辑。
  • main.rs:程序的主入口文件,负责启动Web服务器和定义路由。

深入代码解析

上一节我们概述了项目结构,本节中我们来详细看看各个核心文件的内容和作用。

Dockerfile 解析

这个Dockerfile采用了一种高效的构建策略。它首先使用一个完整的Rust环境作为构建器(builder),这个环境包含了所有开发所需的资源。然后,它将编译好的、独立的可执行文件复制到一个全新的、更精简的容器中。这种方法能生成体积非常小的最终镜像。

# 使用Rust官方镜像作为构建阶段
FROM rust:latest as builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release

# 创建最终运行阶段,使用极简的Debian镜像
FROM debian:buster-slim
COPY --from=builder /usr/src/app/target/release/web-docker /usr/local/bin/web-docker
EXPOSE 8080
ENTRYPOINT ["web-docker"]

依赖与库文件

Cargo.toml文件定义了项目依赖,主要包括rand(用于生成随机数)和actix-web(Web框架)。

lib.rs文件中的逻辑非常简单,它定义了一个公开的函数random_fruit,用于从一个预定义的水果列表中随机返回一个名称。

// 在 lib.rs 中
pub fn random_fruit() -> &‘static str {
    let fruits = [“apple”, “banana”, “cherry”, “durian”, “orange”];
    let idx = rand::random::<usize>() % fruits.len();
    fruits[idx]
}

主程序与路由

main.rs文件是应用的核心,它看起来很像一个Flask或FastAPI应用。它导入了必要的依赖,然后设置了Web服务器的路由。

以下是路由定义:

  • GET /:返回一个简单的“Hello World”欢迎信息。
  • GET /fruit:调用lib.rs中的random_fruit函数,返回一个随机的水果名。
  • GET /health:用于健康检查的端点。
  • GET /version:返回应用版本信息。

最后,在main函数中注册这些服务并启动服务器。

本地构建与运行

理解了代码结构后,我们来看看如何在本地构建和运行这个服务。这个过程非常简单。

以下是使用Makefile的步骤:

  1. 运行 make format 来格式化代码。
  2. 运行 make build 来编译项目。
  3. 运行 make run 来启动本地服务。

服务启动后,你可以在浏览器中访问 http://localhost:8080 来测试各个端点,例如访问 /fruit 来获取随机水果。

在AWS上部署

在本地验证无误后,下一步就是将其部署到AWS云平台,实现服务的线上访问。

构建并推送Docker镜像

首先,我们需要将项目构建成Docker镜像,并推送到AWS的弹性容器注册表(ECR)。

  1. 在AWS控制台创建ECR仓库。
  2. 使用AWS CLI获取登录命令,在本地终端完成Docker到ECR的认证。
  3. 执行 docker build -t your-ecr-repo-uri . 命令构建镜像。
  4. 执行 docker push your-ecr-repo-uri 命令将镜像推送到ECR。

使用App Runner部署

镜像推送成功后,就可以使用AWS App Runner服务进行部署了,这是一个全托管的容器应用服务。

在App Runner控制台创建新服务的步骤如下:

  1. 选择“容器注册表”作为源。
  2. 选择你刚刚推送镜像的ECR仓库。
  3. 配置服务名称(例如 rust-actix-demo)。
  4. 选择部署触发方式(手动或自动。选择自动后,每次向ECR推送新镜像,App Runner会自动重新部署)。
  5. 点击“创建并部署”。

部署完成后,App Runner会提供一个可访问的URL。通过这个URL,你就可以像在本地一样访问 //fruit 等所有API端点了。

总结与优势

本节课中我们一起学习了如何使用Rust和Actix Web框架构建一个微服务,将其容器化,并最终部署到AWS App Runner上。

这个演示凸显了Rust在微服务领域的几个关键优势:

  • 极小的二进制体积:最终生成的Docker镜像体积可以控制在100MB以下,这得益于Rust的零成本抽象和高效的编译输出。使用 docker images 命令可以查看镜像大小。
  • 卓越的性能:Rust提供了接近C/C++的运行效率,非常适合高性能后端服务。
  • 内存安全:在提供高性能的同时,通过所有权系统保证了内存安全,避免了常见的内存错误。
  • 简单的部署流程:结合Docker和AWS App Runner这类托管服务,部署变得非常顺畅和自动化。

因此,对于追求高性能、高资源利用率和安全性的微服务场景,Rust是一个非常值得认真考虑的选择。

075:使用Rust构建AWS Step Functions工作流 🚀

在本节课中,我们将学习如何使用Rust语言来构建和部署AWS Step Functions工作流。Step Functions是强大的无服务器工作流服务,它允许你将多个AWS Lambda函数串联起来,构建复杂的、可视化的业务流程。我们将通过一个简单的“Marco Polo”游戏示例,演示从编写Rust Lambda函数到在AWS控制台拖拽构建工作流的完整过程。


概述:Step Functions与Rust

上一节我们介绍了Step Functions的基本概念。本节中,我们来看看如何用Rust语言实现它。

Step Functions在构建无服务器工作流方面非常强大,因为它可以将多个操作链接起来,将一个Lambda函数的输出作为另一个Lambda函数的输入进行处理。其最有趣的地方在于,你可以通过拖放的方式创建自己的工作流,就像玩乐高积木一样。下图展示了一个工作流的示意图:

当工作流运行时,你可以深入检查每个函数的输出和下一个函数的输入,这在调试方面是无与伦比的优势。那么,可以用Rust来实现吗?答案是肯定的。


第一步:创建Rust Lambda函数

首先,我们需要创建Step Functions中要使用的Lambda函数。我们将创建两个函数:rust_marcorust_polo

以下是创建过程的核心步骤,我们使用了优秀的 cargo-lambda 工具库。

  1. 创建第一个函数 (rust_marco)
    使用命令 cargo lambda new rust_marco 创建项目。

  2. 查看源代码
    进入项目目录查看 src/main.rs 文件。函数定义了输入和输出的数据结构,并在 handler 函数中处理业务逻辑。

    // 输入事件的结构体
    #[derive(Deserialize)]
    struct StepFunctionInput {
        name: String,
    }
    
    // 输出响应的结构体
    #[derive(Serialize)]
    struct LambdaResponse {
        body: String,
    }
    
    // 主要的处理函数
    async fn function_handler(event: LambdaEvent<StepFunctionInput>) -> Result<LambdaResponse, Error> {
        // 从输入事件中提取 name 字段
        let name = event.payload.name;
    
        // 核心逻辑:如果输入是“Marco”,则回复“Polo”
        let body = if name == "Marco" {
            "Polo".to_string()
        } else {
            "Nobody".to_string()
        };
    
        // 添加追踪日志,便于在AWS控制台调试
        tracing::info!("Processed name: {}, Responding with: {}", name, body);
    
        // 构造并返回响应
        let resp = LambdaResponse { body };
        Ok(resp)
    }
    
  3. 构建与部署
    我们可以使用 Makefile 来简化构建和部署命令。

    • make release:运行 cargo lambda build --release 编译Rust代码。
    • make deploy:将编译好的函数部署到AWS Lambda。
    • make invoke:远程调用该Lambda函数进行测试。

第二步:创建第二个函数 (rust_polo)

现在,我们来看如何创建第二个函数,它将接收第一个函数的输出。

  1. 创建项目
    同样使用 cargo lambda new rust_polo 创建。

  2. 编写业务逻辑
    这个函数将检查输入中是否包含“Polo”,并返回相应的结果。

    async fn function_handler(event: LambdaEvent<LambdaResponse>) -> Result<LambdaResponse, Error> {
        // 接收上一个Lambda函数的输出 body
        let received_body = event.payload.body;
    
        // 核心逻辑:如果包含“Polo”,则返回“You win”
        let body = if received_body.contains("Polo") {
            "You win".to_string()
        } else {
            "You lose".to_string()
        };
    
        tracing::info!("Received: {}, Responding: {}", received_body, body);
    
        let resp = LambdaResponse { body };
        Ok(resp)
    }
    
  3. 测试函数
    同样使用 make invoke 命令进行测试。如果传入的payload是 {"body":"Polo"},将返回 {"body":"You win"}


第三步:在AWS控制台组装Step Functions工作流

我们已经有了两个Rust Lambda函数,接下来看看如何将它们串联成一个工作流。

  1. 创建状态机
    在AWS Step Functions控制台,点击“创建状态机”。

  1. 拖拽构建工作流
    在可视化编辑器中:

    • 从左侧拖拽一个“Lambda调用”任务到画布,将其配置为调用 rust_marco 函数。
    • 再拖拽第二个“Lambda调用”任务,将其配置为调用 rust_polo 函数。
    • 用箭头连接两个任务,表示执行顺序。

  2. 配置与创建
    为状态机命名(例如 rust_marco_polo_chain),然后点击创建。


第四步:执行与调试工作流

工作流创建完成后,我们可以执行它并观察运行细节。

  1. 启动执行
    在状态机详情页点击“开始执行”。需要提供一个输入,例如:

    {
      "name": "Marco"
    }
    
  2. 观察执行过程
    执行页面会可视化展示流程。你可以点击每个步骤查看详情:

    • rust_marco 的输入是 {"name":"Marco"},输出是 {"body":"Polo"}
    • rust_polo 接收到 {"body":"Polo"},输出 {"body":"You win"}
  3. 测试失败场景
    如果启动执行时输入 {"name":"Other"}rust_marco 将返回 {"body":"Nobody"}。这会导致 rust_polo 判断失败,最终工作流执行失败。控制台会清晰显示错误发生的位置和原因,非常利于调试。


总结

本节课中我们一起学习了如何使用Rust构建AWS Step Functions工作流。我们首先使用 cargo-lambda 创建并部署了两个简单的Rust Lambda函数。然后,在AWS Step Functions控制台通过拖拽的方式,将这两个函数连接成一个可执行的工作流。最后,我们执行了该工作流,并观察了成功与失败两种场景下的运行状态和调试信息。这种方法结合了Rust的性能与安全性和Step Functions的可视化与强大编排能力,是构建可复用的无服务器服务的优秀实践。希望你能尝试使用这种方法。

076:部署App Engine Rust微服务

在本节课中,我们将学习如何使用Google App Engine的灵活环境来部署一个用Rust语言编写的微服务。我们将从创建项目目录开始,逐步配置App Engine、编写Rust代码、构建Docker镜像,最终完成部署。

概述

我们将创建一个名为“web_docker”的Rust微服务项目,并通过App Engine将其部署到云端。整个过程涉及创建配置文件、编写应用代码、配置Docker,并使用GCloud命令行工具进行部署。

创建项目目录与配置文件

首先,我们需要创建一个项目目录并进入该目录。

mkdir web_docker
cd web_docker

接下来,创建App Engine的配置文件 app.yaml。这个文件用于告知App Engine我们的部署配置。

runtime: custom
env: flex

初始化Rust项目

现在,我们初始化一个Rust项目。

cargo init --name web_docker

此命令会生成 Cargo.toml 文件。我们需要在其中添加项目依赖。

以下是 Cargo.toml 文件的内容示例:

[package]
name = "web_docker"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = "4"
serde = { version = "1", features = ["derive"] }
rand = "0.8"

配置Dockerfile

为了在App Engine的灵活环境中运行,我们需要一个Dockerfile来定义容器环境。

创建 Dockerfile 文件:

# 使用Rust官方镜像作为构建环境
FROM rust:1.68 as builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release

# 使用轻量级Debian镜像作为运行环境
FROM debian:buster-slim
COPY --from=builder /usr/src/app/target/release/web_docker /usr/local/bin/web_docker
CMD ["web_docker"]

编写Rust应用代码

我们需要编写应用的核心逻辑。首先创建 src/lib.rs 文件,其中包含一个随机水果生成器。

use rand::Rng;
use serde::Serialize;

#[derive(Serialize)]
pub struct Fruit {
    name: String,
}

pub fn random_fruit() -> Fruit {
    let fruits = vec!["Apple", "Banana", "Cherry", "Date", "Elderberry"];
    let mut rng = rand::thread_rng();
    let index = rng.gen_range(0..fruits.len());
    Fruit {
        name: fruits[index].to_string(),
    }
}

接着,创建 src/main.rs 文件,定义Web服务的路由。

use actix_web::{get, App, HttpResponse, HttpServer, Responder};
use web_docker::random_fruit;

#[get("/")]
async fn index() -> impl Responder {
    let fruit = random_fruit();
    HttpResponse::Ok().body(format!("Welcome! Random fruit: {}", fruit.name))
}

#[get("/health")]
async fn health() -> impl Responder {
    HttpResponse::Ok().body("OK")
}

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/619973d394e16b470c915fb24e8f0b1c_4.png)

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(index)
            .service(health)
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}

本地测试与验证

在部署之前,我们应在本地测试应用是否正常运行。

运行以下命令启动服务:

cargo run

服务启动后,可以通过浏览器访问 http://localhost:8080 来验证。页面应显示“Welcome! Random fruit: [随机水果名]”。访问 http://localhost:8080/health 应返回“OK”。

准备部署

在部署前,需要清理 target 目录以避免上传不必要的构建文件,并设置构建超时时间。

rm -rf target
gcloud config set app/cloud_build_timeout 1600

设置较长的超时时间是因为Rust编译过程可能耗时较长。

部署到App Engine

一切就绪后,使用以下命令进行部署:

gcloud app deploy

此命令会将应用打包并部署到Google App Engine。部署过程可能需要几分钟时间,请耐心等待。部署成功后,应用将在生产环境中运行。

扩展与多语言支持

App Engine的灵活环境支持多种编程语言。例如,如果你想使用Python,可以在 app.yaml 中指定官方运行时。

runtime: python37

你还可以通过添加 cloudbuild.yaml 文件来配置更复杂的自动化部署流程。这种灵活性使得你可以轻松地在Rust、Python、Go等语言之间切换,并根据需要采用不同的持续交付策略。

总结

本节课中,我们一起学习了如何将一个Rust微服务部署到Google App Engine。我们从创建项目、编写配置文件和应用代码开始,接着配置Docker并完成本地测试,最后使用GCloud命令行工具成功部署应用。App Engine的灵活环境为不同语言的微服务部署提供了强大且便捷的支持。

077:AWS S3容量计算器 🧮

在本节课中,我们将学习如何使用Rust语言和AWS SDK构建一个高性能的异步Lambda函数。这个函数的核心功能是监控AWS S3存储服务,具体来说,它会异步地遍历账户中的所有S3存储桶,计算每个桶中所有对象的总存储容量,并将结果汇总。这种模式非常适合构建高效的系统监控工具。

架构概述 🏗️

上一节我们介绍了MLOps中监控工具的重要性,本节中我们来看看一个具体的实现案例。下图展示了一个基于Rust的AWS Lambda函数架构。这是一个系统编程类型的Lambda,它能够与S3服务进行异步通信。

该Lambda函数可以处理包含成千上万个文件的S3存储桶。它会异步地遍历所有存储桶,检查每个桶内的每个对象,并执行特定操作。在这个作为监控工具的特定Lambda中,它会计算每个对象的大小并累加得到总量。在我的特定存储桶配置下,运行大约需要三秒钟。计算结果之后,可以将其推送到仪表盘(如Grafana)、监控系统或计费系统中。这一切都通过强大的异步Rust SDK实现。

代码实现解析 💻

现在我们已经了解了这个工具的功能,接下来让我们深入看看它的代码是如何工作的。

首先,我们需要使用AWS SDK。以下是一个代码示例,展示了如何开始使用SDK和Tokio异步运行时库。这个环境将展示如何异步地列出AWS环境中的所有表。

use aws_sdk_s3 as s3;
use tokio; // 异步运行时库

在看过基本用法后,让我们直接查看代码本身。在Github CodeSpaces中,我有一个异步AWS Lambda项目。你可以看到部分代码,例如我声明了 use aws_sdk_s3,并首先创建了一个AWS S3客户端。

// 创建S3客户端
let config = aws_config::load_from_env().await;
let client = s3::Client::new(&config);

然后,我编写了一个列出所有存储桶的函数。你可以看到我将其定义为 pub async fn list_all_buckets()。再次强调,async 关键字赋予了我们以异步网络方式运行此函数的能力。

// 异步列出所有存储桶
pub async fn list_all_buckets(client: &s3::Client) -> Result<Vec<String>, s3::Error> {
    // ... 实现代码
}

最后,我能够通过累加桶中每个对象的大小来计算存储桶的容量,这非常实用。

最终,我在这里使用 list_buckets 函数获取账户中所有存储桶的列表,然后遍历它们并计算每个桶的大小。

如果查看 main.rs 文件,它的主要作用是使用Lambda运行时库来创建一个便于人类阅读的辅助方法。至于函数处理器(function handler),它能够运行我们之前设置的代码,然后返回响应。

在这个特定的 main 方法中,它会依次调用其他方法。接下来,让我们也看看 Cargo.toml 文件。

项目依赖与运行 🛠️

以下是项目的主要依赖项,在 Cargo.toml 文件中定义:

[dependencies]
serde = { version = “1”, features = [“derive”] } # 用于序列化/反序列化
tokio = { version = “1”, features = [“full”] }   # 异步运行时库
aws-sdk-s3 = “1”                                  # AWS S3 SDK
humansize = “2”                                   # 用于将字节数转换为易读格式(如KB,MB)

Makefile 中,我们可以看到为了调用这个Lambda,可以直接运行make命令。让我们实际操作一下,我会将命令名称改为更简洁的,比如 runcount。我们就执行 make invoke

在这个例子中,如果我没有启用 cargo-lambda,很容易修复。只需进入我们的虚拟环境(这是我安装cargo-lambda的方式),然后再次运行。大约三秒钟后,它会异步地完成计算并统计出总存储量。在我的案例中,所有存储桶的总容量是114 GB。

现在,让我们看看Lambda本身。如果我们转到AWS Lambda控制台,可以看到这个异步Lambda函数。我也可以在这里面进行测试。

我只需点击“测试”,就能看到之前的调用记录。在这个案例中,我有一个负载(payload),内容只是 {“name”: “run”},这实际上是一个空负载。我点击测试,就能看到它运行的过程。这是一个非常棒的模式。

模式优势与应用场景 🚀

使用Rust构建高性能系统监控Lambda是一个极佳的模式。再次说明,这个Lambda的功能是计算所有存储桶的大小,但你可以想象如何构建与其他组件通信的工具,例如EFS、EMR、所有EBS存储,或者其他类型的系统监控工具。这些工具能够非常高效地运行,并且持续时间很短。在这个案例中,运行只花费了大约2.5秒,并且我可以在最低配置层级运行它,因此它是一个内存使用率非常低的Lambda。

总而言之,使用Rust构建高性能系统工具非常简单。在这个案例中,我们成功将其集成到Lambda中,我可以从Grafana等仪表盘工具调用它、在终端调用它、在定时事件(例如每天一次)中调用它,或者将结果集成到仪表盘中。

总结 📝

本节课中我们一起学习了如何利用Rust的异步特性和AWS SDK构建一个用于监控S3存储容量的Lambda函数。我们分析了其架构、核心代码逻辑、项目依赖以及实际运行方式。这种高性能、低资源消耗的模式,为构建各类云原生系统监控和运维工具提供了强大的技术方案。

078:认识课程讲师诺亚·吉夫特 👨‍🏫

欢迎来到应用机器学习运维课程。我是诺亚·吉夫特,是这门课程的讲师。

我是杜克大学的兼职教授。我的正式头衔是驻校执行官。我同时在信息系统硕士项目、跨学科数据科学项目以及人工智能产品创新项目中任教。

这门课程尤其令人兴奋,因为它涵盖了许多使用云平台将机器学习项目投入生产所必需的基础技能。

课程概述

在本课程中,我们将学习如何利用AWS平台,将机器学习模型从开发阶段推进到生产部署。课程内容涵盖了数据工程、探索性数据分析、模型构建以及最终的MLOps实践。

课程内容详解

上一段我们介绍了课程的整体情况,接下来,我们将详细拆解课程每周的核心内容。

第一周:AWS数据工程

在第一周,我们将重点学习使用AWS技术进行数据工程。以下是本周将涵盖的关键主题:

  • AWS机器学习入门:了解如何在AWS上启动机器学习项目。
  • 创建数据仓库:为机器学习任务构建和管理数据存储库。
  • 数据摄取与转换:识别并实施数据获取和预处理解决方案。

这部分内容不仅有助于准备AWS机器学习认证,更重要的是,它能帮助你构建可在AWS平台上投入生产的解决方案。

第二周:探索性数据分析

在学习了数据工程基础后,第二周我们将聚焦于使用AWS技术进行探索性数据分析。以下是本周的核心任务:

  • 数据清洗与准备:对原始数据进行清理和预处理。
  • 特征工程:从数据中提取和构建有效的特征。
  • 分析与可视化:分析和可视化数据,为机器学习建模做准备。

数据清洗和预处理是机器学习流程中至关重要的环节。AWS平台的优势在于提供了许多无服务器解决方案,帮助你高效构建基础设施。MLOps的目标之一是追求效率,因此利用AWS的无服务器技术进行预处理非常重要。

第三周:AWS建模技术

完成了数据准备,第三周我们将进入建模阶段,学习如何使用AWS技术构建模型。以下是需要掌握的内容:

  • 模型选择:如何为当前任务选择合适的模型(例如,是深度学习问题还是简单线性回归)。
  • 超参数选择:确定需要调整的关键超参数。
  • 解决方案权衡:了解使用AWS这类供应商时的权衡,例如是选择完整的解决方案(如AWS Canvas)还是SageMaker的自动调优方案。
  • 模型训练与评估:在平台上训练机器学习模型,并对其进行评估。

第四周:AWS MLOps实践

最后,在第四周,我们将深入探讨使用AWS进行MLOps实践。这是将模型投入生产的最终阶段。以下是本阶段的核心议题:

  • 效率与运维化:如何使流程高效,以及如何实际运维一个机器学习模型。
  • 生产环境设计考量:在部署模型到生产环境时需要考虑的不同选择,例如:
    • 编程语言选择:使用何种语言部署。
    • 部署目标与计算资源:目标是CPU还是GPU。
    • 优化技术:是否使用像ONNX这样的技术来优化模型,以提高推理效率。
  • 部署与维护:如何部署模型,并确保其能够持续运行,处理生产系统的负载。

课程总结

本节课中,我们一起认识了讲师诺亚·吉夫特,并详细了解了本课程的结构与核心内容。本课程是希望深入实践、利用AWS平台进行机器学习的宝贵资源。完成本课程不仅有助于掌握实用的MLOps技能,也能为你备考AWS机器学习认证提供有力支持。

079:使用SageMaker Studio Lab 🧪

在本节课中,我们将要学习如何使用Amazon SageMaker Studio Lab。这是一个免费的机器学习项目原型开发环境,基于Jupyter Notebook,并提供了CPU和GPU选项。我们将探索其界面、功能,并学习如何利用它来运行和实验Hugging Face的预训练模型。


概述

Amazon SageMaker Studio Lab是一个基于Jupyter Notebook的免费环境,专为机器学习项目原型设计。它提供CPU和GPU选项,其中GPU选项特别适合运行涉及预训练模型的现代机器学习工作流。该环境集成了丰富的资源,包括AWS机器学习大学课程和Hugging Face教程,方便用户快速上手。


环境界面与功能

上一节我们介绍了SageMaker Studio Lab的基本概念,本节中我们来看看它的用户界面和核心功能。

界面左侧是文件系统浏览器,可以查看和管理所有项目文件。点击相应的图标可以查看正在运行的笔记本和终端会话。

以下是界面中几个关键功能图标的作用:

  • 文件浏览器图标:用于浏览和管理项目文件系统。
  • 运行中图标:显示所有正在运行的笔记本和终端会话。
  • Git集成图标:提供版本控制功能,可以与Git仓库进行集成。
  • 目录图标:显示Jupyter Notebook的目录大纲。
  • 实验功能图标:用于启用实验性功能。

使用终端与环境管理

了解界面后,我们可以通过终端进行更深入的操作。终端是管理环境和监控资源的有力工具。

如果打开一个终端,可以执行各种命令。例如,要查看所有可用的Conda环境,可以输入:

conda env list

此命令会列出所有已创建的环境,方便用户在不同环境间切换或创建新环境。

另一个有用的功能是监控GPU使用情况。这对于运行本地模型训练(如Hugging Face的迁移学习)尤为重要。要监控GPU,可以输入命令:

nvidia-smi -l 1

该命令会每秒刷新一次,显示GPU驱动版本、CUDA版本、当前利用率以及GPU型号(例如Tesla T4)等信息。


运行Hugging Face教程

现在我们已经熟悉了环境的基本操作,接下来可以运行一些实际的机器学习代码。SageMaker Studio Lab预置了Hugging Face的教程资源。

在文件系统中,可以找到“huggingface-course”目录,其中包含了与O‘Reilly出版的Hugging Face书籍对应的各章节笔记本。例如,打开第一章的第三节笔记本,可以开始学习Transformer模型。

首先,通常需要安装必要的库。在笔记本单元格中运行:

!pip install datasets evaluate transformers

这条命令会从Hugging Face安装transformers库及其相关依赖。安装完成后,就可以利用GPU环境运行预训练模型。


体验Transformer管道

安装好库之后,我们就可以使用Hugging Face的pipeline API来轻松调用各种预训练模型进行推理。

pipeline函数封装了从模型加载到推理的全过程。例如,进行情感分析:

from transformers import pipeline

classifier = pipeline("sentiment-analysis")
result = classifier("I love this course!")
print(result)
# 输出可能为:[{'label': 'POSITIVE', 'score': 0.9998}]

除了情感分析,pipeline还支持多种任务:

  • 零样本分类:给定一段文本和一组候选标签,模型会判断文本与哪个标签最相关。
  • 文本生成:根据提供的开头,自动生成后续文本。
  • 掩码填充:将句子中的[MASK]标记替换为模型认为最合适的词语。

这些任务都可以在SageMaker Studio Lab的GPU支持下快速运行,让用户直观体验Transformer模型的能力。


与AWS服务的集成

SageMaker Studio Lab作为AWS生态系统的一部分,也提供了与AWS服务的集成可能性,为将来将项目迁移到完整的AWS环境做准备。

在终端中,如果配置了相应的凭证,可以直接使用AWS命令行工具。例如,可以尝试列出S3桶:

aws s3 ls

通过查看帮助菜单(aws help),可以探索所有可用的命令。这种集成使得在原型开发后期,能够更平滑地将数据和模型工作流迁移到Amazon S3、SageMaker等生产级服务中。


总结

本节课中我们一起学习了如何使用Amazon SageMaker Studio Lab这个强大的免费工具。我们从其界面和基本功能开始,学习了如何通过终端管理环境并监控GPU资源。接着,我们动手实践,运行了Hugging Face的教程,并使用transformers库的pipeline接口体验了情感分析、文本生成等多种机器学习任务。最后,我们了解了它与AWS服务的集成潜力。SageMaker Studio Lab是一个极佳的实验环境,能有效帮助初学者和开发者原型化机器学习想法,并为后续部署到AWS云平台打下基础。

080:开始使用AWS CloudShell 🚀

在本节课中,我们将学习如何使用AWS CloudShell。AWS CloudShell是一个基于浏览器的命令行工具,可以直接访问AWS资源和服务。我们将探索其核心功能,包括如何启动、管理环境、上传下载文件,以及如何利用它来操作AWS服务(如S3存储桶)。


什么是AWS CloudShell? 💡

AWS CloudShell是一个基于浏览器的命令行界面,用于访问AWS资源和工具。其关键特性在于,它允许用户在任何地方(如图书馆或咖啡馆)通过浏览器直接登录并开始工作。由于它运行在AWS生态系统内部,因此操作速度非常快。

以下是其主要优点:

  • 无需管理额外凭证:访问权限基于IAM角色。
  • 自动更新:操作系统和工具会自动更新至最新版本。
  • 免费使用:服务本身不产生费用。
  • 附带存储:提供1GB的持久性存储空间。
  • 可定制:用户可以根据需要定制环境。

简而言之,AWS CloudShell是用于以编程方式控制AWS平台的接口之一。


启动与重置环境 🔄

现在,让我们启动CloudShell环境。在AWS管理控制台的任何区域,都可以找到并启动CloudShell。

启动后,你可能会看到之前工作的记录。在开始新任务前,有一个实用技巧:你可以重置整个CloudShell环境。如果你在环境中进行了大量实验并导致混乱,这个功能非常有用。重置后,环境将恢复为初始状态。


界面操作与多任务处理 🖥️

接下来,我们看看CloudShell界面中的“操作”菜单。这里有几个非常有用的功能:

  • 打开新Shell:你可以打开多个独立的Shell标签页。
  • 上下分割视图:将界面分为上下两个面板。这在处理前后端分离的任务时非常方便,例如,你可以在上半部分运行一个Flask或FastAPI服务,在下半部分调用它。
  • 左右分割视图:将界面分为左右两列。这可以让你构建一个类似仪表盘的终端工作区。

此外,你还可以上传和下载文件。


文件上传与下载 📁

CloudShell允许你从本地计算机上传文件到其主目录(/home),也支持从CloudShell下载文件到本地。主目录的存储空间限制为1GB,这对于许多任务来说已经足够。

上传文件:你可以一次上传一个文件。这对于数据工作非常常见,例如上传一个CSV文件或用于机器学习的其他数据文件。

下载文件:你需要知道目标文件在CloudShell中的完整路径。例如,路径可能类似于 /home/cloudshell-user/cats_dogs_small/cat.0.jpg

你可以使用 df -h 命令查看文件系统使用情况,以监控剩余的存储空间。


支持多种Shell环境 🐚

CloudShell默认使用Bash shell,但你也可以使用其他流行的shell环境。

  • Bash:默认环境。你可以编辑 ~/.bashrc 文件来自定义它。
  • Zsh:许多开发者喜爱的shell,提供更多命令和功能(如自动补全)。你可以通过运行 zsh 命令切换到Zsh,并编辑 ~/.zshrc 文件进行配置。
  • PowerShell:如果你是.NET开发者,可以使用PowerShell环境。只需运行 pwsh 命令即可进入。

这意味着无论你习惯使用Bash、Zsh还是PowerShell,都可以在CloudShell中找到合适的工作环境。


实战:使用CloudShell操作AWS S3 🛠️

现在,让我们使用CloudShell进行一些实际工作。我们将演示如何通过命令行创建S3存储桶并同步文件。

1. 创建S3存储桶
我们可以完全通过命令行创建存储桶,无需使用AWS控制台。命令格式如下:

aws s3 mb s3://你的存储桶名称

例如,创建一个名为 cats-dogs-11212021 的存储桶:

aws s3 mb s3://cats-dogs-11212021

创建后,你可以使用 aws s3 ls 命令列出所有存储桶来验证。

2. 同步本地文件到S3
假设我们已将一些文件上传到CloudShell的当前目录。我们可以使用 sync 命令将这些文件同步到S3存储桶。

aws s3 sync . s3://你的存储桶名称/

这个命令会将当前目录(.)下的所有文件同步到指定的S3存储桶中。sync 命令是高效的,它只会上传新增或更改的文件。

3. 从S3下载文件
同样,你也可以从S3下载文件。例如,如果你想下载一个ZIP文件,可以先确认其路径,然后使用下载功能。


总结 📝

本节课我们一起学习了AWS CloudShell的核心功能。我们了解了它作为一个基于浏览器的命令行工具的优势,包括便捷的访问、内置的AWS工具链和免费存储。我们实践了如何启动和重置环境、使用多任务视图、上传下载文件,以及切换不同的Shell环境(Bash、Zsh、PowerShell)。最后,我们通过创建S3存储桶和同步文件的实战演示,展示了如何使用CloudShell高效地操作AWS服务。掌握CloudShell将极大提升你在AWS平台上进行开发、数据工程和机器学习运维工作的效率。

081:使用云开发者工作区的优势 ☁️💻

在本节课中,我们将要学习云开发者工作区相较于传统本地开发环境的优势。我们将探讨其核心特点、不同云平台提供的解决方案,以及它如何为软件工程、数据科学和机器学习运维工作流带来变革。


传统本地环境的挑战

上一节我们介绍了机器学习运维的基本概念,本节中我们来看看开发环境的选择。首先,让我们审视传统的笔记本电脑或工作站开发环境。

这种环境存在几个关键问题:

  • 环境非确定性:没有标准化的保证环境。
  • 存在干扰包:可能安装了你不希望存在的软件包。
  • 硬件成本高:获取GPU和大容量固态硬盘等高性能硬件的成本高昂。
  • 与部署环境脱节:如果你的应用最终部署在云端,本地开发环境(除少数特例外)与生产环境存在差异。

虽然可以使用容器技术来缓解部分问题,但这并非根本解决方案。

云端开发环境的兴起

现在,让我们将目光转向云端。云开发者工作区是当前软件工程、数据工程、数据科学和机器学习工程领域一个非常有趣的新趋势。本质上,如果你不使用基于云的开发环境,你将错过许多在个人笔记本电脑上无法获得的新功能。

以下是主流的云开发环境选项:

集成开发环境类
这类环境更适用于软件工程、机器学习工程和运维工作流。

  • GitHub Codespaces:其独特优势在于与GitHub Actions(持续集成系统)和GitHub Copilot(基于OpenAI Codex的代码辅助工具)的深度集成,并且整个生态与GitHub紧密耦合。
  • AWS Cloud9:提供定制化功能,包括基于角色的权限管理(无需在代码中硬编码API密钥),并与AWS Lambda、S3、API Gateway等服务深度集成,便于构建无服务器应用。
  • AWS Cloud Shell / GCP Cloud Shell / Azure Cloud Shell:这些是更轻量级的云端命令行环境,适合执行简单的软件工程任务,并支持在Bash、Zsh或PowerShell之间切换。
  • GCP Cloud IDE 与 Azure Cloud IDE:谷歌云和微软Azure也提供了各自的云端代码编辑器。

笔记本环境类
这类环境更适合以笔记本为中心的工作流程。

  • Colab Notebooks:允许在云端构建兼容Jupyter、并能使用GPU的系统。甚至可以使用专业版本。
  • AWS SageMaker Studio Lab:允许用户免费使用AWS平台提供的GPU来运行Jupyter笔记本。

核心优势与未来展望

观察这些环境,你会发现一个共同趋势:世界正在转向这些功能强大、即用即弃、预配置好的环境。它们与云服务深度集成,SDK已预先安装,并且最关键的是——与数据同地协作

试想一下,如果你在咖啡馆需要处理TB级的数据,在本地和云端之间来回传输数据将非常困难。但如果数据本就存储在云端,而你启动了一个云开发环境,你就直接与数据位于同一位置,消除了数据传输的瓶颈。

因此,云开发者工作区的优势代表着未来发展方向。它提供了标准化、高性能、且与基础设施和数据无缝集成的开发体验。我强烈推荐大家深入探索并采用这种工作方式。


本节课中,我们一起学习了云开发者工作区相比传统本地环境的巨大优势。我们了解了它如何解决环境一致性、硬件成本和数据本地化等核心挑战,并概览了各大云平台提供的具体解决方案。拥抱云开发环境,将助力你的机器学习项目更加高效和可扩展。

082:在CloudShell中原型化AI API 🚀

在本节课中,我们将学习如何在AWS CloudShell环境中,利用命令行工具快速原型化和测试AI服务API。我们将从简单的情绪分析开始,逐步深入到如何获取、处理外部数据,并构建一个完整的数据处理流水线。


概述

AWS提供了丰富的AI服务,例如高级文本分析、代码审查、聊天机器人、预测和文档分析等。我们将从CloudShell开始,这是一个无需设置本地环境即可快速尝试和原型化想法的理想平台。

开始使用AWS Comprehend

首先,我们使用AWS Comprehend服务进行情绪分析。这是一个分析文本情感(积极、消极或中性)的服务。

在CloudShell中,我们可以通过aws comprehend命令来访问该服务。使用--help参数可以查看所有可用的子命令。

aws comprehend help

以下是可用的子命令示例:

  • batch-detect-dominant-language
  • classify-document
  • detect-sentiment

我们将从detect-sentiment开始,分析一句简单文本的情感。

执行第一个情感分析

我们可以构建一个命令来分析“I love C#”这句话的情感。为了使命令更易读,我们使用换行符来分隔参数。

aws comprehend detect-sentiment \
    --language-code "en" \
    --text "I love C#"

执行上述命令后,服务会返回一个JSON格式的结果,其中包含Sentiment字段,其值为POSITIVE。这表明我们的首次AI API调用成功了。

处理更复杂的文本输入

上一节我们介绍了如何分析短文本,但在实际应用中,我们可能需要分析来自网页等外部源的长文本。本节中我们来看看如何获取并处理这类数据。

AWS Comprehend对单次输入的文本有长度限制(少于5000字节)。为了处理更长的文本,我们需要先获取内容,然后截取合适的部分。

首先,我们安装一个名为links的终端网页浏览工具,它可以将网页内容以纯文本形式输出。

sudo yum install links -y

安装完成后,我们可以用它来获取维基百科上关于阿尔伯特·爱因斯坦的文章。

links -dump https://en.wikipedia.org/wiki/Albert_Einstein | less

使用wc命令可以查看获取到的文本字节数,这远超过5000字节的限制。

links -dump https://en.wikipedia.org/wiki/Albert_Einstein | wc -c

为了符合API限制,我们使用head命令截取前5000字节的文本。

links -dump https://en.wikipedia.org/wiki/Albert_Einstein | head -c 5000

将文本集成到AI命令中

现在我们已经能获取文本,接下来需要将其作为变量传递给AWS Comprehend命令。在Bash中,我们可以使用反引号或$()将命令输出赋值给变量。

我们将截取后的文本存储在一个变量中:

TEXT=$(links -dump https://en.wikipedia.org/wiki/Albert_Einstein | head -c 5000)

然后,在情感分析命令中引用这个变量:

aws comprehend detect-sentiment \
    --language-code "en" \
    --text "$TEXT"

分析长篇文章的情感,结果可能显示为NEUTRAL(中性)或带有POSITIVE(积极)倾向,这为数据科学分析提供了有趣的视角。

探索实体检测功能

除了情感分析,AWS Comprehend还能识别文本中的关键实体(如人名、地点、组织)。本节我们将使用detect-entities子命令,并学习如何处理其输出。

基本的实体检测命令如下:

aws comprehend detect-entities \
    --language-code "en" \
    --text "$TEXT" \
    --output text

命令将以表格形式输出,其中一列包含了识别出的实体名称。

构建AI数据处理流水线

为了从实体检测结果中获得更有价值的洞察,我们可以构建一个Bash流水线,来统计每个实体出现的频率。

以下是完整的流水线命令,它执行了多个步骤:提取实体、清洗文本、排序并计数。

aws comprehend detect-entities \
    --language-code "en" \
    --text "$TEXT" \
    --output text | \
awk '{print $3}' | \
tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr -d '\n' | \
sort | \
uniq -c | \
sort -nr | \
head -10

让我们分解这个流水线的每一步:

  1. aws comprehend detect-entities ...: 调用API检测实体,并以文本格式输出。
  2. awk '{print $3}': 使用awk提取输出结果中的第三列(实体名称)。
  3. tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]': 使用tr命令删除标点符号并将所有字母转换为小写,以实现标准化。
  4. sort: 对清洗后的实体列表进行排序,这是uniq -c正确计数的前提。
  5. uniq -c: 统计每个唯一实体出现的次数。
  6. sort -nr: 按计数降序排序,使出现最频繁的实体排在最前面。
  7. head -10: 只显示前10个最常出现的实体。

运行此流水线,我们会得到类似“Einstein”、“University”、“German”等高频实体列表,这快速揭示了文章的核心内容。

总结

本节课中我们一起学习了如何在AWS CloudShell中利用命令行原型化AI API。我们从简单的情感分析入手,逐步掌握了如何从外部获取文本数据、处理API的长度限制、将数据集成到命令中,最后构建了一个复杂的Bash流水线来自动化实体提取和频率统计。这个过程证明,即使不依赖Python或R等高级语言,仅使用CloudShell和Bash也能快速进行AI服务的概念验证和复杂的数据处理。

083:使用AWS Cloud9与CodeWhisperer进行AI结对编程

在本节课中,我们将学习如何在AWS Cloud9集成开发环境中,利用CodeWhisperer这一AI结对编程工具来辅助开发工作。我们将涵盖从环境创建到编写和调试代码的完整流程。

概述

了解Cloud9的最佳途径是查阅官方文档。AWS官方文档提供了关于如何在Cloud9中处理环境以及新功能开发的详细指南。随着新特性的开发,相关文档会持续更新。文档中包含大量资源,例如如何访问AWS工具包。接下来,我们将深入探索这些资源。

创建Cloud9环境

首先,确保你选择了正确的区域来创建Cloud9资源。你可以选择多个不同的区域。在本例中,我们将选择北弗吉尼亚区域。

以下是创建新环境的步骤:

  1. 点击创建新环境。
  2. 将环境命名为 Cloud9_CodeWhisperer_Demo
  3. 可以添加描述,例如“用于演示”。
  4. 如果需要,可以从命令行工具查询并拉取信息。

通常,选择适合你解决问题的实例规格是一个好习惯。如果只是进行探索,可以保留所有默认设置,并选择包含Amazon Linux 2。在本例中,我们将选择一个稍大的实例:具有16GB内存和4个CPU。最后,点击“创建环境”。

熟悉Cloud9界面

环境创建完成后,启动速度相当快。你将可以访问这个界面。加载时,欢迎屏幕会提供关于环境的更多信息。

界面右侧的资源区域允许你与他人共享此环境以进行结对编程。右侧的小齿轮选项卡是设置区域。你还可以通过选择调试图标来调试代码。

文件菜单包含各种有助于工作的功能,例如代码折叠或将代码向左或向右移动。

使用终端

开始使用Cloud9时,最重要的事情之一是熟悉终端。这里是所有强大功能的起点。

一个很好的展示方式是,如果我输入 aws s3 ls --help,可以看到这里有一个帮助菜单,我可以与之交互,它会确切地告诉我这个特定工具的功能。所有AWS工具都已安装在此环境中。

例如,我可以输入 aws s3 ls 来列出我拥有的所有存储桶,然后使用 wc -l 来统计可用的存储桶数量。这本质上是一个可以让你通过命令行操作所有资源,甚至在此环境内外复制数据的平台。

例如,如果我想上传文件,我可以使用上传本地文件功能,从我的文件系统中选择文件(例如截图、代码或其他需要与S3同步的内容)。然后,我可以使用 aws s3 cp 命令将其复制到我关心的存储桶中。

访问AWS工具包

除了终端,你还可以在此选项卡中访问文件系统、源代码控制和AWS工具包。

AWS工具包可能是这里最有用的组件,因为在这个区域,你可以访问许多具有深度集成的不同服务。这意味着我可以在此调用这些服务。如果需要,我甚至可以部署新服务、查看容器注册表、与Lambda交互,并能够与所有这些不同的资源进行交互。

例如,如果我查看其中一个Lambda函数,我可以选择“在AWS上调用”,并实际向该Lambda发送有效负载,或者甚至可以下载并在本地进行操作。Cloud9内置了大量优秀的右键点击式集成。

配置AI结对编程环境

另一个很酷的功能是,它预装了云开发工具包,并且具备代码补全能力。在本例中,这被称为CodeWhisperer,即AI结对编程。

一个好的实践方式是首先设置一个虚拟环境。让我们开始操作:

python3 -m venv venv
source venv/bin/activate
pip install boto3
pip install black

我发现格式化工具在与AI结对程序员协作时非常有帮助。pip install black 将允许我格式化代码。

使用CodeWhisperer编写代码

设置完成后,我可以回到文件树视图,创建一个名为 s3_demo.py 的文件来尝试这个代码结对编程工具。

右键点击并打开文件。然后,我可以为这个工具设定我想要它做什么的提示。这种新工作方式的强大之处在于,你可以在此设置一个提示,说明你的意图。

例如,我输入提示:“创建一个列出AWS S3存储桶的函数”。这样,它就对我想要做的事情有了更多了解。

然后,我可以让它提示我接下来该做什么。例如,我输入 import boto3,它会识别。接着,我可以输入 def list_buckets():,它足够智能,知道我将尝试列出存储桶。它会给我所有需要的信息,并提供一些很好的建议。

你必须保持警惕,确保遵循语言的最佳实践。这就是我喜欢使用格式化工具的原因。使用Python格式化工具,我可以运行 black s3_demo.py 来清理代码,确保一切就绪。

现在,我需要告诉它帮我构建最后一部分。它会给出建议,例如需要创建S3实例,然后将其传递给列表存储桶函数,最后运行这段代码。

调试与优化

获得代码后,我可以再次运行格式化命令以确保格式正确。然后运行 python s3_demo.py。如果遇到错误,例如提示“没有服务属性”,这意味着我需要稍微清理一下代码。

更好的方式可能是调整代码。例如,将 s3 = boto3.resource('s3') 改为 s3 = boto3.client('s3'),并调整打印信息。这样,代码就能正常工作了。

总结

在使用AI结对程序员时,事情并非总是完美的,就像与普通人协作一样。但是,如果你能善用它的长处,同时结合外部工具,你可以获得很好的反馈。

Cloud9环境和CodeWhisperer是使用AWS工具包时的绝佳工具。能够同时使用AWS工具包和CodeWhisperer是一个很好的集成。目前它处于预览阶段,未来会越来越好,并将构建出深度集成并针对你的AWS工作流定制的解决方案。

084:数据存储简介 📚

在本节课中,我们将要学习数据工程策略中的一个基础环节:如何识别和编目组织内的各种数据源。这是构建有效数据处理流程的第一步。

数据源识别与编目 📋

上一节我们介绍了数据工程的重要性,本节中我们来看看如何系统地识别和盘点公司内的数据源。当组织开始实施数据工程策略时,首要且关键的一步是编目公司内所有不同的数据来源。

例如,你可以从一个移动应用程序开始,查看其用户数据,并分析这些数据存储在何处。这些数据通常可能存储在像 DynamoDB 这样的键值存储数据库中,其中包含特定用户档案信息的记录。这个用户记录就可以作为一个数据源被编目,以便数据工程师后续能够对其进行处理。

数据源编目实践 📝

以下是进行数据源编目时可以遵循的步骤:

首先,确定你想要编目的数据类型。以日志数据为例,你需要识别它是什么。

接着,你可以将数据源信息记录在一个电子表格中,这个表格包含了所有其他数据源的清单。

在编目时,需要记录内容类型。例如,对于 HTTP 请求日志,可以记录有多少 200 状态码的请求、多少 400 状态码的请求,以及发出这些请求的 URL 是什么。

此外,还需要识别数据的存储位置。例如,亚马逊 S3 是存储原始日志数据的绝佳位置,它属于基于对象的存储。

从编目到处理策略 🔄

一旦你将数据源信息编目到主数据源列表中,就可以围绕如何在数据工程管道中实际处理这些数据来制定策略。这为后续的数据清洗、转换和分析工作奠定了基础。

本节课中我们一起学习了数据存储的初步概念,重点是数据源的识别与编目。我们了解到,通过系统地盘点数据源(如用户数据、日志数据)及其存储位置(如 DynamoDB、S3),可以为构建高效的数据处理流程做好充分准备。这是实现成功机器学习运维的基石。

085:确定正确的存储介质 💾

在本节课中,我们将学习AWS提供的多种存储介质,了解它们各自的特点和适用场景,以便为不同的数据科学和机器学习任务选择最合适的存储方案。

AWS提供了多种不同的存储介质,包括多种类型的数据库。

数据库类型

以下是AWS提供的几种主要数据库类型:

  • 键值数据库:例如 DynamoDB。这类数据库非常适合存储用户记录或游戏统计数据。
  • 图数据库:例如 Neptune。它允许你构建和分析关系,这通常是新数据科学工作流中的重要部分,例如识别特定社交网络中的关键人物,并计算中心性等描述性统计量。
  • SQL数据库:例如 Amazon AuroraRDS。这些SQL数据库非常适合执行传统的基于事务的查询。

数据湖与对象存储

上一节我们介绍了不同类型的数据库,本节中我们来看看数据湖和对象存储。

另一种存储介质是数据湖。数据湖建立在S3之上,从计算和存储的角度来看,S3可以提供近乎无限的扩展能力。但数据湖在其之上增加了元数据层,以便对S3中的内容建立索引。AWS Glue就是一个很好的例子,它可以索引S3的特定部分,之后你可以通过Athena进行查询。

S3本身显然是一个出色的对象存储机制。任何需要生命周期管理、存储大文件,或者适合“全有或全无”访问模式(即一次性完整读取或写入,无需增量读写)的场景,S3都是绝佳选择。

文件系统

除了对象存储,AWS也提供了适用于不同工作负载的文件系统解决方案。

同样,EFS生态系统也有几种不同的类型。一种是NFS风格的EFS,它的优势在于可以按需增量扩展磁盘。根据施加的负载或存储的数据量,EFS可以自动增长,并且集群或挂载点在整个生态系统中可以保持统一。这种网络挂载点的实用技术已经存在数十年,但在云环境中,它由AWS全托管,这是一个巨大的优势。

EFS还有适用于Windows的FSX部分,这对于许多需要集中式挂载点的工作流也非常方便,同时由AWS为你管理存储。

块存储

最后,还有EBS。EBS的一个优势是能够提供自定义磁盘。这意味着,如果你需要为某些交易或机器学习训练任务配置一个非常快速的文件系统,你可以为特定任务定制、配置它,然后在任务完成后将其删除。

需要注意的一点是,EBS只能通过单个挂载点使用。

总结

总而言之,AWS几乎提供了你能想到的每一种存储介质,并且在每种存储介质下还有更细分的子类别。作为数据科学家、机器学习工程师或数据工程师,你的职责是根据手头工作的需求,正确选择和组合这些存储介质。

本节课中我们一起学习了AWS的核心存储服务,包括键值数据库、图数据库、SQL数据库、数据湖、对象存储S3、弹性文件系统EFS以及块存储EBS。理解每种存储的特性和最佳适用场景,是构建高效、可扩展的机器学习运维流水线的基础。

086:使用Amazon S3

概述

在本节课中,我们将学习Amazon S3的核心概念与基本操作。Amazon S3是每位工程师或机器学习工程师都需要了解的核心服务。我们将从控制台操作开始,逐步介绍如何创建存储桶、上传文件,以及使用高级功能如S3 Select查询数据。此外,我们还将探索如何通过AWS Cloud 9和命令行工具与S3进行交互,构建一个高效的数据处理工作流。


认识Amazon S3控制台

Amazon S3提供了多种访问方式,既可以通过控制台,也可以通过开发者工具进行功能强大的交互。首先,一个很好的起点是查看“存储桶”列表。在这里,你可以浏览账户中的所有存储桶,并决定对它们进行何种操作。

创建你的第一个存储桶

开始使用S3的简单方法之一是创建一个存储桶。

在控制台中,选择“创建存储桶”即可轻松完成。你可以为存储桶命名,例如 my-test-bucket-12345。然后,点击创建即可。

需要注意的是,存储桶名称必须在全球范围内唯一。如果你使用了一个非常常见的名称,可能会遇到命名冲突。一个简单的解决方法是使用一个较长的随机字符串来创建一个临时存储桶。

上传与管理文件

创建好临时存储桶后,你可以轻松地向其中上传文件。你可以直接从控制台上传。

例如,你可以将一个本地文件(如一份棒球数据CSV文件)拖放到存储桶中,或通过控制台的“上传”按钮添加。

这个工作流的优势在于,它能让你立即访问S3生态系统中的高级功能。

使用S3 Select查询数据

现在,让我们来看看S3的一些高级功能。假设我们有一个包含NBA数据集的存储桶。

选中一个文件后,你会看到许多选项,包括“属性”、“权限”、“版本”。其中一个更有趣的功能是“对象操作”下的“使用S3 Select查询”。

想象你有一个包含数百万行的TB级文件,直接理解其内容会很困难。但借助S3 Select,你可以使用SQL语言进行查询。

控制台会提供一些默认设置,如CSV分隔符和输出设置,甚至提供一个默认查询语句。例如,要查看CSV文件的前5行,你可以直接运行查询,并以原始或格式化形式查看结果。这对于数据科学家来说非常宝贵。

此外,你还可以从模板中添加SQL语句。例如,你可以选择一个查询球员姓名和位置的模板,稍作修改后运行,便能快速获得所需数据。

这是一种非常实用的数据查询方式,你可以直接在控制台中探索数据。

通过AWS Cloud 9与命令行交互

除了控制台,你还可以使用AWS Cloud 9作为与S3交互的界面。例如,你可以通过Cloud 9上传和下载数据。

在Cloud 9的文件菜单中,你可以右键点击并选择“上传本地文件”,将数据文件上传到工作环境。

更强大的方式是通过终端命令行操作。一个很好的入门方法是使用AWS CLI工具。例如,输入 aws s3 cp --help 可以查看该命令的所有帮助信息。

为了快速找到特定操作(如复制文件)的示例,你可以使用管道和grep命令进行搜索:

aws s3 cp --help | less | grep -A 5 -B 5 "copying"

这会显示相关的文档和示例模式,便于你学习和模仿。

根据帮助文档,将一个文件从本地复制到S3存储桶的命令格式很直观。例如:

aws s3 cp ./local_file.csv s3://your-bucket-name/path/

执行此命令后,文件便会上传到指定的S3路径。你可以返回AWS控制台,刷新对应的存储桶目录,确认文件已存在。

整合工作流

最后,一个有趣的实践是,回到S3控制台,打开刚刚通过命令行上传的文件,再次使用S3 Select功能对其进行查询。你可以执行与之前类似的SQL查询,深入分析数据。

由此可见,Cloud 9、命令行工具和控制台之间形成了一个强大的生态系统,它们协同工作得非常好。

总结

本节课中,我们一起学习了Amazon S3的基本操作与核心功能。我们从控制台创建存储桶和上传文件开始,接着探索了使用S3 Select直接查询大型数据集的高级技巧。然后,我们了解了如何通过AWS Cloud 9和AWS CLI命令行工具与S3进行高效交互,实现文件的上传与管理。对于数据科学家和机器学习工程师而言,掌握这种结合图形界面与命令行工具的工作流,是管理和分析云端数据的推荐实践。

机器学习运维:10.01.02:批处理与流式作业风格对比 🚀

在本节中,我们将探讨AWS平台上两种核心的数据处理作业风格:批处理与流式处理。我们将了解它们各自的特点、适用场景以及AWS提供的相关服务。


概述:两种作业风格

AWS提供了几种不同的作业处理思路。一种是批处理,另一种是流式处理

上一节我们介绍了数据处理的基本概念,本节中我们来看看这两种风格的具体实现和区别。


批处理作业

批处理是指对累积的大量数据进行一次性、集中式的处理。这种方式通常更简单:你获取一批数据,对其运行操作,然后得到结果。

AWS平台上有三项服务充分体现了批处理的概念并将其整合:

以下是三项核心的AWS批处理服务:

  1. AWS Glue:这是一项无服务器的数据集成服务。它创建元数据,允许你对S3或数据库中的数据执行操作并进行转换。它是处理海量数据批处理任务的一个典型例子。
  2. AWS Batch:这是一个通用的、基于批处理的框架。你可以用它大规模处理任何任务。它非常擅长在容器中运行大量作业,以及使用GPU进行模型训练。
  3. AWS Step Functions:这项服务允许你对不同的步骤进行参数化和编排。一个很好的例子是协调多个Lambda函数,让输入数据在它们之间顺序传递。

流式处理作业

流式处理是指对连续到达的数据流进行实时或近实时的处理。与批处理相比,流式处理更为复杂,因为你必须在数据到达时立即处理,这增加了出错的可能性。

在AWS平台上,两种流行的流式处理技术是:

以下是两种主流的AWS流式处理技术:

  • Amazon Kinesis:你可以向Kinesis发送小的数据载荷(payload),它会在接收到这些载荷时立即进行处理。
  • Apache Kafka(通过Amazon MSK):Amazon Managed Streaming for Kafka (MSK) 提供了完全托管的Kafka服务,用于构建高吞吐量的实时数据流管道。

核心对比与选择考量

在比较批处理和流式处理时,可以从数据规模和操作复杂性两个维度来思考:

以下是区分两者的关键点:

  • 操作复杂性

    • 批处理更简单。你获取一批数据,执行操作,然后得到结果。
    • 流式处理更复杂。你必须实时处理不断涌入的数据,因此出错的几率更高。
  • 数据规模

    • 批处理非常适合处理大型数据集。当然,它也能处理小数据,但通常你会将任务批量处理以利用如AWS Batch这样的服务进行大规模操作。
    • 流式处理通常处理较小的、连续的数据单元。你会在数据到达时立即处理它们。这是区分批处理和流式处理的一个有效方式。

总结

本节课中,我们一起学习了AWS上的两种数据处理风格。批处理适用于对海量历史数据进行离线、集中式计算,其服务如Glue、Batch和Step Functions侧重于可扩展性与任务编排。流式处理则适用于对连续数据流进行实时分析,其服务如Kinesis和MSK侧重于低延迟和高吞吐。选择哪种风格取决于你的具体需求:是处理规模庞大的静态数据,还是需要实时响应动态流入的数据。理解它们的差异是设计高效数据管道的关键。

088:数据摄取与处理流水线简介 🚀

在本节课中,我们将要学习数据摄取与处理流水线的基本概念,并了解AWS如何通过其托管服务来构建这些流水线,以解决复杂的机器学习运维问题。

概述

AWS的数据摄取与处理流水线通过使用托管的服务来解决复杂问题。一个典型的例子是AWS Batch服务。它将解决周期性作业的许多复杂部分整合在一起。

AWS Batch:托管批处理服务

上一节我们概述了AWS流水线的概念,本节中我们来看看AWS Batch的具体工作方式。它通过将多个组件组合在一起来处理周期性任务。

以下是AWS Batch工作流程的关键步骤:

  • 触发器:流程的启动点。它可以基于定时器、代码调用或其他事件。
  • 作业创建:触发器被激活后,会创建一个新的作业。
  • 作业队列:新创建的作业被放入作业队列中。队列中可以容纳成千上万个作业。
  • 作业处理:作业根据你为AWS Batch设置的并发处理数量进行处理。例如,可以启动200个不同的容器(比如GPU容器)来并行处理作业。

AWS Batch用途广泛,尤其适用于机器学习任务,例如基于组织内的事件计划对Hugging Face模型进行GPU微调。

AWS Step Functions:无服务器编排服务

了解了批处理服务后,我们再来看看另一种流水线编排方式:AWS Step Functions。它同样是一项无服务器技术,由AWS托管。

当有事件触发时(例如一个API调用或某处数据到达的触发器),Step Functions可以将多个Lambda函数串联起来。每个Lambda函数接收一个数据载荷,处理其中定义的任务,最终在流水线末端输出结果。

Step Functions的显著优势在于其强大的内置编排能力。以下是它提供的主要管理功能:

  • 日志查看:你可以清晰地查看每个步骤的执行日志。
  • 性能监控:能够了解每个步骤的耗时情况。

这意味着你无需自己构建复杂的生态系统来实现任务编排,Step Functions已经为你构建好了。你只需要将业务逻辑组合进去即可。

总结

本节课中我们一起学习了数据摄取与处理流水线的核心概念。我们了解到,AWS通过像AWS Batch(用于大规模批处理作业)和AWS Step Functions(用于无服务器工作流编排)这样的托管服务,简化了复杂流水线的构建与管理。这些服务允许开发者专注于业务逻辑,而无需操心底层的基础设施和编排复杂性,从而高效地支持机器学习任务,如模型微调。

089:使用AWS Batch 🚀

在本节课中,我们将学习如何使用AWS Batch服务在云端运行计算任务。AWS Batch是一个用于解决基本云端运行问题的优秀技术,它简化了批处理作业的提交、调度和执行过程。

概述 📋

AWS Batch的核心流程非常直观。它涉及创建一个计算环境、一个作业队列、一个作业定义,最后提交作业。整个过程无需管理底层服务器,特别适合运行容器化的工作负载。

创建计算环境 ⚙️

上一节我们介绍了AWS Batch的基本概念,本节中我们来看看如何创建计算环境。这是运行作业的基础设施层。

首先,在AWS Batch控制台启动向导,选择“开始使用”。第一步是创建计算环境。你需要决定作业的运行平台。

以下是主要的计算环境类型选项:

  • Fargate:无需管理服务器,AWS完全托管。强烈推荐此选项,因为它能自动处理所有后端基础设施。
  • Fargate Spot:基于Fargate的竞价实例,可获得高达70%的折扣。如果需要运行大量作业,这是一个非常经济的选择。
  • EC2(按需或竞价):基于虚拟机的传统方式。在此场景下,你可以精细调整所需的虚拟CPU数量。

此外,你还需要配置网络设置,例如选择作业将在其中运行的VPC(虚拟私有云)。

配置作业队列与定义 📥

创建好计算环境后,下一步是设置作业队列和作业定义。作业队列用于存放等待处理的工作。

接下来是通用配置部分,你可以在此设置参数,例如作业的超时时间。你还可以指定一个不同的执行角色。如果作业需要与其他AWS服务(如S3、DynamoDB)或外部API通信,可以通过分配具有相应权限的IAM角色来实现。

定义作业内容 🐳

最后,也是最关键的一步,是配置作业本身。这定义了任务的具体内容。

核心配置是容器镜像。你可以使用公共镜像,但通常更好的做法是构建自己的Docker镜像,其中包含运行所需的一切依赖,例如特定的机器学习库(如Hugging Face库)。

然后,指定容器启动时要执行的命令。例如,我们可以从一个简单的“Hello World”开始,并加上date命令以记录运行时间。

echo "Hello, AWS Batch!" && date

你还可以配置为该容器保留的虚拟CPU数量和内存大小。此外,AWS Batch支持一些高级容器配置,例如挂载存储卷、配置日志记录选项等。

提交与运行作业 🚀

完成所有配置后,向导会汇总所有信息。确认无误,即可提交作业。AWS Batch会自动处理作业的调度,并在你创建的计算环境中执行它。

总结 🎯

本节课中,我们一起学习了使用AWS Batch运行云端批处理作业的完整流程。我们了解了如何创建托管计算环境(推荐使用Fargate)、设置作业队列、定义包含自定义镜像和启动命令的作业,并最终提交作业。AWS Batch提供了一种简单、直接且强大的方式,将计算任务扩展到云端,而无需操心服务器管理。

090:使用AWS Step Functions编排工作流 🚀

在本节课中,我们将学习如何使用AWS Step Functions来编排和自动化机器学习或数据处理工作流。AWS Step Functions是一个可视化的工作流服务,非常适合协调AWS上多个不同的服务与任务。

上一节我们介绍了工作流编排的概念,本节中我们来看看如何实际使用AWS Step Functions来构建一个简单的自动化流程。

什么是AWS Step Functions? 🤔

AWS Step Functions是用于编排作业的理想工具,尤其擅长协调AWS上许多不同的服务。其核心优势在于可视化设计一系列步骤(选择、并行、条件判断等),并将其放入一个管道中运行,同时提供出色的执行过程监控。

入门指南:从“Hello World”开始

一个好的入门方式是点击“入门指南”,它会提供一个“Hello World”示例。这个示例本质上是一个JSON定义,其中包含了不同的“状态”。

以下是该示例工作流的简化表示:

{
  "StartAt": "PassState",
  "States": {
    "PassState": {
      "Type": "Pass",
      "Result": "Hello",
      "Next": "WaitState"
    },
    "WaitState": {
      "Type": "Wait",
      "Seconds": 3,
      "Next": "FinalState"
    },
    "FinalState": {
      "Type": "Pass",
      "Result": "World",
      "End": true
    }
  }
}

该工作流从一个“Pass”状态开始,输出“Hello”,然后等待三秒,接着执行“Final”状态输出“World”,最后结束。运行这个工作流非常简单:创建状态机并执行它。Step Functions会详细展示每个步骤的发生情况与结果。这种强大的可视化监控能力是其显著优点。

在演示中看到这一点很好,但如果我们想自己从头构建一些东西呢?

实战:构建一个Lambda函数编排管道 🛠️

我们可以通过编排自己的Lambda函数来构建一个管道。我们将创建两个Lambda函数,并用Step Functions将它们连接起来。

第一步:创建“Premarco” Lambda函数

首先,我们创建一个名为premarco的Lambda函数,使用Python运行时。

这个函数的功能是:接收一个包含name字段的载荷(payload),如果name的值是“Marco”,则返回“polo”;否则返回“no”。

以下是该函数的代码:

def lambda_handler(event, context):
    name = event.get('name', '')
    if name == 'Marco':
        return {'name': 'polo'}
    else:
        return {'name': 'no'}

创建后,我们可以配置一个测试事件来验证它。例如,使用输入{"name": "Marco"},函数应返回{"name": "polo"}。部署并测试该函数,确认其工作正常。

第二步:创建“Postmarco” Lambda函数

接下来,我们创建第二个名为postmarco的Lambda函数,同样使用Python运行时。

这个函数的功能是:检查输入载荷中的name字段。如果值是“polo”,则返回祝贺信息;否则返回鼓励信息。

以下是该函数的代码:

def lambda_handler(event, context):
    name = event.get('name', '')
    if name == 'polo':
        return {'message': 'Great job!'}
    else:
        return {'message': 'Keep trying!'}

同样,部署这个函数并创建测试事件进行验证,确保它能根据输入返回正确的消息。

为了确保两个函数在管道中能正确传递数据,我们调整了premarco函数的返回格式,使其输出一个包含name键的字典(如{"name": "polo"})。postmarco函数则期望接收相同结构的输入。

第三步:在Step Functions中编排工作流

现在,我们转到AWS Step Functions控制台,创建一个新的状态机,并选择“可视化设计”。

以下是构建工作流的步骤:

  1. 添加第一个状态,类型为“调用Lambda函数”。我们将其命名为“Lambda Invoke Premarco”,并选择之前创建的premarco函数。
  2. 添加第二个状态,同样类型为“调用Lambda函数”。我们将其命名为“Lambda Invoke Postmarco”,并选择postmarco函数。将第一个状态的输出作为第二个状态的输入。

这样,我们就定义了一个简单的顺序工作流:先执行premarco,将其输出传递给postmarco执行。

我们将这个状态机命名为“PrePostMarcoPipeline”并创建它。

第四步:测试工作流执行

创建完成后,我们可以开始执行(Start Execution)这个状态机。执行时需要提供输入载荷。

测试用例一:成功路径
输入载荷为:{"name": "Marco"}
工作流执行过程如下:

  1. premarco函数接收{"name": "Marco"},返回{"name": "polo"}
  2. postmarco函数接收{"name": "polo"},返回{"message": "Great job!"}
    在Step Functions的可视化界面中,我们可以清晰地看到每个步骤的输入和输出。

测试用例二:非成功路径
输入载荷为:{"name": "Bob"}
工作流执行过程如下:

  1. premarco函数接收{"name": "Bob"},返回{"name": "no"}
  2. postmarco函数接收{"name": "no"},返回{"message": "Keep trying!"}

通过Step Functions的界面,我们可以监控整个流程的每一步,这正是其强大之处。

总结 📝

本节课中我们一起学习了AWS Step Functions的核心用法。我们首先了解了它作为可视化工作流编排工具的价值。然后,我们通过一个“Marco Polo”风格的实践示例,逐步创建了两个Lambda函数,并使用Step Functions将它们串联成一个自动化管道。最后,我们通过不同的输入测试了工作流的执行,并观察了其详细的执行过程与结果。

这种“Marco Polo”示例是熟悉Step Functions基础概念的绝佳方式。一旦掌握了这些基础,你就可以利用它构建更复杂的数据摄取、数据处理和机器学习工作流,实现任务的自动化与协调。

091:传输中的数据转换 🔄

在本节课中,我们将学习如何在AWS平台上进行传输中的数据转换,并重点了解AWS Glue这一无服务器ETL系统的运作模式。

上一节我们介绍了数据转换的基本概念,本节中我们来看看一个具体的、在AWS平台上实现传输中数据转换的架构示例。

架构概览与流程解析

首先,让我们从头到尾解析这张架构图。整个流程由一个定时器触发开始。

以下是该数据转换流程的核心步骤:

  1. 定时器触发:一个定时器会周期性地触发AWS Glue作业。
  2. 执行ETL操作:AWS Glue是一个无服务器的ETL系统。这意味着你可以将其指向多个数据源。
  3. 数据源整合:例如,你可能在S3中有一个包含数百万行数据的大型CSV文件,同时还有一个外部的PostgreSQL数据库。Glue可以将这两者关联起来。
  4. 创建ETL管道:基于这些数据源,你可以创建一个提取、转换、加载的操作。
  5. 数据转换与输出:Glue会转换这些数据,并将其放入S3中的另一个存储桶。

这样,你就得到了一个强大的、可重复使用的操作,它能够持续生成数据的新版本。因为外部数据库可能由你合作的供应商进行更新,而定期运行的触发器会转换这些新数据并放入新的存储桶。

AWS Glue的附加优势

AWS Glue的另一个优点是,它可以为你自动编目这个新的存储桶并创建元数据记录。

这意味着,之后你的数据科学家实际上可以使用Athena来查询这个数据目录,而无需将数据全部从S3中拉取出来。他们可以运行无服务器查询,进行数据可视化,甚至可能基于Athena加Glue的组合进行数据操作。

因此,在你的生态系统内部,Glue带来了许多无服务器的便利。这种特定的架构是一个非常常见的模式,对许多组织来说都是一个合适且相当易于理解和维护的方案。


本节课中我们一起学习了AWS平台上利用Glue进行传输中数据转换的完整流程。我们了解到,通过定时触发无服务器的ETL作业,可以整合多源数据(如S3文件和外部数据库),进行转换后输出到新的存储位置。同时,Glue的自动数据编目功能与Athena查询服务的结合,为数据科学家提供了高效、便捷的数据访问与分析能力。这种架构模式兼具实用性、可维护性和可扩展性。

092:处理机器学习的MapReduce

📚 概述

在本节课中,我们将学习如何利用AWS生态系统处理机器学习中的MapReduce任务,特别是通过Spark与Hadoop分布式文件系统(HDFS)的交互来实现。我们将了解其核心架构、工作原理以及如何通过编写简单的函数实现分布式计算,而无需显式进行复杂的并行编码。


🏗️ 核心架构与组件

上一节我们概述了MapReduce在机器学习中的应用,本节中我们来看看支撑这一过程的核心架构与组件。

AWS为机器学习的MapReduce处理提供了一个强大的机制,它能够运行Spark。Spark可以在第三方平台(如Databricks)上运行,也可以在EMR(Elastic MapReduce)生态系统内部运行。

Spark的核心能力之一,也是其真正的核心功能,在于它与Hadoop分布式文件系统(HDFS)的交互。HDFS建立在S3之上,并将文件系统视为一个分布式、并行的计算和存储机制。

这意味着,如果你有一个笔记本(Notebook),并且该笔记本在后台需要处理越来越多的数据,S3的对象存储系统将能够通过启动虚拟机来有效处理所有进出操作。它可以将计算和存储任务分布到集群内的各个节点上。


⚙️ 工作原理与优势

了解了核心组件后,我们来看看这套系统是如何工作的,以及它带来了哪些优势。

这套机制的优点在于,它允许你相当无缝地编写一个函数。例如,该函数可以应用某些操作(可能进行相关性计算或其他计算),然后“归约”(Reduce)阶段会将所有结果合并在一起,比如说用于创建可视化图表。

这正是Spark生态系统的美妙之处:在后台,通过一个笔记本界面,任务被分布在这个文件系统上执行。作为程序员,你只需构建你的函数,该函数就能无缝工作,而无需你进行任何显式的并行编码。

以下是其工作流程的关键点:

  • 函数编写:开发者编写一个用于数据处理的函数(例如计算相关性)。
  • 自动分布:Spark自动将该函数要处理的数据和计算任务分布到HDFS集群的各个节点上。
  • 并行计算:每个节点在本地数据上并行执行相同的函数操作(Map阶段)。
  • 结果聚合:各个节点的计算结果被收集并聚合起来,形成最终结果(Reduce阶段,如生成可视化)。
  • 抽象并行性:整个复杂的分布式并行计算过程对开发者是透明的,无需手动管理。

🎯 总结

本节课中,我们一起学习了机器学习中MapReduce任务的处理方式。我们了解到AWS通过Spark和基于S3的Hadoop分布式文件系统(HDFS)提供了一个强大的解决方案。该方案的核心价值在于,它允许数据科学家和工程师通过编写普通的处理函数,就能自动利用后台的分布式集群进行大规模数据计算,极大地简化了并行编程的复杂性,提高了开发效率。

093:使用EMR Serverless

在本节课中,我们将学习如何在AWS平台上使用EMR Serverless来运行数据处理作业。我们将了解其核心功能,包括创建应用、提交作业以及使用托管笔记本进行问题诊断。

概述

EMR是AWS平台上可用于运行MapReduce等大数据处理任务的服务之一。通过EMR Serverless,我们可以无需管理底层集群,直接提交作业并利用托管环境进行分析。

创建Serverless应用

上一节我们介绍了EMR Serverless的基本概念,本节中我们来看看如何创建一个具体的应用。

从EMR Studio界面,我们可以启动无服务器应用并提交作业。我们还可以使用这些完全托管的Jupyter笔记本,将笔记本附加到集群,然后诊断作业中的问题。

以下是创建Spark应用的步骤:

  1. 在EMR Studio界面中,选择创建应用。
  2. 选择创建Spark应用。
  3. 可以选择默认配置进行创建。

现在我们已经创建了这个应用。如果需要,我们可以提交一个作业。这个作业可以运行特定的配置,接受一些参数,并且我们还可以通过额外的JSON负载来配置这个作业。

总结

本节课中我们一起学习了AWS EMR Serverless的基本使用。我们了解了如何通过EMR Studio界面创建无服务器应用、提交可配置参数的作业,以及利用托管笔记本环境来辅助开发和诊断问题。这为在云上运行大规模数据处理任务提供了一个简化管理的强大选项。

094:数据清洗

在本节课程中,我们将学习如何处理“脏数据”。脏数据是现实世界数据集中常见的问题,它可能包含缺失值、无关字符或不一致的格式。为了进行有效的分析或模型训练,我们必须先对数据进行清洗和预处理。我们将探讨两种常见的数据清洗场景:处理缺失值和为自然语言处理任务准备文本数据。

处理缺失值 🔍

上一节我们介绍了脏数据的概念,本节中我们来看看如何处理数据中的缺失值。这是数据清洗中最常见的任务之一。当你拥有一些数据,并希望在进行分析之前进行探索性数据分析时,查找并处理缺失值是关键的第一步。

以下是处理缺失值的常见步骤:

  • 查找缺失值:在Python的pandas库中,你可以使用 df.isna()df.isnull() 方法来识别数据框中的缺失值。
  • 决定处理策略:作为数据科学家,你需要根据具体情况决定如何处理这些缺失值。主要有两种策略:
    • 删除行:如果数据量很大,缺失值所在的行占比很小,直接删除这些行可能是一个简单有效的选择。可以使用 df.dropna() 方法。
    • 填充值:如果数据量较小,或者删除行会导致信息严重丢失,则可以选择填充缺失值。一个常见的方法是使用该列的中位数或平均值进行填充。例如,使用 df[‘column_name’].fillna(df[‘column_name’].median(), inplace=True)

文本数据预处理 📝

处理完数值型数据的缺失值后,我们转向另一种常见的数据类型:文本。在自然语言处理领域,对原始文本进行预处理是至关重要的,这能显著提升后续任务(如情感分析)的效果。

以下是针对NLP的文本预处理常见步骤:

  • 分词:将连续的文本序列切分成独立的单词或符号(即词元)的过程。例如,句子“I love MLOps!” 会被分词为 [‘I’, ‘love’, ‘MLOps’, ‘!’]
  • 去除停用词:停用词是指在语言中非常常见但通常对文本含义贡献不大的词语,例如英文中的“the”、“and”、“or”、“because”。在情感分析等任务中,去除这些词可以减少噪声,让模型更专注于有实际意义的词汇。

本节课中我们一起学习了数据清洗的两个核心场景。首先,我们介绍了如何处理数据集中的缺失值,包括查找缺失值以及根据数据情况选择删除或填充的策略。接着,我们探讨了为自然语言处理任务进行文本预处理的常见步骤,特别是分词和去除停用词。这些预处理步骤是构建高质量机器学习模型不可或缺的基础工作,能确保我们输入模型的数据是干净、一致且富有信息量的。

095:数据扩展

概述

在本节课中,我们将要学习机器学习中一个关键的数据预处理步骤:数据扩展。我们将了解为什么需要对数据进行扩展,以及如何通过简单的缩放技术使不同量纲的数据具有可比性,从而提升机器学习模型的性能。


为什么需要数据扩展?

上一节我们介绍了数据预处理的重要性,本节中我们来看看数据扩展的具体原因。

机器学习数据通常需要进行扩展,并非所有情况都需要,但大多数机器学习问题都要求你对数据进行扩展。这背后有一个非常简单的直觉。

这里有一个很好的例子。假设你有一个数据集,里面包含许多不同的列。有些列在比较数值。比如,有人说“我跑了5”。这到底是什么意思?是指跑了5英里、5公里还是5英尺?根据所使用的度量单位,差异是巨大的。

这就是数据扩展的一般直觉:一列数据可能以英里为单位,另一列可能以英尺为单位。直接进行比较并不是处理机器学习问题的好方法。例如,如果你在进行聚类分析,聚类结果将不会正确。


如何解决?通过数据扩展

那么,如何解决这个问题呢?答案是通过数据扩展。你可以做的事情之一是将数值缩放到0到1之间。这样,你就是在进行相对比较,而不是使用错误度量单位进行绝对比较。

因此,大多数机器学习算法确实要求你扩展数据,其原理相当直接。一旦你这样做了,你就能够将数据输入到,比如说,一个K均值聚类解决方案中。

以下是数据扩展的核心概念:

  • 目的:消除不同特征因量纲(单位)不同带来的影响,使模型能够公平地学习所有特征。
  • 常用方法:最小-最大缩放,将数据线性变换到[0, 1]区间。
  • 公式X_scaled = (X - X_min) / (X_max - X_min)

总结

本节课中我们一起学习了数据扩展。我们了解到,由于原始数据中不同特征可能具有不同的单位和尺度,直接用于机器学习算法(如聚类)会导致结果偏差。通过将数据缩放到一个统一的区间(如0到1),我们可以进行有效的相对比较,从而为大多数机器学习算法准备好数据。这是数据预处理中至关重要且常见的一步。

096:数据标注

在本节课中,我们将要学习机器学习中的一个核心概念:数据标注。我们将通过一个具体的例子来理解什么是标签、什么是特征,以及它们在监督式机器学习中的作用。

标签数据示例

上图展示了一个处理标签数据的例子。如果我们从一个笔记本中提取一些数据,例如一个包含NBA球员信息的数据集,其中“场均得分”这一列就可以作为标签。

特征与标签的关系

这个标签同时也是一个特征。对于同一列数据,我们可以使用两个不同的术语来描述它。我们可以使用这个特征来预测一个目标变量。例如,目标变量可以是该NBA球员的薪水。

因此,我们可能想要确定的是:基于球员的场均得分,我可以为该球员安排多少薪水。假设我是一支NBA球队的老板,这里的逻辑相当直接:你用来预测目标变量的任何东西都是一个特征,而这个特征需要有一个特定的标签。

获取标签的方法

如果你没有标签,可能需要通过其他方法来获取。你可以使用人工标注,例如通过亚马逊的Mechanical Turk等众包平台。或者,你也可以使用无监督机器学习来创建自然分组,然后利用这些分组来为数据打上标签。

监督式学习的要求

总的来说,所有监督式机器学习问题都需要一个带有标签的特征。这是构建预测模型的基础。

总结

本节课中,我们一起学习了数据标注的基本概念。我们明确了特征与标签的区别与联系,了解了标签在监督式学习中的必要性,并介绍了获取标签的两种主要方法:人工标注和无监督学习分组。理解这些概念是进行有效机器学习项目开发的第一步。

097:识别与提取特征

在本节课中,我们将学习如何利用公开数据集来构建机器学习系统。我们将介绍几种常见的公开数据源,并探讨如何在这些数据的基础上进行模型微调、特征工程和模型开发。


构建机器学习系统的一种非常常见的方法是使用公开数据集。

我们来介绍几种可用的常见公开数据集。

一个非常流行的公开数据源是 Hugging Face Datasets,你可以用它来微调模型。假设你从 Hugging Face 获取了一个预训练模型,并使用一个启用了 GPU 的环境,例如 GitHub Codespaces 或启用了 GPU 的 Amazon SageMaker 环境。然后,你可以基于可用的新数据,使用该 Hugging Face 数据集进行微调,创建一个新模型,并将其部署到生产环境或重新上传回 Hugging Face。

Amazon S3 的情况类似。拥有一个大型公开数据集是非常常见的场景。你可以将该数据集拉取到,例如一个 Jupyter Notebook 中,对其执行探索性数据分析,明确你想要构建的目标,然后基于该 S3 数据集创建一个模型。

另一个常见的公开数据集是 Kaggle。此外,还有许多公开数据集的例子,它们已经附加了许多特征工程组件,因此你可以在此基础上进行构建,利用这些特征工程解决方案来创建你自己的定制模型。

这样的例子有很多,以上只是三个有用的公开数据集示例。利用它们,你可以构建用于生产环境的模型,或者进行实验以开发出更进一步的模型,无论你是爱好者还是生产环境下的机器学习工程师。


本节课中,我们一起学习了利用公开数据集构建机器学习系统的基本流程。我们了解了 Hugging Face Datasets、Amazon S3 和 Kaggle 等常见数据源,并探讨了如何在这些数据上进行模型微调、探索性数据分析和特征工程,最终创建可用于生产或实验的定制模型。

098:特征工程概念

概述

在本节课中,我们将学习特征工程的核心概念。我们将通过一个具体的例子——NBA赛季数据,来理解如何通过改造或组合现有特征来创建新的、更有用的特征,并用于机器学习预测系统。

特征工程:从旧特征到新特征

上一节我们介绍了特征工程的基本概念,本节中我们来看看一个具体的应用实例。

这里我们面临一个传统的特征工程问题。在这个案例中,我们拥有NBA比赛的统计数据表。表中包含一个记录球队赛季总胜场数的列。我们可以采取的做法是重新利用这个旧特征,并将其转换成一个新特征。

具体而言,我们可以观察总胜场数,并判断它是否超过某个阈值。例如,根据一个赛季的总比赛场数,你可以设定:如果一支球队赢得了50场比赛,那么它就拥有一个“胜利赛季”,这个新特征的值将被标记为1。反之,如果一支球队只赢了35场比赛(再次强调,这取决于赛季总场数),那么这个新特征的值可能被标记为0。这个新列可以命名为“胜负记录”。

新特征的用途

一旦创建了这个新特征,你就可以用它来进行预测。我们可以将这个新特征作为我们试图预测的标签。例如,我们可以提出一个问题:能否利用一支球队的平均得分来预测他们在一个赛季中会拥有胜利记录还是失败记录?

假设你想要基于这个属性创建预测模型。上述方法就是一种可行的途径。你同样也可以创建其他新的特征。但这里的核心思想是:通过重用旧特征或将旧特征组合在一起,你可以创建出一个新特征,然后将其用于机器学习预测系统。

以下是创建新特征的关键步骤:

  1. 识别现有特征:找到数据集中可用的原始特征,例如“赛季总胜场”。
  2. 定义转换规则:根据业务知识或分析目标设定规则,例如“胜场 >= 50 则为胜利赛季”。
  3. 应用转换:根据规则为每条数据生成新特征的值,例如生成一个名为 winning_season 的新列,其值为 1 或 0。
  4. 用于模型:将这个新特征作为模型的输入(特征)或输出(标签/目标变量)进行使用。

总结

本节课中我们一起学习了特征工程的一个核心实践:如何通过转换或组合现有数据来构建新的特征。我们以NBA数据为例,演示了如何将“赛季总胜场”转换为二进制的“胜负记录”特征,并探讨了如何将此新特征用于预测模型。理解并掌握这种创造性地生成特征的能力,是构建有效机器学习模型的关键步骤。

099:数据可视化 📊

在本节课中,我们将学习一个传统数据科学项目的工作流程,重点关注数据获取、探索性数据分析以及如何通过可视化和统计方法发现数据中的模式。我们将以纽约时报的州级新冠疫情数据为例,演示从数据加载到生成见解的完整过程。

项目结构与工作流程 🔄

上一节我们介绍了课程背景,本节中我们来看看一个典型数据科学项目的结构。我建议在处理数据科学项目时,创建一个遵循以下四个阶段的结构:数据获取探索性数据分析建模结论。这四个阶段各自包含所需的关键组件,并且你可以在它们之间来回切换。

数据获取与初步探索 📥

首先,让我们看看探索性数据分析和数据获取阶段。这里,我可以直接从纽约时报获取数据,这是按州划分的新冠疫情数据。我通常会做的一件事是查看最后几条记录,以了解数据的当前状态。你可以看到这是非常新的数据。然后,如果我查看列,我们也可以看到列名以及数据的形状。这实际上是对数据的初步检查。

探索性数据分析:数值统计 🔢

现在,当你进入探索性数据分析时,其真正含义是,你希望以数值形式查看描述性统计信息。例如,如果我在这里使用 describe() 方法,我们可以查看病例数和死亡数等。例如,50%分位数(中位数)显示,各州的死亡人数中位数为 4,345 例,但最大值是 96,960 例。

以下是查看数据描述的代码示例:

data.describe()

探索性数据分析:数据可视化 📈

如果我们查看美国的新冠病例和死亡数据,这正是我们可以直接进行绘图分析的地方。我会绘制一个列与另一个列的关系图,比如病例数与死亡数。我甚至可以添加一个色调参数,为我们提供更多关于正在发生的情况的信息。

以下是绘制病例与死亡关系图的代码示例:

import seaborn as sns
sns.scatterplot(data=data, x='cases', y='deaths', hue='state')

你可以看到,这里报告的新冠病例数量与发生的死亡数量之间存在直接的线性相关性。这是一个经典问题。我注意到我在这里将数据框传递给了绘图函数。

数据操作与过滤 ⚙️

如果我想进一步操作数据,我可以做的一件事可能是按日期进行调整,然后按日期范围过滤结果。这样,我就获取了仅仅几天的数据。如果我查看最近的数据,你可以看到这里存在我可以发现的模式。

以下是按日期过滤数据的代码示例:

filtered_data = data[(data['date'] >= start_date) & (data['date'] <= end_date)]

排序与州级分析 🗺️

我们能做的另一件事是,通过排序来查找数值。我也可以进行州级分析,查看在病例数方面具有最高数值的独特州。你可以看到加利福尼亚、佛罗里达、纽约、宾夕法尼亚、德克萨斯,显然这些也是非常大的州。

以下是查找病例数最多州的代码示例:

top_states = data.groupby('state')['cases'].sum().sort_values(ascending=False).head()

然后,如果我想将其绘制出来,我们可以在这里进行并绘制出来。

核心概念与模式发现 💡

进行数据科学的核心思想是,你有一个数据获取阶段,一个探索性分析阶段,你需要同时查看数值数据和数据的图形化表示,以便发现模式。我们在这里可以看到的一点是,对于加利福尼亚州,似乎存在潜在的对数结果。在这里面也可以看到,开始出现对数结果。而纽约可能是这种情况最显著的版本。

以下是可能观察到的增长模式公式:
指数增长最终会开始趋于平缓

因此,这可能意味着在已发生的死亡人数方面将会出现一个平台期。

总结 📝

本节课中,我们一起学习了一个结构化的数据科学工作流程。我们从数据获取开始,通过describe()方法进行数值统计探索,然后利用散点图等工具进行可视化分析以发现线性关系。我们还演示了如何通过日期过滤和排序来深入挖掘数据,并进行州级分析。最后,我们通过观察增长曲线,讨论了数据中可能存在的指数增长与平台期模式。整个过程强调了结合数值分析与可视化来理解和解释数据的重要性。

100:数据聚类

概述

在本节课中,我们将要学习数据聚类的核心数学原理。我们将通过一个直观的篮球数据例子,来理解如何在多维空间中寻找数据点的自然分组。

核心数学原理

让我们来探讨聚类的核心数学原理。

我们可以用一个非常直观的方式来理解它,那就是观察NBA的赛季统计数据。

我们拥有得分、篮板和助攻三项数据。在一场典型的比赛中,如果一名球员表现出色,取得了10分、10个篮板和10次助攻,这被称为“三双”,因为它非常罕见。

但是,我们可以观察这三个数值,并将它们绘制在多维空间中,从而发现自然的群组。

因此,如果我们在这里看到,在一个坐标轴上我们有点数,另一个坐标轴上有助攻,还有一个坐标轴上有篮板。我们本质上为每个自然群组分配一个聚类,其中得分、篮板和助攻彼此接近。

你会看到自然群组出现。在这种情况下,这里有一些球员得分很高,但同时也有相当数量的助攻,因为他们距离篮筐很远,所以不会抢到很多篮板。因此,你可以看到他们自然地聚集在这里。

与此同时,控球后卫的助攻数会领先。所以你会看到他们都聚集在这里。他们也能抢到一定数量的篮板,但不如中锋那么多,中锋靠近篮筐,专注于抢篮板这项特定工作。

因此,你可以看到,当你在多维空间中对事物进行聚类时,会出现一个浮现的标签,它可能是得分手、控球后卫或中锋。这实际上取决于数据集,但这确实是核心的直觉。

事实上,你可以自己尝试,通过访问NBA数据并使用K-means聚类算法,你会发现会出现非常容易的自然分组,这些分组会与你通常认为的球员场上位置(例如控球后卫、前锋或其他位置)相对应。

总结

本节课中,我们一起学习了数据聚类的核心思想。我们了解到,通过将拥有多个特征(如得分、篮板、助攻)的数据点置于多维空间中,并计算它们彼此间的“距离”,可以自动发现数据中存在的自然分组或“簇”。这种方法无需预先定义标签,就能从数据本身的结构中识别出有意义的类别,例如篮球运动员的不同角色。

101:何时使用机器学习 🤔

在本节课中,我们将探讨一个关键问题:何时应该选择使用机器学习,而不是其他技术方法。理解这一点对于高效、合理地应用机器学习至关重要。

概述

选择正确的技术方案是项目成功的第一步。本节将提供一个清晰的决策框架,帮助你判断在何种场景下,机器学习是合适的工具,而在何种情况下,传统的启发式方法或其他技术可能更优。

启发式方法优先原则

一个简单的判断方法是:如果问题可以通过启发式方法解决,那么你应该首先尝试使用启发式方法。

以下是判断何时使用启发式方法的一个好例子。

案例:旅行商问题

假设我们遇到一个基于地理位置的问题:一家航运公司需要规划一条访问一系列城市的最短路径。这就是经典的旅行商问题

公式最小化总旅行距离 = Σ 城市i到城市j的距离

在这种情况下,使用启发式方法是更好的选择。原因如下:

  • 该问题在计算机科学领域已有许多成熟的解决方案。
  • 使用启发式方法更容易调试和理解算法的运行过程。

例如,你可以采用一种“随机贪婪起点”算法,运行多次模拟,然后从中选择总旅行距离最短的路线。

机器学习的适用场景

上一节我们介绍了优先使用启发式方法的场景,本节中我们来看看机器学习在什么情况下能大显身手。

核心条件:拥有带标签的历史数据

当你的问题满足以下条件时,机器学习通常是一个绝佳的选择:

  • 你拥有带标签的历史数据
  • 你的目标是基于某些已知数据(特征)来预测另一个相关的未知值(标签)。

案例:NBA球员薪资预测

假设你收集了一份数据集,其中包含:

  • 特征:每位球员每场比赛的平均得分。
  • 标签:球员对应的薪资。

你的目标是建立一个模型,根据球员未来的场均得分来预测其应得的薪资。

代码(伪代码表示数据关系):

# 特征 (X) 与 标签 (y) 的关系
X = df['points_per_game']  # 场均得分
y = df['salary']           # 薪资
# 目标:训练模型 f,使得 salary ≈ f(points_per_game)

这正是一个典型的机器学习用例。你利用历史数据中的模式(得分与薪资的关系),来对未来进行预测。

决策总结

总而言之,在面对一个问题时,你可以遵循以下决策流程:

以下是选择技术方案的基本指导原则:

  1. 首先评估启发式方法:如果问题可以通过清晰、确定的规则或优化算法(如旅行商问题)有效解决,应优先使用启发式方法。它通常更简单、高效且易于调试。
  2. 考虑机器学习:如果你拥有表格形式的、带标签的历史数据,并且目标是根据一些列(特征)的值来预测另一列(标签)的值,那么机器学习非常适合。这在商业预测场景中非常常见。

课程总结

本节课中我们一起学习了如何决定何时使用机器学习。关键在于审视问题的本质和可用数据的类型:对于规则明确的问题,启发式方法是简洁高效的利器;而对于拥有丰富标签数据、需要从历史模式中学习并进行预测的任务,机器学习则是强大的工具。做出明智的选择,能让你的项目事半功倍。

102:监督式与非监督式机器学习

在本节课中,我们将要学习监督式机器学习与非监督式机器学习之间的核心区别。我们将通过具体的例子来理解它们各自的工作原理、适用场景以及它们如何协同工作。

概述

机器学习主要分为两大范式:监督式学习和非监督式学习。理解它们的区别是构建有效机器学习解决方案的基础。本节将清晰地阐述这两种方法,并说明它们在实际项目中的应用。

监督式机器学习

上一节我们介绍了机器学习的两种主要类型,本节中我们首先来看看监督式机器学习。

监督式机器学习的工作原理是使用带有标签的历史数据,并基于这些数据来做出预测。在回归问题中,我们拥有自变量(特征)和因变量(目标标签)。例如,我们可能有球员的“场均得分”数据,如果我们想用这个数据来预测“薪资”,那么“薪资”就是我们的目标标签。

我们可以基于“场均得分”这个特征,创建一个监督式机器学习模型来预测“薪资”这个目标。因此,在任何你拥有标签数据的场景下,尤其是像这样以数值形式存在的表格数据,都可以通过监督式机器学习来解决。

其核心过程可以概括为:
模型 = 训练(特征数据, 标签数据)
然后使用训练好的模型进行预测:
预测结果 = 模型(新特征数据)

非监督式机器学习

了解了需要明确标签的监督式学习后,我们来看看非监督式机器学习。它的核心思想是发现数据中隐藏的模式,而这些被发现的模式随后可以成为数据的标签。

以下是一个很好的例子:使用聚类算法。假设我们拥有篮球运动员的“得分”、“助攻”和“篮板”数据,但没有给他们打上“位置”标签(如控卫、中锋)。

通过在这些特征上进行聚类分析,你能够发现隐藏的模式。例如:

  • 谁是NBA中的高得分手?
  • 谁是控球后卫?
  • 谁是中锋?

你可以通过聚类发现这些,因为当你在多维空间中进行聚类时,具有相似特征的球员会自然地聚集在一起。在这三个轴(得分、助攻、篮板)构成的空间里,同一类球员的数据点彼此距离最近。然后,领域专家(如篮球分析师)就能够识别这些隐藏的模式,并为每个簇赋予一个有意义的标签(如“控卫”、“得分手”、“中锋”)。

通常,在非监督式机器学习中,最好有领域专家参与,以便为发现的隐藏模式进行标注,从而可以将这些标签应用到数据上。这正是非监督式学习的核心:探索与发现,而不是基于已有标签进行预测。

核心区别与协同工作

现在,让我们总结一下两者的关键区别。监督式学习是在你已经拥有标签数据的情况下,针对一个具体问题(如预测)进行工作。而非监督式学习则侧重于发现数据中未知的结构或模式。

这两者并非互斥,它们可以协同工作。在许多实际项目中,非监督式机器学习可以作为第一步,用于发现数据中的标签或细分群体。然后,第二步可以将这些新生成的标签数据用于监督式学习,构建预测模型

例如:

  1. 非监督式步骤:对客户数据进行聚类,发现不同的客户群体(如“高价值客户”、“价格敏感型客户”)。
  2. 监督式步骤:使用这些新定义的客户群体作为标签,训练一个模型,用于预测新客户属于哪个群体。

总结

本节课中我们一起学习了监督式与非监督式机器学习。监督式学习利用已知的输入和输出(标签)关系来训练模型,用于预测新数据的输出。而非监督式学习则是在没有预定义标签的情况下,分析数据的内在结构和模式。理解这一根本区别,能帮助你在实际工作中根据数据情况和业务目标,选择合适的学习方法,甚至将两者结合,构建更强大的机器学习流水线。

103:如何选择机器学习解决方案 🧠

在本节课中,我们将学习如何在AWS平台上选择正确的机器学习解决方案。我们将探讨几种实用的方法,帮助你根据业务需求和技术特性,为项目匹配合适的算法或工具。

概述

选择正确的机器学习解决方案是项目成功的关键一步。本节将介绍两种核心方法:一是查阅官方技术文档,二是从业务角度正确定义问题。通过这两种方法,你可以更系统地为你的机器学习项目找到合适的起点。

方法一:查阅官方文档 📚

一个非常简单的入门方法是阅读SageMaker算法文档。AWS提供了关于SageMaker内置算法工作原理的详细文档,这是一个很好的起点。

以下是查阅文档时可以参考的算法类别:

  • 分类算法:用于区分不同类别,例如判断一张图片是书还是食物。
  • 回归算法:用于预测连续数值,例如预测球员每场比赛的得分。
  • 预测算法:用于预测未来时间序列事件,例如库存预测。

方法二:正确定义业务问题 🎯

上一节我们介绍了如何利用技术文档,本节中我们来看看如何从业务角度切入。选择正确机器学习解决方案的第二种方法是确保你从业务层面正确定义了问题。

许多时候,选择解决方案本身就是一个“问题定义”的过程。如果你能正确定义问题,就更容易识别出解决该问题所需的合适机器学习方案。

以下是几种常见业务问题及其对应的机器学习任务类型:

  • 分类问题:如果你的组织想要区分书籍和食品,这就是一个分类问题。
  • 回归问题:如果你想预测一个连续值,例如每场比赛的得分,这就是一个回归问题。
  • 预测问题:如果你想预测未来的时间序列事件,例如库存预测,你可以将其视为预测问题,并可能使用SageMaker内置的预测工具或AWS平台上的其他预测工具。
  • 聚类问题:如果你想发现隐藏的客户关系,这实际上是一个聚类问题,例如可以使用SageMaker的K-Means聚类算法。
  • 推荐问题:如果你想通过提供更好的推荐来增加客户量,你可以将其定义为一个推荐问题。

总结

本节课中我们一起学习了在AWS平台上选择机器学习解决方案的两种主要方法。首先,我们可以通过查阅详尽的SageMaker算法文档来了解技术选项。其次,更重要的是从业务出发,正确定义问题(如分类、回归、预测等),这能直接指引我们找到合适的机器学习任务类型和工具。将业务目标清晰转化为机器学习问题,是成功构建解决方案的第一步。

104:选择机器学习模型 🧠

在本节课中,我们将学习如何为待解决的特定问题选择合适的机器学习模型。我们将探讨两种主要方法:利用自动化机器学习工具进行探索,以及基于先验经验直接选择模型。

概述

为特定问题选择正确的模型没有完美的解决方案。存在多种不同的技术可以考虑。其中一种非常有趣的技术是首先使用自动化机器学习工具。

利用AutoML工具进行探索

然而,你不能在不首先确定问题类型的情况下,就直接对问题使用AutoML工具。你需要在回归或分类等问题类型中进行选择。

假设我们选择了分类问题。接下来,你可以指示AutoML系统从一系列模型和超参数中,通过大量不同的实验来进行选择。例如,系统可能会尝试XGBoost、逻辑回归以及其他多种分类模型,并使用大量不同的超参数,可能通过网格搜索来完成这个过程。

所有这些实验都会出现在SageMaker实验跟踪或MLflow实验跟踪等工具中。一旦你获得了这些实验跟踪结果,就可以选择符合你解决问题所要求的准确性和可解释性目标的模型。

因此,从某种意义上说,AutoML不一定是选择合适模型的唯一用例,但它在探索哪些特定模型和超参数可能适用于你试图解决的问题时,会非常有帮助。所以,使用AutoML是选择合适模型的解决方案之一。

基于经验直接选择模型

另一种解决方案是,如果你对特定问题已有经验,可以直接针对问题本身进行选择。例如,如果你知道XGBoost在你解决的问题上效果很好,就可以直接深入使用它。

总结

总而言之,AutoML可以作为一个非常好的探索性工具,帮助你确定可以选择的一些选项。本节课中,我们一起学习了通过AutoML工具探索模型选项以及基于已有经验直接选择模型这两种策略。

105:使用SageMaker Canvas进行建模演示 🧑‍💻

在本节课中,我们将学习如何使用亚马逊SageMaker Canvas这一低代码或无代码机器学习工具,来了解建模的基础组成部分。我们将从数据导入开始,逐步完成模型创建、数据探索、模型训练与评估的完整流程。


数据导入 📤

建模的第一个阶段是数据摄取。在SageMaker Canvas中,我们可以通过“导入”功能来加载数据。

以下是导入数据的两种主要方式:

  • 从本地计算机拖拽文件。
  • 从亚马逊S3存储桶中拉取数据。

例如,这里有一个关于美国职业棒球大联盟的数据集。要导入它,只需选中文件并点击“导入”按钮,系统便会开始导入数据。


数据探索与模型创建 🔍

数据导入完成后,我们就可以开始建模了。

首先,需要创建一个新模型,例如命名为“new baseball model”。接着,选择要使用的数据集,这里我们选择刚才导入的棒球数据。

这个工具的一个优点是,它能直观地展示数据的初步信息:

  • 数据类型
  • 是否存在缺失值
  • 是否存在不匹配的值
  • 唯一值的数量
  • 平均值和众数

如果想进一步可视化数据,可以点击“可视化”。例如,我们知道身高和体重可能存在关联,数据可视化图表可以清晰地展示这一点。

此外,工具还支持类似Excel的函数功能,允许我们应用一些公式对数据进行处理。这是一个为机器学习构建的、具备强大数据可视化能力的好工具。


模型训练与初步构建 ⚙️

回到模型创建界面,我们需要选择要预测的目标列。例如,我们可以选择预测球员的“位置”。

系统显示“位置”包含多个类别,如救援投手、先发投手等。在开始训练前,可以先验证数据是否正确。

确认无误后,可以启动“快速构建”。该功能会尝试创建一个模型来预测所选的目标变量。由于我们已经预先运行过,现在可以查看一个已创建好的模型。

该模型显示,其正确预测位置的准确率为37%。


模型评估与指标解读 📊

我们可以深入查看模型对每个具体位置的预测效果。例如,查看“救援投手”的预测情况,发现这是模型预测效果较好的类别之一。

系统提供的“模型准确率洞察”功能,能以图表形式展示预测值与实际值的对比。对于“救援投手”,模型仅根据身高和体重就能在41%的情况下正确预测;而对于数据中实际是“救援投手”的样本,模型能正确识别出其中的73%。

我们还可以查看高级评估指标:

  • F1分数:兼顾精确率和召回率的平衡性指标。
  • 平均准确率:所有预测中正确的百分比。
  • 平均精确率
  • 平均召回率
  • 平均AUC(曲线下面积)

这些是不同的模型性能评估指标。工具甚至提供了每个指标的解释。例如:

  • 点击“精确率”,它会说明:在所有被预测为“接球手”的情况下,预测正确的比例为28%。
  • 点击“召回率”,它会说明:当实际位置是“接球手”时,模型能正确预测出其中的13%。

这是一个学习数据科学和机器学习概念的绝佳方式。通过这个工具,我们可以逐一探究每个指标的含义。界面中还展示了混淆矩阵,让我们能清楚地看到真阳性、假阳性等预测结果。


结果导出与应用 📥

最后,如果需要对结果进行进一步分析或展示,我们可以:

  • 下载训练好的模型。
  • 下载可视化图表,并将其集成到仪表板中。

本节课中,我们一起学习了如何使用SageMaker Canvas完成从数据导入、探索、模型训练到评估的完整机器学习建模流程。通过这个低代码工具,我们直观地理解了数据准备、模型选择及性能评估等核心概念,为深入学习机器学习运维打下了基础。

106:使用训练-测试-分割方法 📊

在本节课中,我们将要学习机器学习中的一个核心概念:训练-测试-分割方法。我们将探讨如何将数据集划分为训练集和测试集,以及这种方法如何帮助我们评估模型的真实性能。同时,我们也会了解其潜在的局限性,并介绍交叉验证作为一种可能的解决方案。


核心概念:训练-测试-分割

机器学习的一项核心能力是理解训练-测试-分割。一个简单的理解方式是,你将按照80/20规则来划分数据。

公式表示:
总数据集 = 训练集 (80%) + 测试集 (20%)

这意味着80%的数据将被随机选择出来,用于训练模型。你将通过调整超参数和选择正确的模型,利用这部分数据来获得最佳准确率。

然后,你会保留这20%的数据,使其不参与模型训练过程。


评估模型性能

上一节我们介绍了如何划分数据,本节中我们来看看如何使用测试集。接下来,你将用这20%的测试集来评估模型的性能。

这样做的好处是,你能更真实地了解模型在现实世界中的表现。


潜在的过拟合问题

然而,即使采用了这种方法,你仍然可能面临过拟合的问题。因为随机选择的数据可能存在选择偏差。

例如,如果你随机选择的数据彼此之间过于相似,这种情况就可能发生。


解决方案:交叉验证

为了解决这个问题,你可以使用交叉验证。以下是交叉验证的基本思路:

你可以将数据分成许多不同的“折”,例如,将每一折都按80/20的比例进行划分。

然后,重新采样所有这些折,并将它们组合起来作为解决方案。

代码示例(概念性描述):

# 伪代码:K折交叉验证
将数据分为K个相等的部分(折)
对于 i 在 范围(K) 内:
    将第 i 折作为测试集
    将剩余的 K-1 折作为训练集
    在训练集上训练模型
    在测试集上评估模型
最终性能 = 所有K次评估结果的平均值

这并不能保证一定能解决过拟合问题,甚至不能保证一定存在过拟合问题。但如果确实存在选择偏差的问题,交叉验证可以作为一种解决方案。

因此,如果你发现模型存在过拟合问题,尝试交叉验证是值得的。其核心直觉在于,你的数据划分可能不当,这可能导致过拟合,而交叉验证有助于解决这个问题。


总结

本节课中我们一起学习了训练-测试-分割方法。我们了解到,将数据按比例(如80/20)划分为训练集和测试集,是评估模型泛化能力的基础步骤。同时,我们也认识到随机分割可能引入选择偏差和过拟合风险,而交叉验证是应对这些潜在问题的有效技术之一。掌握这些概念对于构建稳健的机器学习模型至关重要。

107:解决优化问题

在本节课中,我们将要学习深度学习中的一个核心概念:优化。我们将探讨在寻找问题最优解时可能遇到的挑战,例如局部最小值和全局最小值,并理解学习率在梯度下降过程中的关键作用。

理解局部最小值与全局最小值 🏔️

深度学习的一个基础问题是优化。让我们通过几个不同的场景来解释这个原理。

当你试图解决一个问题时,可能会遇到局部最小值全局最小值。如果你被困在一个局部最小值中,你将无法获得最终的最佳解决方案。

在这个场景中,如果你缓慢下降并被困在这个局部最小值里,那么你最终将无法到达下方的这个全局最小值,也就无法获得可能的最佳解决方案。例如,这会影响你试图解决的分类问题的错误率。

理解这个问题的一个直观方法是想象在黑暗中走下山。你可能会被困在半山腰的某个湖泊里,那就是局部最小值。但如果你能到达最底部,那就是全局最小值。

梯度下降与学习率 📉

思考这个问题的另一种方式是考虑梯度下降问题。其核心是构建一个损失函数,你希望获得越来越高的准确率,即减少损失。最终,你需要确定学习率,也就是每次迭代中参数更新的步长。

以下是梯度下降的核心公式:
新参数 = 旧参数 - 学习率 * 梯度

在向下移动以寻找全局最小值的过程中,如果你设置的学习率太小,那么将需要很长时间才能到达解决方案,即找到全局最小值。反之,如果你采用的学习率太大,你可能会越过并跳过全局最小值。

因此,在解决深度学习问题时,需要考虑学习率的设定。你可以通过试错法来找到合适的学习率。一个非常好的工具是使用 TensorFlow Playground。它为你提供了一个绝佳的起点,让你可以尝试不同的学习率,并实验各种损失函数。

总结

本节课中我们一起学习了深度学习的优化基础。我们了解了在优化过程中,模型可能会陷入局部最小值而非找到全局最优解。同时,我们探讨了梯度下降法中学习率的关键作用:过小的学习率会导致收敛缓慢,而过大的学习率则可能使算法无法收敛。最后,我们提到了使用像TensorFlow Playground这样的工具进行实验是理解和调整这些超参数的有效方法。

108:选择GPU与CPU 🚀

在本节课中,我们将探讨如何为你的训练任务或推理任务选择合适的处理器:是使用GPU还是CPU。理解两者的核心差异和适用场景,对于优化机器学习项目的成本与效率至关重要。


CPU与GPU的核心差异 💡

上一节我们介绍了选择处理器的重要性,本节中我们来看看CPU和GPU各自的特点。CPU(中央处理器)是一种通用、成本较低的芯片。它擅长处理顺序任务和通用计算。

CPU的特点可以概括为:
CPU = 低成本 + 通用计算 + 顺序处理

相比之下,GPU(图形处理器)则专为并行处理设计。它拥有大量核心,能够同时执行大量相同的计算任务,但成本通常更高。

GPU的特点可以概括为:
GPU = 高成本 + 专用计算 + 并行处理


如何做出选择:权衡与考量 ⚖️

了解了基本概念后,我们来看看在实际项目中如何做出选择。这主要取决于你所要解决的问题类型、对速度的要求以及预算限制。

以下是做出选择时需要考虑的关键因素:

  • 任务性质:如果你的任务涉及大量独立的、可并行化的计算(例如矩阵运算,这在深度学习训练中非常常见),GPU是更优的选择。如果任务更偏向逻辑控制、串行处理或通用计算,CPU可能就足够了。
  • 时间要求:如果任务对完成时间不敏感,可以接受较长的处理时间(例如一些可批量处理的后台任务),那么使用成本更低的CPU是合理的。
  • 性能需求:如果任务要求极高的处理速度,尤其是进行大规模并行操作时,GPU能显著加速训练或推理过程,其带来的时间节省可能远超其额外的成本。

总结 📝

本节课中我们一起学习了如何为机器学习任务选择GPU或CPU。核心在于理解CPU适用于成本敏感、顺序处理的通用任务,而GPU则专为需要大规模并行计算的高性能场景设计。在实际决策时,请综合考虑你的任务性质、时间限制和性能需求,在成本与效率之间找到最佳平衡点。

109:神经网络架构探索 🧠

在本节课中,我们将通过一个交互式工具来直观地理解神经网络的工作原理。我们将学习如何调整超参数,并观察这些调整如何影响模型的训练过程和性能。


探索神经网络背后原理的一个绝佳方法是使用 TensorFlow 的交互式工具。下图展示了该工具的界面。

界面上,我们选择了一个包含两个明显类别的数据集。这里有几个特征可供使用。神经网络包含一个隐藏层,其中有几个神经元,以及另一个隐藏层,也包含几个神经元。我们可以实时看到测试损失和训练损失的变化。

模型训练与观察

现在,如果我们开始训练这个模型,可以看到这里有一个控制学习率的参数。随着训练进行,模型逐渐开始区分这两个类别。

然而,这里出现了一点过拟合的迹象,因为测试损失较高。

超参数调优

为了解决过拟合问题,我们可以尝试调整其他超参数。例如,我们可以改变学习率,以可能更快地找到解决方案。我们也可以调整正则化参数来防止过拟合。

首先,让我们尝试调整学习率,看看效果如何。

通过改变学习率,模型收敛的速度似乎快了一些。同时,测试损失也略有降低。这意味着模型能够更快地找到一个更好的解决方案。

应用正则化

接下来,如果我们添加一点正则化来帮助模型更好地泛化,会怎么样呢?

我们调整正则化参数后,发现它对当前问题的改善效果似乎不明显。但这里的核心思想是,通过手动调整这些超参数,并在不同数据集之间切换、运行实验,是理解你正在做的事情背后原理的绝佳方式。

进一步探索

你还可以尝试调整测试数据的使用比例,或者尝试不同的数据集。这能帮助你真正建立起对神经网络工作方式的直觉。


本节课中,我们一起学习了如何利用交互式工具直观探索神经网络的架构。我们实践了通过调整学习率正则化等超参数来观察模型训练与泛化效果的变化。这种方法能有效帮助初学者建立对神经网络工作原理的直观理解。

110:过拟合与欠拟合 🔍

在本节课中,我们将要学习机器学习模型训练中的两个核心概念:过拟合欠拟合。理解这两个概念对于构建一个泛化能力强、预测准确的模型至关重要。


概念介绍

上一节我们介绍了模型评估的基本思想,本节中我们来看看模型在训练数据上可能出现的两种典型问题。

首先,我们可以将欠拟合问题理解为:模型(例如一条回归线)未能很好地捕捉数据点(散点图)的整体趋势。

观察上图所示的散点图,数据呈现出轻微的线性上升趋势。如果在此数据集上绘制一条回归线,但这条线未能贴合大部分数据点的分布,就可能遗漏对其他上升趋势数据的预测。换句话说,模型过于简单,未能学习到数据中的基本模式。


平衡模型

为了创建一个更平衡的模型,我们需要让预测线更贴合数据的中心趋势。

在上图中,一个更理想的模型会呈现出一条轻微弯曲的线,这条线直接穿过数据的中间区域。这种模型可以被称为平衡的预测。它既不过于简单(欠拟合),也不过于复杂(过拟合),在捕捉趋势和保持泛化能力之间取得了平衡。


过拟合问题

然而,同样存在过拟合问题。当模型试图过于紧密地匹配训练数据时,就会发生过拟合。

在这种情况下,模型可能会产生不切实际的预测,因为它无法泛化到其他数据集。它可能在你当前使用的特定测试数据上表现良好,但由于它过于紧密地跟随数据点,甚至学习到了数据中的噪声和随机波动,从而形成了一个不寻常的、复杂的模式。当你获得新的数据集时,这个不寻常的模式将导致预测失败,这就是过拟合问题。


核心直觉总结

以下是理解这两个概念的核心直觉:

  • 欠拟合:模型过于“安全”或简单,未能充分学习数据中的模式,导致预测能力不足。
  • 平衡模型:模型在“风险”与“安全”之间取得平衡,适度贴合数据趋势,具有良好的泛化能力。
  • 过拟合:模型过于“冒险”或复杂,试图完美拟合训练数据(包括噪声),导致在新数据上无法做出合理的预测。

本节课中我们一起学习了过拟合欠拟合的概念。欠拟合意味着模型太简单,未能捕捉数据规律;而过拟合意味着模型太复杂,过度学习了训练数据的细节(包括噪声),从而丧失了泛化到新数据的能力。构建一个成功的机器学习模型,关键在于找到两者之间的平衡点。

111:选择评估指标 📊

在本节课中,我们将学习如何为机器学习模型选择合适的评估指标。评估指标是衡量模型性能好坏的关键工具,它帮助我们理解模型在解决特定问题上的表现。我们将从分类问题入手,然后探讨回归问题,并了解如何通过多个指标来全面评估模型。

分类问题中的评估指标 🐱🐶

上一节我们介绍了评估指标的重要性,本节中我们来看看在分类任务中如何定义“好”的模型。一个经典的问题是:你必须弄清楚什么是“好”。如何做到这一点?一种方法是为你的问题选择一个指标,以确定你试图解决的是什么。

让我们以一个简单的场景为例:你试图区分猫和狗。假设这里有10个样本,其中有一些猫和一些狗。你需要能够确定你正确识别出狗的次数(这被称为真正例),以及你正确识别出它不是狗(即它是猫)的次数(这被称为真反例)。同时,也存在错误的情况:如果你将猫识别为狗,这就是假正例;如果你将狗识别为猫,这就是假反例。这些概念构成了评估分类模型的基础。

为了量化这些概念,我们引入两个核心指标:精确率召回率

以下是这两个指标的定义:

  • 精确率:在所有被模型预测为“正类”(例如“狗”)的样本中,有多少是真正的正类。其公式为:
    精确率 = 真正例 / (真正例 + 假正例)
  • 召回率:在所有实际为正类的样本中,有多少被模型成功预测了出来。其公式为:
    召回率 = 真正例 / (真正例 + 假反例)

精确率关注的是预测结果的准确性,而召回率关注的是模型发现正类样本的能力。一个模型可能精确率很高但召回率很低(即只对非常有把握的样本进行预测),反之亦然。

综合评估:ROC曲线与AUC

在现实中,我们很少能获得完美的分类器。模型的表现通常需要在精确率和召回率之间,或者在真正例率(即召回率)和假正例率之间进行权衡。这种权衡关系可以通过受试者工作特征曲线(ROC曲线)来可视化。

ROC曲线以假正例率为横轴,真正例率为纵轴。一个完美的分类器的ROC曲线会紧贴左上角。而一个随机猜测的分类器的ROC曲线则是一条从原点出发的对角线。曲线下面积(AUC)是衡量模型整体性能的一个综合指标,AUC值越接近1,模型性能越好。

选择评估指标的核心直觉在于,我们需要找到能够为我们的问题(例如区分猫和狗)提供最佳预测能力的平衡点,既要尽可能消除假正例,也要尽可能选出真正例。

回归问题中的评估指标 🏠

上一节我们探讨了分类任务的指标,现在我们将目光转向回归问题。在回归任务中,我们预测的是连续数值,例如房屋价格。

在SageMaker Canvas等工具中,我们可以查看模型对数值的预测情况。例如,在左侧是房屋的实际价格,右侧是模型的预测值。一个常用的核心指标是均方根误差(RMSE),它衡量了预测值与实际值之间的平均差异。例如,一个模型的RMSE为45,000美元,意味着其预测值平均偏离实际值45,000美元。这个值是否可接受,完全取决于具体的应用场景(例如,在怎样的房产市场中)。

深入分析:辅助指标

除了核心指标,深入分析其他辅助指标也是一个好主意。例如,我们可以查看R平方(R²),它被称为“拟合优度”。

R²表示目标变量(如房价)的变化中有多大比例可以由输入特征解释。其值介于0和1之间。例如,如果R²为0.8,意味着我们选择的特征可以解释房价差异的80%。这也暗示,如果我们能获得更多相关特征数据,模型性能还有提升空间。

回到模型构建选择界面,我们可以看到使用了哪些特征列,例如房间数、卧室数、人口、地理位置、收入中位数等。正是这些特征解释了80%的房价变化。

在分析界面,我们甚至可以查看每个特征对模型预测的具体影响程度。因此,评估模型性能有很多方法,不应只看核心指标,还要结合支持性指标,以成功完成预测的成本效益分析。

总结 📝

本节课中我们一起学习了如何为机器学习模型选择评估指标。我们了解到:

  1. 对于分类问题,核心概念包括真正例、假正例、真反例、假反例,并由此衍生出精确率、召回率以及综合性的ROC曲线与AUC指标。
  2. 对于回归问题,我们介绍了均方根误差(RMSE)和拟合优度(R²)等指标。
  3. 最重要的是,不存在完美的单一指标。为了成功进行机器学习预测,你通常需要查看多个指标,并结合具体业务场景进行综合判断。通过核心指标与辅助指标的结合分析,才能全面评估模型性能并指导后续优化。

112:使用实验跟踪比较模型

在本节课中,我们将学习如何利用实验跟踪功能来管理和比较不同的模型训练任务。我们将以Amazon SageMaker平台为例,展示如何通过其仪表板筛选、查询和分析历史训练任务。


实验跟踪的核心价值

上一节我们介绍了实验跟踪的基本概念,本节中我们来看看它在实际平台(如SageMaker)中的具体应用。实验跟踪的核心价值在于,它允许你系统化地记录、查询和比较大量训练任务的属性和结果。

在SageMaker中查看训练任务

以下是访问和筛选训练任务的基本步骤:

  1. 导航至训练任务面板:在SageMaker控制台仪表板中,找到并点击“Training jobs”(训练任务)选项。
  2. 查看所有任务:在此面板下,你可以浏览所有已完成的、正在运行的或失败的历史训练任务。
  3. 使用筛选功能:这是实验跟踪的关键功能之一,允许你根据特定条件过滤任务。

如何筛选训练任务

利用筛选功能,你可以快速定位到感兴趣的任务。以下是几种常见的筛选方式:

  • 按状态筛选:例如,你可以过滤出所有状态为“Completed”(已完成)的任务。这有助于你快速查看夜间批量任务的完成情况。
  • 按名称关键词筛选:例如,你可以在任务名称中搜索“principal component analysis”(主成分分析),从而过滤出所有相关的任务。
  • 查看任务详情:点击任意任务,可以深入查看其详细信息。

分析任务详情与指标

深入任务详情页面,你可以获取用于比较和分析模型的关键信息。以下是一些重要的可查看指标:

  • 任务运行时长:了解模型训练消耗的时间。
  • 使用的训练镜像:记录训练时所依赖的软件环境。
  • 实例类型:明确训练任务是运行在CPU还是GPU实例上,这关系到计算成本与效率。

实验跟踪在团队协作中的作用

实验跟踪功能对于团队协作管理大规模训练任务至关重要。如果一个10人或100人的团队同时进行大量实验,此功能允许每位成员:

  • 快速查询历史:从庞大的任务历史中迅速找到所需记录。
  • 深入挖掘细节:根据各种属性(如算法、参数、数据集版本)进行筛选。
  • 有效管理流程:系统化地比较不同实验的配置和结果,从而优化模型选择与迭代流程。

本节课中,我们一起学习了如何使用SageMaker的实验跟踪功能来比较和管理模型训练任务。我们了解了如何通过状态、名称等条件筛选任务,以及如何查看运行时长、硬件配置等关键指标。掌握这些技能,能帮助你在个人或团队环境中,更高效地追踪实验过程、比较模型性能并管理机器学习项目的生命周期。

113:监控与日志记录 📊

在本节课中,我们将要学习机器学习运维中一个至关重要的环节:监控与日志记录。我们将探讨如何将其视为“软件系统的数据科学”,并了解实施监控的关键组成部分。

概述:监控与日志记录

监控与日志记录是确保生产环境中机器学习系统稳定、可靠运行的基础。我们可以将其理解为软件系统的数据科学

这意味着,尽管你正在进行机器学习运维并将模型部署到生产环境,你同样需要关注你所使用基础设施的“数据科学”。对于一个服务器系统,其源代码、添加的日志记录以及代码中的性能埋点(例如,执行一次预测所需的时间)都是重要的信息来源。

监控的核心要素

上一节我们介绍了监控的基本概念,本节中我们来看看构成有效监控的几个核心部分。

以下是监控代理通常需要收集的关键指标:

  • CPU使用率:监控服务器的计算资源消耗。
  • 内存使用量:跟踪系统的内存占用情况,防止内存泄漏。
  • 自定义性能指标:例如,通过代码埋点记录的模型预测延迟,公式可表示为 预测延迟 = 请求结束时间 - 请求开始时间

可视化与管理工具

了解了需要监控什么之后,我们来看看如何查看和管理这些数据。

你可以使用如 AWS CloudWatch 这类工具来实现监控。通过它,你可以:

  • 拉起一个仪表盘,直观地查看各项指标。
  • 设置并查看警报,及时响应异常。
  • 在特定系统中搜索日志,进行问题排查。
  • 获取来自 CloudWatch 系统的自动化洞察报告。

因此,将监控与日志记录视为软件系统的数据科学,是理解其价值的最佳方式。你必须建立监控与日志记录机制,才能了解系统中正在发生什么,并获得系统的可观测性。

总结

本节课中我们一起学习了机器学习运维中的监控与日志记录。我们认识到,拥有数据科学这样的严谨学科思维是很好的,作为一名数据科学家,你需要将同样的技能应用到你构建的软件系统上,通过监控和日志来确保其健康运行。

114:多区域部署

在本节课中,我们将学习如何利用云服务提供商(如AWS)的地理区域和可用区概念,来构建一个能够抵御全球性故障的、高可用的分布式应用程序架构。

理解核心概念:区域与可用区

上一节我们介绍了构建弹性应用的重要性,本节中我们来看看实现这一目标的具体架构组件。云服务提供商通过区域可用区来组织其全球基础设施。

  • 区域:指云服务提供商在全球范围内划分的、地理上隔离的物理位置。例如,美国东海岸或欧盟都可以是一个独立的区域。每个区域包含多个可用区
  • 可用区:指在一个区域内,相互之间物理隔离、具备独立供电、冷却和网络设施的一个或多个数据中心集群。一个可用区通常由两个或更多数据中心组成。

这种设计的核心思想是:通过在不同地理区域和同一区域内的不同可用区部署资源,可以构建出能够抵御数据中心、可用区甚至整个区域级别故障的应用程序。

构建弹性架构的实践

理解了区域和可用区的概念后,我们来看看如何将它们应用于实际架构设计。以下是构建一个高可用、地理分布式应用程序的关键步骤:

  1. 跨区域部署:将应用程序的关键组件(如前端、后端服务)部署在两个或更多不同的地理区域。这样,即使一个区域发生大规模故障,其他区域的实例仍可继续提供服务。
  2. 多可用区架构:在每个区域内,将资源(如数据库、计算实例)分布在多个可用区中。例如,一个数据库集群可以同时使用区域内的所有三个可用区。
  3. 实现冗余与故障转移:通过上述部署方式,确保任何一个数据中心、可用区或区域发生问题时,流量和负载都能自动、无缝地转移到健康的资源上,从而保证应用程序的持续可用性。

通过结合跨区域部署和多可用区架构,你实际上遵循了软件开发的最佳实践,构建了一个极具弹性的应用程序。这种架构能够从容应对数据中心故障、可用区中断甚至整个区域的服务问题。

本节课中我们一起学习了云架构中区域可用区的核心概念,并探讨了如何利用它们来设计一个能够抵御全球性故障的、高可用的分布式应用程序。关键点在于通过在不同地理区域和同一区域内的不同物理隔离单元中部署冗余资源,来实现应用程序的弹性和持续可用性。

115:可复现工作流

在本节课中,我们将要学习可复现工作流的概念,特别是“基础设施即代码”的核心思想。我们将了解如何通过代码来定义和管理基础设施,从而实现自动化、一致且可追踪的部署流程。

什么是可复现工作流? 🧱

一个可复现的工作流包含了“基础设施即代码”的理念。

除了构建系统和源代码仓库等组件外,可复现工作流的核心在于将基础设施的配置和管理也通过代码来实现。

基础设施即代码工作流 🔄

上一节我们介绍了可复现工作流的基本概念,本节中我们来看看一个具体的“基础设施即代码”工作流是如何运作的。

在这个工作流中,我们从基于云的开发环境(如 Cloud 9)或本地开发环境(如 GitHub Codespaces)开始,然后执行测试、合并、触发构建的流程。

这个流程会测试我们的代码,确保代码规范检查(Linting)正常工作,并确保部署系统能够运行。

基础设施即代码的运作原理 ⚙️

在后台,“基础设施即代码”工具负责实际创建和管理基础设施。

以下是其运作的几个关键点:

  • 创建基础设施:例如,它可以创建一个亚马逊 S3 存储桶。
  • 维持状态:如果在下一次部署时配置没有变化,它将保持 S3 存储桶的现有状态不变。
  • 变更基础设施:如果你需要做出更改,例如将 S3 存储桶配置为静态网站,你可以部署一个变更配置的代码,工具会相应地修改基础设施。
  • 销毁基础设施:如果你需要删除之前的变更,你可以通过代码指令来销毁基础设施,例如删除一个 S3 存储桶。

核心理念总结 🎯

“基础设施即代码”的根本理念在于,不是由人工点击按钮来触发操作,而是由代码来驱动一切。这确保了整个过程是可版本控制、可重复且不易出错的。

本节课中我们一起学习了可复现工作流及其核心实践“基础设施即代码”。我们了解了如何通过代码自动化地管理基础设施的创建、更新和销毁,从而构建出可靠、一致且高效的机器学习运维流程。

116:AWS风格的容器化DevOps 🚀

在本节课中,我们将学习一种基于AWS云服务的容器化DevOps实践。这种模式强调将所有组件,从代码到基础设施,都定义为代码并进行统一管理,从而实现高效、可复现的部署。

核心流程概述

上一节我们介绍了DevOps的基本理念,本节中我们来看看其在AWS云平台上的具体实现。整个过程围绕容器化和“基础设施即代码”展开,旨在实现完全的可视化和可追溯性。

以下是该流程的关键组成部分列表:

  • 源代码仓库:将你的应用程序代码存放在如GitHub这样的源代码控制仓库中。
  • 声明式部署:实现幂等且可复现的部署。这意味着无论执行多少次,部署结果都是一致的。
  • 构建系统配置:构建系统的配置文件(例如,用于编译或打包的脚本)本身也是部署的一部分。
  • 基础设施即代码:服务器、网络等基础设施也通过代码(例如,使用AWS CDK)来定义和配置。
  • 应用源代码:你的核心业务逻辑代码。
  • Dockerfile:一个定义了如何构建容器镜像的文本文件,其中包含了运行应用所需的所有依赖和配置。

工作流程详解

正如我们所见,所有组件都集中管理。接下来,我们看看它们是如何协同工作的。

整个流程始于一次构建触发。具体步骤如下:

  1. 触发构建:当代码仓库有更新(如推送新提交)时,会触发AWS CodeBuild服务开始执行构建任务。
  2. 构建与推送容器:CodeBuild根据Dockerfile构建出一个Docker容器镜像,并将其推送到Amazon Elastic Container Registry (ECR) 进行存储。
  3. 部署基础设施与服务:同时,基础设施即代码(如CDK代码)会被执行,在AWS上创建或更新所需的基础设施,并将上一步构建好的容器部署到某个计算服务中。
  4. 运行微服务:容器最终会在AWS的某个托管服务上运行,例如:
    • Amazon ECS (弹性容器服务)
    • AWS Batch (批处理计算服务)
    • AWS Lambda (无服务器计算服务)
    • AWS App Runner (完全托管的容器应用服务)
      这些服务负责将容器作为一个微服务对外提供。

模式优势总结

本节课中我们一起学习了AWS风格的容器化DevOps模式。这种设计的核心思想在于获得完全的可见性和构建一个可追溯的基础设施。在此模式下,从构建配置、基础设施到容器环境的每一个组件,都直接对应一个具体的AWS服务,并通过代码进行管理,从而确保了部署过程的一致性和可靠性。

117:回顾计算选项

在本节课中,我们将回顾机器学习应用部署时可用的不同计算选项。我们将探讨从虚拟机到无服务器架构的演变,并分析每种方案在基础设施控制与开发部署速度之间的权衡。

基础设施控制与开发速度的权衡

上一节我们介绍了机器学习运维的基本概念,本节中我们来看看部署应用时可选择的不同计算环境。下图展示了从高基础设施控制到快速应用开发与部署的演变过程。

图中左侧代表虚拟机。这些可以是轻量级的销售型实例。随着我们向无服务器架构演进,会依次经过容器平台即服务。最终,在像 LambdaFargate 这样的无服务器方案中,开发者无需管理太多基础设施,只需构建业务逻辑并将其投入生产。

不同计算选项的职责划分

以下是不同计算模式下开发者的职责对比:

  • 虚拟机与容器:开发者需要管理操作系统、运行时环境、依赖项以及应用代码,拥有最高的控制权。
  • 平台即服务:开发者仍需进行少量工作,例如在应用中放置配置文件,但平台会承担大部分基础设施管理工作。
  • 无服务器:开发者几乎不管理基础设施,主要专注于编写和部署函数或应用逻辑。

如何为机器学习应用选择计算选项

因此,作为开发者,在构建机器学习应用时,选择取决于你的具体需求。如果你希望更专注于业务逻辑而非底层运维,可以倾向于使用无服务器选项。如果你需要执行底层定制或对运行环境有特殊要求,则可能更倾向于使用虚拟机和容器。

对于你正在构建的每一个具体方案,都需要选择能够解决你当前问题的最合适的配置。


本节课中我们一起学习了从虚拟机到无服务器等多种计算选项。关键在于理解在基础设施控制权应用开发部署速度之间存在的权衡关系,并根据机器学习项目的具体需求,在虚拟机容器平台即服务无服务器等方案中做出明智选择。

118:配置EC2实例

在本节课中,我们将学习如何配置亚马逊AWS的EC2实例。EC2是弹性计算云的简称,它允许用户在云中启动和管理虚拟服务器。我们将详细拆解配置EC2实例所涉及的各个核心组件。

概述

配置一个EC2实例并非单一操作,而是一个涉及多个子组件的生态系统。每个子组件都扮演着关键角色,共同确保EC2实例能够按预期启动和运行。理解这些组件是成功部署和管理云基础设施的基础。

EC2启动生态系统

上一节我们概述了EC2配置的整体概念,本节中我们来看看构成这个生态系统的具体子组件。下图展示了这些核心组件的关系:

以下是配置EC2实例时必须考虑的关键子组件:

  1. 启动方式

    • 你可以通过AWS管理控制台启动EC2。
    • 你可以使用软件开发工具包(SDK)以编程方式启动EC2。
    • 你还可以从持续集成(CI)管道中启动EC2。
  2. 用户数据

    • 这是你放置特殊指令的地方。例如,你可以在实例首次启动时运行脚本,用于安装软件包或配置环境。代码示例:#!/bin/bash yum update -y
  3. 存储

    • 你需要选择存储类型:是使用持久化的EBS存储,还是临时的实例存储?
  4. 安全组

    • 这定义了你的EC2实例的防火墙规则,控制着入站和出站的网络流量。
  5. SSH密钥对

    • 你需要一个密钥对,以便从其他位置(例如AWS Cloud Shell)安全地通过SSH连接到你的实例。
  6. 亚马逊机器镜像

    • 你是使用预构建的AMI,还是基于特定配置创建了自定义的AMI?
  7. 实例类型

    • 根据工作负载需求选择实例规格,例如侧重于CPU、内存或GPU。
  8. 成本模式

    • 选择计费方式:是按需实例,还是为了降低成本使用竞价型实例?
  9. 虚拟私有云

    • 你是否将资源隔离到特定的VPC中?这个VPC的网络配置是怎样的?
  10. IAM角色

    • 你希望这个EC2实例拥有什么权限?例如,你是否需要它能够读取S3存储桶中的数据,或与DynamoDB数据库通信?角色封装了这些权限。

总结

本节课中我们一起学习了配置亚马逊EC2实例的完整生态系统。我们了解到,成功启动一个EC2实例是多个子组件协同工作的结果,包括启动方式、用户数据脚本、存储选项、安全组规则、SSH密钥、AMI镜像、实例类型、成本模型、VPC网络以及IAM角色。正是这些组件的封装与配合,使得EC2实例能够顺利启动并执行预定任务。掌握这些组件是进行有效机器学习运维的基础。

119:配置EBS

在本节课中,我们将学习如何在AWS云平台上配置弹性块存储,并理解其在构建弹性机器学习系统架构中的作用。

概述

上一节我们介绍了AWS的基础服务,本节中我们来看看如何利用弹性块存储来构建高性能、可扩展的机器学习基础设施。我们将重点分析一个典型的云架构图,并解释其中各个可配置组件的作用。

架构图解析

下图展示了一个基于AWS平台的云架构,它清晰地列出了在构建系统时可以调整的各种配置选项。

核心组件与配置

以下是该架构中涉及的关键服务及其功能:

  • 弹性块存储:在云环境中,你可以按需配置块存储设备。其核心优势在于存储性能可以根据需求进行弹性伸缩。
  • 自动伸缩组:你可以设置自动伸缩,使EC2实例能够通过Elastic Beanstalk服务根据负载情况自动增加或减少。其工作流程可以概括为:

    负载均衡器监控健康指标 -> 触发自动伸缩策略 -> EC2实例数量动态调整

  • 应用服务层:这些弹性伸缩的实例可以运行业务智能查询或机器学习查询等任务,具体取决于你当前需要解决的问题。

架构设计的关键理念

此架构的核心思想是弹性。自动伸缩组中的实例会根据负载均衡器提供的健康指标动态启停。同时,块存储本身也可以被配置为提供极高的带宽。

作为构建机器学习系统的架构师,需要由你来决定哪些部分应该预先配置,哪些部分应该保持弹性,以及你希望应用程序具备哪些能力。

例如,如果你需要进行机器学习训练,并且需要一个由多台机器集群共同访问的、具有极高带宽的共享存储挂载点,那么上图展示的配置可能就是解决该问题的一个可行方案。

总结

本节课中我们一起学习了AWS EBS的配置及其在弹性架构中的角色。我们分析了如何结合自动伸缩、负载均衡和可配置的高性能存储来构建一个能够适应不同工作负载(特别是机器学习训练)的云上系统。理解这些组件的协同工作方式,是设计高效、可靠机器学习运维平台的基础。

120:AWS AI与ML服务 🚀

在本节课中,我们将学习AWS(亚马逊云科技)平台提供的一些核心机器学习服务。我们将通过控制台和代码两种方式,探索如何利用这些服务进行自然语言处理和图像分析等任务。


探索AWS机器学习服务

上一节我们介绍了机器学习运维的总体概念,本节中我们来看看AWS平台提供的具体服务。访问AWS控制台的“服务”菜单并找到“机器学习”部分,是了解平台能力的好方法。AWS提供了一些高级服务,值得首先了解。

使用AWS Comprehend进行自然语言处理 🌐

第一个值得关注的服务是AWS Comprehend。该服务可用于自然语言处理任务。一种使用方式是通过其内置的分析功能。

例如,输入文本“This is a great day.”并进行分析。

分析后,服务能够识别关键短语、检测语言、查找是否存在个人身份信息,并判断情感倾向的置信度。在本例中,这是一条非常积极的信息。


这是一个非常实用的服务,并且可以轻松地从控制台调用。此外,也可以通过Cloud Shell环境使用SDK进行调用。

打开Shell并开始使用SDK也是一种很好的方式。我们可以让Shell保持运行,然后继续探索其他服务。

使用Amazon Rekognition进行图像分析 🖼️

回到机器学习服务列表,另一个可以体验的高级服务是Amazon Rekognition。该服务展示了AWS在图像分析方面的能力。

该服务可以用于检测标签、进行面部分析、识别图像中的文字等。所有这些功能都可以在控制台中通过上传文件直接体验。

例如,从桌面选择一张猫咪图片并上传到指定位置。

服务能够成功识别出这是一只猫,并提供其他相关标签。同样,我们也可以通过API调用来使用此服务。例如,使用Python解释器构建解决方案。

通过Boto3 SDK以编程方式调用服务 💻

那么,如何通过编程方式调用这些服务呢?一种方法是使用AWS的Python SDK——Boto3。


可以查找你试图使用的特定服务。以Comprehend为例,使用该服务的方式相当直接。创建客户端只需一行代码。

如果想进行情感分析,可以找到相应的方法。整个过程非常直观。

我们可以回到Cloud Shell,输入ipython进入交互式环境。

检查Boto3是否已加载,并导入它,然后创建Comprehend客户端。

以下是调用情感分析的核心代码示例:

import boto3

# 创建Comprehend客户端
client = boto3.client('comprehend')

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/9630e4395c6fcc2385d2456b62a5f595_14.png)

# 定义要分析的文本
text = "This is a great day."

# 调用情感分析API
response = client.detect_sentiment(
    Text=text,
    LanguageCode='en'
)

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/9630e4395c6fcc2385d2456b62a5f595_16.png)

# 查看响应结果
print(response['Sentiment'])

执行后,我们将得到一个积极的情感判断。



因此,无论是通过控制台界面,还是通过Cloud Shell环境使用SDK,都是使用AWS机器学习服务的有效方式。


总结

本节课中,我们一起学习了AWS平台上的两项核心机器学习服务:用于自然语言处理的AWS Comprehend和用于图像分析的Amazon Rekognition。我们通过控制台界面直观体验了它们的功能,并学习了如何使用Boto3 SDK以编程方式调用这些服务,特别是完成了情感分析的代码示例。这些高级服务让开发者能够快速集成强大的AI能力,而无需深入底层模型的细节。

121:最小权限原则与AWS Lambda 🛡️

在本节课中,我们将要学习无服务器架构中的最小权限原则,并了解如何将其应用于AWS Lambda微服务,以构建更安全的机器学习系统。


上一节我们介绍了无服务器架构的基本概念,本节中我们来看看如何在这种架构中实施安全策略。

这里展示的是无服务器架构中的最小权限原则设计。

在这个特定的微服务中,你可以看到,Lambda微服务仅被授予从S3读取数据的权限,以及访问DynamoDB表的权限。

这样做的好处是,它允许我们精确地限制这个微服务的能力,使其只能执行其功能所必需的操作。

它没有被赋予额外的职责,这使其安全性大大提高。

以下是该微服务的工作流程:

  1. 一张图片被上传并放入S3存储桶。
  2. 这个操作会触发这个Lambda函数。
  3. 随后,这个Lambda函数会执行并更新用户资料。

这可以是一个机器学习系统的一部分。系统后续可能会应用某种预训练模型来处理S3中加载的这些图像,然后进行某种图像处理或为图像识别标签。

核心思想是,在系统开发的所有部分中,每个组件都只使用解决其特定微服务问题所必需的权限。


本节课中我们一起学习了最小权限原则在AWS Lambda无服务器架构中的应用。通过为每个微服务精确配置仅需的权限(例如仅访问特定的S3和DynamoDB),我们可以有效限制其能力范围,减少潜在的安全风险,从而构建出更安全、职责更分明的机器学习系统。

122:集成安全性 🔐

在本节课中,我们将学习如何为机器学习系统构建一个集成的安全体系。我们将以AWS云平台为例,剖析一个设计良好的网络如何通过多层次的安全措施来保护数据和资源。


上一节我们介绍了安全的重要性,本节中我们来看看一个具体的集成安全架构图。

上图展示了一个AWS的集成安全示意图,它揭示了一个正确构建的网络如何通过多种不同的安全层来发挥强大的防护能力。

以下是构成这个集成安全体系的核心组件:

  • 网络防火墙:AWS安全防火墙能够阻止未经授权的入站端口访问,这是第一道防线。
  • 基于角色的权限控制:从图中EC2实例部分可以看到,我们采用了基于角色的权限管理。这将有效限制攻击面。
  • 数据加密
    • 静态数据加密:数据在存储时(如EBS卷中)处于加密状态。
    • 传输中数据加密:数据在传输过程中(例如,从EBS存储传输到S3存储时)也进行端到端加密。
  • 虚拟私有云:整个系统被部署在一个虚拟私有云内部,提供了逻辑上的网络隔离。
  • 基础设施即代码:由于我们使用自动化部署或基础设施即代码,因此无需担心因手动操作而引入的错误。
  • 集成监控系统:监控系统能够与此安全体系集成,实现全方位的可观测性。

了解了基础防护层后,我们进一步看看如何通过监控和策略来加强安全治理。

这个集成安全系统还包含以下高级监控与合规功能:

  • API调用审计:通过AWS CloudTrail,我们可以查看所有API调用记录,从而深入审视网络中发生的每一个操作。
  • 账户访问控制:登录控制台账户时,可以启用双因素认证。我们还能审计和监控具体是谁登录了账户。
  • 最小权限原则:借助AWS IAM策略,我们可以实施最小权限原则。这意味着:
    • 构建系统仅拥有执行部署所必需的确切权限。
    • 服务本身也仅拥有其运行所需的确切权限,因为它使用的是基于角色的权限。

本节课中我们一起学习了集成安全的概念。这种集成的安全理念,结合了网络防护、数据加密、权限管理和持续监控,是设计一个安全网络的关键基础。它确保了从基础设施到应用层的每一个环节都受到保护,是构建可靠机器学习运维体系不可或缺的一环。

123:SageMaker Studio 工作流概述 🚀

在本节课中,我们将学习亚马逊 SageMaker Studio 的工作流概览。我们将了解从数据准备到模型部署与管理的完整流程,并探索 SageMaker Studio 提供的各种开发工具和环境。


AWS 上的 SageMaker 工作流

下图展示了一个在 AWS 上的典型 SageMaker 工作流。

工作流始于数据准备,随后是数据构建。接着,通过训练和调优确保模型正确性。之后是模型部署,并在生产环境中管理该模型。管理内容包括处理模型的特定版本、进行 A/B 测试、针对该模型进行预测,以及判断何时应执行重新训练任务(例如,应对数据漂移问题)。

这构成了完整的开发者工具链故事。


SageMaker 工具套件分类

除了核心工作流,还有一整套工具,可按机器学习应用的不同方面进行分类。

Studio 范畴内,不仅包含常规的 SageMaker Studio,还有其集成版本。工具主要分为三类:管道(Pipelines)项目(Projects)模型注册表(Model Registry)

此外,还有 Canvas。这是一个高度商业智能化的无代码/低代码工具,允许您通过上传数据、选择目标列然后进行预测来构建机器学习解决方案。


Amazon SageMaker Studio 开发环境

Amazon SageMaker Studio 是一个对开发者友好的环境,用于构建机器学习应用程序。

一个很好的起点是 启动器(Launcher)。您可以通过它快速启动模型算法解决方案。

您也可以通过创建 AutoPilot 实验 来自动构建模型。操作方式是输入实验名称和数据位置,然后开始执行。


数据导入、探索与可视化

您可以执行的另一项操作是导入和探索数据。如果选择此选项,其优势在于允许您从环境中已有的任何数据开始,通过点击操作构建解决方案,从而启动数据可视化流程。


启动菜单中的任务与组件

如果您查看此处的启动菜单,还可以浏览不同的任务和组件。

例如,构建数据流、新建编译任务或新建项目。所有这些选项都会显示出来。

您也可以更深入细节,或者直接启动一个笔记本,从头开始构建解决方案。这涵盖了项目开始时您可能需要做的任何事情。


实验跟踪与资源复用

总的来说,SageMaker Studio 提供了一整套工具。这些启动菜单是一个很好的起点,但它也允许您查看之前的实验和试验。

这种实验跟踪也是一个极好的资源,您可以利用它来构建指标、参数和工件,并在不同项目之间复用。


总结

本节课中,我们一起学习了 Amazon SageMaker Studio 的端到端工作流,涵盖了从数据准备到模型部署与监控的各个环节。我们还介绍了 SageMaker 提供的各类工具,特别是 Studio 环境中的启动器、数据探索、自动化建模以及实验跟踪功能,这些工具共同为高效构建和管理机器学习应用提供了支持。

124:使用SageMaker Canvas进行模型预测 🎨

在本节课中,我们将学习如何使用亚马逊SageMaker Canvas平台进行模型预测。我们将了解如何评估模型性能、分析特征重要性,并探索进行批量预测与单样本预测的方法。


模型概览与性能评估

上一节我们介绍了模型训练的基础,本节中我们来看看如何评估和使用已训练好的模型。

我们正在查看SageMaker Canvas中的一个模型。该模型能够正确预测住院时间的准确率为22%。因此,这个模型可能还需要一些改进工作。

分析特征重要性

评估模型时,理解哪些因素对预测结果影响最大至关重要。以下是分析特征重要性的方法:

我们可以查看每一列(特征)对模型预测结果的影响。例如,“用药数量”似乎是驱动此特定模型的最强特征之一,“实验室检查程序数量”也是影响力最高的特征之一。

执行模型预测

在理解了模型表现和关键特征后,下一步就是利用模型进行实际预测。

如果我想将此模型投入生产,方法之一是点击“预测”。进入预测界面后,我们有几个选项。

以下是可用的预测模式:

  • 批量预测:我可以输入一批数据,模型将对这些数据进行批量预测。
  • 单样本预测:此模式允许我针对此特定模型进行单一样本的实时预测。

实时调整与预测

这个预测过程的一个非常实用的特点是,通过在此处实时调整输入值,我可以看到系统能够允许我对此预测系统进行更改并立即观察预测结果的变化。

管理多模型版本

在模型开发迭代过程中,经常需要测试不同版本。以下是管理模型版本的方法:

我们还可以在此处切换到模型的不同版本,允许我们构建并在不同版本之间切换。例如,如果我刚刚创建了一个新特征并基于此重新训练了模型,我可以拥有多个版本,然后进行批量预测来比较不同版本的表现。


总结

本节课中我们一起学习了如何使用SageMaker Canvas进行模型预测。我们首先查看了模型的整体性能(22%的准确率),然后通过特征重要性分析识别出关键驱动因素(如用药数量和实验室检查数量)。接着,我们探索了两种预测模式:批量预测和单样本预测,并体验了实时调整输入以观察预测变化的功能。最后,我们了解了如何管理多个模型版本以进行迭代测试。使用Canvas是快速验证机器学习想法的高效方式,当然你也可以选择使用SageMaker Studio或Cloud 9等工具构建自己的机器学习系统。

125:数据漂移与模型监控 📊

在本节课中,我们将学习数据漂移与模型监控的核心概念和工作流程。这是一个确保机器学习模型在生产环境中持续有效的重要过程。

概述

数据漂移与模型监控是一个持续的过程,旨在检测模型性能因输入数据变化而下降的情况,并触发模型更新。接下来,我们将详细拆解这个过程。

工作流程详解

上一节我们概述了监控的重要性,本节中我们来看看数据漂移与模型监控的具体步骤。

整个过程始于数据。这些数据被用于创建一个初始的机器学习模型。

这个模型会被部署到生产环境的某个地方。例如,它可能正在预测新冠疫情的发展趋势,或者是一个已生成的疫苗模型,这构成了整个流程的终端应用。

随着时间的推移,当新的数据开始出现时,例如疾病的新变种出现,监控系统会检测到数据分布的变化。

此时,系统会创建一个数据漂移警报。这个警报表明,我们需要基于新的数据情况重新训练模型。

新模型的数据集由原始数据和自上一个模型部署以来出现的新数据共同组成。

以下是触发模型更新的关键步骤:

  1. 检测到数据分布发生显著变化。
  2. 系统自动或人工确认发出数据漂移警报。
  3. 准备结合了历史数据与最新数据的新训练集。

一旦上述步骤完成,一个新的模型就会被注册、训练、部署,并最终投入生产使用。

在未来,当再次出现显著的数据漂移时,相同的过程会再次发生,从而产生第三个、第四个模型。

因此,思考数据漂移与模型监控的过程其实相当直观。其核心思想是:当新的数据输入时,你需要创建新模型并将其投入生产。

总结

本节课中我们一起学习了数据漂移与模型监控的完整流程。我们了解到,这是一个循环往复的机制,通过持续监控数据变化、及时发出警报并重新训练模型,来确保机器学习应用能够适应现实世界的变化,保持预测的准确性和可靠性。

126:使用AWS App Runner部署PyTorch FastAPI应用 🚀

在本教程中,我们将学习如何将一个基于PyTorch和FastAPI构建的机器学习应用,通过AWS App Runner平台即服务(PaaS)部署到云端。整个过程涵盖本地开发、容器化构建、推送到AWS容器仓库(ECR),以及最终在App Runner上创建和运行服务。


概述 📋

我们将从一个包含PyTorch模型和FastAPI框架的代码仓库开始。首先在本地或云端开发环境(如GitHub Codespaces)中运行并测试应用。接着,我们将应用容器化,并推送到AWS Elastic Container Registry(ECR)。最后,利用AWS App Runner服务,从ECR拉取容器镜像并部署为一个可公开访问的、安全的机器学习微服务。


1. 准备开发环境与代码 🛠️

我们从一个专为AWS App Runner部署设计的PyTorch FastAPI代码仓库开始。该应用也可以在GitHub Codespaces等云端开发环境中运行。

以下是项目requirements.txt文件的主要内容,它列出了运行所需的核心依赖:

fastapi
uvicorn
pillow
torch
torchvision

这些包确保了FastAPI Web框架、ASGI服务器、图像处理以及PyTorch深度学习库的可用性。项目也包含一个Dockerfile,为后续的容器化部署提供了基础。


2. 理解应用代码结构 🧠

上一节我们介绍了项目依赖,本节我们来深入查看应用的核心代码逻辑。主应用文件(例如app.py)主要包含以下几个部分:

  1. 导入与初始化:导入必要的库(FastAPI, PyTorch, PIL等),加载一个预训练的PyTorch模型,并初始化FastAPI应用实例。
  2. 图像处理与预测函数:定义辅助函数,用于对上传的图像进行预处理(变换),并调用模型进行预测。
  3. API路由定义
    • /:一个简单的“Hello World”端点,用于调试和服务健康检查。
    • /predict:核心预测端点。它接收上传的图像文件,调用预测函数,并返回分类结果(例如,判断是否为“猫”)。

代码的核心预测逻辑可以简化为以下流程:

# 伪代码示意核心流程
@app.post("/predict")
async def predict(file: UploadFile):
    image = read_image(file)          # 读取上传文件
    tensor = transform_image(image)   # 预处理图像
    prediction = model(tensor)        # 模型预测
    label = decode_prediction(prediction) # 解析预测结果
    return {"prediction": label}

3. 本地运行与测试 ✅

在部署到云端之前,在本地环境中运行和测试应用至关重要。

在项目根目录下,使用以下命令启动开发服务器:

python app.py
# 或使用 uvicorn: uvicorn app:app --reload

服务启动后,在浏览器中访问 http://localhost:8000/docs,即可打开自动生成的Swagger API文档界面。

以下是测试步骤:

  1. 在Swagger UI中,找到 /predict 端点并点击“Try it out”。
  2. 选择一张本地图片(例如一张猫的图片)进行上传。
  3. 点击“Execute”执行请求。
  4. 观察返回的JSON响应,确认应用成功地对图片进行了分类(例如,返回 "Egyptian cat")。

本地测试成功,验证了应用逻辑的正确性。


4. 容器化与推送到AWS ECR 🐳

上一节我们确保了应用在本地运行正常,本节我们将应用打包成Docker容器,并推送到AWS Elastic Container Registry(ECR),为App Runner部署做好准备。

步骤概览:

  1. 创建ECR仓库:在AWS控制台为你的容器镜像创建一个新的私有仓库(例如命名为 pytorch-fastapi)。
  2. 准备构建环境:使用AWS Cloud9(一个基于云的IDE)或任何已配置AWS CLI的环境。克隆代码仓库并安装依赖。
  3. 构建Docker镜像:在项目目录下,使用Dockerfile构建镜像。
    docker build -t pytorch-fastapi .
    
  4. 标记镜像:将本地镜像标记为指向你的ECR仓库URI。
    docker tag pytorch-fastapi:latest <your-aws-account-id>.dkr.ecr.<region>.amazonaws.com/pytorch-fastapi:latest
    
  5. 推送镜像:登录ECR,并将标记好的镜像推送到仓库。
    aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <your-aws-account-id>.dkr.ecr.<region>.amazonaws.com
    docker push <your-aws-account-id>.dkr.ecr.<region>.amazonaws.com/pytorch-fastapi:latest
    

完成推送后,你的容器镜像已安全地存储在AWS ECR中。


5. 使用AWS App Runner部署服务 ☁️

现在,容器镜像已准备就绪,我们可以使用AWS App Runner来部署和管理我们的微服务。

部署流程:

  1. 在AWS控制台导航到App Runner服务,点击“创建服务”。
  2. 选择来源:选择“容器注册表”,然后点击“浏览”找到并选择你在ECR中推送的镜像(pytorch-fastapi:latest)。
  3. 配置部署
    • 部署触发器:选择“自动”,这样每次向ECR推送新镜像时,服务会自动更新。
    • 服务名称:为你的服务命名,例如 pytorch-container-service
    • 计算配置:根据应用需求(如PyTorch模型大小)选择合适的CPU和内存配置(例如,1 vCPU,2 GB内存)。
  4. 网络与安全:App Runner会自动提供一个HTTPS端点,无需额外配置即可获得安全的加密连接。
  5. 点击“创建并部署”。App Runner将开始从ECR拉取镜像并启动容器。

部署过程中,你可以在控制台查看实时日志。当状态变为“运行中”时,服务即部署成功。


6. 测试生产环境服务 🌐

部署完成后,App Runner会提供一个唯一的服务URL(例如 https://xxx.us-east-1.awsapprunner.com)。

  1. 在浏览器中访问该URL,应能看到根路径(/)返回的“Hello World”信息。
  2. 访问 {你的服务URL}/docs,打开生产环境下的Swagger UI。
  3. 如同本地测试一样,使用 /predict 端点上传图片进行预测。

如果成功返回预测结果,则表明一个完整的、生产级的机器学习微服务已在AWS云上成功运行。任何获得URL的用户都可以通过API调用使用这个图像分类服务。


总结 🎯

本节课中,我们一起完成了一个完整的MLOps实践流程:

  1. 开发与测试:我们首先在本地运行并测试了一个基于PyTorch和FastAPI的机器学习应用。
  2. 容器化:接着,我们将应用及其环境打包成Docker容器,确保环境的一致性。
  3. 存储镜像:我们将构建好的容器镜像推送至AWS ECR进行集中管理。
  4. 一键部署:最后,利用AWS App Runner这个PaaS服务,我们轻松地将容器镜像部署为一个可自动扩展、自带HTTPS的云端微服务。

通过结合FastAPI的便捷性、PyTorch的机器学习能力以及AWS云服务(ECR, App Runner)的托管优势,我们可以快速构建和部署高性能、可维护的机器学习应用,这正是现代MLOps的核心实践。

127:Azure认证简介 🎓

在本节课中,我们将了解微软Azure平台提供的相关认证如何帮助你扩展知识,特别是在机器学习和云服务领域。虽然目前没有专门的MLOps认证,但一些基础认证涵盖了互补的核心概念。

上一节我们介绍了MLOps的生态系统,本节中我们来看看如何通过结构化学习路径来巩固相关知识。

认证的价值 📜

认证是深入学习Azure知识的绝佳途径。Azure是微软的云服务平台,提供了一些实用的认证。你可以利用这些认证,更深入地学习我们已涉及的部分概念。

目前没有专门的MLOps认证。但例如,Azure AI基础认证就是一个非常全面的认证,它涵盖了多个不同方面。这不仅包括Azure本身,也包括机器学习。

知识的应用与迁移 🔄

你可以将这些概念应用到其他领域。你将学到更多关于回归、分类等机器学习技术。尽管这些技术并非专门针对机器学习运维(MLOps),但它们在你日常的常规操作中非常有用。因为这些知识与你作为MLOps工程师或日常从事MLOps工作所进行的大多数活动是互补的。

接下来,我将引导你了解一些需要知道的信息,例如学习模块、学习路径,以及微软如何组织所有这些信息。目的是让你理解,为了完成学习材料,需要做些什么。

如何利用学习资源 🛠️

即使你最终决定不参加认证考试,实际上也可以浏览并选择你感兴趣的部分内容,或者选择那些你需要进一步扩展知识以更从容地进行机器学习的部分,并希望也能将它们应用到机器学习运维中。

以下是微软典型的学习资源组织方式:

  • 学习模块:针对特定主题的简短、集中的课程单元。
  • 学习路径:由多个学习模块组成的结构化课程系列,旨在帮助你掌握更广泛的技能。

总结 📝

本节课中我们一起学习了Azure认证作为扩展机器学习与云知识工具的价值。我们了解到,虽然没有直接的MLOps认证,但如Azure AI基础认证等提供了广泛且互补的知识体系。掌握这些结构化学习路径中的概念,能够有效增强你作为MLOps实践者的能力。

128:Azure认证学习资源指南 🎯

在本节课中,我们将系统性地了解如何获取和准备微软Azure平台的认证。我们将重点介绍官方学习门户、核心认证路径,并提供获取免费学习与考试资源的实用方法。

微软官方学习门户:一站式起点

上一节我们介绍了课程背景,本节中我们来看看获取Azure认证的核心平台。微软官方学习门户 learn.microsoft.com 是获取所有Azure相关学习材料和认证信息的中心。

  • 功能全面:该门户提供Azure平台上所有API的完整文档。
  • 集成培训:除了文档,用户还可以申请相关培训资源。
  • 认证中心:我们将重点关注其提供的认证考试准备路径。

浏览与筛选认证路径

了解平台后,我们来看看如何找到目标认证。在 learn.microsoft.com 上,主要有两种方式定位认证。

  • 直接搜索:例如,搜索“Azure fundamentals”,搜索结果会直接显示相关认证,并可使用产品过滤器进行精确筛选。
  • 导航栏入口:点击网站顶部的“Certifications”链接,可以进入专门的认证浏览页面。

按角色与热门度选择认证

进入认证页面后,您可以根据自身职业角色或热门程度来选择适合的认证。

  • 按角色浏览:页面提供按角色(如数据科学家、开发人员、DevOps工程师)分类的认证选项。
  • 浏览热门认证:页面也会展示如“Azure Fundamentals”等热门认证,方便用户快速选择。
  • 查看全部:用户也可以选择浏览所有可用的认证列表。

以AI基础认证为例

为了具体说明,我们以“AI Fundamentals”认证为例。在搜索该认证后,通常会出现两个结果。

  • 认证详情页:此页面包含认证的完整描述、所需技能大纲以及学习路径。
  • 考试页面:此页面专门用于报名和参加认证考试。

以下是查看技能大纲的步骤:

# 访问认证详情页 -> 点击“Skills measured” -> 查看详细考核领域与权重

例如,AI基础认证可能考核:描述AI工作负载(20-25%)、Azure机器学习基础(25-30%)、计算机视觉与自然语言处理等。

两种主要学习准备方式

确定目标认证后,接下来是准备阶段。官方为每个认证提供了两种主要的学习方式。

  • 自定进度学习:免费提供,用户可在 learn.microsoft.com 上按自己的节奏学习。学习内容以“学习路径”和“模块”的形式组织,用户可以跟踪进度。
  • 讲师指导学习:由讲师带领的培训课程,通常需要付费。

学生专属福利:免费认证机会

对于学生群体,微软提供了非常有价值的福利,可以免费参加认证考试。

  • 资格验证:学生需要创建个人资料并验证其学生身份。
  • 费用减免:通过验证后,价值约100至150美元的考试费用将被免除,学生可以远程参加考试。
  • 附加价值:在某些情况下,获得认证还可能转换为大学学分。

扩展知识:Azure基础认证的价值

即使你的主要兴趣在MLOps,我也强烈建议你关注“Azure Fundamentals”认证。

  • 超越Azure:该认证不仅涵盖Azure特定服务,更教授通用的云计算核心概念。
  • 知识体系:内容包括云概念、Azure架构与服务、计算服务管理、成本管理、以及安全治理等。
  • 基础夯实:这些知识对于理解任何云平台上的MLOps实践都至关重要。

总结与行动建议

本节课中我们一起学习了如何利用微软官方资源规划Azure认证路径。

我们介绍了从访问 learn.microsoft.com 门户,到浏览和筛选认证(如AI基础认证),再到利用免费的自学材料或学生福利进行准备的完整流程。最后,我们强调了即使专注于MLOps,学习“Azure Fundamentals”以构建扎实的云计算基础也同样重要。建议你根据自身角色和目标,浏览官方认证目录,选择适合的学习路径,系统地提升你的专业技能。

129:微软认证学习路径与学习笔记指南

在本节课中,我们将学习如何利用微软官方提供的结构化学习资源来准备认证考试。我们将了解学习路径和学习模块的组织方式,并探讨如何创建个人学习笔记以高效备考。


学习资源的组织结构

上一节我们介绍了认证考试的基本信息,本节中我们来看看微软如何组织其学习材料。微软的学习内容采用层级结构,便于系统化学习。

以下是其核心层级关系:

  • 集合:这是最高层级的分类,是学习路径分组
  • 学习路径:这是学习模块集合,通常围绕一个特定技能或认证目标组织。
  • 学习模块:这是构成学习路径的基本单元,每个模块包含多个单元
  • 单元:这是学习模块中的单个页面,包含视频、文本、图表等具体学习内容。

这种层级结构帮助你规划学习进程,从宏观的集合入手,逐步深入到具体的学习模块和单元。


探索一个学习路径实例

为了让你更清楚地理解,我们以“AI-900: Microsoft Azure AI 基础”认证的学习路径为例进行探索。

当你点击进入“AI 基础”学习路径后,会看到一系列学习模块。每个模块都有明确的学习目标,例如“Azure 上的 AI 入门”。模块内容被分解为多个单元,每个单元代表一个独立页面。

以下是该学习路径的几个特点:

  • 内容普适性:虽然认证冠以“Azure”之名,但许多概念(如机器学习、异常检测)是通用的,这有助于你建立扎实的AI基础认知。
  • 易于消化:每个单元的学习时间通常很短(例如3分钟或10分钟),信息被精心组织,便于快速吸收。
  • 进度跟踪:如果你登录账户,可以追踪学习进度,进行知识检查,并能随时从上次中断的地方继续学习。

现在,让我们进入“Azure 上的 AI 入门”模块。你会看到一个典型的单元页面,它可能包含一个介绍视频、一些核心定义(如计算机视觉、异常检测),以及解释关键概念的图文。通过点击“下一步”,你可以逐一完成所有单元,系统会清晰显示你的进度(例如“2 / 10”)。这种方式将复杂知识打包成易于消费的信息块,是扩展知识的有效途径。


创建个人学习笔记与学习指南

了解了如何浏览学习资源后,我们来看看如何将其转化为个人知识并高效复习。创建个人学习笔记是一个极佳的方法。

以下是我创建学习笔记的步骤与建议:

  1. 为每个学习路径创建独立文档:例如,为“Azure AI 基础”认证的每个学习路径建立一个单独的Markdown文件。
  2. 记录原始链接:在笔记开头,保存学习路径和学习模块的官方链接,便于快速回溯。
  3. 用自己的话总结:不要复制粘贴。阅读每个单元后,用你自己的语言重新阐述核心概念、定义和关键点。这个过程能加深理解。
  4. 聚焦认证重点:在总结时,有意识地筛选和记录那些对通过认证考试尤为重要的信息,例如特定服务的组件、工作流程或关键区别。
  5. 利用代码仓库管理:将笔记保存在GitHub等代码仓库中是个好习惯。这不仅能进行版本管理,还能让你随时随地通过单个页面回顾所有学习内容。

通过这种方式,你不仅被动接收信息,更主动地构建了知识体系,并生成了专属于你的、高度浓缩的复习指南。


本节课中,我们一起学习了微软认证学习资源的层级结构(集合 > 学习路径 > 学习模块 > 单元),并通过实例了解了如何浏览这些内容。更重要的是,我们掌握了创建个人学习笔记的方法,这将帮助你有效组织学习、深化理解,并最终为成功通过认证考试打下坚实基础。

130:创建Azure机器学习工作区 🚀

在本节中,我们将学习如何在Azure门户中创建一个机器学习工作区。这是使用Azure机器学习服务的第一步,它将为我们提供一个集中管理所有机器学习资产的环境。

概述

开始使用Azure机器学习工作室是一个直接的过程。如果你知道在哪里寻找,操作会很简单。现在我已经打开了Azure门户,并且之前创建过一个工作区,所以你能看到“demo automl”。但让我们假设你从未创建过,并且是第一次操作。

创建新工作区

如果你在门户中搜索“M”,首先显示的服务之一就是“Azure机器学习”。点击它,或者点击下拉菜单,你可以创建一个新的工作区并开始使用。

我将点击“Azure机器学习”,然后创建一个新的工作区。虽然我已经有一个了,但我会演示从头开始的步骤。如果你从未创建过任何内容,这里将是空的,不会有任何列表。

以下是创建新工作区的步骤:

  1. 点击“创建”:在服务页面,点击“创建”按钮或下拉菜单中的选项。
  2. 选择工作区类型:你会看到两个选项:“新建工作区”和“新建注册表”。如果你是初学者,想尝试Azure机器学习并使用其Web交互界面(机器学习工作室),你需要选择“新建工作区”。“新建注册表”是一个更高级的功能,适用于管理多个工作区的情况。因此,我们点击“新建工作区”。

配置工作区详情

现在,我们进入配置表单。界面会自动选择我的订阅。这是在Azure中创建服务时需要填写的标准Web表单。

以下是需要填写的核心信息:

  • 订阅:选择你的Azure订阅。
  • 资源组:选择一个现有的资源组或创建一个新的。我倾向于在演示或尝试新功能时创建新的资源组,并为其加上“demo”前缀。例如,我将创建一个名为 demo-ML-studio 的新资源组。
  • 工作区名称:为你的工作区命名。我通常将其命名为与资源组相同的名称,例如 ML-studio。当你输入名称时,一些相关资源(如存储帐户、密钥保管库和应用洞察)的名称会自动填充。

这种自动化是Azure机器学习工作室环境高度专业化的体现,它专为机器学习任务设计。这与在Azure中自行搭建各种虚拟机和其他环境有本质区别,因为诸如密钥保管库、存储帐户和应用洞察等资源都会自动为你设置好。

高级选项:容器注册表

有一个选项不会自动完成,但非常有用,那就是容器注册表。如果你打算处理容器(我高度怀疑你会在将机器学习模型部署到生产环境时用到),你会希望创建一个容器注册表。你可以选择一个现有的,或者创建一个新的。关联的容器注册表允许你推送容器镜像,使所有工作更集成、更轻松。由于本次演示不涉及创建容器,我将跳过此步骤。

验证与部署

填写完表单后,点击“查看 + 创建”。系统会进行验证,确保表单中填写的内容无误。验证通过后,点击“创建”。

此时,部署将开始初始化,你会看到“部署正在进行中”的状态。这意味着Azure正在后台创建我们选择的所有资源,包括密钥保管库、存储帐户等。如果之前选择了创建容器注册表,它也会被创建。这个过程需要一些时间。

访问工作区

部署完成后,系统会提示我们可以“转到资源”。点击后,我们会进入该工作区的资源页面。

重要提示:这个资源页面不是Azure机器学习工作室。这不是你与Azure机器学习服务交互的实际场所。这是一个管理面板,你可以在这里查看概览、活动日志、设置访问控制、管理标签和网络等。这对于不熟悉Azure服务的人来说可能有些困惑。许多具有独立交互界面的Azure服务都有这样一个用于管理的着陆页,而实际的服务交互发生在别处。

那么,实际交互界面在哪里呢?继续向下滚动资源页面,你会找到它。

启动工作室按钮就在这里。点击这个按钮,你将进入真正的Azure机器学习工作室Web界面,开始你的机器学习项目之旅。

总结

本节课中,我们一起学习了创建Azure机器学习工作区的完整流程。我们从在门户中搜索服务开始,逐步完成了选择订阅、创建资源组、命名工作区、理解自动化资源配置(如存储帐户和密钥保管库),并了解了可选的高级功能(如容器注册表)。最后,我们区分了工作区的管理资源页面和用于实际机器学习操作的Azure机器学习工作室界面。成功创建工作区是构建、训练和部署机器学习模型的第一步。

131:创建Azure Auto ML作业 🚀

在本节课中,我们将学习如何在Azure Machine Learning Studio中创建一个自动化机器学习(AutoML)作业。我们将从访问平台开始,逐步完成数据资产选择、计算资源配置、任务类型定义等关键步骤,最终启动一个回归预测模型的自动化训练流程。


访问Azure Machine Learning Studio

首先,点击链接进入Azure Machine Learning Studio。界面会打开一个新标签页。

初次使用这个界面可能会感到有些复杂,但它集成了处理机器学习时所需的大部分功能,便于用户访问。

界面左侧面板提供了多种选项。你可以随时点击“主页”返回初始屏幕。主要功能包括:

  • Notebooks:用于编写和运行代码。
  • Automated ML:我们本节课将重点使用的自动化机器学习功能。
  • Designer:一个拖放式界面,用于构建机器学习流水线(本节课不涉及)。

你可以通过左侧面板导航,或直接点击界面上的“Automated ML”图标或“立即开始”按钮来启动Automated ML。这三种方式都有效。


启动并创建新的AutoML作业

我将点击“Automated ML”下的“立即开始”按钮,进入创建新运行的流程。

由于我之前没有创建过任何AutoML作业,因此列表是空的。我需要创建一个新作业。

点击“创建新的自动化ML作业”,然后按照向导的步骤(从第1步到第5步)进行操作。我们将跳过第4步,因为本节课不涉及计算机视觉任务。我们将使用一个表格数据集。


步骤一:选择数据资产

第一步是选择数据资产。Azure最近将“数据集”更名为“数据资产”。我将使用一个逗号分隔值文件。

当前数据资产列表为空,因此我需要创建一个。Azure提供了一个便捷功能,允许你直接在此界面创建,无需跳转到其他页面。

点击“创建”。我将数据集命名为“wine_ratings”,描述为“World wine ratings”。数据源选择“从Web文件”。

为了获取数据文件的直接链接,我打开了一个包含wine_ratings.csv文件的GitHub仓库。点击文件后,选择“查看原始内容”,以获得文件的直接URL。这个URL的格式通常是 https://raw.githubusercontent.com/...

复制该URL,回到Azure Machine Learning的创建界面。在数据源处选择“从Web文件”,粘贴URL。我选择让Azure验证数据,然后点击“下一步”。


配置数据集

数据验证完成后,界面会显示数据预览和一些设置选项。预览中可以看到一些问题,例如有一个无意义的“column1”列,以及包含大量空值的“grapes”列。

文件格式信息显示为CSV,包含表头。我确认有表头后,点击“下一步”。

接下来是数据架构界面。这里可以移除不感兴趣或不需要的列,这对后续处理很重要。

  • 移除column1(无用)。
  • 移除name(对于本次预测任务不重要)。
  • 移除grapes(空值过多)。
  • 保留regionvarietyrating列作为特征和目标。
  • 移除notes(文本内容过多,本次不使用)。

点击“下一步”并完成数据集的创建。创建完成后,需要点击“刷新”按钮,新创建的“wine_ratings”数据集才会出现在列表中。选择它,然后点击“下一步”。


步骤二:配置作业与计算资源

现在需要为AutoML作业创建一个新实验。我将其命名为“Auto ML experiment”。你可以根据项目意义自行命名。

接下来需要选择目标列。目标列是模型将要预测的内容。在本例中,我希望模型根据regionvariety来预测rating。因此,目标列选择 rating

然后需要选择计算资源。点击下拉菜单,可以看到“计算集群”或“计算实例”选项,但目前列表为空。

我希望使用计算集群来并行化运算。因此,点击“新建”来创建一个集群。在创建界面,需要选择虚拟机类型。

  • 低优先级:成本极低(例如每小时0.01美元),但资源可用性取决于Azure的闲置容量。
  • 专用:成本较高,但能保证资源可用。

我选择“专用”以确保稳定性。在推荐的配置中,我选择了一个具有14GB内存的虚拟机类型(每小时约0.29美元)。点击“下一步”。

在高级设置中,我将节点数设为1(由于配额限制,目前只能使用单节点)。虚拟机类型选择CPU集群。其他如虚拟网络、托管身份等高级设置保持默认,然后点击“创建”。集群创建需要一些时间。

集群创建完成后,回到作业配置界面。现在实验名称、目标列均已设置。在“选择Azure ML计算集群”处,选择刚刚创建好的“CPU-cluster”,然后点击“下一步”。


步骤三:选择任务类型并启动

现在需要选择机器学习任务类型。Azure根据目标列rating是连续数值,自动检测并推荐了 回归 任务,这完全符合我们的预测目标。

验证类型选择“自动”,并且不指定单独的测试数据资产。点击“完成”以创建新的AutoML作业。

默认情况下,AutoML会尝试多种算法并运行较长时间,以寻找最佳模型。作业启动后,模型结果将陆续显示。

返回“Automated ML”主界面,可以看到作业正在运行。此时,我们等待作业完成即可查看结果。


总结

本节课中,我们一起学习了在Azure Machine Learning Studio中创建自动化机器学习作业的完整流程。我们逐步完成了从创建数据资产、配置计算集群、定义回归预测任务到最终启动作业的核心步骤。这个过程展示了如何利用云平台的自动化工具,快速构建和部署一个机器学习模型原型。

132:基础Azure ML与MLOps概念 🧠

在本节课中,我们将学习Azure机器学习平台的核心组件及其与机器学习运维(MLOps)的关系。我们将了解Azure ML Studio提供的服务,并初步探索开放数据集和软件开发工具包(SDK)的使用。


Azure平台包含多个值得深入探讨的组件。

上一节我们介绍了Azure ML的概况,本节中我们将更详细地了解其核心服务。

Azure机器学习工作室提供了丰富的服务,虽然涵盖所有内容可能令人望而生畏,但在接下来的课程中,我们将重点介绍与MLOps最相关的一些核心功能。

我们将简要介绍开放数据集以及如何使用SDK进行工作。你将看到所有这些组件如何协同工作,并与Azure上的机器学习运维实践相关联。

以下是Azure ML中与MLOps相关的一些关键服务:

  • 计算资源:用于模型训练和部署的托管计算环境,例如 ComputeInstanceComputeCluster
  • 数据存储与版本控制:用于管理训练数据和跟踪数据集的变更。
  • 自动化机器学习(AutoML):自动进行模型选择和超参数调优的工具。
  • 模型注册表:用于存储、版本控制和跟踪已训练模型的中央仓库。
  • 管道:用于自动化端到端机器学习工作流的可重复步骤序列,例如 Pipeline(steps=[data_prep_step, train_step])
  • 端点:用于将模型部署为可通过HTTP请求访问的实时或批量推理服务。

本节课中,我们一起学习了Azure机器学习平台的基础概念及其与MLOps的关联。我们概述了关键组件,如计算资源、数据管理、自动化工具和模型部署服务,为后续深入实践这些工具奠定了基础。

133:先修技术 🛠️

在本节课中,我们将学习如何为备考 Azure 助理数据科学家认证 DP-100 做好技术准备。我们将介绍两个核心工具:Azure 免费账户和 GitHub Codespaces。这些工具能帮助你免费或以极低成本,在云端环境中学习和实践机器学习运维。


上一节我们明确了学习目标,本节中我们来看看具体需要准备哪些技术工具。以下是两项关键的先修技术。

Azure 免费账户

首先,你可以从创建一个 Azure 免费账户开始。当你获得免费账户后,主要目标是利用其提供的免费服务。查看可用的服务列表,你会发现大部分考试所需的服务都可以免费使用12个月。

在此之后,你可以根据需要转为“即用即付”模式。因此,在备考初期,使用免费账户是一个理想的起点。

GitHub 账户与 Codespaces

其次,另一个强大的工具是 GitHub 账户。如果你拥有 GitHub 账户,就可以使用 Codespaces 功能。通过 Codespaces,你可以直接针对 Azure API 进行开发,这是备考的一种非常高效的方式。

让我们看看 Codespaces。你可以创建一个 Codespace,在一个基于云的环境中真正开始开发,并将其与 Azure 深度集成。这里也是存放你代码示例的绝佳场所。



本节课中我们一起学习了备考 DP-100 认证的两项先修技术:Azure 免费账户GitHub Codespaces。通过利用这些免费或低成本的云端资源,你可以搭建一个实践环境,为深入学习机器学习运维打下坚实基础。

134:实时与批处理部署 📊

在本节课中,我们将学习在 Azure ML Studio 中部署机器学习模型的两种主要方式:实时部署批处理部署。我们还将了解一种将模型直接打包为 Web 服务的进阶选项。

概述

通过 Azure ML Studio 部署模型时,主要有两种选择:批处理部署和实时部署。此外,还可以直接将模型部署为 Web 服务,从而抽象掉模型打包过程中的部分复杂性。

批处理部署

上一节我们介绍了部署的基本概念,本节中我们来看看批处理部署的具体含义。

在批处理部署模式下,模型通常是周期性运行的。例如,可以设定每晚执行一次信用卡评分任务。

以下是批处理部署的关键特点:

  • 模型按预设时间表(如每日、每周)运行。
  • 适用于不要求即时响应的任务,如批量数据预测或报表生成。
  • 在 Azure ML Studio 中,操作路径为:模型预测界面 -> 选择“部署到批处理”。

实时部署

了解了批处理部署后,我们再来看看实时部署有何不同。

在实时部署模式下,模型能够以 24/7 不间断 的方式提供服务。你需要部署一个端点,并持续地向这个实时端点发送预测请求。

以下是实时部署的关键特点:

  • 模型持续运行,随时准备响应 API 请求。
  • 适用于需要即时预测的应用,如欺诈检测或推荐系统。
  • 在 Azure ML Studio 中,操作路径为:模型预测界面 -> 选择“部署到实时”。

在 Azure ML Studio 中的操作

现在,让我们具体看看在 Azure ML Studio 中如何操作。

如果我们进入 Azure ML Studio 的模型预测界面,会看到几个部署选项:“部署到实时”、“部署到批处理”和“部署到服务”。请注意,“部署到服务”等选项通常仅适用于基于特定框架(如 Scikit-learn 或 PyTorch)的模型。

选择“部署到批处理”后,系统会要求你配置一些选项,完成配置后便会创建相应的服务。

我们可以查看一个现有的端点。在 Azure ML Studio 中,已注册的实时端点会显示在对应区域,已注册的批处理端点也会显示在专属区域。例如,我之前创建的一个批处理端点就显示在这里。

这个批处理端点可以定期运行。如果我想针对它创建一个任务,它被设计为按计划运行。这与另一种端点——实时端点——形成对比。实时端点的设置是为了持续运行并接收来自客户端的 API 请求。

进阶部署选项

除了上述两种核心部署方式,Azure ML Studio 还提供了一种进阶选项。

这种进阶选项允许你直接获取一个框架并将其部署到生产环境,进一步简化了流程。

总结

本节课中我们一起学习了在 Azure ML Studio 中部署模型的两种主要模式:批处理部署(周期性运行)和实时部署(持续服务)。我们还了解了如何在实际界面中操作,并提及了直接将框架模型部署为 Web 服务的进阶可能性。理解这些部署方式的区别,有助于你根据实际应用场景选择最合适的策略。

135:在Azure机器学习工作室中管理数据集

概述

在本节课中,我们将学习如何在Azure机器学习工作室中管理数据集。我们将涵盖创建新数据资产、上传本地文件、以及利用内置工具生成数据概况报告等核心操作。这些步骤是构建机器学习工作流的基础。


Azure机器学习工作室提供了一套复杂的数据集管理方式。

如果点击左侧的“数据”标签页,可以看到系统中已存在一个数据集。

若要创建新数据集,可以点击“新建资产”。

我们将此资产命名为“测试资产”。添加描述是一个好习惯,例如“这是一个使用MLB数据的测试”。

接下来需要决定要存入系统的数据类型。是文件、文件夹还是表格?这里我们选择“文件”。

点击“下一步”后,会出现三个不同的选项。

从用户界面看,数据资产可以来自一个网络URL,这是获取数据的有效方式。

也可以选择现有存储。如果你在Azure存储中拥有需要处理的海量数据(例如PB级别),可以在此处浏览并选择。

或者,你也可以选择本地文件,这非常适合用来测试工作流。

我们将选择“从本地文件”上传。

点击“下一步”后,系统会让我们选择存储位置。我们选择“工作区Blob存储”。

现在,只需将文件上传到此位置。点击“上传文件”。

我将选择一个包含美国职业棒球大联盟球员身高和体重的数据集。

点击“下一步”后,就可以创建这个资产了。

现在,我们可以查看新上传的数据。

我们可以滚动浏览、探索数据并查看不同的列。例如,通过切换表头显示,数据会看起来更清晰,我们也可以对此数据进行其他操作。

这是一种将资产导入Azure机器学习流程的非常成熟的方式。

回到“数据”主页面,另一个非常有趣的功能是“生成概况”。我已经预先执行了这个操作。

让我们看看它是如何工作的。例如,我可以选择一个正在运行的“计算实例”,然后点击“生成”。系统将遍历数据并构建一个数据概况报告。

由于我已经执行过此操作,我可以点击“查看概况”。这个功能的价值在于,它能为我提供一个有用的可视化报告,本质上就是为我完成了探索性数据分析。

我可以在这里查看各个列,查看数据类型、计数、位置,以及显示身高和体重数据分布的直方图等。

因此,在开始使用Azure机器学习时,一个非常宝贵的资源是:首先导入数据集,然后生成并查看数据概况报告。这样你就能更好地理解如何创建机器学习模型。


总结

本节课我们一起学习了在Azure机器学习工作室中管理数据集的核心流程。我们掌握了如何创建新的数据资产、从本地文件上传数据,以及如何使用“生成概况”功能来快速获得数据的可视化分析报告。这些步骤是准备数据和理解数据特征的关键,为后续构建机器学习模型奠定了坚实的基础。

136:探索开放数据集SDK 📊

在本节课中,我们将学习如何利用Azure开放数据集,并将其集成到Azure ML Studio中。我们将通过Python SDK来探索和操作这些数据集,从而为后续的机器学习任务做好准备。

注册与探索数据集

Azure开放数据集的一个显著优势是,您可以在Azure ML Studio中注册它们,然后使用Python SDK通过代码进行探索。

上一节我们介绍了Azure开放数据集的概念,本节中我们来看看如何在Azure ML Studio中实际操作一个已连接的数据集。从图形用户界面(GUI)中,您可以执行许多便捷的操作。

以下是您可以在GUI中执行的主要操作:

  • 查看文件的总大小。
  • 在需要时对数据集进行分析。
  • 进行基本探索,系统会在此处提供快速预览以供查看。

在代码中使用数据集

除了通过界面探索,您还可以将数据集导入到代码环境中。如果您选择“使用”(consume)选项,系统会提供一个代码示例。

以下是获取和使用代码示例的步骤:

  1. 在数据集页面选择“使用”选项卡。
  2. 复制提供的代码示例。
  3. 将代码粘贴到您的笔记本(Notebook)中。

我已经完成了上述操作,将代码复制并加载到了这个笔记本中。现在,一旦我运行这个代码单元,就能在代码单元格内直接看到可视化的结果。

在笔记本中进行数据分析

运行该单元后,我能够获取可视化展示,并在代码单元格内查看具体发生的情况。我可以在此滚动浏览,并执行任何需要的操作。

以下是您可以在笔记本中进行的后续分析示例:

  • 运行一些描述性统计。
  • 使用诸如Seaborn或Matplotlib之类的库进行绘图。

通过从已注册的数据集中复制粘贴代码,这是在笔记本中进行集成的绝佳方式。

课程总结

本节课中,我们一起学习了如何在Azure ML Studio中注册开放数据集,并通过GUI和Python SDK两种方式对其进行探索。我们掌握了将数据集代码集成到Jupyter Notebook中的方法,为后续的数据分析和模型开发奠定了坚实的基础。利用这些技能,您可以高效地利用丰富的Azure开放数据资源。

137:进阶Azure ML与MLOps概念

在本节课中,我们将深入学习Azure机器学习平台中的一些高级组件与核心概念。这些知识对于在Azure生态系统中执行更复杂的操作至关重要,并且与多项认证考试内容相关。

上一节我们介绍了认证路径以及与MLOps相关的AI基础概念。本节中,我们将更深入地探讨Azure机器学习工作室服务中的一些其他组件。

计算资源:CPU与GPU

理解Azure机器学习中的计算资源是高效运行工作负载的关键。以下是两种主要计算组件的对比:

  • CPU组件:通用计算单元,适合处理逻辑操作、数据预处理和传统机器学习任务。
  • GPU组件:专为并行处理设计的计算单元,特别适合深度学习模型训练和推理等计算密集型任务。

Azure机器学习工作室服务

Azure机器学习工作室提供了一个集成环境来管理机器学习生命周期。其计算系统允许你根据任务需求灵活配置和选择计算资源。

这些关于资源和计算组件的知识非常实用,能帮助你打下坚实的基础。事实上,这些内容也包含在Azure AI基础认证中。

如果你选择通过考取该认证来扩展知识面,所有这些Azure内部的组件和服务都将非常有用。需要指出的是,其中一些概念并非Azure特有,同样可以应用于其他平台。

本节课中,我们一起学习了Azure机器学习中关于计算资源(CPU与GPU)的核心区别,以及Azure机器学习工作室服务的基本架构。理解这些概念有助于你更有效地在云平台上管理和执行机器学习工作流。

138:探索Azure ML命令行

在本节课中,我们将学习如何使用Azure ML命令行界面(CLI)来高效地管理和查询Azure机器学习服务中的各种资源。我们将通过实际操作,了解如何列出数据集、模型等核心组件,并比较CLI与图形界面(GUI)在操作效率上的差异。

命令行工具概述

Azure ML CLI扩展版本2提供了丰富的命令,允许你高效地查询整个产品。在许多情况下,使用这些命令进行操作比在图形界面上点击更加简便。

上一节我们介绍了命令行工具的优势,本节中我们来看看如何实际使用它。

启动Azure ML终端

要开始使用CLI,一个简单的方法是登录到你的Azure ML工作区,然后选择终端。以下是具体步骤:

  1. 打开Azure ML Studio。
  2. 登录到你的工作区。
  3. 在界面中找到并选择“终端”选项。


选择后,你会看到“欢迎使用Azure机器学习终端”的提示。这个集成的终端环境非常方便,可以让你立即开始使用命令行界面。

探索可用命令

开始探索的第一步是查看所有可用的命令。你可以在终端中输入以下命令来获取帮助菜单:

az ml --help

这个命令会列出所有你可以使用的命令组。你会看到诸如 batch-deploymentcomputedatasetsjobsmodels 等子组。通过CLI,你能够集成所有这些不同的系统,并快速了解Azure ML Studio中实际发生的情况。

操作数据集

让我们首先尝试操作数据集。这是一个很好的起点。要查看与数据相关的具体命令,可以输入:

az ml data --help

这个命令会显示一个菜单,列出可用的不同操作和输出选项。例如,你可以查询不同的数据集以获取其信息。输出格式可以是JSON、表格或YAML文件。

以下是操作数据集的具体步骤列表:

  • 列出数据集:使用 az ml data list 命令。
  • 选择输出格式:通过 --output 参数指定格式,例如 table 表示表格。
  • 执行命令:在终端中运行组合后的命令。

让我们实际操作一下。使用上箭头键调出之前的命令,并将其修改为以表格形式输出:

az ml data list --output table

执行后,你将能看到你名下所有可用的数据集列表。如果你希望对某个数据集进行进一步的操作或查询,可以基于这个列表继续进行。

探索模型资源

我们也可以回到初始状态,探索其他类型的资源。例如,如果你想查看系统上已注册或部署了多少模型,同样可以使用CLI。

要查看与模型相关的命令,请输入:

az ml model --help

从这里,我们可以看到可用的不同命令,例如归档模型、创建模型、下载模型、列出模型、恢复、显示详情、更新等。

让我们尝试列出所有已注册的模型。首先查看列表命令的帮助信息:

az ml model list --help

帮助菜单再次显示了相同的格式选项。接着,我们以表格形式列出模型:

az ml model list --output table

执行后,我们可以看到系统中注册的许多不同模型,并可以对它们进行各种操作。

总结

本节课中我们一起学习了如何利用Azure ML命令行界面(CLI)来高效地探索和管理资源。我们了解了如何启动集成终端、查看可用命令、以及具体操作数据集和模型列表。通过CLI,你能够快速获取信息并执行操作,这通常是比使用图形界面更直接高效的方式。如果你打算通过命令行深入查询Azure ML,使用计算笔记本环境并打开终端是一个最佳起点。

139:使用GitHub触发Azure ML工作流 🚀

在本节课中,我们将学习如何利用GitHub Actions作为自动化工作流引擎,来触发和部署Azure Machine Learning Studio中的任务。我们将重点介绍如何安全地配置凭据,并编写YAML工作流文件来实现两者的紧密集成。


概述

Azure ML Studio与GitHub都提供了出色的集成能力。一个非常实用的功能是,你可以将GitHub配置为一个通用的“工作者”,通过它创建并执行能够部署到Azure ML Studio中的自动化操作。实现这一点的核心在于,通过GitHub的“Secrets”功能安全地存储Azure ML的凭据,然后在GitHub Actions的YAML配置文件中引用这些凭据,从而配置并运行特定的任务。

上一节我们介绍了MLOps中持续集成与部署的基本概念,本节中我们来看看如何具体使用GitHub和Azure ML来实现自动化。

分步教程

第一步:在GitHub仓库中配置Azure凭据

首先,你需要一个用于与Azure ML Studio通信的代码仓库。在仓库的设置中,你可以找到配置机密信息的地方。

以下是具体操作步骤:

  1. 进入你的GitHub仓库页面。
  2. 点击顶部的 “Settings” 选项卡。
  3. 在左侧边栏中,找到 “Secrets and variables” 下的 “Actions” 选项。
  4. 点击 “New repository secret” 按钮。
  5. 这里可以创建新的机密信息,例如你的Azure认证凭据。为它命名(如 AZURE_CREDENTIALS)并将凭据内容粘贴进去。

完成这一步后,你就安全地将Azure ML的访问密钥存储在了GitHub中,并可以在工作流文件中引用它。

第二步:创建GitHub Actions工作流文件

配置好凭据后,下一步是创建定义自动化任务的工作流配置文件。这个文件使用YAML格式。

以下是创建和配置工作流文件的流程:

  1. 在仓库顶部导航栏中,点击 “Actions” 选项卡。
  2. 点击 “New workflow” 按钮,或手动在仓库的 .github/workflows/ 目录下创建一个新的YAML文件(例如 azure-ml-pipeline.yml)。
  3. 在这个YAML文件中,你需要定义几个关键部分:
    • 触发条件:指定工作流何时运行(例如,定时计划、代码推送等)。
    • 任务:定义一个或多个任务(jobs)。其中一个关键任务会使用第一步设置的凭据。
    • 步骤:在任务中定义具体的步骤,例如设置环境、登录Azure、运行特定的Azure ML管道。

这是一个简化的YAML结构示例:

name: Trigger Azure ML Pipeline

on:
  schedule:
    - cron: '0 8 * * 1' # 每周一早上8点运行
  push:
    paths:
      - 'src/**' # 当src目录下的代码有推送时也触发

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Login to Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }} # 引用GitHub Secrets中的凭据

    - name: Run Azure ML Pipeline
      run: |
        # 此处添加运行你的Azure ML管道的命令
        echo "Triggering pipeline..."

在这个配置中,${{ secrets.AZURE_CREDENTIALS }} 就是引用你在第一步设置的机密信息。工作流会根据schedule(定时计划)或代码push事件自动触发,执行登录Azure并运行指定管道的任务。

第三步:集成与执行

将上述YAML文件提交到仓库后,GitHub Actions就会开始监控你设定的触发条件。一旦条件满足,它会自动启动一个虚拟机环境,执行你定义的任务:使用安全的凭据连接到你的Azure ML工作区,并触发指定的机器学习管道。

这种模式非常强大,它使得GitHub成为了一个中心化的自动化控制台。你可以管理代码、跟踪变更,并直接从这里驱动云端复杂的ML工作流,实现了开发(Dev)与运维(Ops)在机器学习项目中的流畅衔接。


总结

本节课中我们一起学习了如何搭建GitHub与Azure Machine Learning Studio之间的自动化桥梁。关键步骤包括:1) 在GitHub仓库的Secrets中安全存储Azure凭据;2) 编写一个YAML格式的GitHub Actions工作流文件,定义触发条件和具体任务;3) 在工作流中引用存储的凭据来认证并触发Azure ML中的管道。通过这种集成,你可以轻松实现机器学习工作流的持续集成与部署(CI/CD),提升运维效率。

140:使用超参数自动调优 🎯

在本节课中,我们将学习如何在Azure机器学习平台上,利用SDK进行自动化的超参数调优。我们将了解其核心设置、工作流程以及如何通过实验选择最佳模型。


概述

超参数调优是机器学习模型开发中的关键步骤,但手动调整往往耗时且繁琐。Azure机器学习平台提供了自动化工具,可以高效地探索超参数空间并找到最佳配置。本节将基于一个SDK V1的示例笔记本来讲解其实现过程。

准备工作

首先,我们需要进行一些基础设置。这包括导入必要的库(如pandas和Azure SDK V1),将数据加载到pandas中进行清洗,并配置工作区。

import pandas as pd
from azureml.core import Workspace

# 配置工作区并加载、清洗数据
ws = Workspace.from_config()
# ... 数据加载与清洗代码

完成数据准备后,我们会将数据划分为训练集和测试集。这与传统的机器学习流程并无不同。

核心:自动化超参数调优设置

上一节我们完成了数据准备,本节中我们来看看如何设置自动化的模型训练与超参数调优。当我们选择“自动训练模型”选项时,有几个关键的训练设置需要特别注意。

以下是配置自动超参数调优时需要注意的几个核心参数:

  • 迭代超时(分钟)iteration_timeout_minutes。这定义了每次迭代(即尝试一组特定超参数)允许运行的最长时间。你需要根据模型复杂度和计算资源来决定这个时长。
  • 实验总超时experiment_timeout_minutes。这是整个超参数调优实验(包含所有迭代任务)允许运行的总时间上限。
  • 早停机制enable_early_stopping。当模型性能达到一个足够好的分数时,是否可以提前终止实验,以节省计算资源。
  • 优化指标primary_metric。这是用于评估和选择最佳模型的核心指标。在本教程示例中,使用的是斯皮尔曼相关系数(spearman correlation)
  • 特征工程featurization。可以设置为auto,平台将自动处理缺失值,并将数据转换为文本和数值格式。
  • 日志详细程度verbosity。控制输出日志的详细级别,便于你监控训练过程。
  • 交叉验证n_cross_validations。在超参数调优中可以设置的参数之一,用于提高模型评估的稳健性。

配置与执行训练任务

将上述所有自动设置组合在一起,我们会将它们分配到一个配置字典中。

automl_settings = {
    "iteration_timeout_minutes": 60,
    "experiment_timeout_minutes": 360,
    "enable_early_stopping": True,
    "primary_metric": 'spearman_correlation',
    "featurization": 'auto',
    "verbosity": logging.INFO,
    "n_cross_validations": 5
}

配置完成后,你只需将此字典推送到训练任务中进行配置并启动它。

查看结果与部署模型

一旦训练任务开始运行,它将在Azure机器学习工作室中显示为一个实验。实验完成后,你可以返回“实验”选项卡查看所有运行记录,并找到性能最佳的模型。

超参数调优的核心思想在于,它将大量手动、繁琐的工作自动化。你无需亲自专注于搜索过程,而是通过SDK调用,让Azure平台自动遍历并挑选出最佳的超参数组合。这些结果会清晰地展示在实验面板中,你只需查看各项运行的指标,选择正确的实验记录,然后即可部署该模型。


总结

本节课中我们一起学习了在Azure机器学习中实施自动化超参数调优的完整流程。我们从基础的环境和数据准备开始,重点讲解了超参数调优的关键设置项,如超时控制、优化指标和早停机制。最后,我们看到了如何通过SDK配置并提交任务,以及在实验面板中选取最佳模型进行部署。这大大简化了模型优化的过程,让数据科学家能更专注于业务逻辑和算法创新。

141:使用Python SDK训练模型

在本节课中,我们将学习如何在Azure机器学习工作室中使用Python SDK来训练机器学习模型。Python SDK提供了强大的控制能力,允许你使用Python语言灵活地设计和增强你的实验。

概述

我们将通过一个示例笔记本,演示如何从配置环境、编写训练脚本,到提交训练作业并查看结果的完整流程。你将了解到如何创建可复现的机器学习工作流。

使用Python SDK进行实验

上一节我们介绍了Python SDK的概览,本节中我们来看看如何具体操作。首先,我们需要在Azure机器学习工作室中打开或克隆一个示例笔记本。

在工作室中,你可以查看现有的笔记本,也可以加载示例笔记本。在示例目录中,提供了SDK V1、SDK V2以及各种教程的笔记本。

以下是操作步骤:

  1. 导航到“Azure ML入门”部分。
  2. 选择一个示例笔记本,例如入门教程。
  3. 点击“克隆此笔记本”,将其复制到你的工作区中。

克隆完成后,刷新页面即可在工作区看到该笔记本。现在,你可以关闭克隆窗口并打开笔记本进行编辑。

配置环境与认证

打开笔记本后,首先需要配置环境并完成身份认证,以确保SDK可以访问你的Azure资源。

以下是需要完成的关键步骤:

  • 在指定单元格中输入你的Azure订阅凭证(例如订阅ID、资源组等)。
  • 运行该单元格以建立连接。

配置完成后,即可运行后续的代码单元格。

编写与组织训练代码

虽然我们在笔记本中操作,但代码可以轻松地转换为独立的应用程序脚本。这有助于代码的模块化和复用。

接下来,我们将创建一个目录来存放源代码,并使用一个命令将笔记本单元格中的代码写入到脚本文件中。

# 示例:使用 writefile 魔术命令将代码写入脚本
%%writefile ./src/main.py
import argparse
import pandas as pd
import mlflow
from sklearn.ensemble import RandomForestClassifier
# ... 其余训练代码

这段代码会生成一个名为 main.py 的脚本。该脚本使用Python标准库进行参数解析,利用pandas处理数据,集成MLflow来跟踪实验参数(如准确率),并使用scikit-learn构建模型。

配置并提交训练作业

现在,我们将使用Azure ML SDK来配置一个训练命令,并提交作业到云端执行。

首先,导入必要的SDK模块。

from azure.ai.ml import MLClient, command, Input

然后,配置作业命令。你可以在此指定训练脚本的路径、输入数据集的位置,并灵活调整超参数。

# 配置作业
job = command(
    code="./src", # 源代码目录
    command="python main.py --train_ratio 0.2 --learning_rate 0.01", # 运行命令及参数
    inputs={
        "input_data": Input(type="uri_file", path="<你的数据集路径>")
    },
    environment="AzureML-sklearn-1.0-ubuntu20.04-py38-cpu:1", # 训练环境
    compute="cpu-cluster", # 计算目标
    display_name="my_training_job"
)

通过调整 command 中的参数(如 train_ratiolearning_rate),你可以轻松进行实验调优。所有配置都被记录,确保了实验的完全可复现性。

配置完成后,使用ML客户端提交作业。

ml_client.jobs.create_or_update(job)

提交作业需要你的订阅信息已正确配置。作业提交后,你可以在Azure机器学习工作室中监控其状态。

查看结果与分析实验

作业完成后,我们可以详细查看实验结果。这种工作流的强大之处在于,所有细节都被完整记录和链接。

你可以查看运行该实验的确切命令、实验名称以及所使用的环境。点击环境链接,可以查看用于构建训练环境的Dockerfile。它展示了从基础镜像、安装命令、依赖项到环境变量的每一步,这对于复现实验至关重要。

此外,在“指标”选项卡中,可以查看所有性能指标,如训练准确率和F1分数。还可能有一些可视化图表,帮助你评估模型性能。在“代码”部分,你可以回顾本次运行所使用的具体代码。

模型部署与清理(可选)

最后,如果你希望将训练好的模型投入实际使用,可以将其部署为在线端点。

以下是部署模型的基本代码框架:

# 部署模型为在线端点(示例代码)
# from azure.ai.ml.entities import ManagedOnlineEndpoint, ManagedOnlineDeployment
# ... 配置端点和部署
# ml_client.online_endpoints.begin_create_or_update(endpoint)
# ml_client.online_deployments.begin_create_or_update(deployment)

部署完成后,你可以通过发送请求来测试端点。如果不再需要相关资源,记得运行清理代码来删除端点和模型,以避免产生不必要的费用。

总结

本节课中我们一起学习了使用Azure机器学习Python SDK训练模型的完整流程。我们从打开示例笔记本开始,逐步完成了环境认证、代码编写、作业配置与提交、结果分析等步骤。关键点在于,通过代码定义整个流程,我们获得了高度可控和完全可复现的机器学习实验能力。对于初学者,强烈建议从SDK V2的示例教程开始,它能一步步指导你如何利用微软Azure机器学习工作室构建可复现的机器学习运维工作流。

142:认识你的课程讲师 🧑‍🏫

在本课程中,我们将学习机器学习运维平台。具体来说,课程将涵盖一些开源的MLOps平台。我们将从MLflow开始,这是一个强大的平台,允许你部署模型,并捕获在构建、训练模型以及部署过程中发生的所有指标和事件。它提供了一种标准化的部署方式和可复现的环境。

我们将学习如何创建这些可复现的环境,无论使用哪个云服务提供商,例如Azure、GCP或AWS,它都能正常工作。这是一个强大的特性,值得深入探索。

接下来,课程将转向Hugging Face。虽然Hugging Face平台本身的服务并非开源,但其库是开源的。我们将学习Transformers和Datasets库,并了解如何与它们交互以获取现成的预训练模型。我们将学习如何部署、打包这些模型,并将其推送到其他云提供商,例如Azure,并使用不同的容器注册表。

最后,我们还将简要了解ONNX。这是一种不同的格式,你可以将模型导出为ONNX格式或从该格式导入。这允许你在一个框架(例如TensorFlow)中生成模型,然后将其转换为ONNX格式,并部署到其他可能没有TensorFlow等完整环境的设备上。这提供了另一种标准化的方式,这在机器学习运维乃至整个机器学习领域都是一个强大的概念。

此外,课程将涵盖一些高级的Hugging Face应用,例如微调,以及使用GPU运行现成模型并对其进行微调,进行一些细微的修改以适应新的用途。

所有这些内容将使你能够与这些技术交互,并获得强大的知识,以实现标准化的部署,与当今由重要公司开发的强大现有模型进行交互,并为你提供在任何地方部署的灵活性。这种部署可以通过ONNX、其他注册表或其他云提供商来实现。

本质上,本课程将使你能够完成许多与机器学习运维相关的不同任务。很高兴你能在这里,让我们一起学习。希望在课程结束时,你能有足够的信心与所有这些技术交互,并开始在日常的机器学习工作中应用它们。


本节课中,我们一起认识了课程讲师,并概述了本课程的核心内容:我们将学习MLflow、Hugging Face和ONNX等关键MLOps平台与技术,目标是掌握标准化模型部署、与预训练模型交互以及实现跨平台灵活部署的能力。

143:MLflow概述

在本节课中,我们将要学习MLflow的核心概念与主要组件。MLflow是一个用于管理机器学习生命周期的开源平台,它能帮助数据科学家和工程师追踪实验、打包代码以及部署模型。我们将逐一了解其三大核心组件:追踪(Tracking)、项目(Projects)和模型(Models)。

追踪(Tracking)组件

追踪是MLflow的核心功能之一。它允许你在机器学习实验过程中,系统地记录各种信息,以便后续比较、复现和分析。

以下是追踪功能可以记录的主要数据类型:

  • 参数(Parameters):参数是键值对(key-value pairs),用于记录实验的配置信息。例如,你可以记录正则化强度 regularization: 0.1。这些值可以是任何内容,关键在于在项目开发中保持一致性,以便追踪模型训练或代码变更。
  • 指标(Metrics):指标用于记录模型在训练或评估过程中的表现数值,例如 accuracy: 0.1。与参数类似,指标也可以是任何对你训练任务有意义的数值。两者的主要区别在于,参数通常是输入配置,而指标是输出结果。
  • 制品(Artifacts):记录制品并非生成日志文本,而是捕获并上传重要的文件。例如,你可以将训练好的模型文件(如 model.pkl,代表pickle格式的序列化对象)推送到远程服务器进行存储和版本管理。

项目(Projects)组件

上一节我们介绍了如何追踪实验细节,本节中我们来看看如何规范化和重现整个机器学习项目。MLflow的项目组件提供了一种基于纯文本配置文件的标准化方法。

通过一个类似下图的配置文件,你可以定义项目的运行环境、入口点以及依赖关系。这意味着你可以将整个机器学习操作流程以文本形式记录下来,并放入版本控制系统(如Git) 中管理。

例如,配置文件可以指定使用Conda环境、依赖的YAML文件以及执行的Python脚本。这样做的好处是,如果未来对他人的代码或自己的旧代码进行修改时出错,你可以轻松地回退到之前能正常工作的配置版本,确保实验的可复现性。

模型(Models)组件

最后,我们来了解如何打包和部署训练好的模型。MLflow的模型组件提供了一种标准格式来封装机器学习模型,使其易于被不同的下游工具使用,例如通过REST API进行实时服务或进行批量推理。

它允许你以多种方式(如Python函数)定义模型,并指示MLflow如何加载该模型、需要使用哪些特定版本的机器学习库。例如,你可以指定模型依赖于 scikit-learn==0.19.1,并最终生成 model.pkl 文件。这种封装确保了模型运行环境的一致性,简化了部署流程。

本节课中我们一起学习了MLflow的三大核心组件:追踪(Tracking) 用于记录实验参数、指标和制品;项目(Projects) 通过配置文件标准化和重现整个机器学习项目;模型(Models) 则提供了一种标准格式来打包和部署模型。理解这些组件是构建高效、可复现的机器学习工作流的基础。在后续课程中,我们将对每个组件进行更深入详细的探讨。

144:安装和使用MLflow 🚀

在本节课中,我们将学习如何安装MLflow,并创建一个简单的Python脚本来体验其核心的跟踪功能。我们将看到如何记录参数、指标和文件,并通过MLflow的Web界面查看这些信息。

概述

MLflow是一个用于管理机器学习生命周期的开源平台。本节将指导你完成MLflow的安装过程,并演示其基础的跟踪功能。我们将通过一个简单的脚本,学习如何记录实验数据。

安装MLflow

安装MLflow的过程非常直接,前提是你已经有一个Python环境。这个环境可以是虚拟环境、Conda环境或其他任何环境。

以下是安装步骤:

  1. 激活你的Python环境。
  2. 使用pip包管理器进行安装。

在终端中执行以下命令:

pip install mlflow

安装过程通常只需几秒钟即可完成。安装成功后,你就可以使用MLflow了。

启动MLflow UI界面

在深入使用MLflow记录实验之前,我们先启动其用户界面(UI),以便后续查看结果。

在终端中输入以下命令:

mlflow ui

这个命令会在本地启动一个服务器。默认情况下,UI会在 http://localhost:5000 地址运行。打开浏览器访问这个地址,你将看到一个初始界面。目前,由于还没有记录任何实验,界面是空的,只显示一些基本的图表区域。当我们开始记录数据后,这里就会变得内容丰富。

创建并运行MLflow跟踪脚本

现在,让我们切换回代码编辑器,创建一个Python脚本来体验MLflow的核心跟踪功能。

我们将创建一个名为 test_mlflow.py 的文件。这个脚本将演示如何记录参数指标文件

以下是脚本的详细内容:

# 从mlflow库中导入必要的跟踪函数
from mlflow import log_metric, log_param, log_artifact

# 标准的Python脚本入口点
if __name__ == "__main__":
    # 1. 记录参数 (Parameters)
    # 参数通常是模型训练所需的配置或超参数
    log_param("threshold", 3)
    log_param("verbosity", "debug")

    # 2. 记录指标 (Metrics)
    # 指标用于评估模型性能,例如准确率、损失或训练时间
    log_metric("time_to_complete", 33)

    # 3. 记录文件 (Artifacts)
    # 文件可以是任何输出文件,如模型文件、数据集或图表
    # 假设我们有一个名为 ‘produced_dataset.csv‘ 的文件
    log_artifact("produced_dataset.csv")

为了测试文件记录功能,你需要在同一目录下创建一个名为 produced_dataset.csv 的空文件(或包含任何内容的CSV文件)。

保存脚本后,在终端中运行它:

python test_mlflow.py

脚本执行成功后,数据就已经被记录到MLflow的后端存储(默认为本地 ./mlruns 目录)中了。

在UI中查看跟踪结果

脚本运行完毕后,我们回到之前打开的MLflow UI界面(http://localhost:5000)。

刷新页面,你现在应该能看到刚刚运行的实验记录出现了。界面会显示类似“9秒前”的运行信息。

以下是界面中展示的内容:

  • 参数:在“Parameters”部分,可以看到我们记录的两个参数:threshold: 3verbosity: debug
  • 指标:在“Metrics”部分,可以看到记录的指标 time_to_complete: 33
  • 文件:点击实验运行记录,进入详情页。在“Artifacts”区域,可以看到我们记录的文件 produced_dataset.csv。点击它,MLflow会显示该文件的元数据,在真实场景中,你可以从这里查看或下载文件。

总结

本节课中,我们一起学习了MLflow的安装和基础使用。我们首先通过 pip install mlflow 命令完成了安装,然后使用 mlflow ui 启动了Web界面。接着,我们编写了一个Python脚本,使用 log_paramlog_metriclog_artifact 函数分别记录了实验的参数、指标和输出文件。最后,我们在MLflow UI中刷新并查看了这些被成功跟踪的实验数据。这为后续进行更复杂的机器学习实验管理和跟踪打下了基础。

145:跟踪服务器UI介绍

在本节课程中,我们将深入探索MLflow的跟踪服务器及其用户界面。我们将学习如何创建新实验、记录指标,并利用UI界面进行数据查询和可视化分析。

上一节我们介绍了MLflow的基本概念,本节中我们来看看如何通过其跟踪UI来管理和分析实验数据。

创建新实验

首先,我们需要创建一个新的实验来存放即将记录的指标数据。你可以让MLflow自动生成实验ID,也可以手动创建。

以下是创建新实验的步骤:

  1. 打开终端。
  2. 运行以下命令来创建一个名为“produce_metrics”的实验:
    mlflow experiments create --experiment-name produce_metrics
    
  3. 命令执行后会返回一个实验ID(例如:2)。

创建完成后,你可以在跟踪UI中刷新页面,看到名为“produce_metrics”的新实验已经出现,但其中还没有任何运行记录。

记录实验指标

接下来,我们需要运行一个Python脚本来向这个新实验记录指标数据。我们将通过设置环境变量来指定实验ID。

以下是记录指标的步骤:

  1. 在终端中,设置环境变量 MLFLOW_EXPERIMENT_ID 为你刚获得的实验ID(例如:2)。
    export MLFLOW_EXPERIMENT_ID=2
    
  2. 运行你的Python脚本(例如:produce_metrics.py)来生成并记录指标。
    python produce_metrics.py
    

脚本会模拟记录CPU、内存(RAM)和磁盘(Disk)的使用率百分比,每个指标随机记录约30次,数值在0到100之间随机选择。

运行完成后,返回跟踪UI并刷新,你就能在“produce_metrics”实验下看到新的运行记录,以及被捕获的CPU、Disk和RAM这三个指标。

在UI中分析指标

现在,让我们利用跟踪UI的功能来深入分析这些记录的数据。

以下是UI提供的主要分析功能:

  • 查看指标详情:点击任意一个指标名称(如CPU),你可以看到该指标在每次迭代中被记录的具体数值列表。
  • 可视化图表:UI会为指标生成趋势图。你可以调整图表的平滑度等参数,以便更好地观察数据变化。
  • 数据查询:UI提供了强大的查询功能,类似于SQL查询。例如,你可以在查询框中输入 metrics.CPU > 88 来筛选出CPU使用率超过88%的所有运行记录。
  • 多维度筛选:你不仅可以按指标筛选,还可以对参数(Parameters)和制品(Artifacts)进行同样的查询和过滤操作。筛选条件可以针对所有运行,或选择特定版本。

为了演示更丰富的图表,我们可以修改脚本,让它仅记录CPU指标,并将迭代次数增加到400次。再次运行脚本后,回到UI查看CPU的图表,你会得到一个包含400个数据点的、更连续和真实的趋势图,这对于监控模型训练过程非常有用。

本地文件结构

所有实验的运行数据都存储在本地。你可以通过终端查看 mlruns 目录下的结构。每个实验ID对应一个文件夹,里面包含了该实验的所有运行记录、参数、指标和制品。这种结构化的存储方式便于管理和追溯。

本节课中我们一起学习了如何使用MLflow跟踪服务器UI。我们掌握了创建新实验、通过环境变量记录指标数据的方法,并重点探索了UI界面中查看指标详情、可视化图表以及进行高级数据查询和筛选的核心功能。这些工具能帮助你有效地管理和分析机器学习实验的整个过程。

146:参数、版本、工件与指标 🔧

在本节课中,我们将深入学习MLflow中的核心概念:参数、工件与指标。我们将通过一个具体的例子,了解如何记录和追踪这些元素,以及它们如何帮助我们管理和复现机器学习实验。


上一节我们介绍了MLflow的基本概念,本节中我们来看看如何在实际代码中记录参数、工件和指标,并理解它们之间的区别与联系。

让我们深入探讨参数、工件与指标。我们已经了解了如何生成大量指标并将其记录到用户界面。现在,我将尝试运行一个来自Databricks/MLflow文档的示例代码,然后展示生成的文件内容。执行这段代码时,它会获取项目,但遇到了一个错误。

让我们看看发生了什么。MLflow对某些规则比较严格,其中之一就是不允许更改已记录的参数值。你可以看到,初始值是5,但后续尝试以5.0(浮点数)的形式记录它。这是不被允许的。

异常信息非常有用,它指出这样记录参数是不行的。原因在于,参数通常代表你运行实验的方式,例如在命令行界面中传递的参数。如果你已经以--log-level=warning运行了一个命令,之后不太可能将其更改为debug,因为实验已经基于warning级别运行了。因此,MLflow会在此类情况发生时报错。虽然理论上可以强制覆盖某些参数,但强烈建议不要这样做。正确的方法是从一开始就正确设置参数,并保持其一致性。

让我们看看这个示例的具体内容。我将转到MLflow示例,并查看train.py文件。该文件使用著名的葡萄酒质量CSV数据集进行训练。我们关注的是它如何记录参数。代码中传递了值为5的alpha参数。这里有一个逻辑:如果alpha大于1,则使用其值,否则使用0.5。问题可能出在这里,因为代码抱怨参数值被更改。我们需要确保参数被正确设置。

为了解决这个问题,我对示例进行了修改,强制将alpha转换为整数,以避免类型不一致的问题。现在,让我们回到编辑器并再次运行它。

回到Visual Studio Code,我们运行修改后的脚本,指定alpha为5。运行完成后,终端会输出一些值。这些值来自train.py中的打印语句。然而,将信息打印到终端仅在直接运行时有用;MLflow的优势在于它能自动捕获并记录所有信息,包括指标和模型本身。

在这个例子中,代码使用log_model辅助函数(来自sklearn)来记录训练好的弹性网络模型。模型在调用fit方法后生成,并被MLflow捕获。

现在,让我们在MLflow UI中查看运行结果。刷新页面后,我们可以看到多次运行记录。其中一次运行失败了,这正是之前提到的Databricks示例,它由于参数记录问题而失败。在详情中,我们可以看到参数alpha被记录为5,但后续尝试记录为5.0导致了失败。状态显示为“失败”,因此没有生成任何指标或工件。

查看最近一次成功的运行,情况就不同了。参数alpha被成功记录为5。我们还可以看到三个指标:MAE、R2和RMSE。点击这些指标,可以看到它们都是固定值(例如RMSE为0.85),这与我们在代码中看到的一致。

为了展示实验追踪的威力,我们可以用不同的参数值多运行几次。例如,用alpha=3alpha=2(注意避免使用浮点数以免冲突)再运行两次。完成后,回到UI查看所有运行记录。

以下是多次运行后的关键观察点:

  • 参数变化:UI清晰地展示了每次运行时alpha参数的不同值。
  • 指标对比:我们可以轻松比较不同参数下模型性能指标(如RMSE)的差异。
  • 工件存储:成功的运行都保存了完整的模型工件。点击“Artifacts”可以查看所有被捕获的内容,包括MLmodel文件、conda环境配置(conda.yaml)、序列化的模型文件(model.pkl)等。这非常强大,因为它捕获了复现实验或进行预测所需的一切。

例如,我们可以直接加载这个被记录的模型进行预测。以下是如何操作的示例代码:

import mlflow
import pandas as pd

# 根据UI中的路径加载模型
logged_model = 'runs:/<RUN_ID>/model'

# 加载模型为Python函数(pipeline)
loaded_model = mlflow.pyfunc.load_model(logged_model)

# 假设有一个测试DataFrame `test_data`
# predictions = loaded_model.predict(test_data)

我们可以在一个Jupyter Notebook中尝试运行类似的代码。虽然可能需要正确定义测试数据,但这个例子很好地展示了如何快速访问并使用MLflow UI中记录的模型。即使本地没有安装pandas,通过mlflow.pyfunc.load_model这个辅助函数,我们也能轻松地从MLflow加载模型进行交互。


本节课中我们一起学习了如何在MLflow中区分和记录参数、工件与指标。我们通过一个实际例子看到,参数定义了实验配置,指标衡量了模型性能,而工件则保存了实验的完整产出(如模型文件)。正确使用这些功能,能够极大地提升机器学习实验的可追踪性、可复现性和管理效率。记住,从一开始就清晰、一致地定义和记录参数,是保证实验流程顺畅的关键。

147:使用MLflow项目 🚀

在本节课中,我们将学习MLflow项目的核心组成部分。MLflow项目提供了一种标准化的方式来打包和复用机器学习代码,确保实验的可重复性。我们将了解其基本结构,包括项目定义文件、环境配置和入口点脚本。


上一节我们介绍了MLflow项目的概念,本节中我们来看看一个MLflow项目的具体构成组件。

以下是MLflow项目的主要组成部分:

  • 项目名称:在项目定义文件中声明,用于标识项目。
  • Conda环境:通过一个YAML文件指定,用于定义代码运行所需的依赖项,确保环境一致性。
  • 入口点:至少需要定义一个入口点。入口点允许你通过不同的参数来运行脚本,参数可以是路径、数字(如浮点数)等类型。
  • 执行脚本:通常是Python脚本或Shell脚本。推荐使用Python脚本,以便利用Conda环境中为数据科学预置的丰富库。

接下来,我们详细看一下项目定义文件(MLproject)。由于该文件没有.yaml.yml扩展名,某些编辑器可能无法提供语法高亮。

以下是项目定义文件的一个示例结构:

name: my_project
conda_env: conda.yaml
entry_points:
  main:
    parameters:
      data_file: path
      validation_split: {type: float, default: 0.2}
    command: "python train.py --data-file {data_file} --validation-split {validation_split}"

在这个示例中:

  • name 字段指定了项目名称。
  • conda_env 字段指向定义依赖的Conda环境文件。
  • entry_points 下定义了至少一个入口点(例如 main),其中包含了参数和要执行的命令。

现在,让我们看一个具体的Python脚本示例。这个脚本使用click库来创建命令行工具,但其核心逻辑与框架无关,你也可以使用纯Python脚本。

该脚本的主要功能是:

  1. 读取一个CSV文件。
  2. 根据一个布尔参数决定是否记录指标。
  3. 检查数据中是否存在未命名列或全零列,并进行计数报告。
  4. 使用MLflow的API记录相关指标。

脚本的关键逻辑部分如下(示意):

import click
import pandas as pd
import mlflow

@click.command()
@click.option('--data-file', required=True)
@click.option('--log-metrics', is_flag=True)
def main(data_file, log_metrics):
    df = pd.read_csv(data_file)
    # ... 数据验证逻辑 ...
    if log_metrics:
        mlflow.log_metric("unnamed_columns_count", count)
    # ... 其他操作 ...

最后,我们来看一下Conda环境文件(conda.yaml)。这个文件用于声明项目所依赖的所有软件包,是创建可重复环境的关键。

一个典型的环境文件内容如下:

name: exploratory
channels:
  - conda-forge
dependencies:
  - python=3.8
  - pandas
  - scikit-learn
  - mlflow
  - click

在这个文件中:

  • name 指定了Conda环境的名称。
  • channels 指定了下载包的渠道(这里使用了conda-forge)。
  • dependencies 列出了所有必需的依赖包及其版本。

本节课中我们一起学习了MLflow项目的基本结构。一个标准的MLflow项目通常包含:一个定义项目属性和入口点的MLproject文件、一个指定依赖的conda.yaml环境文件,以及一个或多个执行核心逻辑(如数据验证、模型训练)的Python脚本。通过这种方式,你可以将数据验证、模型训练等多种任务以可重复、标准化的形式打包和管理。


148:创建MLflow项目 🚀

在本节课中,我们将学习如何创建一个实际的MLflow项目。我们将使用一个名为“wine ratings”的示例项目,并处理一个包含特殊字符(如回车符)的CSV数据文件。通过本教程,你将掌握创建项目、管理依赖、运行项目以及传递参数的核心步骤。


创建项目环境与依赖管理

上一节我们介绍了MLflow项目的基本概念,本节中我们来看看如何从零开始创建一个项目。首先,我们需要设置项目环境并管理其依赖。

创建一个MLflow项目的第一步是定义其运行环境。我们将使用Conda来创建一个隔离的环境,确保项目依赖不会影响系统或其他项目。

以下是创建和激活Conda环境的步骤:

  1. 创建环境:使用命令 conda create --name exploratory python=3.8 创建一个名为“exploratory”的新环境,并指定Python版本为3.8。
  2. 激活环境:使用命令 conda activate exploratory 来激活这个新创建的环境。激活后,所有后续的包安装都将仅限于此环境。

激活环境后,我们需要将环境的配置导出为一个YAML文件。这个文件定义了项目的所有依赖,可以被MLflow识别和复现。

使用命令 conda env export > exploratory.yaml 来导出当前环境的配置。生成的YAML文件内容结构如下:

name: exploratory
channels:
  - defaults
dependencies:
  - python=3.8
  - pip
  - pip:
    - pandas==1.3.0
    - mlflow==1.20.2

在这个文件中:

  • name 字段标识了环境名称。
  • channels 字段指定了包来源(例如,PyTorch有特定的channel)。
  • dependencies 字段列出了核心的Conda包。
  • 通过 pip 字段,我们可以指定需要由pip安装的额外Python包,例如 pandasmlflow

如果你后续需要更新依赖(例如添加或移除某个包),请修改 exploratory.yaml 文件,然后运行以下命令来更新环境并保持其整洁:

conda env update --file exploratory.yaml --prune

参数 --prune 会移除环境中已不再YAML文件中定义的包。


配置与运行MLflow项目

现在我们已经准备好了项目环境,接下来需要配置MLflow项目本身并运行它。

一个MLflow项目的核心是 MLproject 文件。它定义了项目的入口点、参数和运行环境。在我们的示例中,入口点是一个名为 validate 的Python脚本,它负责读取CSV文件并进行数据验证。

MLproject 文件内容示例如下:

name: wine_ratings_project

conda_env: exploratory.yaml

entry_points:
  main:
    parameters:
      file_name: {type: string}
      log: {type: string, default: "true"}
      max_errors: {type: int, default: 1}
    command: "python validate.py {file_name} {log} {max_errors}"

在这个配置中:

  • conda_env 指向我们刚才创建的YAML文件。
  • entry_points 定义了如何运行项目。main 是默认入口点。
  • parameters 部分声明了运行脚本所需的参数。file_name 是必需参数,而 logmax_errors 有默认值。

项目将使用我们提供的 carriage.csv 文件。这个文件虽然只有一行数据,但其中包含回车符等可能造成处理问题的特殊字符。validate.py 脚本的任务就是检测并报告这些问题。

一切就绪后,我们可以在终端中运行该项目。首先确保你位于项目目录下,并且 exploratory 环境已激活。

使用 mlflow run 命令来执行项目,并通过 -P 参数传递必需的 file_name 参数:

mlflow run . -P file_name=carriage.csv

命令执行后,MLflow会:

  1. 检测到并使用现有的 exploratory Conda环境。
  2. 使用默认值 true1 来填充 logmax_errors 参数。
  3. file_name 参数解析为文件的绝对路径,确保在不同机器上运行的一致性。
  4. 执行 python validate.py 命令并传入所有参数。

如果运行成功,你将在终端看到相应的输出。如果传递了不存在的文件名(例如 fake.csv),MLflow会报错提示文件未找到。如果不传递必需的 file_name 参数,则会收到缺少参数的警告。

你还可以在运行时覆盖默认参数。例如,如果你想将最大错误数改为10,可以这样运行:

mlflow run . -P file_name=carriage.csv -P max_errors=10

这样,max_errors 参数的值就会被替换为10,并传递给验证脚本。


总结

本节课中我们一起学习了创建一个完整MLflow项目的流程。

我们首先使用Conda创建并管理了一个独立的Python环境,并通过YAML文件定义了项目依赖。接着,我们编写了 MLproject 文件来配置项目的入口点和运行参数。最后,我们使用 mlflow run 命令成功地执行了项目,并学习了如何传递以及覆盖运行参数。

通过这个简单的“数据验证”项目示例,你掌握了MLflow项目标准化、可复现运行的基础。这是构建更复杂机器学习工作流的第一步。

149:从远程Git仓库运行项目 🚀

在本节课中,我们将要学习如何使用MLflow直接从远程Git仓库(如GitHub)运行机器学习项目。这是一种便捷的方式,可以让你无需在本地克隆代码库就能执行和复现项目。

概述

MLflow具备运行远程项目的能力,只需传入一个类似GitHub的URL即可。本节将通过一个在MLflow文档中广泛使用的示例仓库,来演示这一功能是如何实现的。

项目结构分析

上一节我们介绍了MLflow项目的基本概念,本节中我们来看看这个远程示例项目的具体结构。

这个项目非常简短,与我们之前视频中看到的类似。它位于MLflow官方组织的仓库中:mlflow/mlflow-example。这个仓库结构简单,更新频率不高。

以下是该项目的主要文件结构:

  • MLproject文件:这是一个非常简单的文件,只有大约10行代码。它定义了一个Python入口点 train.py,并包含两个参数:
    • alpha:默认值为 0.5
    • L1_ratio:默认值为 0.1
  • train.py文件:这个文件同样非常直接。它会启动一个MLflow运行,并使用上面定义的 alphaL1_ratio 参数。

运行远程项目

了解了项目结构后,接下来我们看看如何实际运行它。

我们将通过终端,使用 mlflow run 命令来执行这个远程项目。为此,我们需要项目的SSH地址(或HTTPS地址)。

具体操作步骤如下:

  1. 复制项目的Git仓库地址。
  2. 在终端中执行命令 mlflow run <仓库地址>

例如,命令可能如下所示:

mlflow run git@github.com:mlflow/mlflow-example.git

首次运行时,MLflow会自动从GitHub获取项目代码,检查或创建所需的Python环境(例如Conda环境),然后执行项目中定义的 train.py 脚本。

传递运行参数

默认情况下,项目会使用 MLproject 文件中定义的默认参数运行。但MLflow也允许我们在运行时覆盖这些参数。

根据文档,我们可以通过 -P 选项来传递参数。例如,如果我们想将 alpha 设置为 0.7,可以运行:

mlflow run git@github.com:mlflow/mlflow-example.git -P alpha=0.7

执行后,MLflow会使用我们指定的新参数值(alpha=0.7)来运行项目,而不是文件中的默认值(alpha=0.5)。这证明了我们能够成功地远程运行一个MLflow项目,并动态地控制其参数。

总结

本节课中我们一起学习了MLflow的核心功能之一:从远程Git仓库运行项目。我们首先分析了一个示例项目的结构,然后演示了如何使用 mlflow run 命令直接执行远程代码,最后还了解了如何在运行时覆盖项目的默认参数。这个过程完全是自动化的,MLflow会处理代码获取、环境管理和任务执行的所有细节,极大地简化了机器学习项目的共享与复现流程。

150:将MLflow连接至远程服务 🚀

在本节课中,我们将学习如何将MLflow连接到远程的模型跟踪服务器。具体来说,我们将探索两种主流云服务——Databricks和Azure Machine Learning——的连接配置方法。掌握这些连接方式,能让你在本地开发时,将实验记录、参数和模型统一存储到云端,实现协作与可追溯性。

连接MLflow与Databricks

上一节我们介绍了MLflow的基本概念,本节中我们来看看如何将其与Databricks服务连接。Databricks提供了托管式的MLflow跟踪服务器。

根据Databricks官方文档,配置的核心在于正确设置环境变量,以允许本地MLflow客户端与远程服务器通信。无论底层是AWS、Azure还是GCP,连接原理相同。

以下是连接所需的关键步骤:

  1. 设置跟踪服务器URI:你需要导出 MLFLOW_TRACKING_URI 环境变量,其值指向你的Databricks工作区。
  2. 配置认证信息:你有两种主要的认证方式选择。

以下是两种可选的认证配置方法:

  • 使用用户名和密码:直接设置 DATABRICKS_USERNAMEDATABRICKS_PASSWORD 环境变量。
  • 使用访问令牌(推荐):生成一个REST API令牌,然后设置 DATABRICKS_HOSTDATABRICKS_TOKEN 环境变量。

正确设置这些变量后,本地MLflow的运行数据就会发送到Databricks的跟踪服务器。

生成个人访问令牌的过程很直接。按照文档指引,在你的Databricks工作区中,点击左下角的“设置”选项卡,进入“用户设置”。在设置页面中,你可以创建新的令牌。建议为令牌设置一个有效期(例如90天),这是一个良好的安全实践。令牌生成后只会显示一次,请妥善保存。

连接MLflow与Azure Machine Learning

接下来,我们看看如何将MLflow连接到另一个流行的服务——Azure Machine Learning。这使你能够利用Azure ML的工作区和模型注册中心。

连接Azure ML同样需要配置MLflow跟踪URI。官方提供了几种获取和设置该URI的方法。

一种方法是手动构建URI字符串。其格式通常如下:

azureml://<region>.api.azureml.ms/mlflow/v1.0/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.MachineLearningServices/workspaces/<workspace-name>

你需要填入你的Azure区域、订阅ID、资源组名称和工作区名称。

另一种更简便的方法是通过Azure门户获取。在Azure Machine Learning工作室中,你可以找到“MLflow跟踪URI”字段,并直接点击链接复制到剪贴板。随后,你可以将其导出为环境变量。

总结

本节课中我们一起学习了将MLflow连接到远程跟踪服务器的两种主要方式。我们详细介绍了连接Databricks和Azure Machine Learning所需的配置步骤与认证方法。无论是通过环境变量设置Databricks的访问令牌,还是手动构建或从门户复制Azure ML的跟踪URI,核心目标都是建立本地工具与云端服务之间的桥梁。这为团队协作、实验管理和模型部署奠定了重要基础。

151:MLflow包的组件 📦

在本节课中,我们将学习MLflow模型的核心概念及其组件。MLflow模型是一种标准化的格式,用于定义如何与机器学习模型交互、其来源、依赖关系以及如何运行和部署它。理解这些组件对于有效使用MLflow至关重要。


MLflow模型概述

MLflow模型是一种规范化的格式,它定义了如何与机器学习模型交互。它包含了模型的来源、运行所需的依赖项、如何执行以及如何提供服务等信息。本质上,它旨在记录模型的构建和运行环境。

MLflow模型的存储格式

上一节我们介绍了MLflow模型的概念,本节中我们来看看一个MLflow模型包具体包含哪些文件。当你保存一个MLflow模型时,它会生成一组标准化的文件。

以下是MLflow模型包中常见的文件:

  • MLmodel: 这是一个YAML格式的元数据文件。它定义了模型的基本信息,例如使用哪种“风味”来加载和运行模型。如果文本编辑器不支持YAML语法高亮,它可能看起来格式混乱。
  • 模型文件: 例如一个Python的pickle文件(.pkl),其中包含了序列化的模型权重和参数。
  • conda.yaml: 这个文件定义了创建模型环境所需的Conda依赖项,我们之前已经见过它的样子。
  • python_env.yamlrequirements.txt: 这些文件指定了Python环境的具体细节或通过pip安装的包列表。

深入解析 MLmodel 文件

现在,让我们具体查看一个MLmodel文件的内容,以理解其提供的关键信息。在Visual Studio Code中打开该文件,可以看到其结构。

flavors:
  python_function:
    loader_module: mlflow.sklearn
    python_version: "3.8.13"
    env: conda.yaml
artifacts:
  model: model.pkl
utc_time_created: '2023-10-27 10:30:00'
mlflow_version: 1.28.0
run_id: abc123def456
signature:
  inputs: '[{"name": "feature1", "type": "double"}]'
  outputs: '[{"name": "prediction", "type": "double"}]'
  • 风味flavor指明了MLflow应如何与该模型交互。例如,python_function是一种通用风味,而sklearn则专门用于Scikit-learn模型。一个模型可以支持多种风味。
  • 构件路径artifacts部分指明了模型主体文件(如model.pkl)的位置。
  • Python版本: 例如"3.8.13"。这是关键信息,确保了模型能在兼容的Python环境中运行。版本不匹配会导致运行失败。
  • MLflow版本: 记录了创建此模型时使用的MLflow库版本(例如1.28.0)。
  • 运行ID: 关联到生成此模型的特定MLflow实验运行。
  • 签名signature定义了模型预期的输入和输出的数据结构,这对于正确调用模型至关重要。

环境依赖文件解析

接下来,我们看看定义运行环境的文件。conda.yamlpython_env.yaml文件提供了重现模型环境的完整蓝图。

conda.yaml文件内容示例如下:

name: mlflow-env
channels:
  - defaults
  - conda-forge
dependencies:
  - python=3.8.13
  - pip
  - pip:
    - mlflow==1.28.0
    - scikit-learn==1.0.2
    - pandas==1.4.3

requirements.txt文件则可能列出额外的PyPI依赖包,例如:

transformers==4.25.1
torch==1.13.0

这些文件明确列出了所有依赖库及其版本(如mlflowscikit-learntransformers),这对于复现模型训练环境或在新机器上部署模型是必不可少的。它们解决了因依赖缺失或版本冲突导致的“在我机器上能运行”的问题。


本节课中我们一起学习了MLflow模型包的各个核心组件。我们了解到,一个MLflow模型不仅仅是一个模型文件,而是一个包含元数据(MLmodel)、序列化模型、完整环境定义(conda.yamlrequirements.txt)的标准化包。这种格式确保了机器学习模型的可追溯性、可复现性和可移植性,是MLOps实践中的重要一环。下一节,我们将学习如何使用MLflow来构建和保存这样的模型包。

152:在MLflow模型中使用注册表 📚

在本节课中,我们将学习如何在MLflow中使用模型注册表。模型注册表是一个核心功能,它允许你注册、版本化和管理机器学习模型。这个功能并非MLflow独有,几乎所有主流云服务商都提供了类似的解决方案。掌握它对于管理持续变化的模型至关重要。

概述

模型注册表的核心作用是注册模型并管理其关联的不同版本。这在模型频繁更新的场景下非常有用。本节将介绍使用MLflow实现这一功能的具体方法。

注册与检索模型

上一节我们介绍了MLflow的基础,本节中我们来看看如何注册和检索模型。本质上,这个过程涉及训练或创建新模型(或新环境),然后找到一种方法来注册它们。

你可以有多种选择来注册和检索模型。以下是几种主要方式:

  1. 使用现有模型进行注册:你可以从一个已存在的模型开始注册。这种方式本身提供的信息很少,基本上只是创建一个几乎为空的信息占位符。
  2. 通过API或SDK注册:如代码所示,你可以通过编程方式(API/SDK)完成注册。
    # 示例:通过MLflow客户端API创建空的注册模型占位符
    client.create_registered_model(name="MyModel")
    
  3. 通过用户界面(UI)注册:MLflow也提供了直观的图形界面来操作注册表。

目前我们不会深入讲解如何检索或更新模型,但要创建一个新模型,你必须先产生一个模型“工件”。产生工件的标准方法是在训练时使用 log_model 函数。

本地运行MLflow服务器

我们已经看到了几种操作方法,但故事还不完整。如果你想在本地尝试这些功能(强烈推荐),你需要运行一个MLflow服务器。具体操作有些技巧,需要按顺序准备几样东西。

以下是启动服务器的完整命令:

mlflow server \
    --backend-store-uri sqlite:///mlflow.db \
    --default-artifact-root ./mlruns \
    --host 127.0.0.1 \
    --port 5000

我们来详细看一下这个命令:

  • mlflow server 是你要使用的命令。
  • --backend-store-uri:我使用了SQLite,这是一个嵌入式数据库。你的系统上应该可用,否则需要安装sqlite3。这里指向当前路径下的一个文件(mlflow.db)。
  • --default-artifact-root:指向 ./mlruns 目录,作为存储模型工件的默认根路径。
  • --host 127.0.0.1--port 5000 指定服务器在本地主机的5000端口运行。

执行命令后,服务器就启动了。现在,如果我在浏览器中访问 http://127.0.0.1:5000,就能看到MLflow的用户界面。

通过UI创建与交互模型

为了开始使用,我们可以通过UI创建一个模型。例如,你可以创建一个名为“D5_onyx”的模型,并为其添加描述和标签。

这种方式与前面提到的API调用效果完全相同。创建模型后,你就可以开始与它交互,并使用注册表功能。注册后,你会发现有几个不同的操作选项。

注册模型与注意事项

你可以使用 mlflow.register_model 来注册一个模型。这个函数会创建一个新的注册模型记录。如果模型名称已存在,操作会失败,因为它要求名称唯一。因此,务必注意你使用的名称。

你也可以手动指定运行ID和模型路径来完成注册,但这种方式通常非常繁琐。请确保只在少数特定情况下(例如需要精确定位到某个运行ID及其存储位置时)才使用手动方式。

这就是你与模型注册表交互的方式:首先如所示那样记录(log)模型,然后与服务器交互。这个服务器允许你存储模型信息,就像我们之前做的那样。

总结

本节课中,我们一起学习了MLflow模型注册表的核心用法。我们了解了注册模型的重要性,探讨了通过API和UI进行注册的方法,并详细介绍了如何在本地启动MLflow服务器来管理模型。关键是要记住,使用 log_model 记录模型是注册的前提,而注册表的核心价值在于对模型进行版本控制和生命周期管理。

153:通过API引用工件 📡

在本节课中,我们将学习如何与存储在远程注册表中的模型进行交互和引用。这是使用MLflow时更深入的一步。我们已经看过如何注册模型,但尚未了解如何检索或更新它们。本节将详细介绍这些操作。

模型注册与日志记录

上一节我们介绍了模型的基本概念,本节中我们来看看如何具体记录一个模型。首先,回顾一下记录模型的关键步骤。

我运行了几个实验,这些实验在几分钟前完成,并成功记录了一个实际模型。但有些操作并不直观,可能需要一些时间才能理解。我想通过示例展示这些过程。

打开Visual Studio Code,这里有一个Jupyter笔记本,包含如何注册模型以及如何动态与API交互的示例。但首先,我们看看如何记录模型。

以下是一个简短的脚本,它使用了Hugging Face库。脚本通过transformers导入pipeline,然后创建一个Python类。这个类告诉MLflow如何与这个Hugging Face模型交互。具体方式是,在构造函数中设置分词器和模型,然后定义一个方法(本例中将英语翻译为德语),构建模型输入和输出,最后启动跟踪运行并记录模型。

记录模型时有几个关键点:

  • log_model方法:当你记录模型时,你正在生成一个工件。你捕获了模型的所有细节。
  • 注册模型名称:最初我没有设置注册模型名称,导致模型没有出现在注册表中。因此,我决定将其命名为T5-small-summarizer,并添加了一些模型细节描述。
  • 跟踪URI:必须设置tracking_uri。如果未设置,模型将无法注册,且不会有任何错误提示。因此,请确保tracking_uri始终设置为预期的值。
  • 动态交互:当你想操作模型时,必须确保设置了正确的URI。例如,我动态运行时使用http://127.0.0.1:5000(本地运行)。我不确定为何默认不是这个,我认为默认是文件系统,这会导致期望在服务器上运行的内容并未运行。

现在,让我们在终端中快速运行这个记录模型的脚本。

python log_model.py

运行成功,显示“成功注册模型 T5-small-summarizer 并创建版本1”。

在Web界面中查看模型

刷新MLflow的Web浏览器界面,可以看到刚刚在16秒前运行的实验,并创建了一个模型。这很好,我们现在有一些版本了。

接下来,点击“Models”选项卡,可以看到T5-small-summarizer出现了,并且版本1是“Production”阶段。

如果点击版本1,然后点击“Source Run”,会显示几个非常有趣的部分:

  1. ML Model:我们之前看到的已捕获的模型。
  2. Python Environment:允许你复制粘贴代码,这些代码可以在Spark DataFrame上运行,以便与模型交互。如果你想在Pandas DataFrame上运行,也完全可以。这是一个非常强大和完整的解决方案。
  3. 其他细节:它捕获了所有内容,包括参数(本例中未使用)、指标(本例中无)和标签(本例中无)。在“Artifacts”部分,可以看到requirements.txt,其中列出了transformerstorch等各种依赖。

这样,我们就设置好了T5-small-summarizer模型。

通过API与模型交互

现在,让我们回到Visual Studio Code,开始通过API与模型进行交互。首先,导入MLflow,设置跟踪URI,并创建一个客户端对象。

import mlflow

# 设置跟踪URI
mlflow.set_tracking_uri("http://127.0.0.1:5000")
# 创建客户端
client = mlflow.client.MlflowClient()

接下来,我们注册一个新模型。

# 注册一个名为't5-onnx'的新模型
client.create_registered_model("t5-onnx")

这个模型之前不存在。注册后,回到Web服务界面,点击“Models”,可以看到t5-onnx出现了,但还没有版本。这是因为我们只创建了一个名称。点击它,里面没有太多内容。

我们也可以删除已注册的模型。

# 删除名为't5-onnx'的注册模型
client.delete_registered_model("t5-onnx")

执行后,刷新界面,可以看到t5-onnx已经消失。

现在,让我们对T5-small-summarizer进行一些操作。在Web界面点击它,可以看到版本1的描述为空,阶段为“None”。我们将通过API更新这些信息。

以下是更新模型版本描述的代码:

# 更新模型版本的描述
client.update_model_version(
    name="T5-small-summarizer",
    version=1,
    description="This is the T5 model in ONNX version 1.6 using OpSet 12."
)

运行这个代码单元,API调用完成。回到Web界面,甚至无需重新加载,描述就已经更新了。现在版本1的描述显示为“This is the T5 model in ONNX version 1.6 using OpSet 12.”

总结

本节课中我们一起学习了如何通过MLflow API与远程注册表中的模型进行交互。我们回顾了记录模型时的关键设置,如指定模型名称和确保tracking_uri正确配置。然后,我们演示了如何在Web界面中查看注册的模型及其详细信息。最后,我们通过编写Python代码,使用MlflowClient来动态注册新模型、删除模型以及更新现有模型版本的描述信息。虽然这里没有涵盖所有可能的API操作,但这些基础知识应该能帮助你顺利开始使用MLflow管理你的机器学习模型生命周期。

154:保存与部署MLflow模型

在本节课中,我们将学习如何与已注册的MLflow模型进行交互,特别是如何通过本地服务(serving)的方式来部署和使用模型。我们将从运行一个本地服务开始,并通过API调用进行预测。

模型服务概述

上一节我们介绍了如何注册模型。本节中,我们来看看如何通过MLflow的本地服务功能来部署模型,并通过HTTP请求与之交互。我们将使用一个基于Hugging Face API的翻译模型作为示例。

模型脚本回顾

首先,我们回顾一下用于记录模型的脚本。该脚本定义了一个继承自mlflow.pyfunc.PythonModel的类,这使得MLflow知道如何与之交互。

以下是核心的模型类定义:

class Summarizer(mlflow.pyfunc.PythonModel):
    def load_context(self, context):
        # 加载模型和分词器
        self.model = AutoModelForSeq2SeqLM.from_pretrained("t5-small")
        self.tokenizer = AutoTokenizer.from_pretrained("t5-small")

    def predict(self, context, model_input):
        # 定义预测逻辑:将英文翻译为德文
        inputs = self.tokenizer(model_input["text"].tolist(), return_tensors="pt", padding=True)
        outputs = self.model.generate(**inputs)
        return self.tokenizer.batch_decode(outputs, skip_special_tokens=True)

在这个类中,我们定义了load_context方法来加载预训练模型和分词器,并在predict方法中实现了从英文到德文的翻译逻辑。脚本运行后,模型被记录并注册为T5-small-sumr

启动本地模型服务

现在,我们将学习如何从本地存储的MLflow运行记录中启动一个模型服务。

以下是启动服务所需的步骤:

  1. 打开终端:确保已安装MLflow。
  2. 定位模型运行ID:使用mlflow runs list命令查看本地存储的运行记录,并找到目标模型的运行ID。
  3. 启动服务:使用mlflow models serve命令,指定模型路径和端口号。

例如,命令格式如下:

mlflow models serve -m runs:/<RUN_ID>/model -p 5001

请注意,如果默认端口5000已被占用(例如被MLflow跟踪UI使用),则需要像示例中一样指定另一个端口,如5001。

服务成功启动后,终端会显示服务正在运行。该服务提供了一个名为/invocations的单一API端点用于预测。

通过API调用模型

模型服务启动后,我们可以通过发送HTTP请求到/invocations端点来进行预测。

以下是调用API的curl命令示例:

curl -X POST http://127.0.0.1:5001/invocations \
  -H 'Content-Type: application/json' \
  -d '{
    "dataframe_split": {
      "columns": ["text"],
      "data": [["Today is a perfect day to practice automation skills."]]
    }
  }'

关键点说明:

  • URL路径:必须使用/invocations路径。
  • 数据格式:请求体需要遵循特定的格式。这里使用了pandas split格式,通过dataframe_split键来传递数据,其中columns指定列名,data是一个二维数组,包含要翻译的文本。
  • 模型输入:输入数据需要与模型定义时预期的输入签名(即text列)相匹配。

执行命令后,服务会返回翻译结果(本例中为德文)。如果输入其他英文句子,模型会返回相应的德文翻译。

模型服务的内部结构

当我们取消服务并查看本地运行目录时,可以了解MLflow模型服务的内部结构。

每个成功记录模型的运行目录都包含一系列标准化文件,这些文件是MLflow能够服务模型的关键。以下是主要文件:

  • MLmodel:这是一个YAML文件,定义了模型的元数据,包括环境要求、签名(输入/输出格式)以及指向其他组件的路径。
  • conda.yaml:指定了运行模型所需的Conda环境依赖。
  • requirements.txt:列出了所需的Python包。
  • python_model.pkl:存储了序列化的Python模型对象(即我们定义的Summarizer类实例)。
  • 其他可能存在的模型二进制文件。

通过查看MLmodel文件的内容,我们可以确认模型签名、创建时间戳等关键信息。正是这些元数据使得MLflow能够统一地加载和服务各种类型的模型。

总结

本节课中我们一起学习了如何部署和使用MLflow模型。我们首先回顾了模型记录脚本的结构,然后逐步演示了如何从本地运行记录中启动一个模型服务,并通过正确的API格式发送请求进行预测。最后,我们探讨了支持模型服务的内部文件结构,了解了MLmodel等元数据文件的重要性。掌握这些步骤,你就能将训练好的模型快速转化为可访问的API服务。

155:什么是Hugging Face 🤗

在本节课中,我们将要学习Hugging Face平台。我们将了解它是什么、它提供哪些核心功能,以及它如何成为机器学习领域的协作中心。


概述

Hugging Face是一个为机器学习社区设计的综合性平台。它不仅仅是一个网站,更是一个集模型、数据集、代码和协作工具于一体的生态系统。你可以将其视为机器学习领域的“GitHub”,它极大地简化了模型的发现、共享、部署和协作过程。

Hugging Face是一个平台

上一节我们介绍了Hugging Face的定位。本节中我们来看看它的核心组成部分。

访问Hugging Face的主页,你会看到几个主要标签:Models(模型)、Datasets(数据集)、Spaces(空间)和Docs(文档)。这清晰地表明它是一个功能丰富的平台。

以下是Hugging Face平台的核心组成部分:

  • Models:一个庞大的预训练模型库,涵盖自然语言处理、计算机视觉、音频等多个领域。
  • Datasets:用于训练和评估模型的各种公开数据集。
  • Spaces:一个可以托管和分享机器学习演示应用(如Gradio或Streamlit构建的应用)的地方。
  • Docs:全面的文档和教程,帮助用户使用平台的各种工具和库。

就像GitHub是软件工程师协作的中心一样,Hugging Face旨在成为机器学习从业者进行协作和互动的中心。

多种交互方式

上一节我们了解了平台的网页界面。本节中我们来看看如何通过编程方式与平台交互。

创建账户后,你不仅可以通过网站使用Hugging Face,还可以通过其提供的Python库进行程序化访问。例如,使用 huggingface_hub 库,你可以直接通过代码来管理模型、数据集或Spaces仓库。

# 示例:使用 huggingface_hub 库创建一个模型仓库
from huggingface_hub import create_repo
create_repo(repo_id="your-username/my-awesome-model", repo_type="model")

这为用户提供了极大的灵活性,允许他们将Hugging Face的功能集成到自己的自动化工作流和工具链中。

强大的开源库:Transformers

平台本身提供了丰富的资源,而为了更高效地使用这些资源,Hugging Face开发了强大的开源工具库。

其中最著名的就是 Transformers 库。你可以在Python包索引(PyPI)上找到它。这个库为处理文本、图像和音频任务提供了统一的、高级的API抽象。

以下是Transformers库的一个核心概念——Pipeline(管道),它让推理变得极其简单:

from transformers import pipeline
# 创建一个文本生成管道,指定使用gpt2模型
generator = pipeline('text-generation', model='gpt2')
# 使用管道进行推理
result = generator("Hello, I'm a language model,", max_length=30)
print(result)

通过短短几行代码,你就可以利用强大的预训练模型(如GPT-2)完成复杂的任务。Transformers库支持PyTorch、TensorFlow和JAX等多个深度学习框架。

实践:探索与使用模型

了解了核心工具后,让我们回到网站,看看如何实际探索和使用一个模型。

在Models页面搜索“GPT”,你会看到许多相关模型。每个模型都有一个Model Card(模型卡片),其中包含模型描述、用途、训练信息,以及最重要的——一个Hosted Inference API(托管推理API)演示窗口。

例如,你可以直接在网页上的演示框里输入文本,模型会实时返回生成结果。这让你无需编写任何代码就能快速体验模型的能力。

此外,平台还提供了多种部署选项,包括:

  • Hosted Inference API:托管的API,用于快速测试和原型开发。
  • Endpoints:专为生产环境设计的可扩展API端点。
  • SageMaker:与AWS SageMaker的直接集成,便于大规模部署。

你还可以看到社区成员如何利用这些模型。许多人会创建自己的Space,展示他们微调(fine-tune)后的模型或构建的特定应用,这充分体现了平台的协作精神。


总结

本节课中我们一起学习了Hugging Face。我们了解到它是一个集模型库数据集演示空间开发工具于一体的机器学习平台。通过其网站和像 Transformers 这样的开源库,它极大地降低了机器学习技术的使用门槛,并促进了全球开发者之间的协作。无论是寻找一个现成的模型进行推理,还是想分享自己训练的模型,Hugging Face都提供了完整的解决方案。

156:Hugging Face Hub 概述 🧠

在本节课中,我们将要学习 Hugging Face Hub 的核心概念与基本操作。Hugging Face Hub 是一个用于托管和共享机器学习模型、数据集及应用的平台,其交互方式与 GitHub 类似。我们将逐一介绍其主要组件和功能。

概述

Hugging Face Hub 允许你与仓库、模型、数据集、空间(Spaces)甚至组织(Organizations)和端点(Endpoints)进行交互。接下来,我们将通过平台界面来了解这些核心功能。

模型仓库

上一节我们介绍了 Hub 的基本概念,本节中我们来看看如何创建和管理模型仓库。

在 Hugging Face Hub 的主页,点击右上角的“New”按钮,会出现三个主要选项。选择“Model”选项,即可创建一个新的模型仓库。这个过程与在 GitHub 上创建新仓库非常相似。

以下是创建新模型时需要填写的关键信息:

  • 所有者:指定仓库的所有者,可以是个人账户或所属的组织。
  • 模型名称:为你的模型命名,例如 example-model-name
  • 许可证:为模型选择一个开源许可证,例如 MIT
  • 可见性:选择仓库是公开(Public)还是私有(Private)。

创建完成后,该模型就可以通过 Hugging Face 库或网页界面被任何人使用。

数据集与空间

了解了模型仓库后,我们来看看 Hub 上另外两个重要组件:数据集和空间。

“Data”选项的界面与创建模型类似,用于托管和共享数据集。所有这些组件(模型、数据)本质上都是 Git 仓库,支持拉取请求(Pull Request)、修改,甚至可以克隆到本地进行交互。

若要将仓库克隆到本地,需要使用 Git LFS(大文件存储)。较新版本的 Git 命令行工具通常已包含 LFS。克隆命令的基本格式如下:

git clone https://huggingface.co/username/model-name

“Space”功能允许你托管自己的交互式机器学习应用。它提供了几种框架选项:

  • Streamlit:用于快速创建数据应用的框架。
  • Gradio:用于构建机器学习演示界面的库。
  • Static:托管静态网页。

选择任一选项,你都可以构建并部署一个交互式应用,用于展示模型的功能。

组织管理

最后,我们来了解一下组织功能,这对于团队协作非常重要。

“组织”功能适用于团队或公司场景。当多名机器学习工程师需要协作时,可以创建一个组织,其管理方式与 GitHub 组织类似。例如,公司可以创建一个组织(如“Google”),并将项目置于该组织下,然后为团队成员分配访问权限,以便共同贡献。

总结

本节课中,我们一起学习了 Hugging Face Hub 的概述。我们讨论了它的几个核心组件:模型仓库数据集空间组织。Hub 本质上是一个基于 Git 的协作平台,专门为机器学习资产设计,使得托管、共享和协作变得简单高效。

157:Hugging Face Hub 介绍 🚀

在本节课中,我们将要学习 Hugging Face Hub 的核心组成部分。Hugging Face Hub 是一个集成了模型、数据集和机器学习应用(Spaces)的平台,旨在简化机器学习项目的开发与部署流程。我们将逐一了解其关键功能,并学习如何开始使用。

账户与访问令牌 🔑

Hugging Face Hub 的核心始于一个用户账户。首先,你需要登录并创建一个账户。在个人资料页面,你可以进行各种设置。

在设置中,除了填写全名和主页等信息外,最重要的一步是创建一个访问令牌。访问令牌允许你以编程方式与 Hugging Face Hub 交互。

这意味着你可以:

  • 从 GitHub Actions 将构建产物推送到 Hugging Face。
  • 在开发环境中读取和写入数据,例如数据集。
  • 配置一个 Spaces 应用。

因此,使用 Hugging Face Hub 的第一步是确保你拥有一个账户,并已创建一个访问令牌,且将该令牌保存在安全的地方。

模型库 🤖

接下来需要了解的是模型库。模型是当前 Hugging Face 平台的核心组成部分。

模型库包含数以万计的预训练模型,涵盖多种任务。你可以看到诸如图像分类、翻译等任务分类。进一步浏览,你还能找到更高级的类别,例如计算机视觉或自然语言处理。

核心概念:模型分类
模型按任务分类,例如:

  • 计算机视觉:处理图像的模型。
  • 自然语言处理:如翻译或文本生成的模型。
  • 音频:如自动语音识别的模型。

在浏览模型时,平台提供了按下载量排序等功能,这有助于你在处理特定类别任务时,快速找到并尝试可能适合的模型。例如,近期热门的 OpenAI Whisper 模型也可以在 Hub 上找到并使用,用于项目内的转录任务。

数据集 📊

了解模型后,下一个重要部分是数据集。平台上也托管着大量的数据集。

这些数据集之所以重要,是因为它们可用于微调。这意味着你可以利用这些数据定制预训练模型,使其针对你正在解决的具体问题更加精确。

以下是数据集的一些典型用途:

  • 语言建模
  • 多类别分类

访问数据集页面时,你可以查看其结构信息、预览数据,甚至可以直接复制提供的 API 调用代码在终端中查询数据。此外,你还可以在 Hugging Face 环境中直接使用这些数据进行训练。

总的来说,数据集是 Hugging Face 平台最有用的功能之一。你同样可以上传自己的数据集到平台。

应用空间(Spaces) 🎨

最后一个关键组件是应用空间(Spaces)。Spaces 是创建和分享机器学习应用的一种便捷方式。

创建一个 Space 非常简单:只需点击“创建新空间”,然后为其命名并选择你想要使用的技术栈,例如 Streamlit、Gradio 或静态 HTML。你还可以选择许可证以便分享。

浏览他人创建的 Spaces 是熟悉各种工具和概念的好方法。例如,你可以查看 Stable Diffusion 的演示,了解其应用文件结构,学习他们是如何使用 Gradio 来构建空间应用的。

核心概念:Spaces 技术栈
创建 Space 时可选择的技术包括:

  • Streamlit
  • Gradio
  • Static

因此,Hugging Face Hub 是一个集模型、数据集和应用空间于一体的平台。要以编程方式使用它,你需要创建一个个人资料,并在设置中配置好 API 密钥。我们将在后续内容中深入探讨这一点。


本节课中,我们一起学习了 Hugging Face Hub 的四大核心功能:账户与令牌管理海量的模型库丰富的数据集以及便捷的应用空间(Spaces)。理解这些组成部分是有效利用该平台进行机器学习运维和开发的第一步。

158:使用Hugging Face仓库 🚀

在本节课中,我们将学习如何创建Hugging Face仓库、生成并使用访问令牌,以及如何上传模型文件。整个过程将通过命令行工具完成,帮助你掌握模型托管和分享的基础操作。

概述

我们将从登录Hugging Face账户开始,通过命令行创建模型仓库,并最终上传一个预训练模型。以下是实现这一目标的主要步骤。

开始使用Hugging Face仓库

首先,我们打开Hugging Face的默认页面并登录。目前账户中没有任何模型或数据集。页面上提供了创建选项,但我们将遵循官方文档,使用命令行工具来创建仓库。

设置环境与安装工具

上一节我们介绍了目标,本节中我们来看看具体的环境配置。为了开始操作,需要创建一个新的虚拟环境并安装必要的库。

以下是具体步骤:

  1. 打开终端。
  2. 创建一个新的虚拟环境,可以命名为 vm
  3. 激活该虚拟环境。
  4. 根据Hugging Face的说明,安装 huggingface-hub 库及其依赖。

安装命令如下:

pip install huggingface-hub

登录与令牌生成

环境设置完成后,下一步是登录Hugging Face账户。登录过程需要使用访问令牌。

以下是登录和生成令牌的步骤:

  1. 在终端运行 huggingface-cli login 命令。
  2. 系统会提示需要一个令牌,需要访问指定URL来生成。
  3. 在Hugging Face网站设置中,创建一个新令牌。为演示目的,可以命名为“demo”,并赋予读写权限。
  4. 生成令牌后,复制它。
  5. 回到终端,粘贴令牌并回车完成认证。令牌会保存在本地。

创建模型仓库

成功登录后,我们现在可以创建模型仓库了。我们将使用命令行工具,而不是网站界面。

创建仓库的命令格式如下:

huggingface-cli repo create --type model <仓库名称>

例如,我们创建一个名为 demo-onnx 的模型仓库。执行命令后,确认创建,仓库即被成功创建。此时在网站上查看,仓库是空的,没有模型卡片和文件。

克隆仓库与添加模型

仓库创建好后,我们需要将模型文件添加进去。首先,将新创建的仓库克隆到本地。

以下是操作步骤:

  1. 使用 git clone 命令克隆 demo-onnx 仓库到本地。
  2. 进入克隆下来的本地仓库目录,目前里面是空的(除了一个初始文件)。
  3. 将准备好的预训练模型文件(例如一个T5-large模型)添加到这个目录中。
  4. 使用 git addgit commit 命令将文件添加到本地版本库。
  5. 使用 git push 命令将更改推送到Hugging Face远程仓库。推送时可能需要再次进行身份验证,使用之前生成的令牌作为密码即可。

通过网页界面上传文件

除了命令行,也可以通过网页界面上传文件。这对于大文件或图形化操作更为方便。

以下是网页上传的步骤:

  1. 在Hugging Face网站进入你的仓库页面。
  2. 点击“上传文件”按钮。
  3. 从操作系统中将模型文件拖拽到上传区域。
  4. 选择提交到主分支,并填写提交信息。
  5. 点击“提交更改”开始上传。对于大模型文件,上传可能需要一些时间。

完善模型卡片

文件上传成功后,为了让其他人更容易理解和使用你的模型,需要完善模型卡片。

模型卡片本质上是一个 README.md 文件,用于展示模型的文档、使用说明和相关链接。你可以参考其他热门模型(如Stable Diffusion)的模型卡片,编辑自己仓库的 README.md 文件,添加必要的描述信息。

总结

本节课中我们一起学习了使用Hugging Face托管模型的全流程。我们从设置环境、安装 huggingface-hub 工具开始,接着学习了如何生成访问令牌并登录。然后,我们通过命令行创建了一个模型仓库,并演示了如何通过命令行和网页界面两种方式将模型文件上传到仓库中。最后,我们了解了完善模型卡片的重要性,它是分享和复用模型的关键文档。掌握这些步骤,你就能有效地利用Hugging Face平台来管理和分发机器学习模型。

159:使用Hugging Face Spaces创建交互式ML演示

概述

在本节课中,我们将学习如何使用Hugging Face Spaces平台创建一个交互式的机器学习演示应用。我们将通过一个文本摘要的实际例子,了解从创建空间、编写应用代码到部署和测试的完整流程。

什么是Hugging Face Spaces?

上一节我们介绍了Hugging Face平台的基本概念,本节中我们来看看其核心功能之一——Spaces。Hugging Face Spaces允许用户创建和托管交互式的机器学习演示应用。它本质上是一个基于Git的仓库,可以自动构建和部署你的应用。

要创建一个新的Space,请点击平台上的“New”按钮。这将引导你创建一个新的交互式机器学习演示。

创建新Space

以下是创建新Space时需要配置的几个关键选项:

  • 名称:为你的Space设置一个唯一的名称。
  • 许可证:选择适合你项目的开源许可证,例如MIT。
  • Space SDK:选择构建应用的前端框架。主要有三个选项:
    • Gradio:用于快速创建交互式界面的Python库。
    • Streamlit:另一个用于创建数据应用的主流框架。
    • Static:用于托管静态网页。

在本教程中,我们将选择Gradio来构建我们的交互式应用。创建完成后,系统会自动生成一个Git仓库作为你的Space。

应用的核心文件

每个Space应用都需要一些核心文件来运行。最重要的两个文件是应用入口文件和依赖声明文件。

1. 应用入口文件 (app.py)

app.py 文件是你的应用主程序,是必需的入口点。对于Gradio应用,其基本结构如下:

import gradio as gr

# 定义处理输入的函数
def process(input_text):
    # 你的处理逻辑
    result = "处理后的结果"
    return result

# 创建Gradio界面
iface = gr.Interface(fn=process,
                     inputs=gr.Textbox(lines=10, placeholder="请输入文本..."),
                     outputs="text")
# 启动应用
iface.launch()

2. 依赖文件 (requirements.txt)

requirements.txt 文件用于声明你的Python应用所依赖的第三方库。Hugging Face Spaces会根据这个文件自动安装所有依赖。文件内容示例如下:

transformers==4.21.2
tensorflow==2.9.1

构建文本摘要演示

现在,让我们动手构建一个具体的文本摘要应用。我们将使用Hugging Face的transformers库中的预训练模型。

首先,在Space的文件管理中创建 app.py 文件,并写入以下代码:

from transformers import pipeline
import gradio as gr

# 加载摘要pipeline,使用T5模型
summarizer = pipeline("summarization", model="t5-small")

def summarize(text):
    # 可选的文本清洗步骤
    text = text.replace('"', '').replace('&', 'and')
    # 调用模型进行摘要,设置最小长度
    result = summarizer(text, max_length=230, min_length=180, do_sample=False)
    # 返回摘要文本
    return result[0]['summary_text']

# 创建Gradio界面
# inputs: 定义一个10行的文本输入框
# outputs: 定义一个文本输出框
demo = gr.Interface(fn=summarize,
                    inputs=gr.Textbox(lines=10, placeholder="请输入需要摘要的文本..."),
                    outputs="text")

# 启动应用
demo.launch()

接下来,创建 requirements.txt 文件,确保模型和框架能够正确运行:

transformers==4.21.2
tensorflow==2.9.1

提交这两个文件后,Space会自动开始构建过程。你可以在“Logs”选项卡中查看实时构建日志,这类似于Docker容器的构建输出。

配置与运行

构建成功后,即可访问你的演示应用。在应用界面,你会看到一个文本输入框和一个提交按钮。输入一段长文本并点击“Submit”,模型就会生成摘要。

需要注意的是,应用的运行速度取决于你选择的硬件配置。Hugging Face Spaces提供不同级别的计算资源:

  • CPU Basic:免费,但处理速度较慢,适合轻量级演示。
  • GPU Upgrade(如T4 Small):按小时计费,能显著提升模型推理速度,适合对响应时间要求高的应用。

如果你的应用预期会接收大量公开访问,请考虑选择合适的付费层级以保证性能。

总结

本节课中我们一起学习了如何使用Hugging Face Spaces创建和部署交互式机器学习演示。我们完成了从创建Space、编写Gradio应用代码、管理Python依赖,到最终部署和测试的完整流程。通过这个文本摘要的例子,你可以看到Spaces如何让机器学习模型的展示和分享变得非常简单直观。你可以利用这个平台为任何模型快速构建一个前端界面,与他人分享你的工作成果。

160:应用Hugging Face入门 🚀

在本节课中,我们将学习如何开始使用Hugging Face平台。Hugging Face是一个流行的平台,用于处理大型数据集、预训练模型以及展示这些模型的应用。课程将分为三个主要部分:数据与模型的上传下载、模型的微调训练,以及使用Spaces功能来演示机器学习项目。

课程内容概述

我的名字是Noah Gi,我将向你介绍Hugging Face。这是一个非常流行的新平台,用于处理大型数据集、预训练模型,并演示这些模型的应用。本课程的亮点在于,我们将涵盖三个不同的类别。

第一部分:数据与模型管理

在第一部分课程中,我们将讨论如何将数据和模型上传到Hugging Face,以及如何将它们下载到开发环境中,例如支持GPU的GitHub Codespaces。

上一节我们介绍了课程的整体结构,本节中我们来看看具体如何操作。

以下是数据与模型管理的关键步骤:

  • 将数据上传至Hugging Face数据集仓库。
  • 将预训练模型上传至Hugging Face模型仓库。
  • 在开发环境中(如GPU支持的GitHub Codespaces)下载并使用这些资源。

第二部分:模型微调与训练

接下来,在第二部分,我们将介绍如何对模型进行微调和训练。具体来说,我们将从全球顶尖的AI和机器学习公司获取最新的模型,例如摘要生成模型,然后使用自定义数据对这些模型进行微调。之后,将微调后的模型存回你的Hugging Face模型仓库,以便未来使用。

在未来的课程中,我们还将讨论如何利用GitHub Codespaces或其他支持GPU的环境来加速这个迁移学习过程。

第三部分:使用Spaces进行演示

最后,在第三部分,我们将讨论Spaces功能。这是一个极佳的方式来展示你利用机器学习构建的项目作品集,包括使用Streamlit和Gradio。这两个都是构建产品演示的优秀平台。

总结

本节课中,我们一起学习了Hugging Face平台的入门知识。我们概述了如何管理数据与模型、对预训练模型进行微调,以及使用Spaces功能来创建和展示机器学习应用。让我们开始吧,接下来有很多内容需要学习。

161:使用GPU支持的GitHub Codespaces 🚀

在本节课中,我们将学习如何利用GitHub Codespaces创建一个支持GPU的云端开发环境。这个环境非常适合学生和开发者,因为它提供了比个人笔记本电脑更强大的计算资源,并且可以快速启动预配置的容器。

GitHub Codespaces是一个临时的云端开发环境,你可以直接在其中进行编码。在许多情况下,它比你的笔记本电脑更强大,并且能够创建预构建的容器镜像,这些镜像可以非常快速地启动。你还可以充分利用Visual Studio Code的全部功能。

接下来,我们来看看我在杜克大学课堂上是如何使用这个功能的。

创建模板仓库与开发容器 🛠️

我创建了一个名为“MLOps模板”的组织仓库,并使用了“公共模板”功能。

以下是创建和配置模板的关键步骤:

  1. 进入仓库设置:在仓库页面,点击“Settings”(设置)。
  2. 启用模板仓库:向下滚动,找到“Template repository”(模板仓库)选项并勾选,将其设为模板仓库。

这个功能之所以强大,是因为我在仓库中配置了一个 .devcontainer 环境。这允许我自定义开发环境,并预加载我在Dockerfile中指定的所有内容。

我的配置主要包括:

  • 基础镜像:使用标准的GitHub通用开发容器。
  • 系统包安装:安装如 ffmpegpython3.8gcc 等必要的系统包。
  • Python环境与包管理:通过 Makefile 来安装项目所需的所有Python包。
  • 环境配置:配置Visual Studio Code环境,并启用NVIDIA CUDA驱动,以便后续使用GPU功能。

完成所有设置后,我可以通过这个模板来启动一个新的Codespace实例,或者用它来创建一个全新的代码仓库。

启动GPU支持的Codespace实例 ⚡

现在,让我们实际操作一下。首先,我们可以直接基于模板仓库启动一个Codespace。

  1. 点击仓库页面的“Code”(代码)按钮。
  2. 在下拉菜单中选择“Create codespace on main”(在主分支上创建代码空间)。
  3. 在创建时,我们可以自定义机器类型。这里提供了多种选项,包括非常适合CPU任务的强大16核机器。
  4. 对于处理Hugging Face模型的任务(如推理、训练、微调),我推荐选择 GPU机型。例如,一个配置为 6核CPU、1个GPU、112GB内存和128GB存储 的机器,这在大学教学环境中非常适用。

选择好配置后,点击启动,系统就会开始创建这个云端开发环境。

实际上,我已经使用这个模板创建了一个名为“Hugging Face Tutorials”的新仓库,这也是本课程将要使用的环境。并且,我已经提前启动了这个环境。

探索预配置的开发环境 🔍

让我们进入这个已经启动的Codespace,看看里面有什么。

首先,我设置了一个虚拟环境。这确保了项目使用特定版本的Python,并且所有依赖都已预先安装好,无需再次手动安装。

我的 requirements.txt 文件固定了许多必要的包,例如:

  • fastapi
  • jupyter
  • transformers (来自Hugging Face)
  • datasets (来自Hugging Face)
  • tokenizers (来自Hugging Face)
  • 以及像 rouge-score 这样的评估指标包。

此外,还有一个 utilities(工具)目录,用于测试机器的GPU功能。

验证GPU与运行示例任务 ✅

为了验证GPU是否正常工作,我创建了一个名为 verify_pytorch.py 的脚本。它的作用是检查NVIDIA CUDA SDK是否可用。

在终端中,我们可以运行:

python utilities/verify_pytorch.py

任何使用我这个模板的人都可以运行这个脚本。如果输出显示CUDA可用,就证明GPU环境配置成功。

接下来,我们运行一个实际的GPU任务来测试。在 utilities 目录中,我上传了一个音频文件,它是《葛底斯堡演说》的朗诵录音。

我将使用OpenAI开源的 Whisper 工具进行自动语音识别(ASR),将其转写成文本。Whisper是一个强大的开源ASR系统,它包含编码器和解码器模块,能够完成高质量的转录和语种翻译。该模型也可以在Hugging Face上找到。

由于Whisper已经安装在系统中,我们可以直接运行以下命令进行转录:

whisper utilities/gettysburg.wav --model large

在运行这个任务的同时,我们可以打开另一个终端窗口来监控GPU的使用情况。运行命令:

nvidia-smi -l 1

这个命令会启动一个监控工具,每秒刷新一次,让我们可以看到转录过程中的GPU使用率。

当Whisper开始工作时,它会加载一个大型语言模型来处理音频文件。我们可以观察到GPU使用率会出现明显的波动和峰值,这表明GPU正在全力工作,将音频数据转换为文本格式。任务完成后,GPU的使用率会回落到零。

这个演示清楚地展示了使用GPU环境的一个核心优势:我可以无缝地与Hugging Face生态系统协同工作,直接使用各种预训练模型进行复杂的计算任务。

此外,如果我进入IPython环境,也可以直接按照Hugging Face或OpenAI提供的指导,一步步地操作和使用这些模型。

总结 📝

本节课我们一起学习了如何利用GitHub Codespaces创建和配置一个支持GPU的云端开发环境。我们涵盖了从创建模板仓库、配置开发容器(.devcontainer),到启动特定GPU机型Codespace的完整流程。我们还通过验证PyTorch的CUDA可用性和运行Whisper语音转录任务,实际测试了GPU环境的工作情况。这套方法为学习和运行需要GPU加速的机器学习项目(特别是使用Hugging Face等大型预训练模型)提供了一个强大、便捷且可复现的解决方案。

162:使用Hugging Face命令行工具 🛠️

在本节课中,我们将要学习如何使用Hugging Face的命令行界面工具。这是一个与Hugging Face平台进行交互的强大方式,尤其适合喜欢在终端中工作的开发者。

概述

Hugging Face命令行工具提供了多种功能,包括身份验证、仓库管理以及本地缓存检查等。掌握这个工具能让你更高效地使用Hugging Face生态系统。

登录与身份验证

上一节我们介绍了CLI工具的基本概念,本节中我们来看看如何进行身份验证。使用命令行工具的第一步通常是登录你的Hugging Face账户。

要登录,你需要一个访问令牌。你可以在Hugging Face网站的设置中生成此令牌。

以下是登录的具体命令:

huggingface-cli login

运行此命令后,系统会提示你输入令牌。完成此步骤后,CLI工具就能识别你的身份。

验证身份与查看信息

登录成功后,你可以验证当前登录的用户是谁。

以下是验证命令:

huggingface-cli whoami

该命令会显示你的用户名以及你所属的组织信息,例如“Duke University”。这对于在团队协作环境中确认权限非常有用。

其他常用命令

除了登录和查看身份,Hugging Face CLI还提供了其他实用命令。

以下是几个重要的子命令介绍:

  • huggingface-cli logout:此命令用于退出当前登录的账户。
  • huggingface-cli repo:此命令用于与模型和数据集的仓库进行交互,例如创建、克隆或列出仓库。
  • huggingface-cli scan-cache:此命令会扫描并列出本地机器上所有通过Hugging Face库下载的模型和数据集缓存。这对于管理磁盘空间至关重要。

扫描缓存以管理空间

在机器学习项目中,模型和数据集文件通常很大,容易占满磁盘空间。scan-cache命令可以帮助你了解本地存储了哪些文件。

运行以下命令来扫描缓存:

huggingface-cli scan-cache

命令执行后,会详细列出每个缓存项目的大小、路径和最后访问时间。你可以根据这些信息决定删除哪些不再需要的文件以释放空间。

总结

本节课中我们一起学习了Hugging Face命令行工具的核心用法。我们了解了如何通过login命令进行身份验证,使用whoami确认身份,并探索了logoutrepo等管理命令。最后,我们重点介绍了scan-cache这个在管理本地存储时非常有用的工具。请确保你拥有有效的令牌并完成了身份验证,这样才能充分利用CLI与Hugging Face Hub进行交互。

163:使用模型中心

在本节课中,我们将学习 Hugging Face 模型中心(Model Hub)的核心功能与使用方法。模型中心不仅包含预训练模型,还集成了数据集(Datasets)和应用演示空间(Spaces),是一个一站式的机器学习资源平台。我们将逐一探索这些组件,了解如何查找、筛选、测试模型,以及如何利用数据集和交互式应用。

模型(Models)概览与筛选

首先,我们对模型中心进行快速概览。它提供的功能远不止我们之前看到的模型、数据和空间。我们已经介绍过其中一些,现在再整体回顾一下 Hugging Face 提供的资源。我们从“模型”部分开始。

在模型页面左侧,您会看到几个筛选部分:任务(Tasks)库(Library)数据(Datas)语言(Languages)。这些都是标签或分类,可以帮助您精确筛选出想要使用的模型。

例如,如果我进入“语言”部分,选择“西班牙语”,页面上的所有模型就会立即被筛选,只显示支持西班牙语的模型。这是一个非常实用的功能。您可以继续叠加筛选条件,比如再选择“文本摘要(Summarization)”。现在,筛选条件就变成了“西班牙语”和“文本摘要”,页面将只显示同时满足这两个条件的模型,例如“mrm8488/bert2bert_shared-spanish-finetuned-summarization”。点击筛选标签旁的“X”可以取消该条件,恢复显示所有适用于“文本摘要”的模型。

模型详情页与交互

接下来,点击任意一个模型进入其详情页。我们已经初步了解过模型卡片(Model Card),它允许创建者通过 README 文件详细描述模型,就像 GitHub 仓库一样。一些模型还提供了“托管推理 API(Hosted Inference API)”,允许用户直接在线与模型交互。

例如,在这个摘要模型页面,我们可以看到一个交互窗口。输入文本后点击“Compute”,就能立即看到模型的摘要结果。响应速度很快,可能是因为结果已被缓存。

此外,您还可以部署这些模型。部署选项包括使用 Amazon SageMaker,或者在您自己的账户上使用 推理 API

另一个重要功能是代码示例。页面提供了 Transformers 库的使用代码片段,您可以复制粘贴到自己的项目中进行推理。如果您想克隆模型仓库,请记住,Hugging Face 的模型通常需要 Git LFS 支持,请确保已启用。


探索数据集(Datasets)

除了模型,模型中心还提供数据集。我们已经接触过一些,现在来看看数据集页面有趣的任务分类。

例如,在“文本生成”任务类别下,我们搜索“wiki text”数据集。数据集页面提供“数据预览(Data Preview)”功能,并且能够按训练集(train)测试集(test)验证集(validation)进行划分,这非常实用,因为您通常需要不同的数据子集进行训练、测试和验证。

在后续更动手的示例中,我们将介绍如何通过 Python 的 datasets 库来加载并使用这些特定的数据划分,甚至创建数据子集。

让我们看一下“代码(Code)”和“数据浏览器(Data Viewer)”部分。这里提供了许多代码片段,帮助您了解如何加载和查看数据。查看“训练”分片,这里的信息更为详尽,让您对数据有一个直观的感受。页面还展示了不同的数据子集类型(例如“raw v1”)。

就像 GitHub 仓库一样,您可以浏览文件的提交历史。数据集页面通常包含 READMEdataset_infos.json 等文件。查看 dataset_infos.json 文件,可以看到数据集的描述信息,这是 Hugging Face 在后台用于优化展示的数据。此外,还有一个 Python 文件(例如 wiki_text.py),它定义了 datasets 库中用于加载该数据集的类。从这里,您可以了解到支持的语言、数据来源等信息,查看数据来源总是一个好习惯。

应用演示空间(Spaces)

最后,我们来看“空间(Spaces)”。我们已经见过一些例子。空间允许您轻松构建和分享交互式机器学习应用。

例如,有些空间用于演示“Bleu 评分”,有些则提供更交互式的体验,比如音乐生成。您可以像我们之前看到的那样,非常轻松地构建这类应用。


总结

本节课中,我们一起深入探索了 Hugging Face 模型中心。Hugging Face Hub 指的就是模型、数据集和空间这些组件协同工作,为您提供的一站式服务平台。通过它,您可以:

  • 体验演示:在线与模型交互。
  • 进行交互:使用托管 API 或复制代码到本地运行。
  • 做出贡献:上传自己的模型、数据集或应用。
  • 复用资源:充分利用平台上丰富的现有资源。

简而言之,Hugging Face Hub 极大地简化了机器学习资源的发现、测试和集成过程。

164:从Hugging Face下载模型的三种方法 🚀

在本节课中,我们将学习如何从Hugging Face平台下载预训练模型。我们将介绍三种不同的下载方法,从最常用的动态加载到手动下载模型文件,帮助你理解在不同场景下如何灵活获取和使用模型。

概述

Hugging Face是一个流行的机器学习模型库和社区。通常,我们希望以动态方式加载模型,这是Hugging Face库的核心特性。首先,我们需要安装并导入必要的库。

# 安装transformers库
# pip install transformers

# 导入pipeline
from transformers import pipeline

方法一:使用Pipeline动态下载与加载 🔄

上一节我们安装了必要的库,本节中我们来看看如何使用pipeline抽象层来动态下载和加载模型。pipeline是Hugging Face提供的一个通用抽象,它简化了模型的使用过程。

以下是使用pipeline进行文本摘要任务的步骤:

  1. 指定任务类型为summarization
  2. 指定要使用的模型,例如t5-small
  3. 设置其他参数,如truncation=True和框架framework=“tensorflow”
summarizer = pipeline(task=“summarization”, model=“t5-small”, truncation=True, framework=“tensorflow”)

执行这行代码时,Hugging Face会在后台自动将指定的t5-small模型下载到本地缓存中。下载完成后,我们可以直接使用这个summarizer对象来处理文本。

例如,我们可以对一个描述MLflow的文本进行摘要:

with open(‘mlflow_text.txt’, ‘r’) as file:
    text_to_summarize = file.read()

summary = summarizer(text_to_summarize)
print(summary)

这种方法的好处是简单快捷,模型在需要时自动下载,非常适合开发和实验。在构建容器化应用时,这种方式可以实现模型的动态加载,避免将大型模型直接打包进容器,从而节省存储空间。

方法二:使用huggingface_hub下载特定文件 📥

虽然动态加载很方便,但有时我们可能需要将模型文件明确下载到本地进行查看或离线使用。这时,我们可以使用huggingface_hub库来下载仓库中的特定文件。

首先,确保安装了该库:

# pip install huggingface_hub

以下是下载模型文件的核心步骤:

  1. 从Hugging Face网站找到目标模型的仓库ID(Repo ID)和想要下载的具体文件名。
  2. 使用hf_hub_download函数并传入仓库ID和文件名。

例如,我们要下载t5-small模型的TensorFlow权重文件(tf_model.h5):

from huggingface_hub import hf_hub_download

model_path = hf_hub_download(repo_id=“t5-small”, filename=“tf_model.h5”)
print(f“模型已下载到:{model_path}”)

运行后,文件会被下载到Hugging Face的本地缓存目录(例如~/.cache/huggingface/hub)。再次运行相同的下载命令时,库会直接使用缓存的文件,而无需重新下载。这种方式让你能精确控制下载哪个文件,并获取其在本地磁盘上的路径。

方法三:使用Git和Git LFS克隆仓库 🛠️

最后一种方法是将整个模型仓库视为一个代码仓库,使用Git和Git LFS(大文件存储)工具进行克隆。这对于需要获取仓库内所有文件,或者希望以版本控制方式管理模型的场景非常有用。

以下是操作步骤:

  1. 安装Git LFS:确保你的系统已安装并初始化了Git LFS。
  2. 获取模型URL:在Hugging Face模型页面的“Files”选项卡旁,可以找到用于克隆的仓库地址。
  3. 执行克隆命令:在终端中使用git clone命令。

例如,克隆bert-base-uncased模型仓库:

git clone https://huggingface.co/bert-base-uncased

这样,你就会在本地获得一个包含该模型所有配置、权重和说明文件的文件夹。这种方法最彻底,让你能完全访问仓库的所有内容。

总结

本节课中我们一起学习了从Hugging Face下载模型的三种主要方法:

  1. 使用pipeline动态加载:最简单直接,适合大多数开发场景,实现按需下载。
  2. 使用huggingface_hub下载文件:更灵活,可以下载特定模型文件并获取本地路径,便于离线使用或集成。
  3. 使用Git LFS克隆仓库:最彻底的方式,获取模型的完整仓库,适合需要全部文件或进行版本管理的场景。

你可以根据实际需求,如网络环境、存储限制和自动化流程的要求,选择最合适的方法来获取和使用Hugging Face上的强大模型。

165:模型操作实践 🚀

在本节课中,我们将学习如何实际操作Hugging Face生态系统中的模型。我们将涵盖从探索和使用模型,到下载、本地保存,再到上传自定义模型的完整流程。通过具体的代码示例,你将了解如何将预训练模型集成到自己的应用中。


探索与使用模型

上一节我们介绍了MLOps的基本概念,本节中我们来看看如何与Hugging Face平台上的海量模型进行交互。Hugging Face不仅是一个模型仓库,更提供了一系列交互式工作流。

以下是开始使用Hugging Face模型的几种主要方式:

  1. 在线体验:访问Hugging Face网站,浏览数十万个模型,并直接在平台上托管的Spaces应用中试用。这是初步探索模型功能的最佳起点。
  2. 在GPU环境中运行:为了获得更好的性能,可以在支持GPU的环境中运行模型,例如GitHub Codespaces。这能显著加速模型推理过程。
  3. 集成到开发工具:可以将模型集成到如Chamelaen等工具链中,利用GPU加速。
  4. 构建应用:通过FastAPI或Gradio等框架构建应用程序,并部署支持GPU的模型服务。

现在,让我们进入实践环节。首先,建议访问Hugging Face,根据下载量或点赞数筛选出热门模型进行试用。例如,Google的Pegasus模型可以用于文本摘要任务。

在模型页面的交互界面中,你可以直接输入文本进行测试。例如,输入一段长文本,模型会将其摘要为一句话。这是验证模型是否满足需求的第一步。


在代码中集成模型

在界面中试用模型后,下一步是将其集成到自己的代码中。我们可以在GitHub Codespace中创建一个项目来实现。

以下是一个使用Hugging Face模型摘要维基百科页面的代码示例。我们使用wikipedia库获取页面内容,然后用Hugging Face的pipeline进行处理。

from transformers import pipeline
import wikipedia

# 1. 获取维基百科页面内容
page = wikipedia.page("Python programming")
text = page.content

# 2. 创建摘要pipeline
summarizer = pipeline("summarization", model="google/pegasus-xsum")

# 3. 生成摘要
summary = summarizer(text, max_length=50, min_length=25, do_sample=False)
print(summary[0]['summary_text'])

这段代码首先获取“Python programming”维基百科页面的全部文本,然后使用Pegasus模型生成一个简洁的摘要。通过调整max_lengthmin_length参数,可以控制摘要的长度。

此外,通过代码可以灵活地切换不同的预训练模型,只需更改pipeline函数中的model参数即可。


下载与本地保存模型

为了提升推理速度并确保版本一致性,我们经常需要将模型下载并保存到本地。

在下载模型时,固定修订版本非常重要。这能确保你每次获取的都是完全相同的模型版本。对于大型模型(如5GB),本地保存可以避免重复下载。

以下是下载并保存模型的代码:

from transformers import pipeline, AutoModelForSeq2SeqLM, AutoTokenizer

model_name = "google/pegasus-xsum"
revision = "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1" # 示例修订号

# 下载并保存模型与分词器
model = AutoModelForSeq2SeqLM.from_pretrained(model_name, revision=revision)
tokenizer = AutoTokenizer.from_pretrained(model_name, revision=revision)

save_directory = "./my_pegasus_model"
model.save_pretrained(save_directory)
tokenizer.save_pretrained(save_directory)
print(f"模型已保存至: {save_directory}")

下载后,你可以直接加载本地模型进行推理,速度会快很多:

from transformers import pipeline

# 从本地目录加载模型
summarizer = pipeline("summarization", model="./my_pegasus_model")

# 读取一个文本文件(例如葛底斯堡演说)
with open("gettysburg.txt", "r") as f:
    text = f.read()

summary = summarizer(text, max_length=30, min_length=15)
print(summary[0]['summary_text'])

上传自定义模型

最后,我们学习如何将自己的模型上传到Hugging Face平台,与他人分享或用于部署。

上传过程非常简单:

  1. 准备好你的模型文件(例如一个.joblib.pkl文件)。
  2. 登录Hugging Face,进入你的个人主页。
  3. 点击“Models”,然后选择“Upload a model”。
  4. 填写模型信息,并上传模型文件。

例如,如果你有一个训练好的Scikit-learn模型保存为model.joblib,可以直接将其拖入上传界面。平台会自动识别文件类型,并为你创建模型仓库。之后,你可以添加模型卡(README)来描述模型用途、训练数据和使用方法。


总结

本节课中我们一起学习了Hugging Face模型生态的实践操作。我们从探索和在线试用模型开始,了解了如何筛选合适的模型。接着,我们学习了如何在自己的代码中集成模型,并运行了一个摘要维基百科页面的实例。然后,我们探讨了下载和本地保存模型的重要性,包括如何固定版本以保障可复现性,以及如何加载本地模型加速推理。最后,我们介绍了如何上传自定义模型到Hugging Face平台。

根据你的具体需求——是直接使用模型、下载到本地、上传自己的成果,还是进行微调训练——Hugging Face都提供了相应的工具和接口来支持你的机器学习运维流程。

166:在Hugging Face添加数据集 📊

在本节课中,我们将学习如何在Hugging Face平台上创建并上传自己的数据集。你将了解通过网页界面操作的完整流程,并最终学会如何在代码中加载和使用这个数据集。

概述

Hugging Face不仅是一个模型库,也是一个强大的数据集托管平台。掌握如何添加和管理数据集,是构建机器学习工作流的重要环节。本节将引导你完成从创建数据仓库到在代码中加载数据的全过程。

准备工作

在开始之前,你需要确保已经拥有一个Hugging Face账户并成功登录。登录后,你的个人资料会显示在页面右上角。这是后续所有操作的基础。

创建数据集仓库

首先,点击页面右上角的个人头像,在下拉菜单中选择“New dataset”来创建一个新的数据集仓库。

虽然这里创建的是“数据仓库”,但其底层仍然是一个Git仓库,你将通过上传文件的方式来添加数据。

以下是创建新数据集时需要填写的关键信息:

  • 数据集名称:例如,我们可以命名为 temporary-data
  • 许可证:你可以选择任何你偏好或熟悉的开源许可证,例如 Apache 2.0

填写完毕后,点击“Create dataset”按钮。当然,这个操作也可以通过命令行工具来完成。

上传数据文件

创建成功后,页面会跳转到新数据集的仓库。初始状态下,仓库里只有Git属性和一个基础的README文件。

此时,你可以通过上传文件的方式添加数据。点击“Files”选项卡,然后点击“Add file”按钮,选择“Upload file”。

你可以直接将一个CSV文件拖拽到上传区域,或点击按钮浏览选择。我们以名为 test.csv 的逗号分隔值文件为例。上传文件后,系统会要求你提交这次更改。使用默认的提交信息即可,点击“Commit changes”完成提交。

查看与使用数据集

文件提交后,数据集预览功能会自动激活。你可以直接在网页上查看数据的结构和前几行内容。

更重要的是,Hugging Face为你的数据集生成了访问API。你可以通过curl命令获取整个数据集,或查看其数据划分(splits)。本质上,这为你提供了多种访问数据的方式。

此外,由于数据集底层是Git仓库,你也可以直接克隆它。更常见的是使用Hugging Face的 datasets 库来交互。

在代码中加载数据集

上一节我们介绍了如何在网页上创建和查看数据集,本节我们来看看如何在Python代码中加载并使用它。

确保你已经安装了 datasets 库。然后,你可以在Jupyter Notebook或任何Python环境中按以下步骤操作。

以下是加载并使用数据集的代码示例:

# 从Hugging Face加载我们刚刚上传的数据集
# 格式为:`load_dataset(“你的用户名/数据集名称”)`
from datasets import load_dataset

data = load_dataset("你的用户名/temporary-data")

# 探索加载的数据对象
print(data)

# 数据集通常以字典形式组织,键名对应数据划分(如‘train‘, ‘test‘)
# 获取‘test‘划分并转换为pandas DataFrame以便查看和分析
test_data = data[‘test‘].to_pandas()
print(test_data.head())

运行代码后,datasets库会从Hugging Face获取数据并进行缓存。随后,你就可以像操作普通的Pandas DataFrame一样,对数据进行探索和分析。

总结

本节课中,我们一起学习了在Hugging Face平台添加数据集的完整流程。我们首先通过网页界面创建了一个新的数据集仓库,然后上传了一个CSV文件。最后,我们学会了如何在Python代码中使用 datasets 库来加载和操作这个远程数据集。除了网页界面,你还可以通过Git命令或Hugging Face CLI工具来完成这些操作,这为集成到自动化流程中提供了便利。

167:使用Hugging Face数据集

在本节课中,我们将学习如何在Hugging Face平台上使用和管理数据集。我们将了解如何上传包含不同数据分割(如训练集、验证集和测试集)的数据集,以及如何通过自定义加载脚本来增强数据集的功能。

概述

上一节我们介绍了如何将CSV文件直接上传到Hugging Face。本节中,我们将进一步探索如何通过添加自定义文件来增强数据集的功能,特别是如何创建和管理数据分割。

添加数据分割

我们已经知道如何将CSV文件添加到Hugging Face,并通过datasets仓库或UI界面来访问它。现在,我们将展示一种略有不同的方法:添加自定义文件。这些文件对于CSV(制表符分隔值)文件是可选的,甚至对于JSON文件,你也可以直接通过UI添加。但这里,我将展示一些额外的、可以实现的功能。

我已经上传了相同的葡萄酒评分数据,但这次包含了不同的数据分割。数据分割允许你访问同一数据集的不同子集,这样用户无需手动分割数据,就能更方便地获取所需部分。由于我添加了一些支持文件,你现在可以看到数据集有了分割选项。

如果我点击这里,可以看到有“test”(测试集)和“validation”(验证集)。而“train”(训练集)——我在这里滚动一下——虽然只显示前10行,但实际上包含了大约两三千行数据。如果我将视图切换到“test”,它将只显示几百行数据(大约是200行)。注意,测试集没有ID列,这可能会带来一些问题,但这种情况确实存在,这也正是数据分割有用的原因。

同样,如果我们在这里列出该数据集的分割名称,就能看到具体有哪些分割,并且可以获取特定的分割。你甚至可以看到,如果使用curl命令,默认获取的将是测试集。如果你不想要测试集,而是想要完整的训练集,那么对应的就是这个文件。

自定义文件详解

那么,具体如何操作呢?让我展示几个可以添加的文件。再次强调,这些都是可选的。

首先,你会注意到训练集文件大小为13MB,并且带有LF(大文件存储)图标。这意味着如果你在命令行工具中添加此文件,需要启用Git LFS。如果点击这里,它会下载文件。我们不想再次下载。如果你在命令行工具中操作,需要运行git lfs install来安装一些预提交和预推送钩子,以确保Git LFS正常工作。如果不这样做,可能会遇到问题。不过别担心,如果你操作正确,终端上会显示相应的输出。

这里有几个关键文件,让我先展示wine_ratings.py文件。

这个文件是一个示例,你可以用它来获取数据的一些具体信息。这是我本人在2022年创建的。它包含一个简短的描述和一个主页链接,这些信息其实也可以通过UI添加。但接下来,我们开始深入这个数据的具体细节。

我在这里添加了版本信息,这会被UI捕获。我们还可以定义数据的特征,也就是我们有哪些列。你可以看到这里有nameregion,并且我指定rating是浮点型,其他都是字符串类型。然后,我们继续填充信息,最后返回一个包含所有这些信息的DatasetInfo对象。

接着,我们来看分割生成器。分割生成器用于定义我们希望通过API向任何下载此数据集的用户提供哪些特定的分割。你可以看到这里有trainvalidationtest分割,这非常常见。Hugging Face为创建这些数据集的可选文件提供了模板,其中预设了这些参数,所以你无需记住所有语法。当然,你也可以随时参考这个wine_ratings.py文件来快速复习如何操作。最后,如果需要,你还可以从数据中生成示例。

文件路径的重要性

让我们回到文件列表,看看为什么这些文件路径很重要。在文件列表中,我们应该能看到一个测试集文件。没错,还有训练集和验证集的CSV文件。训练集是主要的、完整的、大的CSV文件。但为什么这些文件会在这里?因为当你拥有CSV文件时,Hugging Face允许你上传它们。但这些数据也可以存放在其他地方,这时你可能就需要考虑使用一个可选的加载文件。

一个不托管在Hugging Face上的文件需要一个加载器。加载器会指向数据源。让我用另一个数据集“blimp”来举例说明。如果我们点击这个数据集,有一个完美的数据集预览。让我们看看它的文件。文件列表里没有实际数据,只有一个“dummy”文件。但如果我们查看blimp.py这个加载器文件,看看它的URL是什么。

你可以看到下载URL指向GitHub。这个加载器知道如何通过这些URL获取数据,并通过Hugging Face提供,这是一种非常巧妙的数据服务方式。你还可以在这里看到特征定义,也就是实际的列名。然后,我们进入生成示例的部分,这和我之前展示的非常相似。在分割生成器中,你会看到它使用了URL。这里定义了下载URL和资源位置,以便访问它们。

回到葡萄酒评分数据集,我们现在已经解释了这些CSV文件的作用,以及这个加载文件的作用。README文件包含一些信息,称为数据集卡片,是人们如何使用你数据的文档。这个数据集的信息还不够完善。最后是dataset_inf.json文件,这同样是完全可选的。它包含了描述、引用等信息,这些内容实际上是从wine_ratings.py文件中的类和info等信息生成的。

如果你还记得,这个数据集有不同的分割,我们实际上可以在那里进行一些操作。你可以在代码库中使用这些数据。这个例子很好,因为它包含了一切。你可以克隆这个仓库,但请记住,你必须安装Git LFS(就是这里显示的这个),以确保一切正常。但如果你不想把所有超大的文件都下载到电脑上,也可以选择不这样做。

我们将复制这里的代码,然后转到Jupyter笔记本,看看如何操作。

在代码中使用数据集

我们现在在Jupyter笔记本中。我将粘贴Hugging Face建议我们执行的代码,然后运行它。当我们查看这个数据集对象时,会发现它找到了缓存数据,所以无需再次下载任何东西。运行这段代码会非常快,因为数据已经下载过了。

让我们探索一下这个数据对象,看看它返回什么。和往常一样,它将返回一个数据字典。这个字典包含了分割:traintestvalidation。你可以看到测试集有200行,而主要的训练集有3200行(实际上是约32000行),这是完整的数据集。特征包括nameregionvarietyrating

你完全可以创建一个自定义配置,只包含特定的列,例如只包含regionrating。你通过这个配置来发布这些数据。

例如,假设我们只想要测试集。我们获取测试集,使用自动补全功能,然后我们可以说:

test_dataset = dataset[‘test’]

接着,我们将其转换为Pandas DataFrame。我将调用它,并将其赋值给df变量。

运行这段代码,一切正常。现在我们可以调用df.describe()来看看这个数据的情况。你可以看到确实有200行,评分列有一些数值。通常评分范围从85到100,但这个数据中最高只到99。

总结

本节课中,我们一起学习了在Hugging Face上处理数据集的具体细节。我们看到了之前非常简单的操作,而现在这是一个稍微进阶的步骤,使你能够通过自定义加载文件与不同的数据分割进行交互。你现在应该知道如何利用数据分割和增强功能来更有效地管理和使用Hugging Face上的数据集了。

168:Hugging Face数据集操作实践 🗂️

在本节课中,我们将学习如何在Hugging Face平台上操作数据集。我们将涵盖浏览现有数据集、上传自定义数据集以及通过代码与数据集进行交互等核心操作。

浏览Hugging Face数据集

Hugging Face Hub是机器学习工作的重要资源库,数据集是其中的核心原材料之一。

以下是浏览和筛选数据集的方法:

  • 访问Hugging Face的“Datasets”界面。
  • 使用筛选功能,例如按“Most Likes”(最多点赞)进行排序。
  • 例如,“Wikipedia”数据集是一个非常有用的资源,它包含了所有语言的清理后文章,源自维基百科的转储文件。用户可以获取特定日期的完整数据,或提取部分数据用于特定任务。

另一个流行的数据集是“GLUE”。在数据集查看器中,可以清晰地看到其专为机器学习设计的结构。通过“Split”选项,用户可以获取验证集、测试集或数据的子集,这些数据可以直接用于微调任务。

上传自定义数据集

上一节我们介绍了如何浏览现有数据集,本节中我们来看看如何上传自己的数据到Hugging Face平台。

上传自定义数据的过程非常直接。

以下是上传自定义数据集的步骤:

  1. 在个人资料页面,点击“New dataset”(新建数据集)。
  2. 为数据集命名,例如“NBA data”。
  3. 点击“Create dataset”(创建数据集)。
  4. 进入数据集页面后,在“Files”选项卡下点击“Add file”(添加文件)。
  5. 从本地选择文件(例如一个CSV文件)并上传。

上传完成后,数据会立即可用。你可以通过“Dataset viewer”(数据集查看器)预览数据,也可以通过API调用将其拉取到本地项目中使用。

通过代码与数据集交互

我们已经了解了如何浏览和上传数据集,接下来看看如何通过编程方式与这些数据集进行交互。

上传数据集后,页面会提供该数据集的API调用信息。例如,可以使用curl命令直接获取数据。

更常用的方式是通过Hugging Face的datasets库来加载数据。核心代码如下:

from datasets import load_dataset

dataset = load_dataset("socialpower/nba-data")
print(dataset.features)
print(dataset[0])

运行上述代码,程序会从Hugging Face拉取指定的数据集,并打印出数据特征和第一条记录。

交互式探索与工具

加载数据到变量后,有几种有效的方式进行交互式探索。

以下是推荐的交互方式:

  • 使用IPython:在交互式环境中加载数据,便于逐条查看和探索。例如,执行dataset[1]可以获取第二条记录。
  • 使用命令行工具库:例如使用click库构建自定义的命令行工具来操作数据。
  • 返回Web界面:始终可以回到Hugging Face网站的数据集卡片页面,查看数据详情并复制API调用命令。

本节课中我们一起学习了Hugging Face数据集的核心操作:从浏览和筛选平台上的优质数据集,到上传和管理自己的自定义数据,最后通过代码和交互式工具有效地加载与探索数据集。这些技能是构建机器学习工作流的重要基础。

169:Hugging Face与FastAPI集成 🚀

在本节课中,我们将学习如何将Hugging Face的预训练模型与FastAPI框架结合,创建一个能够通过HTTP接口提供服务的机器学习API。我们将通过一个简单的文本生成示例,了解整个集成过程的核心步骤。


概述

我们将创建一个Web应用,其核心功能是接收一段文本输入,使用Hugging Face的GPT-2模型生成后续文本,并通过FastAPI提供的API端点返回结果。整个过程涉及模型加载、API定义和请求处理。


代码结构解析

首先,我们来看一下项目的主要目录和文件。为了简化,我们专注于 web_app 目录下的一个文件:main.py。这个文件包含了集成Hugging Face与FastAPI的所有必要代码。

导入必要的库

我们首先需要导入项目依赖的各个模块。

from transformers import pipeline
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
  • pipeline 来自 transformers 库,它提供了一个高级抽象,让我们能够轻松使用各种预训练模型,而无需关心不同模型背后的复杂细节。
  • FastAPI 用于创建我们的Web应用框架。
  • HTMLResponse 允许我们返回HTML内容(用于简单的根路径响应)。
  • BaseModel 来自 pydantic,用于定义API请求体的数据模式,确保输入数据的类型安全。

初始化模型与FastAPI应用

导入库之后,我们需要初始化文本生成器和FastAPI应用实例。

generator = pipeline('text-generation', model='gpt2')
app = FastAPI()
  • generator = pipeline('text-generation', model='gpt2'):这行代码创建了一个文本生成管道。它会动态下载Hugging Face上的GPT-2模型。pipeline 函数封装了模型加载、预处理和后处理的所有步骤。
  • app = FastAPI():这行代码实例化了我们的FastAPI应用。

定义请求数据模型

为了规范API的输入,我们需要定义一个数据模型来描述客户端应发送的JSON数据结构。

class TextRequest(BaseModel):
    text: str

这里定义了一个 TextRequest 类,它继承自 BaseModel。它只有一个字段 text,类型为字符串 (str)。这表示我们的API端点期望接收一个JSON对象,其中包含一个名为 text 的键。

创建API端点

现在,我们可以开始定义具体的API端点了。我们的应用将有两个端点:一个根路径 / 用于提供简单的前端界面,另一个 /generate 用于处理文本生成请求。

根路径端点

首先,我们定义一个访问应用根路径时触发的端点。

@app.get("/")
async def root():
    return HTMLResponse("""
    <html>
        <body>
            <form action="/generate" method="post">
                <input type="text" name="text" value="Once upon a time">
                <input type="submit" value="Generate">
            </form>
        </body>
    </html>
    """)
  • @app.get("/") 是一个装饰器,它将下面的函数 root 注册为处理 GET 请求到 / 路径的路由。
  • 该函数返回一个 HTMLResponse,其中包含一个非常简单的HTML表单。用户可以通过这个表单输入文本并提交到 /generate 端点。

文本生成端点

接下来,我们定义核心的文本生成端点。

@app.post("/generate")
async def generate(request: TextRequest):
    results = generator(request.text)
    return results[0]
  • @app.post("/generate") 装饰器将函数 generate 注册为处理 POST 请求到 /generate 路径的路由。
  • request: TextRequest 参数声明了这个端点期望接收的数据格式,即我们之前定义的 TextRequest 模型。FastAPI会自动验证传入的JSON数据并将其转换为 TextRequest 对象。
  • results = generator(request.text):这行代码使用加载好的GPT-2生成器,对请求中的 text 字段进行文本生成。
  • return results[0]generator 返回的是一个列表,其中包含生成的文本序列。这里我们返回列表中的第一个(也是通常唯一的一个)结果。

项目依赖

为了运行这个应用,我们需要确保环境中安装了正确的依赖包。这些依赖通常列在一个 requirements.txt 文件中。

以下是核心依赖:

  • transformers:Hugging Face的库,用于加载和使用预训练模型。
  • torchtensorflow:深度学习框架。transformers 库需要其中之一作为后端来运行模型。示例中使用了TensorFlow。
  • fastapi:用于构建API的Web框架。
  • uvicorn:一个轻量级的ASGI服务器,是运行FastAPI应用的推荐选择。

一个示例的 requirements.txt 文件内容如下:

transformers
tensorflow
fastapi
uvicorn

总结

本节课中,我们一起学习了如何将Hugging Face的机器学习模型与FastAPI框架进行集成。我们通过创建一个文本生成API,详细讲解了从导入库、初始化模型、定义数据模式到创建API端点的完整流程。这种模式可以扩展到其他类型的模型(如文本分类、问答等),为部署机器学习服务提供了一个简洁而强大的基础。

170:Hugging Face模型容器化教程 🐳

在本节课中,我们将学习如何将基于Hugging Face和FastAPI构建的机器学习Web应用进行容器化。我们将重点解析Dockerfile的配置,理解如何将应用及其依赖打包到容器中,并确保其能够顺利运行。


概述

上一节我们快速了解了Hugging Face与FastAPI结合的基本工作流程。本节中,我们将具体探讨如何将这样的应用容器化。我们将详细分析Dockerfile的每一部分,并解释相关依赖的选择,以确保构建出的容器镜像能够稳定运行。

Dockerfile解析

Dockerfile是一个仅13行的配置文件,它指导Docker如何构建容器镜像。如果你熟悉Docker,这会非常直观;如果不熟悉,可以将其理解为一个构建清单。

以下是构建步骤的分解:

  1. 选择基础镜像
    我们使用 python:3.8 作为基础镜像。选择此版本的原因将在查看 requirements.txt 文件时说明。

  2. 设置工作目录
    通过 WORKDIR /webapp 命令,将容器内的工作目录设置为 /webapp

  3. 安装依赖
    接下来,我们执行 RUN pip install -r requirements.txt 来安装所有Python依赖包。

  4. 复制应用代码
    使用 COPY . /webapp 命令,将本地Web应用的所有内容复制到容器内的 /webapp 目录中。

  5. 定义启动命令
    最后,我们通过 ENTRYPOINT 指定容器启动时的可执行文件为 uvicorn。这是用于服务FastAPI应用的Python服务器命令行工具。启动命令为:

    uvicorn main:app --host 0.0.0.0
    

    这表示启动应用,并绑定到所有网络地址。

依赖管理 (requirements.txt)

现在,我们来看看为什么选择Python 3.8。关键在于 requirements.txt 文件中的依赖项。

以下是关键依赖示例:

transformers==4.15.0
torch==1.9.0
fastapi==0.70.0
uvicorn==0.15.0
tensorflow==2.7.0

TensorFlow等库与特定Python版本的兼容性至关重要。在本例中,Python 3.8被验证能与所列的TensorFlow版本稳定协作。作为工程师(无论是数据工程师、MLOps工程师还是机器学习工程师),处理依赖关系是核心任务之一,你需要找到并确定能够协同工作的版本组合,以确保打包的应用能够顺利运行。

总结

本节课中,我们一起学习了如何将Hugging Face模型与FastAPI Web应用进行容器化。我们解析了Dockerfile的各个组成部分,从基础镜像选择、依赖安装到应用代码复制和启动命令定义。同时,我们也探讨了依赖管理的重要性,特别是Python版本与特定库(如TensorFlow)的兼容性问题。通过这种方式,你可以将机器学习应用可靠地打包和部署。

171:使用FastAPI运行Hugging Face模型 🚀

在本节课中,我们将学习如何将一个基于FastAPI和Hugging Face模型构建的Web应用进行容器化。我们将从在本地环境中运行和验证应用开始,然后使用Docker构建容器镜像,并最终在容器中运行该应用,确保其功能与本地环境一致。


本地运行与验证 🔍

上一节我们介绍了使用FastAPI构建Hugging Face模型应用的基本组件。本节中,我们来看看如何在本地运行这个应用,这是容器化之前的关键验证步骤。

在构建容器之前,首先需要在本地环境中运行应用,以确保所有功能正常工作。如果本地运行失败,容器化后也无法正常工作。

以下是具体的操作步骤:

  1. 创建并激活虚拟环境:使用Python的venv模块创建一个隔离的Python环境。

    python3.8 -m venv venv
    source venv/bin/activate  # 在Windows上使用 `venv\Scripts\activate`
    
  2. 安装依赖:根据requirements.txt文件安装所有必要的Python包。

    pip install -r requirements.txt
    
  3. 验证Uvicorn可访问:确保用于运行FastAPI应用的Uvicorn服务器已正确安装。

    which uvicorn
    
  4. 运行应用:进入应用目录并使用Uvicorn启动FastAPI应用。--host 0.0.0.0参数允许从任何地址访问。

    cd web_app
    uvicorn --host 0.0.0.0 main:app
    

    应用默认运行在8000端口。启动后,Hugging Face会下载所需的模型。

  5. 测试API:在浏览器中打开http://localhost:8000/docs,访问FastAPI自动生成的交互式API文档(基于Swagger UI)。在这里可以测试文本生成端点,例如向模型发送一个提示并查看其生成的响应。

完成本地测试后,使用Ctrl+C停止本地服务器。


构建Docker容器 🐳

在确认应用可以在本地正常运行后,下一步是将其打包到Docker容器中,以实现环境一致性和便捷部署。

首先,确保Docker已安装在你的系统上。然后,在包含Dockerfile的目录中执行构建命令。

以下是构建和运行容器的命令:

  1. 构建镜像:使用docker build命令,指定一个标签(如huggingface:local)来命名镜像,并使用.指定当前目录为构建上下文。

    docker build -t huggingface:local .
    

    该命令会依据Dockerfile中的指令,逐层构建镜像,包括安装系统依赖、复制代码和安装Python包。

  2. 运行容器:使用docker run命令启动容器。-p 8000:8000参数将容器的8000端口映射到主机的8000端口,-it参数允许交互式运行。

    docker run -it -p 8000:8000 huggingface:local
    

    容器启动后,应用会开始运行。初次运行时,容器内部需要重新下载Hugging Face模型。

  3. 验证容器化应用:在浏览器中再次访问http://localhost:8000/docs。如果看到API文档页面,说明容器化应用已成功启动。你可以像在本地一样,通过Swagger UI测试文本生成功能。


总结 📝

本节课中我们一起学习了将FastAPI与Hugging Face模型结合的应用进行容器化的完整流程。

我们首先在本地创建虚拟环境、安装依赖并运行应用,验证了核心功能的正确性。接着,我们使用Docker命令构建了容器镜像,并通过端口映射在容器中运行了该应用,最终确认了容器化版本与本地版本功能一致。

这个过程涵盖了从开发环境验证到生产环境部署准备的关键步骤,是机器学习模型服务化(Model Serving)中一项重要的实践技能。

172:使用GitHub Actions实现CI/CD容器化打包 📦

在本节课中,我们将学习如何利用GitHub Actions自动化机器学习模型的容器化打包与发布流程。我们将从一个已容器化的Hugging Face模型仓库出发,实现一个完整的持续集成与持续部署(CI/CD)流水线。


概述

上一节我们介绍了如何使用Docker和FastAPI将机器学习模型容器化。本节中,我们来看看如何将构建和推送容器镜像的步骤自动化,从而无需手动执行这些重复性任务。我们将使用GitHub Actions来实现这一目标。

创建GitHub Actions工作流

GitHub Actions允许你在代码仓库中直接定义自动化的工作流。以下是创建一个自动化构建和推送Docker镜像工作流的步骤。

首先,在GitHub仓库中点击“Actions”选项卡,然后选择“New workflow”。你可以搜索并使用预置的工作流模板。

例如,你可以搜索“publish Docker container”并选择一个合适的模板。这些模板已经为你配置好了大部分必要的步骤。

以下是一个我创建的基础工作流示例,它非常简单直接,适合作为你自动化流程的起点:

name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Convert repository name to lowercase
        run: |
          echo "REPO_NAME=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV

      - name: Build and push Docker image
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: |
            ghcr.io/${{ env.REPO_NAME }}:${{ github.sha }}

工作流步骤详解

以下是上述工作流中每个步骤的详细说明:

  1. 触发条件:工作流会在代码推送到main分支、创建拉取请求到main分支,或通过workflow_dispatch手动触发时运行。
  2. 检出代码:第一步总是将仓库的最新代码检出到运行环境中。
  3. 设置Docker构建环境:此步骤配置了Docker Buildx工具,用于构建镜像。
  4. 登录容器注册表:此步骤使用GitHub Actions内置的GITHUB_TOKEN自动认证到GitHub容器注册表(GHCR)。
  5. 规范化仓库名称:容器镜像名称必须为小写。此步骤将仓库名转换为全小写格式。
  6. 构建并推送镜像:这是核心步骤,它构建Docker镜像并将其推送到GHCR。镜像的标签使用了本次提交的哈希值(${{ github.sha }}),确保了每次构建版本的唯一性。

运行工作流

创建工作流文件(通常位于.github/workflows/目录下)并提交到仓库后,你可以手动触发它。

进入仓库的“Actions”页面,找到你创建的工作流(例如名为“CI”的)。点击“Run workflow”按钮,选择从main分支运行。

工作流开始执行后,你可以点击进入查看实时日志。日志会清晰地展示每个步骤的执行状态,例如代码检出、环境设置、认证、镜像构建和推送。

验证结果

工作流成功运行后,你可以前往GitHub容器注册表(https://ghcr.io)查看已推送的镜像。

在注册表中,你应该能找到以你仓库名命名的包。点击进入后,可以看到刚刚推送的镜像,其标签为对应的提交哈希。这证明自动化流程已成功将你的容器化应用发布到了云端注册表。

现在,任何人都可以通过docker pull ghcr.io/你的用户名/仓库名:标签命令来获取这个镜像,并在任何支持Docker的环境中运行你的FastAPI模型服务。


总结

本节课中我们一起学习了如何使用GitHub Actions为机器学习项目搭建一个自动化的CI/CD流水线。我们创建了一个工作流,它能够自动构建Docker镜像、登录到GitHub容器注册表,并将镜像推送上去。这个过程消除了手动操作的繁琐和潜在错误,实现了“一键”发布,是机器学习运维中实现高效、可靠部署的重要一步。

173:Hugging Face与Azure ML Studio

概述

在本节中,我们将学习如何创建并使用Azure机器学习工作室(Azure Machine Learning Studio)的工作空间,并了解其核心组件,特别是如何为后续集成Hugging Face资源(如数据集和模型)做准备。


Azure机器学习工作室简介 🧠

Azure机器学习工作室是一个云端环境,用于准备数据、训练、测试、部署、管理和跟踪机器学习模型。它提供了一个集成的界面,支持从数据到模型的全流程操作。

上一节我们介绍了机器学习运维的基本概念,本节中我们来看看如何设置一个核心的云平台工作环境。

创建工作空间 🛠️

首先,我们需要在Microsoft Azure门户中创建一个机器学习工作空间。工作空间是Azure机器学习中的顶级资源,它包含了进行所有机器学习活动所需的环境和配置。

以下是创建新工作空间的步骤:

  1. 在Azure门户中,导航至“Azure机器学习”或“Azure机器学习工作室”部分。
  2. 选择“创建”一个新的工作空间。
  3. 为工作空间选择一个资源组。资源组是用于存放相关Azure资源的容器。
  4. 为工作空间命名。为方便演示,通常将资源组和工作空间命名为相同或相似的名称。
  5. 点击“查看 + 创建”,系统将进行配置验证。
  6. 验证通过后,点击“创建”以提交部署。

部署过程需要一些时间来完成初始化。部署完成后,即可进入该资源并启动工作室。

工作室界面导览 🖥️

部署完成后,我们可以进入资源并启动Azure机器学习工作室。工作室界面主要分为几个功能区,支持各种机器学习操作。

核心功能区允许我们执行多种操作,例如创建新的数据资产或注册模型。虽然界面布局可能因缩放比例略有不同,但主要模块清晰可辨。

我们将重点关注“数据”和“模型”这两个部分,因为它们是与Hugging Face集成的关键。

管理数据资产 📊

在“数据”部分,我们可以创建和管理数据资产(Data Assets)。数据资产可以来自多种来源,例如本地文件、Web URL或Azure开放数据集。

以下是创建数据资产的基本流程:

  1. 点击“创建数据资产”。
  2. 填写名称(如“test”)和描述。
  3. 选择数据类型,例如“表格”类型。
  4. 在“下一步”中,选择数据来源。来源可以是本地文件、Web文件或Azure开放数据集等。
  5. 对于Web文件,只需粘贴URL并进行数据验证即可。

我们将在后续专门注册Hugging Face数据集时详细演练这些步骤。

注册与管理模型 🤖

在“模型”部分,我们可以注册和管理机器学习模型。注册模型意味着将模型文件及其元数据存储到工作空间中,便于版本控制和部署。

注册模型的途径包括:

  • 从本地文件注册:上传本地训练好的模型文件。
  • 从作业输出注册:将训练作业输出的模型直接注册。

这些操作不仅可以通过工作室界面完成,也可以通过Azure SDK以编程方式实现,便于自动化流程。

其他功能与环境 🚀

返回工作室主页,我们还能看到其他功能模块,如自动化机器学习(AutoML)、设计器和笔记本。

  • 笔记本:提供了一个完全集成的Jupyter Notebook环境,支持进行数据探索、模型训练和实验。
  • 自动化机器学习:自动尝试多种算法和参数以找到最佳模型。
  • 设计器:通过拖放界面构建、测试和部署机器学习管道。

这些工具共同构成了一个全面的机器学习操作环境。


总结

本节课中,我们一起学习了如何创建Azure机器学习工作室工作空间,并快速浏览了其核心界面与功能。我们重点了解了如何管理数据资产和注册模型,这是后续集成Hugging Face资源的基础。工作室还提供了笔记本、AutoML等强大工具,支持端到端的机器学习工作流。在接下来的课程中,我们将具体实践如何将Hugging Face的数据集和模型注册到该平台中。

174:在Azure注册Hugging Face数据集 📥

在本节课中,我们将学习如何从Hugging Face平台下载一个数据集,并将其上传并注册到Azure机器学习工作室中。整个过程将涉及使用Python库、处理数据以及通过Azure的图形界面完成数据资产注册。


现在,让我们看看如何为这个操作从Hugging Face下载一个数据集。

我们将使用Hugging Face的datasets库。这里可以看到,我将使用我账户中的winebradance数据集。我将点击这个数据集,它非常方便。我真的很喜欢它。它包含了我们所需的所有示例。

我们本质上需要从datasets导入load_dataset来获取这些数据。你必须确保已经通过pip install datasets安装了datasets库。我已经完成了这一步。

我将复制这段代码,并使用Jupyter笔记本来加载数据,使其正常工作。我将转到Visual Studio Code,我已经安装了datasets,并确保它能正常工作。我将粘贴from datasets import load_dataset

然后我将执行第3行代码,并确保它已加载。好的,这样它下载了一个CSV数据。

现在我将创建一个新的单元格,让我们看看这个数据集包含什么内容。

我将运行这段代码。正如预期,我们将有三种不同类型的数据。我确实想要完整的训练集。

为了获取它,我必须指定train。我将设置train_dataset = dataset['train']。然后运行它。很好。

现在如果我查看train_dataset并运行这些代码,你会看到我现在拥有了所有的3200行数据。我想要什么?我想在本地下载它。

这里有很多信息。我想将其转换为pandas格式。所以我会说df,代表数据框。我将把它发送到pandas看看结果。很好,这可行。

现在我可以运行df.describe()。是的,让我们看看结果。很好。3200行,这正是我想要的。

接下来我要做的是将其保存为CSV文件。好的,我将再次点击代码。我将执行df.to_csv('wine_ratings.csv', index=False)。这将创建一个CSV文件在那里。好的。

我喜欢用pandas做这个。如果你想使用其他方法,那也可以。但在这里,使用pandas会很方便。

我将执行这些代码,你可以在这里看到我的wine_ratings.csv文件已经在这里了,里面包含了各种不同的数据。

我们要做什么?我们要在Azure上注册这个文件。为此,我们将转到网页浏览器。

然后,我将前往Azure机器学习工作室,接着导航到“数据”部分。我将点击“创建”,然后说“wine_dataset”,这是一个来自Hugging Face的葡萄酒数据集。

类型将是“表格型”。我点击“下一步”,然后我们将选择从我的本地驱动器上传。所以选择“本地文件”,然后“下一步”。

存储设置这里没问题,Azure Blob存储就可以。我点击“下一步”。现在我说,是的,如果路径已存在也没关系。然后我点击“上传”。

这将弹出一个小的窗口。我将选择wine_ratings.csv文件。我知道这个文件很小,但这是必要的步骤。我打开它并上传。那是12兆字节。我点击“下一步”。

然后它会在后台进行一些验证。验证完成了,是的,格式是CSV,UTF-8编码,完美。我不希望跳过任何列标题,所有文件都有相同的标题。那很好。

我们有名称为、地区、品种、评分等列,这正是数据集的内容。如果你记得,我回到这里点击查看,名称、地区、品种、评分和一些备注,完全一样。没有任何变化。所以我点击“下一步”。

现在在这里,Azure在后台对列名和我们正在处理的数据类型进行了大量验证。这更像是十进制数,我原本期待的是浮点数,但带点的十进制数听起来很好,很完美。所以它能够正确识别。例如,如果这是布尔值,你可以在这里更改它。这很完美。点击“下一步”。

最后,我点击“创建”。这样它将创建一个数据资产,我仍然称之为数据集,这没问题。这里的关键点是,我们有版本控制。你可以在这里看到“文件在data1中,当前版本是1”。这意味着每次我向这个数据推送新版本时,都会上传并记录。这在以编程方式进行时更有意义,例如使用Azure CI/CD或某些API,你可能以编程方式执行此操作并进行更改。但我想通过用户界面向你展示,以便你能更轻松地理解你将看到的一些内容,而不是我运行一堆命令让事情发生。

不过,这也可以通过Python API以及其他受支持的语言SDK以编程方式访问。所以,如果我这里有100个版本,你可以指定要版本10而不是版本100,那也会起作用。

就是这样。这就是你如何下载Hugging Face数据集到本地,然后将其上传到Azure机器学习工作室的方法。


本节课中,我们一起学习了从Hugging Face下载数据集、使用pandas进行基本处理、以及通过Azure机器学习工作室的界面将数据注册为可版本控制的数据资产的全过程。这为后续的机器学习工作流提供了可靠的数据基础。

175:在Azure注册Hugging Face模型

概述

在本节课中,我们将学习如何将一个Hugging Face模型下载到本地,然后将其注册到Azure机器学习工作室中。这个过程涉及使用transformers库下载模型,以及通过Azure机器学习工作室的界面手动上传和注册模型资产。


从Hugging Face下载模型

上一节我们介绍了课程目标。本节中,我们来看看如何从Hugging Face Hub获取模型。

首先,在Hugging Face的Web UI中找到目标模型(例如GPT-2)。为了了解如何在代码中使用它,我们可以查看其API。在模型页面上,通常会有一个“Use in Transformers”的卡片,其中提供了加载模型的示例代码。

以下是加载模型和分词器的核心代码:

from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")

运行这段代码后,transformers库会自动从Hugging Face Hub下载模型文件并缓存到本地系统。如果是首次运行,下载可能需要一些时间。

模型下载完成后,我们可以使用以下方法将其保存到指定的本地目录:

model.save_pretrained("./gpt2")

执行此命令后,会在./gpt2目录下生成两个关键文件:

  • config.json:包含模型的配置和元数据。
  • pytorch_model.bin:这是模型的可加载权重文件,供PyTorch使用。

至此,我们已经成功将模型文件保存到了本地。


在Azure机器学习工作室中注册模型

我们已经将模型下载到本地。接下来,我们将学习如何将其作为一个资产注册到Azure机器学习工作室中。

打开Azure机器学习工作室,导航到“模型”部分。我们将通过图形界面手动注册模型。

以下是注册模型的具体步骤:

  1. 点击“注册模型”。
  2. 选择“从本地文件”注册。
  3. 模型类型可以保持为“未指定类型”。
  4. 在“选择模型文件或文件夹”时,浏览并选择之前保存的pytorch_model.bin文件(约486MB)。
  5. 点击“下一步”。
  6. 为模型命名(例如“GPT-2”),并添加可选的描述信息。
  7. 版本号通常会自动设置为“1”,可以保持默认。
  8. 点击“下一步”并完成注册。

上传过程可能需要一些时间,因为需要传输较大的模型文件。注册成功后,模型会出现在模型列表中,并拥有一个唯一的资产ID。


注册模型的意义与用途

我们已经完成了模型的注册。现在,我们来探讨一下将模型注册到Azure机器学习工作室的好处。

将模型作为资产进行管理,为机器学习运维(MLOps)带来了诸多便利:

以下是注册模型后的主要优势:

  • 版本控制:可以轻松管理模型的不同版本(如v1, v2, v3),便于追踪和回滚。
  • 部署:可以直接将注册的模型部署为实时端点或批处理端点,用于推理服务。
  • 共享与协作:模型资产可以在团队内共享,方便协作开发。
  • 分析与评估:可以利用工作室的工具进行模型性能分析、公平性评估等。
  • 自动化集成:通过资产ID,可以在代码或自动化流水线(如Azure DevOps)中精确地引用和检索特定版本的模型。

此方法不仅适用于Hugging Face模型,也适用于ONNX或其他格式的模型。


总结

本节课中我们一起学习了将Hugging Face模型集成到Azure机器学习平台的完整流程。我们首先使用transformers库将模型下载到本地并保存,然后通过Azure机器学习工作室的界面手动上传和注册了该模型。最后,我们讨论了将模型作为版本化资产进行管理在MLOps实践中的重要意义,包括版本控制、部署和协作等方面的优势。

176:在Azure中检查Hugging Face数据集

在本节课程中,我们将学习如何在Azure机器学习工作室界面中,对已注册的Hugging Face数据集进行探索性分析。我们将了解如何查看数据概览、生成数据剖面报告,并理解数据集的基本特征。

探索数据集

回到Azure机器学习工作室界面。我们记得已经注册了葡萄酒数据集。现在,我们想进行一些探索性分析。

如果点击上方的“探索”按钮,系统会生成一些数据预览。这类似于使用Pandas库查看数据,它会显示数据的前几行,为你提供一个预览。

生成数据剖面报告

除了简单的预览,你还可以点击“剖面”按钮来获取更详细的信息。为了更清晰地展示,我将界面调整得小一些,以便你能看到更大的视图。

在这里,你可以看到一些信息性的内容。例如,数据集中包含“纳帕谷”、“俄勒冈”、“托斯卡纳”等不同产区。你无需运行任何特定分析,就能直接获取这些信息。

关于葡萄酒的评分,其范围从85分到略高于100分。你可以看到,在3200条数据中,只有88条记录的评分在97到99分之间。并且,我认为没有100分的记录。这些初步信息已经非常有用。

分析数据特征

现在我们已经查看了数据概览。除了探索功能,你还可以在这里看到关于评分和产区的节点信息。由于“产区”字段全是文本字符串,其节点分析没有数值信息。

我想向你展示的另一种使用方式与直接使用Hugging Face略有不同。你本质上是在这里使用Azure的Python SDK。你可以看到一些详细信息,例如,如果你想创建新版本而不是覆盖原有数据,你可以进行修改并重新上传。当然,你也可以通过SDK来完成这个操作。

总结

本节课中,我们一起学习了如何在Azure机器学习工作室中对数据集进行探索性工作。我们查看了数据的外观,学习了如何与之交互,并了解了我们将要处理的数据类型。所有这些数据都来源于Hugging Face平台。

177:Azure机器学习Python SDK入门指南 🚀

在本节课中,我们将学习如何使用Azure机器学习的Python SDK。这个SDK允许我们以编程方式与Azure门户和Azure机器学习工作室中已有的功能进行交互。我们将重点介绍如何注册模型、进行身份验证以及处理数据。

概述

上一节我们介绍了如何使用Hugging Face模型和数据并将其上传到Azure。本节中,我们来看看如何通过Python SDK以编程方式实现类似功能。Azure机器学习Python SDK提供了与我们在门户界面中看到的功能相对应的编程接口,使我们能够自动化执行各种任务。

身份验证与工作区设置

在使用Azure机器学习Python SDK之前,首先需要进行身份验证并设置工作区。工作区是Azure机器学习中的核心概念,它充当了所有资源和操作的中心枢纽。

以下是设置工作区的关键步骤:

  1. 导入必要的库:首先,需要从azureml.core导入Workspace类。
  2. 创建工作区:使用Workspace.create()方法,并提供工作区名称、订阅ID、资源组和位置等信息。
  3. 保存配置:可以将工作区配置保存到config.json文件中,以便后续轻松加载。

核心代码示例

from azureml.core import Workspace

ws = Workspace.create(name='your_workspace_name',
                      subscription_id='your_subscription_id',
                      resource_group='your_resource_group',
                      create_resource_group=True,
                      location='eastus2')

# 将配置保存到文件
ws.write_config(path='.azureml', file_name='config.json')

一旦工作区设置完成,你就可以在任何环境中使用它,并通过加载配置文件来重新建立连接。

注册与管理模型

完成身份验证后,接下来我们可以探索如何注册和管理模型。注册模型是MLOps工作流中的一个关键步骤,它允许你对模型进行版本控制、跟踪和部署。

以下是使用SDK注册模型的主要功能:

  • 命名与描述:为模型指定一个名称和描述,类似于我们在UI表单中填写的信息。
  • 模型交互:一旦模型被注册,你就可以通过SDK与之交互。
  • 下载与本地运行:你可以将模型下载到本地环境运行,只要身份验证有效,不一定非要在云端运行。
  • 删除操作:在需要时,你也可以通过SDK删除已注册的模型。

这个功能非常强大,因为它为模型的整个生命周期管理提供了程序化的控制能力。

数据处理与部署

除了模型管理,Python SDK还提供了强大的数据处理和模型部署能力。这让我们能够以代码形式复现在UI中执行的数据准备和模型服务化流程。

以下是关于数据处理和部署的一些要点:

  • 数据注册:与注册模型类似,你可以使用azureml.core中的Dataset类来注册数据。这类似于我们之前用Hugging Face数据集所做的操作。
  • 数据来源:数据可以来自本地文件、Azure中已存在的数据存储,甚至是URL路径。
  • 转换为Pandas DataFrame:注册的数据集可以方便地转换为Pandas DataFrame,这对于数据探索和预处理非常有用。
  • 模型部署:SDK的核心功能之一是部署Web服务。你可以快速部署和提供模型服务,也可以触发在专用基础设施上的模型训练任务。

数据处理代码示例

from azureml.core import Dataset

# 注册一个基于文件的数据集
datastore = ws.get_default_datastore()
dataset = Dataset.File.from_files(path=(datastore, 'path/to/your/data'))

# 注册一个表格数据集,并可转换为Pandas DataFrame
tab_dataset = Dataset.Tabular.from_delimited_files(path=[(datastore, 'data.csv')])
df = tab_dataset.to_pandas_dataframe()

总结

本节课中我们一起学习了Azure机器学习Python SDK的基础知识。我们了解了如何通过代码设置工作区和进行身份验证,这是与Azure ML服务交互的起点。接着,我们探讨了如何使用SDK注册和管理模型,实现模型的版本控制。最后,我们介绍了如何处理数据以及部署模型为Web服务。

掌握这个SDK非常有用,因为一旦你的项目运行在Azure云基础设施上,你就可以利用这些工具来探索来自Hugging Face等源的数据和模型,进行自己的模型训练和部署,从而充分利用像Azure这样的云服务提供商的计算能力。SDK的文档非常详尽,涵盖了从基础设施配置到高级工作流自动化的方方面面,是构建可扩展机器学习运维流水线的强大工具。

178:使用GitHub Actions部署模型 🚀

在本节课中,我们将学习如何使用GitHub Actions工作流来部署机器学习模型。我们将以一个具体的项目为例,该项目旨在将基于Hugging Face模型的文本生成Web应用部署到Azure云平台。课程将涵盖从代码结构分析到GitHub Actions流水线配置的完整流程。


项目概览与结构 🔍

首先,我们来了解将要部署的项目。这是一个基于FastAPI的Web应用程序,它集成了Hugging Face的GPT-2模型,能够提供实时的文本生成服务。其核心结构与我们在之前课程中见过的许多示例类似。

以下是项目的主要组成部分:

  • 依赖项:项目依赖于几个关键的Python库,包括transformers(用于加载Hugging Face模型)、tensorflow(作为后端框架)、fastapi(用于构建API)和uvicorn(用于运行ASGI服务器)。
  • Dockerfile:用于将应用容器化。这个Docker文件非常简洁,只有大约15行。它的主要步骤包括:安装上述依赖项、复制Web应用代码、暴露端口8000,以及设置启动命令来运行Uvicorn服务器。

通过Docker化,我们确保了应用可以在任何支持Docker的环境中一致地运行,这是现代应用部署的基石。


GitHub Actions工作流详解 ⚙️

上一节我们介绍了项目的基本结构,本节中我们来看看实现自动化部署的核心——GitHub Actions工作流配置文件(.github/workflows/main.yml)。

这个工作流定义了从代码推送到最终部署的自动化步骤。以下是其关键部分的解析:

环境与触发配置

工作流首先定义了一些环境变量,例如Azure容器应用的名称和资源组名称。为了在开发阶段进行控制,自动触发(例如在推送到main分支时运行)通常被注释掉。取而代之的是,我们使用workflow_dispatch事件,这允许我们在GitHub界面上手动触发工作流,便于测试和调试。

构建与推送Docker镜像

工作流的第一步是构建Docker镜像并将其推送到一个容器注册表。

以下是构建阶段的核心步骤:

  1. 设置Docker构建环境:使用docker/setup-buildx-action动作来配置高效的Docker构建环境。
  2. 登录到容器注册表:使用docker/login-action动作进行身份验证。在本例中,目标注册表是GitHub Container Registry (GHCR)。GitHub会自动提供所需的令牌(Token),无需额外配置密钥。
  3. 处理镜像标签:通过一段Shell脚本确保镜像名称全部为小写,以满足大多数注册表的要求。
  4. 构建与推送:使用docker/build-push-action动作。它会构建Docker镜像,并使用当前代码仓库的名称和Git提交哈希作为标签,将镜像推送到GHCR。

部署到Azure容器应用

镜像准备就绪后,下一步就是将其部署到Azure。

以下是部署阶段的核心步骤:

  1. 登录Azure:使用azure/login动作,通过存储在GitHub仓库Secrets中的Azure服务主体凭证进行认证。
  2. 执行部署:使用azure/cli动作运行Azure CLI命令。该命令会创建一个或更新一个现有的Azure容器应用,并指定从GHCR拉取我们刚刚推送的Docker镜像。这里需要提供一个个人访问令牌(PAT)作为Secret,用于授权Azure从GHCR拉取私有镜像。

总结与拓展 🎯

本节课中我们一起学习了如何配置一个完整的GitHub Actions流水线,用于将机器学习模型应用部署到云平台。

我们分解了工作流的两个主要阶段:构建(将代码打包成Docker镜像并推送到注册表)和部署(在云平台创建或更新运行该镜像的服务)。虽然本次示例以Azure和GHCR为目标,但整个模式是通用的。

理解了这个基本框架后,你可以轻松地替换其中组件。例如,你可以将镜像推送到Docker Hub或Azure Container Registry (ACR),也可以将应用部署到AWS ECS或Google Cloud Run。关键在于掌握认证构建推送云平台CLI部署这三个核心环节的配置方法。

通过将这一过程自动化,你能够实现持续集成和持续部署(CI/CD),确保模型更新可以快速、可靠地交付到生产环境。

179:使用Azure容器注册表

在本节课中,我们将学习如何创建并使用Azure容器注册表。Azure容器注册表是一个托管的Docker注册表服务,用于存储和管理容器镜像。我们将逐步完成在Azure门户中创建注册表、配置访问密钥,并了解后续在GitHub Actions等自动化流程中如何使用它。


创建Azure容器注册表

上一节我们介绍了Azure容器注册表的概念,本节中我们来看看如何实际创建一个。

首先,需要登录到Azure门户。在门户中,我们可以搜索并选择“容器注册表”服务来开始创建过程。

以下是创建新容器注册表的步骤:

  1. 在Azure门户中,搜索并选择“容器注册表”。
  2. 点击“+ 创建”按钮以开始创建新的注册表。
  3. 在创建向导中,需要选择订阅。本示例使用一个特定的订阅。
  4. 创建一个新的资源组,将其命名为 demoContainer。此资源组将用于后续创建的其他Azure服务,以便部署容器。
  5. 为注册表设置一个唯一的名称。本示例使用 demoAlfredo。请注意,资源名称只能包含字母数字字符,因此移除了连字符以确保合规。
  6. 选择区域。本示例选择“美国东部”区域。
  7. 对于“可用性区域”,本示例不需要,因此保持默认。
  8. 在“SKU”层选择上,“标准”层已足够。Azure也提供“基本”和“高级”层以满足不同需求。
  9. 完成所有配置后,点击“查看 + 创建”按钮。
  10. 验证通过后,点击“创建”按钮。部署过程将开始,这可能需要一些时间。

部署完成后,可以导航到新创建的资源。


配置访问密钥

创建注册表后,我们需要配置访问密钥,以便能够登录并向其推送容器镜像。

以下是配置和管理访问密钥的步骤:

  1. 在容器注册表的资源页面,导航到“访问密钥”设置部分。
  2. 为了能够推送镜像,需要启用“管理员用户”选项。这是使用Azure容器注册表推送镜像时的要求。
  3. 启用后,系统会显示用户名和两个密码。用户名通常是注册表名称的一部分(例如 Alfredo)。
  4. 可以使用其中一个密码进行身份验证。系统提供两个密码是为了方便在不中断服务的情况下轮换密钥。
  5. 这些密码可以随时重新生成。
  6. 此处显示的用户名和密码,以及“登录服务器”的地址,是后续登录和向该注册表进行身份验证所必需的信息。

重要提示:为了在自动化流程(如GitHub Actions)中使用此注册表,需要将这里的用户名密码添加为GitHub仓库的加密密钥。


总结

本节课中我们一起学习了Azure容器注册表的核心操作。我们首先在Azure门户中创建了一个新的容器注册表,并为其指定了资源组和唯一名称。然后,我们配置了访问密钥,启用了管理员用户,并获取了登录所需的用户名、密码和服务器地址。这些凭证是后续通过Docker命令行或CI/CD工具(如GitHub Actions)向该注册表推送和拉取容器镜像的基础。

180:通过Azure容器注册表实现自动化打包

在本节课中,我们将学习如何利用之前创建的Azure容器注册表,来自动化机器学习模型的打包和推送过程。我们将修改GitHub Actions工作流文件,配置必要的密钥,并最终将Docker镜像推送到Azure容器注册表。

准备工作与流程概述

首先,我们需要回顾并修改现有的GitHub Actions工作流文件。这是一个YAML文件,我们需要更新其中的容器注册表登录信息和镜像标签。

当前工作流中登录的是GitHub容器注册表,我们需要将其改为Azure容器注册表。同时,镜像标签也需要更新为我们创建的Azure容器注册表的服务器地址。

此外,我们需要使用Azure容器注册表的用户名和密码,这些将作为密钥存储在GitHub仓库中。

配置GitHub仓库密钥

现在,我们知道了需要更新的内容,接下来前往GitHub仓库的设置页面,为我们的仓库创建必要的密钥。

进入“Settings” -> “Secrets and variables” -> “Actions”。点击“New repository secret”来创建新密钥。

我们将为所有与Azure容器注册表相关的密钥添加“ACR_”前缀。首先创建用户名密钥。

  1. 密钥名称ACR_USERNAME
  2. 密钥值:从Azure门户中,找到你的容器注册表(例如 demoalfredo),复制其用户名(例如 demoalfredo),并粘贴至此。

点击“Add secret”完成添加。请注意,一旦添加为密钥,你将无法再查看其明文内容,只能更新或删除。

接下来创建密码密钥。

  1. 密钥名称ACR_PASSWORD
  2. 密钥值:从Azure门户的容器注册表设置中,复制访问密钥(例如两个密钥中的第一个),并粘贴至此。

再次点击“Add secret”。现在,我们已经成功配置了ACR_USERNAMEACR_PASSWORD两个密钥,准备工作就绪。

更新GitHub Actions工作流文件

配置好密钥后,我们现在可以更新工作流文件了。进入仓库的.github/workflows目录,找到YAML文件并进行编辑。

我们主要关注构建和推送镜像的步骤,暂时不需要部署部分。需要更新的关键部分如下:

  1. 登录步骤:将登录服务器从GitHub容器注册表改为Azure容器注册表。从Azure门户复制你的容器注册表登录服务器地址(例如 demoalfredo.azurecr.io)。
  2. 认证信息:将用户名和密码的引用改为我们刚刚创建的GitHub密钥。
    • 用户名:${{ secrets.ACR_USERNAME }}
    • 密码:${{ secrets.ACR_PASSWORD }}
  3. 镜像标签:在构建和推送步骤的tags部分,同样需要使用完整的Azure容器注册表地址作为前缀,例如 demoalfredo.azurecr.io/your-repo-name:${{ github.sha }}

修改完成后,提交更改到主分支。

触发工作流并验证结果

提交更改后,我们可以手动触发工作流来测试自动化流程。进入仓库的“Actions”标签页,找到对应的工作流,点击“Run workflow”。

工作流开始运行后,你可以查看实时日志。它会依次执行登录认证、构建Docker镜像,最后将镜像推送到Azure容器注册表。

整个过程大约需要几分钟。完成后,日志会显示所有步骤成功执行,包括推送到ACR注册表。

在Azure门户中验证

最后,我们可以在Azure门户中验证推送是否成功。导航到你的Azure容器注册表资源。

  1. 在“概述”或“活动日志”中,可以看到近期的推送操作记录。
  2. 进入“仓库”部分,你应该能看到一个新创建的仓库,其名称来源于工作流中定义的镜像标签。
  3. 点击该仓库,可以查看详细信息,如标签列表、最后修改时间等。你会看到刚刚通过自动化流程推送上去的镜像标签。

总结

本节课中,我们一起学习了如何实现基于Azure容器注册表的自动化打包流程。我们首先配置了GitHub仓库的密钥以安全地存储认证信息,然后修改了GitHub Actions工作流文件,将构建目标从GitHub容器注册表切换到Azure容器注册表,并更新了相应的登录和标签配置。最后,我们手动触发了工作流,成功地将Docker镜像自动构建并推送到了Azure容器注册表,并在Azure门户中验证了结果。这个过程是构建完整MLOps流水线中持续集成与交付环节的重要一步。

181:通过Docker Hub实现自动化打包 🐳

在本节课中,我们将学习如何利用GitHub Actions工作流,自动将机器学习模型打包成Docker镜像,并推送到Docker Hub仓库。这个过程是实现持续集成与持续部署(CI/CD)的关键步骤。

概述

我们将配置一个GitHub Actions工作流,使其在代码推送到主分支时自动触发。该工作流会执行以下核心操作:检出代码、登录Docker Hub、构建Docker镜像,最后将镜像推送到指定的Docker Hub仓库。

工作流配置详解

上一节我们介绍了自动化打包的目标,本节中我们来看看如何具体配置GitHub Actions工作流文件。

工作流配置文件通常位于仓库的 .github/workflows/ 目录下。以下是一个名为 docker-image.yml 的配置示例:

name: Docker Image CI

on:
  push:
    branches: [ main ]
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Log in to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: yourusername/huggingface-fastapi:latest

以下是该配置文件各部分的详细说明:

  • 触发器 (on):定义了工作流何时运行。pushmain 分支会触发。workflow_dispatch 允许在GitHub界面上手动触发。
  • 检出代码 (actions/checkout):这是一个标准步骤,用于将仓库的代码拉取到工作流运行环境中。
  • 登录Docker Hub (docker/login-action):此步骤使用存储在GitHub仓库机密中的用户名和令牌进行身份验证。
  • 构建与推送 (docker/build-push-action):这是核心步骤。context: . 指定使用根目录的Dockerfile。push: true 表示构建后自动推送。tags 指定了镜像在Docker Hub上的完整名称和标签。

获取并配置Docker Hub凭证

为了安全地进行身份验证,我们需要在Docker Hub生成访问令牌,并将其存储在GitHub仓库中。

生成Docker Hub访问令牌

首先,你需要在Docker Hub网站上创建访问令牌。

  1. 访问 hub.docker.com 并登录。
  2. 点击右上角头像,进入 “Account Settings”
  3. 在左侧菜单选择 “Security”
  4. “Access Tokens” 部分,点击 “New Access Token”
  5. 为令牌添加描述(例如“GitHub Actions for ML”),并设置权限为 “Read, Write, Delete”
  6. 点击生成后,立即复制生成的令牌字符串并妥善保存。

在GitHub仓库中添加机密

接下来,将Docker Hub用户名和刚才生成的令牌添加到GitHub仓库的机密中。

  1. 进入你的GitHub仓库页面。
  2. 点击 “Settings” 选项卡。
  3. 在左侧边栏找到 “Secrets and variables”,然后选择 “Actions”
  4. 点击 “New repository secret” 按钮。
  5. 创建两个机密:
    • 名称: DOCKERHUB_USERNAME: 你的Docker Hub用户名。
    • 名称: DOCKERHUB_TOKEN: 你刚才复制的访问令牌。

关键点:务必确保你在工作流YAML文件中引用的机密名称(例如 secrets.DOCKERHUB_USERNAME)与这里设置的名称完全一致。

手动触发与验证

配置完成后,你可以立即测试工作流。

  1. 进入GitHub仓库的 “Actions” 选项卡。
  2. 在左侧列表中找到你配置的工作流(例如“Docker Image CI”)。
  3. 由于我们配置了 workflow_dispatch,你会看到 “Run workflow” 按钮。点击它并再次确认运行。
  4. 工作流开始执行。你可以点击进入查看实时日志。
  5. 执行成功后(通常需要2-3分钟),返回你的Docker Hub仓库页面。你应该能看到一个带有指定标签(如 huggingface-fastapi:latest)的新镜像,其更新时间与工作流完成时间吻合。

总结

本节课中我们一起学习了如何搭建一个完整的自动化Docker镜像打包与推送流水线。我们首先分析了GitHub Actions工作流配置文件的结构和核心步骤,然后详细讲解了如何安全地生成并使用Docker Hub访问令牌,最后通过手动触发验证了整个流程。通过此设置,你的模型代码每次更新并推送到主分支时,都会自动生成最新的可部署Docker镜像,极大地提升了机器学习项目的运维效率。

182:创建Azure容器应用

概述

在本节课中,我们将学习如何在Azure平台上创建一个容器应用。Azure容器应用提供了一种无服务器的基础设施,使我们能够轻松部署容器化应用,而无需管理底层服务器。这对于部署机器学习模型,特别是基于Hugging Face和FastAPI的模型,是一种非常强大的方式。我们将逐步完成创建过程,并了解如何配置关键设置。

什么是Azure容器应用?

Azure容器应用的核心是提供无服务器部署能力。这意味着你可以部署一个实际的容器,而无需考虑任何其他基础设施问题。这种方式特别适合部署机器学习模型,因为它能提供即时扩展能力,并在创建时允许你选择不同的配置选项。

创建容器应用

现在,我们将开始创建容器应用。这是尝试部署模型的第一步,之后我们将逐步完成部署所需的其他步骤。

以下是创建Azure容器应用的具体步骤:

  1. 选择订阅和资源组:首先,系统会加载你的Azure订阅。我们将使用一个名为 demo-container 的资源组,这符合我们的需求。
  2. 命名容器应用:容器应用的名称非常重要,因为我们后续的自动化流程会用到这个名称。例如,我们将其命名为 demo-container。资源组名称也与之相同。这些名称是变量,可以根据你的实际情况进行设置。
  3. 选择区域:系统可能会建议一个区域(如加拿大中部),但我们可以选择其他区域,例如美国东部。
  4. 配置入口设置:在创建过程中,我们需要配置入口设置。默认设置允许从任何地方通过端口80访问。但根据我们的Dockerfile配置,应用实际运行在端口8000上,因此后续需要更新此设置。
  5. 使用快速启动镜像:初始创建时,系统会使用一个简单的“Hello World”容器镜像作为快速启动示例。
  6. 审查并创建:确认所有配置无误后,点击“审查并创建”按钮,等待部署完成。

配置与验证

创建完成后,我们需要进入资源页面进行验证和进一步配置。

上一节我们介绍了创建过程,本节中我们来看看如何配置和验证已创建的应用。

  1. 访问应用URL:在资源概览页面,你可以找到一个应用URL。点击该URL,如果看到“Welcome to Azure Containers”的页面,说明基础示例容器正在运行。
  2. 管理功能:在容器应用的管理界面,你可以设置密钥、配置持续部署,并通过修订版管理你的应用。同时,监控功能可以帮助你排查问题。
  3. 更新入口端口:由于我们的Hugging Face FastAPI应用使用Uvicorn运行在端口8000,我们必须更新入口的目标端口。将目标端口从默认的80更改为8000,并确保入口类型为HTTP,允许从任何地方访问。
  4. 保存更改:完成端口更改后,点击保存。系统将更新入口配置,为后续的实际部署做好准备。

总结

本节课中,我们一起学习了如何在Azure上创建和配置一个容器应用。我们了解了Azure容器应用的无服务器特性,逐步完成了从选择资源组、命名应用到配置入口端口的关键步骤。现在,我们已经拥有了一个可以运行容器化应用的基础环境。在接下来的课程中,我们将学习如何自动化部署流程,将我们的Hugging Face FastAPI模型应用推送到这个容器中并使其正常运行。

183:配置Azure容器应用

概述

在本节课中,我们将学习如何配置Azure容器应用,以确保其能够顺利运行机器学习模型服务。我们将重点关注入口设置、容器资源配置和自动扩展规则。


入口流量配置

上一节我们创建了容器应用,现在需要确保其入口配置正确。

以下是入口配置的关键检查点:

  • 启用入口:确认入口功能已开启。
  • 流量来源:设置为接受来自任何地方的流量,或限制为容器应用环境内部(防火墙后)。
  • 入口类型:目前选择 HTTP 即可,因为我们尚未启用SSL。
  • 目标端口:必须正确映射到应用实际使用的端口。例如,我们的应用使用端口 8000

容器资源配置

入口配置完成后,我们需要调整容器的计算资源,以确保应用有足够能力运行。

在容器设置中,默认配置可能仅为 0.25个CPU核心0.5GB内存。这对于运行Hugging Face和FastAPI应用来说通常不够。

我们需要编辑容器配置:

  1. 点击容器进行编辑。
  2. 将CPU核心数提升至最大值 2个
  3. 将内存增加至 4GB
# 容器资源配置示例
resources:
  cpu: 2
  memory: 4Gi

设置自动扩展规则

资源配置完成后,我们需要设置自动扩展规则,以应对不同的负载。

在“扩展”设置中,我们可以定义容器的副本数范围:

  • 最小副本数:可设置为 0,以便在无流量时节省成本。
  • 最大副本数:根据需求设置,例如 10

此设置允许应用根据负载自动伸缩,在0到10个实例之间动态调整。


其他配置选项

除了核心配置,Azure容器应用还提供其他重要功能。

以下是两个可选但重要的配置项:

  • 身份验证:如果模型API需要保护,可以在此处添加身份验证层,避免完全公开访问。
  • 持续部署:此功能允许与GitHub集成,自动构建和部署新的容器镜像。当代码仓库更新时,容器应用会自动同步。

总结

本节课中,我们一起学习了配置Azure容器应用的三个关键步骤:正确设置入口流量、调整容器计算资源以满足应用需求,以及配置自动扩展规则以实现弹性伸缩。理解这些配置项是确保机器学习服务稳定、高效运行的基础。在下一课中,我们将进行自动化部署。

184:将Hugging Face模型部署至Azure ☁️

在本教程中,我们将学习如何将一个容器化的Hugging Face应用,通过GitHub Actions工作流,全自动地部署到Azure容器应用服务中。我们将涵盖从设置必要的认证密钥,到配置自动化构建和部署流水线的完整过程。


准备工作与认证设置 🔑

上一节我们介绍了项目的基本结构,本节中我们来看看部署前需要完成的准备工作,主要是设置Azure的认证信息。

我们需要创建一个Azure服务主体,用于在GitHub Actions工作流中认证Azure。运行以下命令(请将<your-subscription-id>替换为你的Azure订阅ID):

az ad sp create-for-rbac --name myMLServicePrincipal --role contributor --scopes /subscriptions/<your-subscription-id> --sdk-auth

命令执行后会输出一段JSON格式的凭据信息。请完整复制这段输出。

接下来,我们需要在GitHub仓库中设置密钥。

  1. 进入GitHub仓库的 Settings 页面。
  2. 在左侧边栏选择 Secrets and variables > Actions
  3. 点击 New repository secret 按钮。
  4. 创建一个名为 AZURE_CREDENTIALS 的密钥,并将上一步复制的JSON内容粘贴为值。

此外,我们还需要设置Azure容器注册表的用户名和密码密钥,分别命名为 ACR_USERNAMEACR_PASSWORD


配置GitHub Actions工作流 ⚙️

完成认证设置后,我们来配置自动化的构建与部署工作流。工作流定义在 .github/workflows/main.yml 文件中。

以下是工作流的核心步骤:

  1. 构建Docker镜像:工作流会基于项目中的Dockerfile构建一个新的容器镜像。
  2. 登录并推送至Azure容器注册表:使用之前设置的 ACR_USERNAMEACR_PASSWORD 密钥,将构建好的镜像推送到指定的Azure容器注册表。关键点:在构建命令中,必须明确指定注册表的地址(例如 demo.azurecr.io),否则Docker会默认推送到Docker Hub。
    - name: Build and push container image to registry
      uses: docker/build-push-action@v2
      with:
        push: true
        tags: demo.azurecr.io/huggingface-azure:latest
    
  3. 认证Azure:使用 AZURE_CREDENTIALS 密钥进行Azure CLI认证,为后续部署操作授权。
  4. 部署到Azure容器应用:使用 azure/CLI 动作执行Azure CLI命令,更新Azure容器应用的配置,使其使用最新推送的镜像。

在部署步骤中,我们通过Azure CLI命令来更新容器应用。主要操作包括:

  • 确保已安装容器应用CLI扩展。
  • 为容器应用配置从ACR拉取镜像的凭据。
  • 更新容器的资源分配(例如,设置为2个CPU核心和4GB内存)。
  • 最终,将容器应用的镜像更新为我们刚推送的新版本。


执行部署与验证 ✅

配置完成后,我们可以在GitHub仓库的 Actions 标签页手动触发工作流运行。

工作流执行分为两个主要任务:

  • Docker构建任务:耗时约数分钟,完成镜像的构建和推送。
  • 部署任务:耗时约1-2分钟,完成Azure容器应用的更新。

部署过程中,我们可以通过Azure CLI在终端实时查看容器日志,以监控应用启动状态:

az containerapp logs show --name demo-container --resource-group demo-container --follow

日志会显示模型下载、服务启动(例如在8000端口监听)等过程。

部署成功后,我们可以在Azure门户中验证:

  1. 进入容器应用资源,确认 镜像源 已更新为我们ACR中的新镜像。
  2. 确认 容器资源配置 已按工作流中的设置更新(如2 CPU, 4GB内存)。

最后,我们可以通过容器应用提供的公开URL(格式为 https://<app-name>.<region>.azurecontainerapps.io)访问已部署的Hugging Face模型API,并使用Swagger UI界面进行测试,例如输入提示词“cloud deployments”来生成文本,验证服务是否正常运行。


总结 📝

本节课中我们一起学习了将Hugging Face模型部署到Azure的完整自动化流程。我们首先设置了Azure服务主体和容器注册表的认证密钥,然后配置了GitHub Actions工作流来自动完成镜像构建、推送至ACR以及更新Azure容器应用。通过这个流程,我们可以实现代码推送后自动触发模型服务的重新部署,从而建立起一个高效的机器学习运维流水线。

185:容器部署故障排查 🔍

在本节课中,我们将学习如何排查容器部署中的常见故障。我们将通过一个具体案例,演示当容器配置了错误的端口时会发生什么,以及如何通过检查日志来定位问题。


概述

在上一节中,我们处理了因语法错误导致容器无法启动的问题。本节中,我们来看看另一种常见情况:容器配置了错误的端口。我们将模拟这一场景,观察其现象,并学习如何通过Azure门户的日志来诊断问题。

故障模拟:配置错误端口

首先,我们修复之前引入的语法错误,然后将容器暴露的端口从默认的80更改为8000。以下是更改的核心代码部分:

# 在Dockerfile或应用配置中,将端口从80改为8000
EXPOSE 8000

或者,在应用配置文件(如app.pyDockerfile的CMD指令)中确保应用监听在8000端口。

提交这些更改后,我们的自动化流程(CI/CD)会构建新的容器镜像,将其推送到GitHub容器仓库,并通知Azure拉取这个新容器并尝试再次运行。

观察部署结果

自动化操作成功完成后,系统会提供一个URL。点击该URL,我们会发现页面持续加载,但没有任何响应。这表明服务没有在预期的端口上成功运行。

诊断问题:检查日志

当应用无响应时,我们需要回到Azure门户进行诊断。

以下是诊断步骤:

  1. 进入Azure门户,找到你的应用服务。
  2. 导航到“部署中心”。
  3. 点击进入并检查部署日志。

将日志窗口放大后,可以清晰地看到关键信息。日志显示容器正在“等待响应以进行预热”,并且已经等待了超过60秒。更关键的是,日志中有一行提示:Do run port 80

这个信息至关重要。它表明Azure应用服务默认期望容器在80端口上提供服务,而我们的容器却配置在了8000端口。由于端口不匹配,Azure的健康检查无法收到响应,导致部署状态一直卡在“等待”中,最终会超时失败。

与语法错误故障的对比

回顾之前遇到的语法错误问题,其排查方式有所不同。我们需要在冗长的日志中向上滚动查找。在接近顶部的位置,可以找到之前引入语法错误的具体报错信息。虽然日志记录了错误,但在大量输出中定位它有一定难度。

总结来说,我们目前遇到了两种会导致部署失败的常见问题:

  1. 错误端口:容器监听端口与平台期望端口不匹配,导致健康检查失败。
  2. 无效代码:如语法错误,导致容器在启动阶段就直接崩溃。

总结

本节课我们一起学习了容器部署中的两种故障排查。我们模拟了配置错误端口的情况,发现服务会无响应,并通过检查Azure部署日志找到了“Do run port 80”的关键线索。这与直接导致容器启动失败的语法错误形成了对比。对于这类端口错误,预防措施是在代码中或通过测试确保容器暴露的端口与云平台(如Azure App Service)的期望端口一致。掌握查看和分析部署日志的技能,是快速定位和解决这类运维问题的关键。

186:微调理论入门 🎯

在本节课中,我们将探讨迁移学习相较于其他机器学习方法的优势,并解释其核心概念,特别是如何通过微调(Fine-tuning)来高效地创建高质量的模型。


迁移学习的优势

上一节我们介绍了机器学习的基本概念,本节中我们来看看迁移学习带来的独特优势。

一种非常经典的机器学习类型是监督式机器学习。许多人听说过它,其本质是利用历史数据训练一个模型,然后进行预测。例如,根据球员的数据点预测其未来的薪资,这就是一个经典的监督式机器学习问题。

在自然语言处理领域,你可以看到这样的例子:拥有一些新闻数据,通过处理并创建一个摘要模型。这个模型可能在大量数据上进行训练,可能是一个拥有数十亿参数的大语言模型,其创建过程会非常昂贵。

如果你遇到另一种NLP问题,并且属于不同的领域,例如一个文学数据集,你就必须重复上述过程,创建一个不同类型的新闻摘要模型。这个模型也可能有数十亿参数,并且非常昂贵。

这里的问题是,对于许多人或组织而言,他们既没有足够的原始数据作为起点,也没有计算资源来进行这种全球规模的监督式机器学习。

幸运的是,这正是迁移学习发挥作用的地方。这也是抱脸平台的优势之一:你可以获取一个在特定领域(例如新闻数据集)上训练过的模型,然后利用该模型的主体部分。你可以替换模型的“头部”,例如新闻摘要模型的头部,并用少量数据对其进行微调,从而得到一个可用的预测模型。

同样地,你也可以在一个完全不同的领域上对模型进行微调。假设一个模型是在新闻数据上训练的,你可以获取文学数据,再次利用其主体部分。这个主体可能包含数十亿参数,并由世界顶尖的机器学习工程师和研究人员训练而成。然后,你只需使用少量新数据,创建一个评估指标,并用这些新数据为该特定微调任务配置一个新的“头部”,之后你就能进行预测了。

因此,核心思想是:你可以创建高质量的模型,这些模型训练效率极高,并且能应用于另一个领域。这是迁移学习的关键优势之一,也是其在抱脸平台上应用的方式。


核心概念总结

本节课中我们一起学习了迁移学习,特别是微调的核心优势。我们了解到,与需要海量数据和计算资源的传统监督学习相比,迁移学习允许我们复用预训练模型(其主体部分),并仅用少量新数据和计算资源来微调其“头部”,从而高效地为新领域或新任务创建高质量的预测模型。这种方法极大地降低了机器学习的门槛和成本。

187:执行模型微调 🚀

在本节课中,我们将学习如何利用Hugging Face的官方教程,在两种不同的计算环境中执行模型微调任务,并对比其性能差异。

概述

模型微调是机器学习中的一个关键步骤,它允许我们在预训练模型的基础上,使用特定领域的数据进行进一步训练,从而提升模型在特定任务上的性能。本节将指导你如何实际操作一个微调流程。

上一节我们介绍了模型微调的基本概念,本节中我们来看看如何具体实施。

访问官方教程与代码

首先,查看Hugging Face的官方文档和配套课程。该课程包含许多有用的内容,但我们将重点关注“微调预训练模型”这一部分,以了解如何自行实现。

选择课程中的相应按钮,它会打开一个Colab笔记本。该笔记本提供了清晰的章节概述,代码量并不大。主要步骤包括:

  • 安装必要的软件。
  • 定义数据分词函数。
  • 配置训练器。
  • 执行训练以完成微调,并展示过程。

在Colab CPU环境中进行基准测试

如果想自行运行此代码并追求更高的准确率,可以使用Colab环境。默认情况下,它会连接到一个基于CPU的运行环境。我们可以通过“更改运行时类型”来确认没有启用硬件加速。

这提供了一个很好的基准测试机会,让我们了解在仅使用CPU的普通硬件上微调模型所需的时间。

以下是执行步骤:

  1. 运行“运行时”菜单下的“全部运行”命令。
  2. 首先会启动安装过程。由于软件并非预装在Colab机器上,这可能需要一些时间。
  3. 安装完成后,代码会加载数据集,这也可能需要一些时间。
  4. 接着,代码会设置训练任务,获取预训练模型。
  5. 最后,进入实际的微调步骤。

这是一个很好的基准,展示了在只有CPU的Colab笔记本上微调模型的情况。我们可以看到,训练开始了三个周期,但每一步都耗时较长。根据进度推断,完成整个训练可能需要20到30分钟。

在启用GPU的代码空间中加速微调

现在,让我们回到代码,看看在启用了GPU的Github代码空间中运行相同代码的效果。基本流程是复现相同的代码逻辑。

核心代码结构如下:

from datasets import load_dataset
# 导入所需的transformer组件,例如训练参数
# 下载要使用的数据(本例中是GLUE数据)
# 创建分词函数
# 设置模型所需的所有参数
# 创建计算评估指标的函数
# 配置训练器,指定使用的数据
# 设置评估指标
# 运行训练

我们可以执行nvidia-smi -l 1命令来启动GPU监控。然后,在屏幕上方的终端中运行训练任务。

执行命令:

python huggingface_ft_fine_tuning_course_example.py

我们将官方文档的示例代码在此特定环境中运行。虽然下载数据等步骤仍需时间,但由于可用的GPU资源,训练过程将显著加快。

可以看到,训练正在非常快速地进行。GPU监控显示GPU已被调用,负载很高(例如Tesla V100)。与此同时,之前在Colab CPU上运行的训练任务进度仍然缓慢。

在训练微调任务时,我们可以获取所关心的评估指标(例如F1分数),并希望这个分数越来越好。随着指标的提升,我们就能构建出使用自定义数据的优质微调模型。

这是一个展示拥有自有GPU资源进行微调的优势的好例子:你可以获得更高的准确率。代码中可能有一个基线准确率,而微调后我们得到了改进的新准确率。

此外,我们还可以在代码的TrainingArguments中稍作调整,设置将模型推送到Hugging Face平台,保存为一个新的托管模型。这与Hugging Face上其他用户的做法类似。例如,在Hugging Face模型库中查看文本摘要模型,会发现许多模型都是基于原始架构(如Facebook的模型)进行微调后发布到特定目录下的。你也可以通过微调来做同样的事情。

使用这些GPU资源,训练任务很快就能完成。这是在自有模型上进行微调实验的绝佳方式。

总结

本节课中我们一起学习了模型微调的实际操作。我们对比了在Colab的CPU环境和启用GPU的代码空间中进行微调的性能差异,直观地展示了GPU对于加速训练过程的重要性。同时,我们也了解了如何将微调后的模型推送到Hugging Face平台进行托管和分享。

188:ONNX与Hugging Face介绍 🧠

在本节课中,我们将学习ONNX(开放神经网络交换)格式以及如何将其与Hugging Face库结合使用。我们将了解ONNX如何实现跨框架的模型部署,并介绍开始使用所需的关键概念和工具。

概述

为了使用Hugging Face和ONNX,我们需要理解几个核心概念。首先,我们将查看ONNX的官方入门页面,它提供了在深入细节之前需要了解的有用信息。

无论你选择使用何种框架来创建或处理模型,你都可以将其导出为一种标准化的格式,即ONNX格式。ONNX格式允许你将模型部署到不同类型的架构上,而无需关心模型最初来自哪个机器学习框架。最后,许多云服务原生支持ONNX格式,这意味着你可以直接与之交互,而不必被绑定在某个特定的框架上。

今天我们将重点讨论如何导出到ONNX格式。我们会快速了解ONNX模型库,并主要使用我们一直在学习的Hugging Face进行实践。使用ONNX进行推理以及将模型导出到其他框架,是我强烈建议你学习和实践的内容。

环境设置与依赖

现在,让我们看一下我准备的 huggingface-onyx 代码仓库。快速浏览一下环境配置文件(YAML文件),了解我们将要使用的依赖项。

主要的依赖项包括:

  • Python 3.8
  • 从PyTorch频道安装的 PyTorch
  • 这是一个Conda环境文件,意味着我们将使用Conda来管理环境。
  • 安装 Hugging Face Transformers 库,并带有特殊标记 [onnx],这将拉取一些额外的依赖项。
  • 最后是 ONNX Runtime 和一些用于Jupyter Notebook的额外工具。

依赖项相当简单,不多,这能让你快速上手运行。

探索入门笔记本

接下来,我们需要探索一下本部分的笔记本。我们将完成其入门部分。让我们快速运行这个笔记本,使用Conda安装依赖项。这就是这里的入门笔记本。

首先,你需要确保使用的是正确的解释器。我使用的是刚刚创建的Conda基础内核,并确保Conda安装了所有依赖项。

这里有一个简短的介绍,再次说明了你需要用Conda安装的内容。请注意,这可能不完全匹配你需要安装的所有东西,所以请参考包含所有必需项的环境YAML文件,它会更新为你需要做的确切步骤。

使用Hugging Face预配置模型

Hugging Face能够使用已经配置好、无需你额外设置的模型。对于一些最流行、最受欢迎的模型,如BERT、OpenAI GPT-2、RoBERTa和T5,你可以直接使用。

安装所有依赖项后,你可以通过执行帮助菜单来确保一切正常。你可以使用 transformers.onnx 的帮助命令,这将显示你正在使用的库的ONNX部分,以便你可以开始与之交互。

你将通过以下方式运行Python的 -m 模块:transformers.onnx 作为一个命令行工具。让我们稍微查看一下帮助菜单的输出。这是验证安装是否成功、一切是否就绪的方法。

这里你有模块,然后传递参数。我们将查看可用的功能。opset 是ONNX的操作集版本,我们不会深入讨论。你可以看到,你可以从TensorFlow或PyTorch导出,默认我们将使用PyTorch。这里还有一些额外的设置,我们也不会涉及。

你需要做的一件事是使用位置参数 output,我们稍后会看到它是如何工作的。你可以为生成的ONNX模型指定任何你想要的名称。

理解模型配置

向下滚动,我们主要想知道我们将使用哪种类型的配置。在这里,你可以看到我从 transformers.models.roberta 导入了 RobertaConfigRobertaOnnxConfig。这些来自Transformers库本身。

运行这段代码,我将能够看到我有几种不同类型的功能配置可供选择。我可以选择其中一个,并查看RoBERTa模型中具体有哪些可用选项。

这里有一些建议阅读材料,Hugging Face Transformers的文档非常棒。但今天我想涵盖的主要内容基本上是:你如何获取所有这些依赖项、我们如何使用ONNX(更确切地说是Conda)、我们如何确保选择了正确的Conda内核、我们如何验证其工作、我们探索了将要使用的一些不同功能和标志及其工作原理。我将在另一个视频中详细展示,但具体来说,配置是非常关键的一环。

ONNX模型库

最后,我想向你展示模型库。如果你从未听说过模型库,它位于GitHub上的 onnx/models,被称为ONNX模型库,因为这是人们通常存储ONNX模型的地方。

让我们快速浏览一下。仓库包含大量信息,但我特别想谈谈机器阅读理解。我们查看一下,那里有GPT-2、BERT on SQuAD,但我想展示我真的很喜欢和使用的RoBERTa。

这里有依赖项、模型描述,你甚至可以下载它们。这些模型使用Git LFS存储在GitHub上。你可以查看模型的详细信息,例如支持的ONNX版本和操作集版本。这是使用ONNX时需要理解的两个关键细节。

你甚至可以看到一些关于预处理、输出以及如果你要使用ONNX进行工作时期望结果的信息。你还可以看到它已经在使用Hugging Face Transformers,因为序列分类器和分词器也来自那里。

所以,每当你听到“让我们看看ONNX模型库”,这意味着你正在查看GitHub上的 onnx/models 组织和模型仓库。

总结

本节课中,我们一起学习了开始使用ONNX和Hugging Face所需的关键概念。我们了解了ONNX格式如何实现跨框架的模型互操作性,设置了包含必要依赖项(如PyTorch、Transformers[onnx]和ONNX Runtime)的Conda环境,并探索了如何通过命令行工具和预配置来使用Hugging Face的ONNX功能。最后,我们介绍了ONNX模型库作为查找和下载预转换ONNX模型的资源。掌握这些基础知识,将为你在实际项目中部署和优化机器学习模型打下坚实的基础。

189:将Hugging Face模型导出为ONNX格式

概述

在本节课程中,我们将学习如何将Hugging Face平台上的预训练模型导出为ONNX格式。ONNX是一种开放的模型格式,旨在提高模型在不同框架和硬件平台之间的互操作性。我们将通过一个具体的例子,演示使用命令行工具将distilbert-base-cased模型转换为仅用于“问答”任务的ONNX模型。

准备工作

在开始之前,请确保你的Jupyter Notebook运行在正确的内核环境中。本示例使用了一个通过Conda管理的环境,该环境已安装了所有必要的依赖库。

探索模型支持的任务

首先,我们需要从transformers.onnx模块中导入FeaturesManager,以查看目标模型支持哪些类型的任务。

以下是导入代码和查看功能的步骤:

from transformers.onnx import FeaturesManager

运行上述代码后,我们可以查询特定模型(例如distilbert-base-cased)支持的功能。对于这个模型,可能支持的任务包括序列分类、多项选择、标记分类和问答等。了解模型支持的任务对于后续的针对性导出至关重要。

导出模型为ONNX格式

如果我们明确需要一个执行特定任务(例如“问答”)的模型,我们可以使用transformers.onnx模块作为命令行工具,将Hugging Face模型导出为专注于该任务的ONNX模型。

以下是导出命令的分解说明:

  • 工具调用:使用python -m transformers.onnx来调用模块。
  • 指定模型:通过--model参数指定要转换的模型,本例中为distilbert-base-cased-finetuned-sst-2-english
  • 指定功能:通过--feature参数指定要导出的模型功能,本例中为question-answering
  • 输出路径:命令末尾的.表示将生成的ONNX模型文件保存在当前目录。你也可以指定一个具体的路径和文件名。

完整的导出命令如下:

python -m transformers.onnx --model=distilbert-base-cased-finetuned-sst-2-english --feature=question-answering .

执行此命令后,程序会开始下载模型并进行转换。这个过程可能需要几秒钟时间。

验证导出结果

命令执行完成后,我们需要在输出信息中寻找“Model validated successfully”或类似的成功验证提示。这表示模型已成功导出并通过了检查。

同时,输出信息中会显示生成的ONNX模型文件名(例如model.onnx)以及模型的输入输出名称。这些信息在后续使用该ONNX模型时非常重要。

回到Jupyter Notebook的文件浏览器,你应该能看到新生成的model.onnx文件,这证实了导出操作的成功。

总结

本节课我们一起学习了将Hugging Face模型导出为ONNX格式的完整流程。我们首先使用FeaturesManager探索了模型支持的任务,然后通过transformers.onnx命令行工具,指定模型和所需功能(如question-answering),成功生成了对应的ONNX模型文件。这种方法使得我们能够将Hugging Face上丰富的预训练模型,便捷地转换为适用于不同推理引擎和硬件加速器的ONNX格式,极大地增强了模型的部署灵活性。

190:Hugging Face Spaces 介绍 🚀

在本节课中,我们将学习 Hugging Face Spaces 平台。这是一个可以探索社区创建的优秀机器学习应用,以及创建你自己新项目的平台。我们将了解如何浏览、测试他人的模型应用,并学习如何快速创建和部署自己的简单应用。

探索社区应用 🧭

上一节我们介绍了 Hugging Face Spaces 的概念,本节中我们来看看如何发现和体验社区中已有的有趣应用。

浏览平台时,查看最新或最受欢迎的项目是一个好主意。例如,你可以找到 Dolly、Mini 或 Stable Diffusion 等模型的应用。这些应用通常设计得很有趣,便于交互体验。

以下是探索社区应用的步骤:

  1. 访问 Hugging Face Spaces 主页。
  2. 浏览“Most Likes”或“Trending”等栏目,发现热门应用。
  3. 点击任意应用卡片即可进入并开始交互。

以 Stable Diffusion 为例,你只需在输入框中输入提示词(例如 “Mickey Mouse on the moon” 🐭),应用就会调用托管在 Hugging Face 上的预训练模型进行推理,并生成相应的图像。

深入研究模型与应用 🔍

除了直接使用应用,我们还可以深入研究其背后的模型,并查看其他开发者是如何使用这些模型的。

例如,如果我们对文本摘要任务感兴趣,可以进入模型板块,选择“Text”类别下的“Summarization”。找到如“Google Pegasus”这样的模型页面后,向下滚动,可以看到“Used in Spaces”部分。这里列出了所有使用了该模型的应用实例。

这种方式非常有用:

  • 快速测试模型:你可以在模型页面的“Hosted inference API”小部件中直接输入文本进行测试。
  • 学习实现方法:点击任意一个关联的 Space 应用,进入其文件页面(通常在 app.py 中),你可以查看并复制其源代码,了解如何将该模型集成到一个完整的应用中。

创建你自己的 Space 🛠️

现在,我们来动手创建自己的 Space。这是将你的想法快速原型化的最佳方式。

首先,点击主页的 “New Space” 按钮。你需要填写一些基本信息:

  • Space 名称:例如 MyDemoSpace
  • SDK:选择构建应用的技术栈。Gradio 与 Hugging Face 集成最紧密,非常适合快速创建机器学习界面。

创建完成后,你有两种主要方式开始开发:

  1. 在线开发:直接在 Space 的网页编辑器中编写代码。
  2. 本地克隆:使用 Git 将 Space 仓库克隆到本地,在熟悉的环境中进行开发。

快速原型开发实例 ⚡

让我们尝试在线快速构建一个“Hello World”应用。

在 Space 的文件页面,点击 “Create new file”,命名为 app.py。然后,你可以粘贴一段简单的 Gradio 代码:

import gradio as gr

def greet(name):
    return "Hello " + name + "!"

demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch()

保存文件后,Space 会自动开始构建。你可以在 “Logs” 选项卡实时查看构建过程。构建成功后,你的应用就会自动发布并提供一个可访问的 URL。

此时,你可以在应用界面输入文本,体验交互过程。通过修改 app.py 中的代码,你可以不断迭代,快速验证关于数据或模型的想法。

总结 📝

本节课中,我们一起学习了 Hugging Face Spaces 的核心功能。

我们首先了解了如何作为一个使用者,去探索和体验社区中丰富多样的机器学习应用。接着,我们学会了如何深入研究模型,并借鉴他人应用的实现代码。最后,我们亲自实践了如何创建和部署一个属于自己的 Space 应用,体验了其快速原型开发的强大能力。

Hugging Face Spaces 极大地降低了机器学习应用的门槛,无论是学习、实验还是分享,它都是一个极其有价值的平台。

191:Hugging Face Spaces 操作演练 🚀

在本节课中,我们将学习如何使用 Hugging Face Spaces 来快速构建和部署机器学习演示应用。我们将通过几个具体示例,展示如何利用现有的代码和模型,在本地或云端快速创建交互式应用。


概述

Hugging Face Spaces 提供了一种简便的方式,可以直接在你的个人资料页面上托管机器学习演示应用。如果你想深入了解其功能,最佳起点是查阅官方文档。文档中展示了各种演示案例,你可以查看其依赖项等信息。此外,你还可以申请 GPU 升级以加速计算,这对于个人项目非常有用。你也能安装其他软件包,例如 PyTorch、JAX 等。

探索与构建应用

上一节我们介绍了 Spaces 的基本概念,本节中我们来看看如何实际探索和构建应用。

如果查看 Gradio 的 Spaces 页面,你会发现大量关于如何构建自己应用程序的文档。其核心思想是,你可以快速加载并构建已有的应用程序。

示例一:热狗分类器 🌭

一个经典的例子是热狗分类器。在文档中找到相应代码后,你可以选择运行环境。虽然可以在 Spaces 界面中直接运行代码,但使用 GitHub Codespaces 也是一个极佳的选择,它为构建演示提供了出色的界面。

以下是在本地环境中运行热狗分类器的核心代码:

import gradio as gr
from transformers import pipeline

# 加载预训练的热狗分类管道
classifier = pipeline("image-classification", model="julien-c/hotdog-not-hotdog")

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/5c62f0a1ee5c6f5ff301638dc1db708f_4.png)

def classify_image(image):
    result = classifier(image)
    return result[0]['label']

# 创建 Gradio 界面
interface = gr.Interface(fn=classify_image, inputs="image", outputs="text")
interface.launch()

运行此代码后,应用会启动。你可以上传一张图片(例如从互联网上找到的热狗图片)进行测试。应用会判断图片中是否包含热狗,并给出结果。你既可以在他人的应用界面中体验,也可以在本地运行并迭代改进。

示例二:文本生成演示 📝

接下来,我们看看另一个演示:文本生成。这个例子非常简单,代码如下:

from transformers import pipeline
import gradio as gr

# 定义文本生成模型
generator = pipeline('text-generation', model='gpt2')

![](https://github.com/OpenDocCN/dsai-notes-zh/raw/master/docs/duke-dataops/img/5c62f0a1ee5c6f5ff301638dc1db708f_6.png)

def predict(prompt):
    # 使用模型生成文本
    completion = generator(prompt)[0]['generated_text']
    return completion

# 创建界面
interface = gr.Interface(fn=predict, inputs="text", outputs="text")
interface.launch()

运行此应用后,你可以在输入框中输入文本(例如“The fastest man in the world”),模型会基于此生成后续内容。这种快速的反馈循环得益于本地环境和已安装的库,使得原型设计非常高效。

示例三:数据集交互演示 📊

除了模型,你还可以构建与数据集交互的应用。例如,下面是一个用于产品预测的数据集演示:

import gradio as gr
from datasets import load_dataset

# 加载数据集
dataset = load_dataset("merve/supereffective-product-prediction")

def add_row(title, description):
    # 此处应包含将新数据行添加到数据集的逻辑
    # 为演示简化,这里仅返回输入信息
    new_entry = {"title": title, "description": description}
    # 实际应用中,你会将 new_entry 添加到 dataset 并可能重新训练模型
    return f"Added: Title - {title}, Description - {description}"

# 创建界面
interface = gr.Interface(fn=add_row, inputs=["text", "text"], outputs="text")
interface.launch()

运行此应用,你可以输入产品的标题和描述,模拟向数据集中添加新数据行。这种界面让你能够快速试验数据属性和模型行为。

核心优势

使用 Gradio 和 Hugging Face Spaces 的主要优势在于能够快速原型化数据属性和模型属性。你可以在一个统一的界面中,高效地测试想法、展示成果并与他人分享。


总结

本节课中,我们一起学习了 Hugging Face Spaces 的基本操作。我们通过热狗分类器、文本生成和数据集交互三个具体示例,演示了如何快速构建和迭代机器学习演示应用。关键在于利用现有的代码库和 Gradio 库,在本地或云端环境中实现快速的开发反馈循环。这为展示模型能力、测试数据想法提供了强大而便捷的工具。

192:部署Hugging Face Spaces应用

在本节课中,我们将学习如何利用GitHub生态系统,为Hugging Face Spaces应用实现持续交付。我们将涵盖从获取访问令牌、配置自动化工作流,到本地测试和自动部署的完整生命周期。

概述

持续交付是现代机器学习运维的核心实践之一。它允许开发者自动地将代码变更部署到生产环境,同时确保质量和稳定性。本节将演示如何为Hugging Face Spaces上的应用搭建这样一个自动化流程。

核心流程与配置

上一节我们介绍了持续交付的概念,本节中我们来看看如何为Hugging Face Spaces应用具体配置。

整个持续交付流程的核心在于利用GitHub Actions自动化工作流。以下是实现此流程的关键步骤:

  1. 获取Hugging Face访问令牌:首先,需要在Hugging Face账户中生成一个访问令牌。这个令牌是进行自动化操作的身份凭证。
  2. 在GitHub中配置密钥:将上一步获取的Hugging Face令牌,以密钥的形式添加到GitHub仓库的Settings -> Secrets and variables -> Actions中。
  3. 创建GitHub Actions工作流:在项目的.github/workflows/目录下创建一个YAML文件来定义自动化流程。

一个典型的工作流配置示例如下:

name: Sync to Hugging Face
on:
  push:
    branches: [ main ]
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Push to Hugging Face
        uses: huggingface/huggingface_hub@main
        with:
          hf_token: ${{ secrets.HF_TOKEN }}
          local_dir: .
          repo_id: your-username/your-space-name

在这个配置中:

  • on: push 指定当代码推送到main分支时触发工作流。
  • secrets.HF_TOKEN 引用了我们在GitHub中配置的Hugging Face令牌。
  • repo_id 需要替换为你的Hugging Face用户名和Space名称。

本地开发与测试

在代码被自动部署到Spaces之前,进行本地测试至关重要。这可以确保应用功能正常,避免将有问题的版本部署到线上。

我们可以利用GitHub Codespaces或本地开发环境来运行和测试应用。以下是测试一个文本摘要应用的基本方法:

  1. 在开发环境中启动Gradio应用界面。
  2. 通过生成的本地URL在浏览器中访问该界面。
  3. 在界面中输入文本(例如一段关于Python语言的描述)进行功能测试。

如果应用能够正确返回摘要结果,就证明本次变更是有效的,可以安全地触发后续的自动化部署流程。

持续交付的价值

通过结合GitHub Actions和Hugging Face Spaces,我们构建了一个高效的持续交付管道。其优势主要体现在以下几个方面:

  • 自动化:代码推送后,构建、测试和部署过程完全自动化,无需手动干预。
  • 快速反馈:如果自动化流程中的任何一步(如测试)失败,开发者会立即收到通知,可以快速定位和修复问题。
  • 可靠部署:只有通过所有预设检查的代码变更才会被部署,保证了生产环境应用的稳定性。
  • 开发体验:开发者可以在本地或Codespace中舒适地开发、原型设计和测试,然后自信地将代码变更交付出去。

总结

本节课中我们一起学习了为Hugging Face Spaces应用实现持续交付的完整流程。我们从配置Hugging Face令牌和GitHub Actions工作流开始,探讨了如何在本地测试Gradio应用,最终实现了代码变更的自动部署。这套实践将帮助您更高效、更可靠地管理和迭代您的机器学习应用。

193:利润共享概念 💰

在本节课中,我们将要学习利润共享的不同模式及其在社会和微观经济学框架下的意义。理解这些概念有助于我们分析技术、商业机会和社会影响。

利润共享的模式多种多样,每种模式都有其优缺点。我们可以从几个核心类别来审视它们。

以下是四种主要的利润共享模式:

  • 搭便车者:指那些享受产品或服务带来的好处,却未支付相应费用的人或实体。
  • 寻租者:指试图通过最小化自身工作量,同时获取租金或支付的行为者。
  • 平台:作为连接供需双方的中介,通过收取交易费用等方式获取利润。
  • 产品:指生产者直接将商品售卖给消费者,获取全部利润的模式。

搭便车者模式 🆓

上一节我们概述了利润共享的几种模式,本节中我们首先来看看“搭便车者”模式。

一个典型的例子是公共广播和电视。许多人每天收听公共广播,但从不支付订阅费,他们就是搭便车者。他们获得了利益却没有支付任何成本。如果足够多的人不付费,公共广播将无法维持。软件盗版也是如此。如果一个软件包可以被免费下载,最终若足够多人成为搭便车者,软件将无利可图,开发者也就失去了继续开发的动力。生成式人工智能也可能面临类似问题。如果从报纸、电影到书籍、软件的所有内容都被无偿消费且没有利润分享,那么最终生产这些内容的动机将消失,可能导致所有创造性产出归零。当然,如果搭便车者只是少数,或许影响不大,但这是一个需要意识到的问题。

寻租者模式 🏦

了解了搭便车者可能带来的问题后,我们接下来探讨“寻租者”模式。寻租行为并非绝对,存在一个梯度,其核心是希望以尽可能少的工作获取某种租金或报酬。

风险投资是一个很好的例子。在某些情况下,一家风投公司可能投资100家公司,他们知道其中可能有95家会破产。那95家公司及其员工承担了巨大风险,他们本可以在成熟公司获得更高的薪水和奖金,但实际得到的期望价值更低。期望价值 = 利润 × 事件发生概率。在这个例子中,成功概率可能只有5%。因此,是创业者在承担所有风险,而风投公司则通过投资组合来对冲风险并获取利润。图书出版商在某些情况下也可能被视为一种寻租形式。有时出版商为作者做了很多,有时则做得很少,但他们通常能获得图书收入的10%到15%。在这类场景中,通常存在高度的管理控制,因为资金掌握在他们手中,他们拿走了大部分利润,并可能将其再投资回组织。至于这是否为社会或产品增加了价值,需要具体情况具体分析。

平台模式 📱

在寻租模式中,资金管理者可能获得大部分利润。与之不同,平台模式则扮演着中介角色。

平台也有一些好处。如果你能获得80%的利润,那对你来说很棒。但如果存在无情的竞争,这对你就不利了。经济学中有一个表述:在完全竞争下,利润最终为零。这意味着,如果平台无法限制参与者加入,甚至无法区分优劣,这确实可能导致利润被消除。平台本身则可能因为拥有大量相互竞争的参与者并通过收取交易费而赚取大量金钱。我们可以从职业体育联盟看到不同的利润分享比例。例如,UFC的选手分成比例较低,约为17%到20%。而更成熟的组织如NFL,则能达到合伙人级别的分成,即50%的收入返还给球员。篮球和棒球等联盟也有类似的比例。这展示了一种合伙人均衡,其中的权衡开始对劳动者和所有者双方都有意义,这可能是一个值得考虑的“甜蜜点”。

产品模式 🍎

最后,我们来看对所有者而言最理想的场景——“产品”模式。

假设你是一个农民,直接在路边销售水果,你获得了100%的利润。这里没有交易费用,没有中间商参与。你是直接将产品卖给客户。因此,每当你听到一个机会、一项新技术或你在思考的某些新事物时,考虑这一点很重要:上述每种模式都存在权衡。搭便车者有权衡,寻租者有权衡,平台有权衡,产品也有权衡。重要的是要睁大眼睛看清场景,并从伦理角度思考:当你与采取其中某种行为的公司打交道时,它对社会产生了什么影响。


本节课中,我们一起学习了利润共享的四种核心模式:搭便车者、寻租者、平台和产品。每种模式都有其特定的运作方式、潜在问题和社会影响。理解这些概念有助于我们在技术开发和商业决策中,更全面、更理性地评估利益分配及其长远后果。

194:生成式AI的公共资源困境

概述

在本节课中,我们将要学习一个重要的经济学与社会学概念——“公地悲剧”,并探讨这一概念如何应用于生成式人工智能领域。我们将分析当一项资源被无限制地共享时可能出现的各种问题,并审视生成式AI在知识产权、就业、质量控制和伦理方面带来的具体挑战与外部性影响。

公地悲剧简介

上一节我们概述了课程内容,本节中我们来看看“公地悲剧”这一核心概念。

“公地悲剧”是一个经典案例,它描述了当一项免费资源被实际上无限数量的人群共享时可能发生的情况。

以下是几种可能发生的情形:

  • 乱扔垃圾:人们可能到处乱扔垃圾,仅此一项就足以毁坏一个公共公园。
  • 过度拥挤:如果没有管制,持续不断的人群涌入可能导致公园过度拥挤,最终使得人们无法游览公园。
  • 栖息地破坏:例如,在国家公园内破坏某些自然景观或山体部分,会导致其不再像以往那样美丽。
  • 经典案例:不同公司拥有牛群,一些牧场主会竞相让牛吃最多的草,因为他们担心别人会比自己消耗得更快。这演变成一场“逐底竞争”,很快草地就会被消耗殆尽,遭到破坏。

这就是“公地悲剧”的经典案例。事实上,根据各地的管制情况不同,你可以在世界范围内(包括美国)的某些公共公园看到这种现象。

生成式AI的公地悲剧

理解了传统公地悲剧后,本节我们来看看生成式AI领域存在的类似困境。

生成式AI的公地悲剧具有一些相似的特征。

以下是生成式AI可能引发的具体问题:

  • 知识产权盗窃:生成式AI模型可能在未经授权的情况下,使用受版权保护的作品进行训练。这可能会贬低原作品的价值,甚至削弱创作者创作新内容的动力。如果作品会被窃取,为何还要创作更多?
  • 工作替代:生成式AI存在风险,可能导致人类创作者的需求下降,进而引发工作替代,并产生相关的负面外部性。如果这些人无法再获得工作,社会就必须承担这种工作替代带来的负担。
  • 质量控制:生成式AI的输出作品可能质量低劣,这甚至会贬低艺术家的价值,因为低质量作品看起来是在模仿该艺术家。这可能导致整体的质量控制问题。
  • 缺乏认可或归属:创作者的作品可能在未经补偿的情况下被窃用,甚至他们作为原创者的身份也得不到认可。这会令人沮丧且不公,并可能严重影响该艺术家未来获得工作的机会。
  • 伦理关切或精神权利:作者可能不希望自己的形象与吸烟、饮酒或其他恶习相关联,而生成式AI的使用者并未征得其许可。

因此,对于生成式AI而言,传统的公地悲剧场景并非神奇地不存在,这些问题同样存在。我们需要同时审视其益处(如总结、提纲生成、内容协同创作等强大功能)和负面外部性。

思考社会影响

上一节我们列举了生成式AI的具体问题,本节我们来思考其更广泛的社会影响。

我们需要审视对社会的影响,即社会并未从某些方面受益的情况。例如,如果是一个商业模型在获利,社会并未得到那份报酬,却必须支付成本。

这再次类似于在公园乱扔垃圾、过度拥挤或破坏公园:你必须为他人滥用资源的行为付出代价。

总结

本节课中,我们一起学习了“公地悲剧”的概念及其在生成式AI伦理中的体现。我们探讨了无管制共享资源导致的过度使用和破坏问题,并具体分析了生成式AI在知识产权、就业、质量控制和伦理方面引发的挑战与负面社会影响。在思考生成式AI的伦理时,考虑公地悲剧至关重要。

195:生成式AI博弈论 🎲

在本节课中,我们将学习博弈论的基本概念,并探讨如何将其应用于理解生成式AI(如大型语言模型)可能引发的系统性风险。我们将通过经典的“囚徒困境”模型,来分析在缺乏合作与迭代策略的情况下,各方如何可能陷入“逐底竞争”的恶性循环。


博弈论简介

博弈论是一个数学框架,用于研究具有玩家、策略和收益的互动游戏,旨在找出最优策略,或分析在特定情境(如囚徒困境)中导致次优结果的“主导策略”。

上一节我们介绍了博弈论的基本定义,本节中我们来看看其最经典的案例。

囚徒困境

囚徒困境是经典的博弈论问题。在这个问题中,自私的主导策略将导致对所有人而言的次优结果。

想象你是一名检察官,你逮捕了涉嫌犯罪的Sam和Helen,但缺乏定罪两人的证据。唯一获取所需证据的方法是让他们互相揭发。

以下是收益矩阵的分析:

  • 双方都保持沉默:每人仅被判入狱1年。
  • 一方坦白,另一方沉默:坦白者将获释(0年),而沉默者将入狱20年。
  • 双方都坦白:每人将入狱5年。

检察官通过分别向两人提供激励,促使他们坦白。即使双方合作保持沉默(总刑期2年)是最优结果,但由于彼此不信任,理性的个体都会选择坦白以避免最坏情况(20年)。最终,双方都选择了坦白这一“主导策略”,导致每人入狱5年,比合作结果多坐了4年牢。

这个案例展示了当系统设置导致所有人受损时,我们可以从博弈论的角度进行思考。接下来,我们将此视角应用于生成式AI领域。

生成式AI中的博弈论风险

在生成式AI的背景下,类似的博弈动态可能导致“逐底竞争”,即各方为短期利益采取行动,最终损害整个生态系统的长期健康。以下是几个潜在场景:

1. 内容审核的放松

假设未来所有内容审核都由某个AI系统完成。平台有强烈的经济激励来确保用户参与度,因为参与度低会导致公司收入减少。

因此,即使平台上充斥着低质量的生成式AI内容,平台也可能选择放松审核标准,因为这直接影响其利润底线。一旦竞争对手也开始因此亏损,双方都会调整内容审核策略。

以下是可能发生的连锁反应:

  1. 平台A为保收入,降低审核标准。
  2. 平台B发现用户流向A,被迫跟进,也降低标准。
  3. 双方审核标准越来越宽松。
  4. 最终,平台可能充斥低质量、甚至有毒的生成式AI内容。

这个过程可被称为 “逐底竞争”

2. 知识产权盗用的恶性循环

在生成式AI领域,可能陷入一种假设性困境:假设竞争对手或他国政府将盗用知识产权。

出于这种预期,你感到自己也不得不盗用相同的知识产权以保持竞争力。结果如下:

  1. 一方因担心对方盗用,率先放弃尊重知识产权。
  2. 另一方作为回应,也开始盗用。
  3. 最终,知识产权概念可能被彻底侵蚀。

这同样是一种 “逐底竞争”,因为行动是基于对他人将做坏事的预期。

3. 创意作品质量的下降

此场景直接映射囚徒困境。假设你感觉竞争对手可能开始使用由简单提示生成的劣质AI作品。

你的应对策略可能是:

  1. 竞争对手为降低成本/提高产量,使用劣质AI生成内容。
  2. 你为保持市场竞争力,被迫采取相同策略。
  3. 双方作品质量越来越差。
  4. 最终,市场上充斥低质量“艺术”。

结果是所有人皆输:客户得不到好作品,真正的艺术家失业,最终可能再无优质艺术产生。


总结与启示

本节课中,我们一起学习了博弈论的核心思想,并通过囚徒困境模型,分析了生成式AI可能引发的三种“逐底竞争”风险:内容审核失效、知识产权体系崩溃以及创意质量下降。

关键启示在于:如果只从追求单次博弈的“主导策略”角度思考,而不进行多轮迭代与合作,就可能导致对所有参与者而言的次优结局。

因此,在考虑像生成式AI这样的新技术时,一个非常重要的问题是:它的潜在影响是什么?以及我们如何能创建一种迭代的合作策略,以避免陷入“逐底竞争”的陷阱?这需要开发者、企业、政策制定者等多方建立长期视野与协作机制。

196:完全竞争市场中的AI战略思考 💡

在本节课中,我们将从经济学的“完全竞争市场”视角,探讨人工智能(AI)领域,特别是大语言模型(LLM)的商业策略。我们将通过类比和公式,理解为何在某些市场条件下,利润会趋于零,以及这对企业选择开源或闭源模型意味着什么。

完全竞争市场的核心逻辑 ⚖️

上一节我们介绍了课程背景,本节中我们来看看“完全竞争市场”的核心含义。在完全竞争市场中,长期来看,所有经济利润最终会趋向于零。

我们可以通过一个小镇餐馆的例子来理解这一点。假设一个小镇上有四家餐馆。起初,它们之间没有显著的竞争差异,直到一位才华横溢的厨师来到镇上。

这位厨师拥有稀缺且高需求的技能,能为餐馆吸引所有顾客。于是,各家餐馆开始竞相争夺这位厨师。

以下是餐馆间竞争的过程:

  • 它们不断相互竞价,提供越来越高的薪水。
  • 最终,厨师通过谈判获得了极高的薪酬。
  • 厨师作为稀缺资源,捕获了所有的经济利润。

这意味着,雇佣厨师的餐馆老板最终可能面临破产,因为他们必须将所有利润支付给厨师,自身无法获得超额收益。

经济利润的定义与公式 📊

理解了案例,我们来看看其中提到的“经济利润”具体指什么。经济利润是指总收入减去总经济成本后的剩余。

其核心公式为:
经济利润 = 总收入 - 总经济成本

其中,总经济成本包含显性成本(如原料、工资)和隐性成本(如投资者期望的正常回报)。因此:

  • 正常利润:是吸引投资所必需的最低回报,已被计入经济成本中。
  • 经济利润:是超过正常利润的超额部分。在完全竞争下,这部分利润最终会被稀缺资源方(如案例中的厨师)获取,导致企业方经济利润为零。

AI领域的类比:闭源模型的竞争 🏢

将上述逻辑应用到AI领域,我们可以观察到类似的情景。假设市场上存在一个性能卓越的闭源模型(如某个领先的专有LLM)。

就像所有餐馆都需要那位天才厨师一样,所有公司为了保持竞争力,都可能被迫使用这个最优的闭源模型。

在这种情况下:

  • 使用该模型的公司之间无法凭借模型本身获得竞争优势。
  • 公司的利润可能会大量转移至模型提供方,通过API调用费的形式被获取,正如餐馆利润被厨师获取一样。
  • 模型提供方成为了稀缺资源,捕获了价值链中的大部分经济利润。

另一种情景:开源模型的竞争 🔓

另一方面,我们也可以设想另一种极端情景。如果所有模型都开源且性能相当,市场会变成怎样?

在这种情况下:

  • 模型本身成为一种可自由获取的“商品”,就像Linux操作系统一样。
  • 由于没有使用壁垒,公司无法通过拥有或使用某个特定模型来赚取超额利润。
  • 训练和开发这些开源模型的公司可能难以盈利,最终面临倒闭风险。
  • 竞争将转向其他维度,例如数据质量、工程落地能力、特定场景优化或用户体验等。

战略启示与总结 🎯

本节课中,我们一起学习了完全竞争市场理论及其在AI战略中的映射。我们通过厨师与餐馆的类比,理解了经济利润如何被稀缺资源方获取。进而,我们探讨了AI领域可能出现的两种情景:

  1. 闭源模型主导:利润可能向模型提供商集中,使用者需支付高额API费用。
  2. 开源模型普及:模型本身商品化、免费化,利润空间被挤压,竞争转向其他技术或服务层面。

这对于评估你的AI战略至关重要:是全力投入某个闭源模型以寻求短期性能优势,还是预见未来模型可能像基础设施一样普及,从而提前布局数据、工程化能力或垂直场景应用等更能构建长期壁垒的领域?这需要从经济学视角进行审慎思考。

197:负外部性

概述

在本节课中,我们将要学习一个重要的经济学概念——负外部性,并探讨其在技术领域,特别是生成式人工智能(AI)中的应用与影响。理解负外部性有助于我们以更负责任的方式开发和部署技术解决方案。

什么是负外部性?🤔

负外部性是指某些行为或决策产生的成本负面影响,不由行为发起者承担,而是转移给了未从中获益的第三方。

用公式可以表示为:
社会成本 = 私人成本 + 外部成本

其中,外部成本就是负外部性,它没有被包含在行为者的决策考量中。

一个现实世界的例子

为了更好地理解这个概念,我们可以看一个基于真实事件的极端例子。

假设有一个犯罪组织,受某公司雇佣,将核废料或其他有毒化学农药非法倾倒在某个小镇上。

以下是这个例子中的利益与成本分配:

  • 犯罪组织:获得了处理废物的全部利润
  • 小镇居民:没有从倾倒行为中获得任何利益,却要承担全部成本。这些成本可能表现为癌症、疾病、土地污染导致无法耕种等健康与环境问题。

这个例子清晰地展示了利润与成本承担者的分离。犯罪行动带来了所有的负外部性,并由无辜的第三方承受。

生成式AI中的负外部性

上一节我们介绍了一个极端的负外部性案例,本节中我们来看看这个概念如何应用于更贴近我们的技术领域——生成式人工智能。

考虑一个商业公司发布了一个生成式AI模型,并通过API调用获利。公司获得了100%的利润,这看起来是成功的商业模式。

然而,我们需要思考:是否存在潜在的负外部性?那些没有获得利润的人,是否会为AI产生的内容付出代价?

以下是生成式AI可能产生的一些负外部性场景:

  • 制造虚假信息:生成模仿著名政治人物声音的内容,可能影响选举结果。
  • 损害个人声誉:生成关于特定个人的不实信息,对其公司或声誉造成伤害。
  • 引发健康问题:传播错误的医疗健康信息,可能导致人们采取有害的行动。

理论上,这些都可能因生成式AI的不负责任使用而发生。商业公司获得了所有利润,而承受代价(即负外部性)的却是公众或特定群体。

如何负责任地思考?💡

负外部性的概念为我们提供了一个重要的思考框架。它并不意味着所有技术方案都会产生极端的负面影响,但强调我们在提出技术解决方案时,不能只关注利润。

在评估一个AI解决方案时,负外部性框架要求我们同时审视以下两点:

  1. 利润:解决方案能带来什么收益?
  2. 负外部性:解决方案会产生什么影响?即使是无意的,你实施的技术对社会的真实影响是什么?

这是一种负责任地思考部署AI解决方案的方式。它促使开发者和公司在追求经济效益的同时,也必须考量其技术可能对社会、环境和个人造成的潜在成本。

总结

本节课中,我们一起学习了负外部性的概念。我们通过一个非法倾倒有毒废物的例子理解了其核心含义,即收益与成本承担的分离。接着,我们将这一概念应用于生成式AI领域,探讨了AI模型可能产生的社会成本,如虚假信息和声誉损害。最后,我们强调,以负外部性的框架审视技术方案,关注利润之外的社会影响,是进行负责任AI开发与部署的关键一步。

198:监管创业 🏛️

在本节课中,我们将学习“监管创业”这一概念。这个概念由Paulllman和Barry于2017年提出,它描述了初创公司如何通过游走在法律灰色地带,最终推动法律本身发生改变的商业策略。我们将探讨其核心定义、常见策略、促成因素、社会影响,并通过具体案例进行分析。

概述

监管创业的核心含义是:通过在法律灰色地带创立公司甚至违反现有法律,使公司快速成长到“大到无法禁止”的规模,从而最终改变法律或法规

上一节我们介绍了机器学习运维的宏观背景,本节中我们来看看一种与之相关的、影响深远的商业策略。

关键策略与促成因素

以下是监管创业公司常用的一些关键策略:

  • 识别法律灰色地带:寻找现有法规模糊或未明确覆盖的业务领域。
  • 快速规模化:以极快的速度扩张用户和市场规模,达到“大到无法禁止”的程度。
  • 动员用户获取政治支持:利用社交媒体和公众舆论,让用户为自己的产品辩护,形成政治压力。

促成这种策略成功的因素包括:

  • 资金充足、可快速扩张的初创公司。
  • 产品或服务对公众有吸引力。
  • 倾向于挑战州或地方法律,而非国家法律,因为前者难度更低。
  • 诉讼过程本身带有政治色彩,而不仅仅是法律问题。

社会影响与外部性

监管创业带来了显著的社会影响。其直接结果是降低了这些公司进入市场的参与成本,并可能促使政策快速改变。然而,这些改变有时可能偏离公共利益,产生需要社会共同承担的“负外部性”。

负外部性是指企业行为对社会或他人造成的、未计入其自身成本的负面影响。其公式可以简化为:
社会总成本 = 企业私人成本 + 外部成本(负外部性)

接下来,我们将通过几个具体公司案例,来观察这些模式和影响是如何体现的。

案例分析

以下是四家公司的案例分析,这些模式同样适用于生成式AI等领域。

  • Airbnb:公司获得了巨额利润和估值,为创始人和投资者带来了回报。但社会需要承担可负担租赁住房单元全球性减少的损失,这是一种负外部性。
  • Uber:公司获得了高估值,风险投资获得了回报。但社会需要承担损失,例如在旧金山,交通拥堵和尾气排放增加。这不仅加剧全球变暖,当地居民吸入污染空气以及拥堵本身,都是社会需要承担且无人获得补偿的负外部性。
  • DraftKings:创造了一个价值数十亿美元的梦幻体育产业。但导致了更多人赌博成瘾和个人破产。例如,若有人将钱用于赌博而无力支付房贷,其家庭可能流落街头,这种极端情况下的负担也由社会承担。
  • OpenAI与生成式AI:在推动技术进步和创造利润的同时,也存在潜在损失。AI可能被用于破坏性用途,并且使用受版权保护的数据训练模型,引发了艺术家的担忧。训练模型所涉及的版权数据成本,也是一种社会需要承担的外部成本。

总结

本节课中我们一起学习了“监管创业”的概念。它并非新现象,而是风险投资中一种长期存在的模式。其典型模式包括:快速成长至规模巨大、需求庞大、资金雄厚、以及拥有能够游说国会的人脉。监管创业的未来尚不确定,可能会有更多或更少的法规出台,但这些行为模式值得我们持续关注。理解这一概念,有助于我们在技术创新的同时,更全面地思考其社会与法律影响。

posted @ 2026-03-26 12:24  布客飞龙III  阅读(3)  评论(0)    收藏  举报