了解如何将机器学习与软件工程相结合,以设计、开发、部署和迭代生产级 ML 应用程序。
在本课程中,我们将从实验(设计+开发)到生产(部署+迭代)。我们将通过激励组件来迭代地完成此任务,从而使我们能够构建可靠的生产系统。
请务必观看下面的视频,快速了解我们将要构建的内容。
机器学习不是一个独立的行业,相反,它是一种思考数据的强大方式,不为任何一种类型的人保留。
请务必完成本课程,以更详细地了解此存储库中的内容。我们将在下面的部分中提供针对本地笔记本电脑和 Anyscale 集群的说明,因此请务必根据您所使用的内容切换 ► 下拉菜单(默认情况下,Anyscale 说明将处于打开状态)。如果您确实想使用 Anyscale 来运行本课程,我们将提供结构、计算 (GPU)和社区,以便在一天内学习所有内容,请加入我们即将推出的下一个现场队列 → 在此注册!
我们将首先使用环境和计算配置设置集群。
我们可以使用网页 UI 创建 Anyscale 工作区。
- Workspace name: ` madewithml `
- Project: ` madewithml `
- Cluster environment name: ` madewithml-cluster-env `
# Toggle ` Select from saved configurations `
- Compute config: ` madewithml-cluster-compute-g5.4xlarge `
或者,我们可以使用 CLI 通过
anyscale workspace create ...
来创建工作区。
如果您不想在本地或通过 Anyscale 完成本课程,您有以下选择:
按照以下说明创建存储库:创建新存储库 → 将其命名为Made-With-ML
→ 切换Add a README file
(非常重要,因为这会创建main
分支)→ 单击Create repository
(向下滚动)
现在我们准备克隆包含所有代码的存储库:
git clone https://github.com/GokuMohandas/Made-With-ML.git .
touch .env
# Inside .env
GITHUB_USERNAME= " CHANGE_THIS_TO_YOUR_USERNAME " # ← CHANGE THIS
source .env
export PYTHONPATH= $PYTHONPATH : $PWD
python3 -m venv venv # recommend using Python 3.10
source venv/bin/activate # on Windows: venvScriptsactivate
python3 -m pip install --upgrade pip setuptools wheel
python3 -m pip install -r requirements.txt
pre-commit install
pre-commit autoupdate
强烈建议使用 Python
3.10
并使用 pyenv (mac) 或 pyenv-win (windows)。
我们已经通过设置 Anyscale 工作区时使用的集群环境为我们设置了具有适当 Python 版本和库的环境。所以我们只需要运行这些命令:
export PYTHONPATH= $PYTHONPATH : $PWD
pre-commit install
pre-commit autoupdate
首先探索 jupyter 笔记本,以交互方式演练核心机器学习工作负载。
# Start notebook
jupyter lab notebooks/madewithml.ipynb
单击 Anyscale Workspace 页面右上角的 Jupyter 图标,这将在新选项卡中打开 JupyterLab 实例。然后导航到notebooks
目录并打开madewithml.ipynb
笔记本。
现在,我们将遵循软件工程最佳实践(测试、文档、日志记录、服务、版本控制等),使用干净的 Python 脚本执行相同的工作负载。我们在笔记本中实现的代码将被重构为以下脚本:
madewithml
├── config.py
├── data.py
├── evaluate.py
├── models.py
├── predict.py
├── serve.py
├── train.py
├── tune.py
└── utils.py
注意:根据您的系统资源更改下面的--num-workers
、 --cpu-per-worker
和--gpu-per-worker
输入参数值。例如,如果您使用的是本地笔记本电脑,合理的配置为--num-workers 6 --cpu-per-worker 1 --gpu-per-worker 0
。
export EXPERIMENT_NAME= " llm "
export DATASET_LOC= " https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv "
export TRAIN_LOOP_CONFIG= ' {"dropout_p": 0.5, "lr": 1e-4, "lr_factor": 0.8, "lr_patience": 3} '
python madewithml/train.py
--experiment-name " $EXPERIMENT_NAME "
--dataset-loc " $DATASET_LOC "
--train-loop-config " $TRAIN_LOOP_CONFIG "
--num-workers 1
--cpu-per-worker 3
--gpu-per-worker 1
--num-epochs 10
--batch-size 256
--results-fp results/training_results.json
export EXPERIMENT_NAME= " llm "
export DATASET_LOC= " https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv "
export TRAIN_LOOP_CONFIG= ' {"dropout_p": 0.5, "lr": 1e-4, "lr_factor": 0.8, "lr_patience": 3} '
export INITIAL_PARAMS= " [{ " train_loop_config " : $TRAIN_LOOP_CONFIG }] "
python madewithml/tune.py
--experiment-name " $EXPERIMENT_NAME "
--dataset-loc " $DATASET_LOC "
--initial-params " $INITIAL_PARAMS "
--num-runs 2
--num-workers 1
--cpu-per-worker 3
--gpu-per-worker 1
--num-epochs 10
--batch-size 256
--results-fp results/tuning_results.json
我们将使用 MLflow 来跟踪我们的实验并存储我们的模型,并使用 MLflow 跟踪 UI 来查看我们的实验。我们一直将实验保存到本地目录,但请注意,在实际的生产环境中,我们将有一个中心位置来存储所有实验。为所有团队成员启动自己的 MLflow 服务器来跟踪他们的实验或使用权重和偏差、Comet 等托管解决方案非常简单且成本低廉。
export MODEL_REGISTRY= $( python -c " from madewithml import config; print(config.MODEL_REGISTRY) " )
mlflow server -h 0.0.0.0 -p 8080 --backend-store-uri $MODEL_REGISTRY
如果您在本地笔记本电脑上运行此笔记本,请前往 http://localhost:8080/ 查看您的 MLflow 仪表板。
如果您使用 Anyscale Workspaces,那么我们需要首先公开 MLflow 服务器的端口。在 Anyscale Workspace 终端上运行以下命令以生成 MLflow 服务器的公共 URL。
APP_PORT=8080
echo https:// $APP_PORT -port- $ANYSCALE_SESSION_DOMAIN
export EXPERIMENT_NAME= " llm "
export RUN_ID= $( python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC )
export HOLDOUT_LOC= " https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/holdout.csv "
python madewithml/evaluate.py
--run-id $RUN_ID
--dataset-loc $HOLDOUT_LOC
--results-fp results/evaluation_results.json
{
"timestamp" : " June 09, 2023 09:26:18 AM " ,
"run_id" : " 6149e3fec8d24f1492d4a4cabd5c06f6 " ,
"overall" : {
"precision" : 0.9076136428670714 ,
"recall" : 0.9057591623036649 ,
"f1" : 0.9046792827719773 ,
"num_samples" : 191.0
},
...
export EXPERIMENT_NAME= " llm "
export RUN_ID= $( python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC )
python madewithml/predict.py predict
--run-id $RUN_ID
--title " Transfer learning with transformers "
--description " Using transformers for transfer learning on text classification tasks. "
[{
"prediction" : [
" natural-language-processing "
],
"probabilities" : {
"computer-vision" : 0.0009767753 ,
"mlops" : 0.0008223939 ,
"natural-language-processing" : 0.99762577 ,
"other" : 0.000575123
}
}]
# Start
ray start --head
# Set up
export EXPERIMENT_NAME= " llm "
export RUN_ID= $( python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC )
python madewithml/serve.py --run_id $RUN_ID
应用程序运行后,我们可以通过 cURL、Python 等使用它:
# via Python
import json
import requests
title = "Transfer learning with transformers"
description = "Using transformers for transfer learning on text classification tasks."
json_data = json . dumps ({ "title" : title , "description" : description })
requests . post ( "http://127.0.0.1:8000/predict" , data = json_data ). json ()
ray stop # shutdown
在 Anyscale Workspaces 中,Ray 已经在运行,因此我们不必像本地那样手动启动/关闭。
# Set up
export EXPERIMENT_NAME= " llm "
export RUN_ID= $( python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC )
python madewithml/serve.py --run_id $RUN_ID
应用程序运行后,我们可以通过 cURL、Python 等使用它:
# via Python
import json
import requests
title = "Transfer learning with transformers"
description = "Using transformers for transfer learning on text classification tasks."
json_data = json . dumps ({ "title" : title , "description" : description })
requests . post ( "http://127.0.0.1:8000/predict" , data = json_data ). json ()
# Code
python3 -m pytest tests/code --verbose --disable-warnings
# Data
export DATASET_LOC= " https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv "
pytest --dataset-loc= $DATASET_LOC tests/data --verbose --disable-warnings
# Model
export EXPERIMENT_NAME= " llm "
export RUN_ID= $( python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC )
pytest --run-id= $RUN_ID tests/model --verbose --disable-warnings
# Coverage
python3 -m pytest tests/code --cov madewithml --cov-report html --disable-warnings # html report
python3 -m pytest tests/code --cov madewithml --cov-report term --disable-warnings # terminal report
从现在开始,为了将我们的应用程序部署到生产中,我们需要在 Anyscale 上或在您自己管理的云虚拟机/本地集群上(使用 Ray)。如果不在 Anyscale 上,命令会略有不同,但概念是相同的。
如果您不想自己设置所有这些,我们强烈建议您加入我们即将推出的实时群组{:target="_blank"},我们将提供一个已经为您设置好所有这些基础设施的环境,以便您只专注于机器学习。
如果我们使用 Anyscale 工作区,则会自动为我们设置以下这些凭据。我们不需要在工作区上显式设置这些凭据,但如果我们在本地或在 Anyscale 作业和服务配置运行的集群之外运行,则需要这样做。
export ANYSCALE_HOST=https://console.anyscale.com
export ANYSCALE_CLI_TOKEN= $YOUR_CLI_TOKEN # retrieved from Anyscale credentials page
集群环境决定了我们的工作负载将在哪里执行(操作系统、依赖项等)。我们已经为我们创建了这个集群环境,但这就是我们自己创建/更新集群环境的方式。
export CLUSTER_ENV_NAME= " madewithml-cluster-env "
anyscale cluster-env build deploy/cluster_env.yaml --name $CLUSTER_ENV_NAME
计算配置决定了我们的工作负载将在哪些资源上执行。我们已经为我们创建了这个计算配置,但这就是我们自己创建它的方式。
export CLUSTER_COMPUTE_NAME= " madewithml-cluster-compute-g5.4xlarge "
anyscale cluster-compute create deploy/cluster_compute.yaml --name $CLUSTER_COMPUTE_NAME
现在我们已准备好执行 ML 工作负载。我们决定将它们全部合并到一个作业中,但我们也可以为每个工作负载(训练、评估等)创建单独的作业。我们将首先编辑workloads.yaml
文件中的$GITHUB_USERNAME
插槽:
runtime_env :
working_dir : .
upload_path : s3://madewithml/$GITHUB_USERNAME/jobs # <--- CHANGE USERNAME (case-sensitive)
env_vars :
GITHUB_USERNAME : $GITHUB_USERNAME # <--- CHANGE USERNAME (case-sensitive)
这里的runtime_env
指定我们应该将当前的working_dir
上传到S3存储桶,以便我们执行Anyscale作业时的所有工作人员都可以访问要使用的代码。 GITHUB_USERNAME
稍后用于将工作负载的结果保存到 S3,以便我们稍后可以检索它们(例如用于服务)。
现在我们准备提交作业来执行 ML 工作负载:
anyscale job submit deploy/jobs/workloads.yaml
在执行我们的 ML 工作负载后,我们就准备好将我们的模型服务投入生产。与我们的 Anyscale 作业配置类似,请务必更改serve_model.yaml
中的$GITHUB_USERNAME
。
ray_serve_config :
import_path : deploy.services.serve_model:entrypoint
runtime_env :
working_dir : .
upload_path : s3://madewithml/$GITHUB_USERNAME/services # <--- CHANGE USERNAME (case-sensitive)
env_vars :
GITHUB_USERNAME : $GITHUB_USERNAME # <--- CHANGE USERNAME (case-sensitive)
现在我们准备启动我们的服务:
# Rollout service
anyscale service rollout -f deploy/services/serve_model.yaml
# Query
curl -X POST -H " Content-Type: application/json " -H " Authorization: Bearer $SECRET_TOKEN " -d ' {
"title": "Transfer learning with transformers",
"description": "Using transformers for transfer learning on text classification tasks."
} ' $SERVICE_ENDPOINT /predict/
# Rollback (to previous version of the Service)
anyscale service rollback -f $SERVICE_CONFIG --name $SERVICE_NAME
# Terminate
anyscale service terminate --name $SERVICE_NAME
我们不会在每次进行更改时都手动部署应用程序。相反,我们将使用 GitHub Actions 自动化此过程!
git remote set-url origin https://github.com/ $GITHUB_USERNAME /Made-With-ML.git # <-- CHANGE THIS to your username
git checkout -b dev
/settings/secrets/actions
页面。 export ANYSCALE_HOST=https://console.anyscale.com
export ANYSCALE_CLI_TOKEN= $YOUR_CLI_TOKEN # retrieved from https://console.anyscale.com/o/madewithml/credentials
main
分支上)并将其推送到 GitHub。但为了将我们的代码推送到 GitHub,我们需要先使用我们的凭据进行身份验证,然后再推送到我们的存储库: git config --global user.name $GITHUB_USERNAME # <-- CHANGE THIS to your username
git config --global user.email [email protected] # <-- CHANGE THIS to your email
git add .
git commit -m " " # <-- CHANGE THIS to your message
git push origin dev
现在,系统将提示您输入用户名和密码(个人访问令牌)。按照以下步骤获取个人访问令牌:新建 GitHub 个人访问令牌 → 添加名称 → 切换repo
和workflow
→ 单击Generate token
(向下滚动)→ 复制令牌并在提示输入密码时粘贴。
main
分支,这将触发工作负载工作流程。如果工作流程(Anyscale Jobs)成功,将直接在 PR 上生成带有培训和评估结果的评论。main
分支中。这将触发服务工作流程,从而将我们的新服务投入生产!通过部署应用程序的 CI/CD 工作流程,我们现在可以专注于不断改进我们的模型。在此基础上扩展以连接到计划运行(cron)、数据管道、通过监控检测到的偏差、在线评估等变得非常容易。而且我们可以轻松添加其他上下文,例如将任何实验与当前生产中的实验进行比较(直接甚至在公关中)等等。
使用 jupyter 配置笔记本时遇到问题吗?默认情况下,jupyter 将在我们的虚拟环境中使用内核,但我们也可以手动将其添加到 jupyter:
python3 -m ipykernel install --user --name=venv
现在我们可以打开一个笔记本→内核(顶部菜单栏)→更改内核→ venv
。要删除该内核,我们可以执行以下操作:
jupyter kernelspec list
jupyter kernelspec uninstall venv