原文:
towardsdatascience.com/mlops-a-gentle-introduction-to-mlflow-pipelines-c7bcec88a6ec
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/b7a15752e3d1d4c9ba8a8fa7deb13e3f.png
图片由Sean Robertson在Unsplash提供
简介
不同的统计数据表明[𝗯𝗲𝘁𝘄𝗲𝗲𝗻 𝟱𝟬% 𝗮𝗻𝗱 𝟗𝟬% 𝗼𝗳 𝘁𝗵𝗲 𝗺𝗼𝗱𝗲𝗹𝘀 𝗱𝗲𝘃𝗲𝗹𝗼𝗽𝗲𝗱 𝗱𝗼 𝗻𝗼𝘁 𝗺𝗮𝗸𝗲 𝗶𝘁 𝘁𝗼 𝗽𝗿𝗼𝗱𝘂𝗰𝘁𝗶𝗼𝗻。这通常是由于工作结构不当造成的。通常在学术界(或 Kaggle)获得的技能不足以构建一个将被数千人使用的基于机器学习的系统。
在寻找机器学习行业工作时,最需求的一项技能是使用能够实现复杂流水线编排的工具,如 MLflow。
在本文中,我们将了解如何将项目结构化成多个步骤,并以一种结构化的方式管理所有步骤。
我使用 Deepnote 运行本文的脚本:这是一个非常适合协作数据科学项目和原型设计的基于云的笔记本。
什么是 Mlflow?
MLflow 是由 Databricks 开发的用于机器学习端到端生命周期管理的开源平台。
MLflow 提供了各种功能,例如监控训练中的模型、使用工件存储、提供模型等。今天我们将探讨如何使用 MLflow 作为机器学习流水线的编排器。这是因为特别是在 AI 世界中,由于存在各种步骤和实验,拥有干净、易于理解且易于重现的代码至关重要。
但我们到底需要管理哪些步骤呢?这取决于我们工作的背景。机器学习流水线可能会根据我们工作的地点和最终目标而变化。例如,解决 Kaggle 任务的流水线很简单,因为大部分时间都花在建模上。而在工业界,我们有许多步骤,例如数据检查和代码质量检查。
为了简化,我们这里假设一个非常基础的流水线。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/bc70577ad1263580533e39ab87623d86.png
简单的流水线(图片由作者提供)
我们希望他们尽可能独立地开发这些步骤。负责建模的人只开发那个组件,而不关心数据收集、数据下载、清理等。
让我们进一步假设(夸张地说)我们为每个管道组件都有一个团队。我们希望通过让他们使用最擅长的工具和语言来简化每个团队的工作。因此,我们希望在每一步都拥有独立的发展环境。例如,数据下载可以用 C++开发,数据清洗可以用 Julia,建模可以用 Python,推理可以用 Java。使用 MLflow 可以实现这一点!
要安装使用的 MLflow,您可以使用 pip。
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fembed.deepnote.com%2F6694affc-1a96-4ae3-8f15-281a33cc0055%2Fbdc19e55b2624fe883cc96864abcf0a0%2Fc9f69b3cc4194e8288805325d881f606%3Fheight%3D83&display_name=Deepnote&url=https%3A%2F%2Fembed.deepnote.com%2F6694affc-1a96-4ae3-8f15-281a33cc0055%2Fbdc19e55b2624fe883cc96864abcf0a0%2Fc9f69b3cc4194e8288805325d881f606%3Fheight%3D83&image=https%3A%2F%2Fdeepnote.com%2Fstatic%2Fthumbnails%2Fmain.png&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=deepnote
定义一个 MLflow 项目
一个 MLflow 项目由 3 个主要部分组成,它们是:
代码:我们编写的用于解决我们正在工作的任务的代码
环境:我们需要定义环境。我的代码需要哪些依赖项来运行?
MLflow 项目定义:每个 MLflow 项目都有一个名为 MLproject 的文件,它定义了何时运行什么,以及用户如何与项目交互。
在本文中,我将用 Python 编写每个管道组件的代码,以保持简单。但如前所述,这并非必须。
我们如何管理环境?为了定义一个可重复和隔离的开发环境,我们可以使用各种工具。主要的是 docker 和 conda。在这个例子中,我将使用 conda,因为它允许我快速轻松地指定依赖项,而 docker 的学习曲线则相对较难。如果您需要下载 conda,我推荐较轻量级的版本,称为miniconda。
我们可以创建一个 conda.yml 文件来定义我们的开发环境,然后创建一个虚拟环境。
我们可以定义 conda.yml 中 pip 的使用,然后使用 pip 进行进一步的安装,就像下面的 wandb 案例一样。(p.s 在这个情况下,我们甚至不需要 wandb)
#conda.ymlname:download_data channels:-conda-forge-defaults dependencies:-requests-pip-mlflow-hydra-core-pip:-wandb现在为了创建 conda.yml 中定义的环境,我们可以在 cli 中运行以下命令。
conda env create--file=conda.yaml让我们激活它。
conda activate download_data现在,我们需要定义一个MLproject 文件。请注意,尽管这个文件是以 yaml 格式编写的,但它不需要扩展名。
在这个文件中,我们首先定义步骤的名称和将要使用的 conda 环境。之后,我们必须指定入口点,即从哪个主 Python 文件开始计算。然后,我们定义启动文件所需的参数。例如,在下载阶段,我期望用户传递一个数据下载的 URL。
作为最后的要点,mlflow 应该实际启动的命令。
name:download_data conda_env:conda.yml entry_points:main:parameters:data_url:description:URL of the data to downloadtype:uri command:>-python main.py--data_url{data_url}#in the brackets insert the input variable我们终于准备好编写主要的 Python 代码 main.py
在 Python 代码中,我们必须接受 MLproject 期望的输入参数,即"_dataurl"。然后我们可以使用 argparser,这样用户就可以从命令行传递这个参数。
然后我们执行 run()函数,该函数只是从 URL 读取 CSV 文件并将其本地保存,从而完成预期的简单数据下载。
我们使用开源数据(MIT 许可证)。具体来说,是可以在 GitHub 上找到的经典泰坦尼克数据集,该 URL 为:raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv
这就是您编写 main.py 文件的方式。
Deepnote
我们可以使用 mlflow 运行整个组件。在 mlflow 中,我们使用-P 标志来指定参数。
mlflow run.-P data_url="https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"您可以从终端日志中看到,首先 Mlflow 会尝试使用 conda.yml 重新创建开发环境(第一次可能需要一些时间)然后它会启动代码。最终,您应该能看到您的数据集已下载!
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ba7114dd3e3b96037af9080464847d41.png
Mlflow 组件结构(图片由作者提供)
从组件到管道
完美,现在我们有了创建由一个组件组成的 MLflow 项目的基石。但我们要如何开发一个完整的管道呢?在 MLflow 中,一个管道不过是由其他 MLflow 项目组成的 MLflow 项目而已!
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f869c7726774c223b7a4f5cb6dba90f2.png
MLflow 管道(图片由作者提供)
由于我想在我的根目录中创建一个由多个组件组成的管道,所以我将有两个子目录,每个组件一个,如下一张图片所示。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c8afef2debe04d1b30c87efd16e01377.png
Mlflow 管道结构(图片由作者提供)
为了简化,我只运行了两个步骤,数据下载和数据清洗。显然,一个真实的管道由更多步骤组成,如训练、推理等。
如上图所示,每个组件/步骤本身就是一个由 3 个文件描述的 MLflow 项目。完整的结构可以在下面的图片中查看。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/62dfb543b4ef4a0d4e6d83e9ae151d13.png
Mlflow 管道结构(图片由作者提供)
现在我们来看看我是如何定义这个目录下所有文件的。
🟢 mlflow_pipeline/conda.yml
这个文件与之前并无不同,它定义了开发环境。
#conda.yamlname:mlflow_pipeline channels:-conda-forge-defaults dependencies:-pandas-mlflow-requests-pip-mlflow🟢 mlflow_pipeline/MLproject
我可能并不总是对启动管道中的所有步骤感兴趣,但有时我只想要其中的一些。因此,我接受一个字符串作为输入,该字符串定义了我想要启动的所有步骤,步骤之间用逗号分隔。
因此,当 MLflow 启动时,命令将类似于:
mlflow run .P steps=“download,cleaning,training”
name:mlflow_pipeline conda_env:conda.yml entry_points:main:parameters:steps:description:steps you want to perform seprarated by commatype:strdata_url:descripton:url of datatype:uri command:>-python main.py--steps{steps}--data_url{data_url}🟢 mlflow_pipeline/main.py
在这个文件中,我们现在将处理步骤。因此,一旦我们将输入传递给解析器,我们就通过逗号分割字符串,并将所有步骤放入一个数组中。
对于每个步骤,我们运行一个 mlflow.run,这次直接从 Python 中运行,而不是使用 cli。虽然命令非常相似,但对于每个运行,我们指定组件的路径、入口点(总是 main)以及如果需要的话,传递参数。
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fembed.deepnote.com%2F6694affc-1a96-4ae3-8f15-281a33cc0055%2Fbdc19e55b2624fe883cc96864abcf0a0%2Fc791c8b2ad0943c381be2d5cf477cd3e%3Fheight%3D713&display_name=Deepnote&url=https%3A%2F%2Fembed.deepnote.com%2F6694affc-1a96-4ae3-8f15-281a33cc0055%2Fbdc19e55b2624fe883cc96864abcf0a0%2Fc791c8b2ad0943c381be2d5cf477cd3e%3Fheight%3D713&image=https%3A%2F%2Fdeepnote.com%2Fstatic%2Fthumbnails%2Fmain.png&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=deepnote
从现在开始,定义其他组件与之前我们所做的是非常相似的。让我们继续描述下载和清理步骤。⚠️ 所有的 conda.yml 都是相同的,所以我会避免多次重复。
🟢 mlflow_pipeline/data_download/MLproject
与之前的数据下载一样,data_download 预期一个输入参数,即下载数据的 URL,其余的都是标准的。
name:download_data conda_env:conda.yml entry_points:main:parameters:data_url:description:url of data to downloadtype:strcommand:>-python run.py--data_url{data_url}🟢 mlflow_pipeline/data_download/run.py
在 run.py 中,我们取 URL 文件,如 MLproject 中定义的,并使用它来打开一个 pandas 数据框,并将数据集以 .csv 扩展名本地保存
cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fembed.deepnote.com%2F6694affc-1a96-4ae3-8f15-281a33cc0055%2Fbdc19e55b2624fe883cc96864abcf0a0%2F97cb89e976634defa2fe865f728e371b%3Fheight%3D353&display_name=Deepnote&url=https%3A%2F%2Fembed.deepnote.com%2F6694affc-1a96-4ae3-8f15-281a33cc0055%2Fbdc19e55b2624fe883cc96864abcf0a0%2F97cb89e976634defa2fe865f728e371b%3Fheight%3D353&image=https%3A%2F%2Fdeepnote.com%2Fstatic%2Fthumbnails%2Fmain.png&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=deepnote
🟢 mlflow_pipeline/data_cleaning/MLproject
在这种情况下,数据清理非常简单。我更感兴趣的是关注如何构建管道,而不是创建复杂的步骤。我们预期没有输入参数,所以我们只需要运行 run.py
name:data_cleaning conda_env:conda.yml entry_points:main:command:>-python run.py🟢 mlflow_pipeline/data_cleaning/run.py
在实际的清理过程中,我们删除包含空值的所有行,并将新的数据框作为 CSV 保存到本地根目录。
Deepnote
现在如果我们没有犯任何错误,我们可以使用单个 mlflow 命令运行整个管道,指定适当的参数,然后是步骤和数据集的 URL。
mlflow run.-P steps="data_download,data_cleaning"-P data_url="https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"你会发现所有步骤都将正确执行,你将在你的目录中找到两个新的 CSV 文件!🚀
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/65d790301c9940ea00af6c25fa6bce2d.png
Mlflow 管道结构(图片由作者提供)
结论
在这篇文章中,我们看到了 MLflow 中的项目由什么组成,以及一个管道是如何通过一系列项目来定义的。
管道中的每一步都可以独立开发,因为每一步都由其自己的环境定义。我们可以为每一步的开发使用不同的语言和工具,而 MLflow 只是一个调度器。我希望这篇文章能给你一些关于如何使用 MLflow 的想法。
尽管 MLFlow 对于跟踪机器学习实验非常有用,但其复杂性和陡峭的学习曲线可能会让小型项目或新接触 MLOps 的团队望而却步。然而,当实验跟踪、数据模型版本控制和协作至关重要时,它使用起来非常方便,因此非常适合中到大型项目。
它提供的功能远不止这些,例如,你可以用它来监控模型的性能或保存你创建的工件。在未来的文章中,我将向你展示如何将额外的工具集成到 MLflow 中,以充分利用其功能!
如果你对这个文章感兴趣,请关注我的 Medium! 😁
💼 LinkedIn ️| 🐦 Twitter | 💻 网站