Join 40K+ developers in learning how to responsibly deliver value with ML.
了解如何将机器学习与软件工程相结合,以设计、开发、部署和迭代生产级 ML 应用程序。
在本课程中,我们将从实验(设计+开发)到生产(部署+迭代)。我们将通过激励组件来迭代地完成此任务,从而使我们能够构建可靠的生产系统。
请务必观看下面的视频,快速了解我们将要构建的内容。
- 💡 第一原则:在我们直接进入代码之前,我们对每个机器学习概念都有一个第一原则的理解。
- 💻 最佳实践:在开发和部署机器学习模型时实施软件工程最佳实践。
- 📈 规模:在 Python 中轻松扩展 ML 工作负载(数据、训练、调整、服务),而无需学习全新的语言。
- ⚙️ MLOps:在我们构建端到端机器学习系统时连接 MLOps 组件(跟踪、测试、服务、编排等)。
- 🚀 开发到生产:学习如何快速可靠地从开发到生产,而不需要对我们的代码或基础设施管理进行任何更改。
- 🐙 CI/CD:学习如何创建成熟的 CI/CD 工作流程,以与任何堆栈集成的模块化方式持续训练和部署更好的模型。
机器学习不是一个独立的行业,相反,它是一种思考数据的强大方式,不为任何一种类型的人保留。
- 👩💻 所有开发人员:无论是软件/基础设施工程师还是数据科学家,机器学习正日益成为您将要开发的产品的关键部分。
- 👩🎓 大学毕业生:学习行业所需的实践技能,并弥合大学课程与行业期望之间的差距。
- 👩💼 产品/领导力:想要开发技术基础,以便能够构建由机器学习驱动的令人惊叹(且可靠)的产品。
请务必完成本课程,以更详细地了解此存储库中的内容。我们将在下面的部分中提供针对本地笔记本电脑和 Anyscale 集群的说明,因此请务必根据您所使用的内容切换 ► 下拉菜单(默认情况下,Anyscale 说明将处于打开状态)。如果您确实想使用 Anyscale 来运行本课程,我们将提供结构、计算(GPU)和社区,以便在一天内学习所有内容,请加入我们即将推出的下一个实时队列 →在此注册!
我们将首先使用环境和计算配置设置集群。
当地的
您的个人笔记本电脑(单机)将充当集群,其中一个 CPU 将作为头节点,其余一些 CPU 将作为工作节点。本课程中的所有代码都可以在任何个人笔记本电脑上运行,尽管它比在更大的集群上执行相同的工作负载要慢。
任意规模
我们可以使用网页 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 ...
其他(云平台、K8s、本地)
If you don't want to do this course locally or via Anyscale, you have the following options:
- On AWS and GCP. Community-supported Azure and Aliyun integrations also exist.
- On Kubernetes, via the officially supported KubeRay project.
- Deploy Ray manually on-prem or onto platforms not listed here.
按照以下说明创建存储库:创建新存储库→命名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: venv\Scripts\activate python3 -m pip install --upgrade pip setuptools wheel python3 -m pip install -r requirements.txt pre-commit install pre-commit autoupdate
Highly recommend using Python
3.10
and using pyenv (mac) or 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 服务器来跟踪他们的实验或使用诸如Weights & Biases、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
当地的
If you're running this notebook on your local laptop then head on over to http://localhost:8080/ to view your MLflow dashboard.
任意规模
如果您使用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
Once the application is running, we can use it via cURL, Python, etc.:
# 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
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
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
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" tabindex="0" role="button">
从现在开始,为了将我们的应用程序部署到生产中,我们需要在 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 工作负载。我们决定将它们全部合并到一个作业中,但我们也可以为每个工作负载(训练、评估等)创建单独的作业。我们将首先编辑文件$GITHUB_USERNAME
中的插槽workloads.yaml
:
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 作业配置类似,请务必$GITHUB_USERNAME
更改serve_model.yaml
.
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
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/
anyscale service rollback -f $SERVICE_CONFIG --name $SERVICE_NAME
anyscale service terminate --name $SERVICE_NAME" tabindex="0" role="button">
我们不会在每次进行更改时都手动部署应用程序。相反,我们将使用 GitHub Actions 自动化此过程!
- 创建一个新的 github 分支来保存我们的更改并执行 CI/CD 工作负载:
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
GitHub 存储库的页面。
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 you@example.com # <-- CHANGE THIS to your email git add . git commit -m "" # <-- CHANGE THIS to your message git push origin dev
现在,系统将提示您输入用户名和密码(个人访问令牌)。请按照以下步骤获取个人访问令牌:新建 GitHub 个人访问令牌→ 添加名称 → 切换repo
并workflow
→ 单击Generate token
(向下滚动)→ 复制令牌并在提示输入密码时粘贴。
- 现在我们可以从该分支启动 PR 到我们的
main
分支,这将触发工作负载工作流程。如果工作流程(Anyscale Jobs)成功,将直接在 PR 上生成带有培训和评估结果的评论。
- 如果我们喜欢结果,我们可以将 PR 合并到
main
分支中。这将触发服务工作流程,从而将我们的新服务投入生产!
通过部署应用程序的 CI/CD 工作流程,我们现在可以专注于不断改进我们的模型。在此基础上扩展以连接到计划运行(cron)、数据管道、通过监控检测到的偏差、在线评估等变得非常容易。而且我们可以轻松添加其他上下文,例如将任何实验与当前生产中的实验进行比较(直接甚至在公关中)等等。
使用 jupyter 配置笔记本时遇到问题吗?默认情况下,jupyter 将在我们的虚拟环境中使用内核,但我们也可以手动将其添加到 jupyter:
python3 -m ipykernel install --user --name=venv
现在我们可以打开一个笔记本→内核(顶部菜单栏)→更改内核→ venv
。要删除该内核,我们可以执行以下操作:
jupyter kernelspec list jupyter kernelspec uninstall venv