# mlflow-ex-project-basic **Repository Path**: yichaoyyds/mlflow-ex-project-basic ## Basic Information - **Project Name**: mlflow-ex-project-basic - **Description**: MLFlow Projects允许我们将代码及其依赖项打包为一个可以在其他平台上以可复制(reproducible)和可重用(reusable)的方式运行的项目。每个项目都包括自己的代码和一个MLproject文件,该文件定义了它的依赖项(例如Python环境),以及可以在项目中运行哪些命令以及它们采用的参数。 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-03-06 - **Last Updated**: 2022-03-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MLFlow Projects Example [`MLFlow Projects`](https://mlflow.org/docs/latest/projects.html#project-directories)允许我们将代码及其依赖项打包为一个可以在其他平台上以可复制(reproducible)和可重用(reusable)的方式运行的项目。每个项目都包括自己的代码和一个MLproject文件,该文件定义了它的依赖项(例如Python环境),以及可以在项目中运行哪些命令以及它们采用的参数。 在这个案例中,我们基于[MLFlow的官方GitHub文档](https://github.com/mlflow),具体说明`MLflow Projects`如何被使用,以及结果。首先,我们先简单地过一遍概念,然后介绍如何把这个代码跑起来。关于此代码的详细解释,请参见我的博客:[MLOps极致细节:5. MLFlow Projects 案例代码解读](https://blog.csdn.net/zyctimes/article/details/123312039)。 - 平台:Win10。 - IDE:Visual Studio Code - 需要预装:Anaconda3。 目录 - [MLFlow Projects Example](#mlflow-projects-example) - [MLProject Yaml文件](#mlproject-yaml文件) - [运行代码](#运行代码) - [运行代码之前](#运行代码之前) - [第一种运行方式](#第一种运行方式) - [第二种运行方式](#第二种运行方式) - [第三种运行方式](#第三种运行方式) ## MLProject Yaml文件 根本上,`MLFlow Projects`的作用就是让其他数据科学家更方便地运行MLFlow项目。在原本的MLFlow项目的基础上,我们需要增加一个`MLProject`的yaml文件,在项目的根目录下。 一个`MLProject`的例子如下: ```yaml name: My Project conda_env: my_env.yaml # Can have a docker_env instead of a conda_env, e.g. # docker_env: # image: mlflow-docker-example entry_points: main: parameters: data_file: path regularization: {type: float, default: 0.1} command: "python train.py -r {regularization} {data_file}" validate: parameters: data_file: path command: "python validate.py {data_file}" ``` `MLProject`里面包含了如下几个参数/属性: - `name`: 项目名称 - `Entry Points`:可以在项目中运行的命令,以及有关其参数的信息。大多数项目至少包含一个entry point,您希望其他用户调用它。有些项目还可以包含多个entry points:例如,我们可能有一个包含多个特征化算法的Git repo。你也可以以`.py`或`.sh`文件作为entry points。在`MLproject`文件中列出entry points的同时,我们还可以为它们指定参数,包括数据类型和默认值。 - `Environment`:应用于执行项目entry point的软件环境。这包括项目代码所需的所有库依赖项。目前MLFlow支持`Conda environments`和`Docker containers`。 - `Conda environments`:在`MLProject`文件中需要添加`conda_env`参数的定义,比如:`conda_env: conda.yaml`。即,引用在`/conda.yaml`路径下的conda yaml文件。关于`conda.yaml`的写法,参见[Anaconda 官网](https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#create-env-file-manually)。一个`conda.yaml`的例子: ```yaml name: tutorial channels: - conda-forge dependencies: - python=3.7 - pip - pip: - scikit-learn==0.23.2 - mlflow>=1.0 - pandas ``` - `Docker container environments`:和conda环境类似的,在`MLProject`文件中需要添加`docker_env`参数的定义。MLFlow支持如下几种定义的方式: - Image without a registry path(还是直接用英文比较合适)。由于未指定registry path,Docker会在运行MLflow项目的系统上搜索此image。如果找不到这个image,Docker会尝试从DockerHub中pull。一个例子: ```yaml docker_env: image: mlflow-docker-example-environment ``` - Mounting volumes and specifying environment variables。`volumes`的作用是将本地的一个路径mount到docker镜像里面的一个路径。`environment`可以从host的环境变量中复制,也可以指定为Docker镜像环境的新变量。环境字段应该是一个列表(list)。此列表中的元素可以是两个字符串的列表(用于定义新变量)或单个字符串(用于从host复制变量)。一个例子: ```yaml docker_env: image: mlflow-docker-example-environment volumes: ["/local/path:/container/mount/path"] environment: [["NEW_ENV_VAR", "new_var_value"], "VAR_TO_COPY_FROM_HOST_ENVIRONMENT"] ``` - Image in a remote registry。当MLflow项目运行时,Docker会尝试从指定的registry path中提取镜像。一个例子: ```yaml docker_env: image: 012345678910.dkr.ecr.us-west-2.amazonaws.com/mlflow-docker-example-environment:7.0 ``` ## 运行代码 这个案例中,我们将使用`scikit-learn`来训练一个简单的线性回归模型,然后打包这个模型使之可重复使用。代码基于[MLFlow官网](https://mlflow.org/docs/latest/tutorials-and-examples/tutorial.html#conda-example)改写。 这里,我们引用[wine quality](http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv)数据集。在此数据集中,我们基于一些特征,如"fixed acidity","volatile acidity","citric acid"等等,来对wine的"quality"进行预测。 预测的模型我们选择`sklearn.linear_model.ElasticNet`,详细的说明参见[官网](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.ElasticNet.html)。 ### 运行代码之前 在运行起代码之前,我们还是需要在我们的主机(host machine)新建虚拟环境(比如`conda create -n [your vm name] python=3.8`),然后进入虚拟环境(`conda activate [your vm name]`),安装好MLFlow(`pip3 install mlflow -i https://pypi.tuna.tsinghua.edu.cn/simple`)。当然,我们也可以不用虚拟环境,而是直接在主机环境中进行MLFlow以及其他依赖的的安装,但我个人依然强烈建议不要随意在主环境中进行操作。 有下面几种方式运行起这个案例的代码: 1. 我们把此案例相关代码克隆到本地:`git clone https://gitee.com/yichaoyyds/mlflow-ex-project-basic.git`。然后进入`mlflow-ex-project-basic`文件夹,在terminal中运行py文件,比如`python main.py`; 2. 我们把此案例相关代码克隆到本地:`git clone https://gitee.com/yichaoyyds/mlflow-ex-project-basic.git`。然后再按照下面章节的步骤运行`mlrun`指令(在terminal中); 3. 不用把代码克隆到本地。mlflow也支持直接跑git上的代码。下面章节会做具体描述。 一个建议:在通过`MLFlow Projects`的方式运行代码前,如果我们对mlflow不了解,我们还是先按照比较原始的方式先把代码跑起来,比如`python main.py`。这也是为什么我们依旧在代码中包含了`requirements.py`的原因。和之前的案例一样,我们先进入之前创建的虚拟环境,然后激活,比如:`conda activate mlFlowEx`(`mlFlowEx`是我们之前创建的虚拟环境)。然后,我们在虚拟环境中下载好相关依赖:`pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple`。和之前一样,这个案例我们选用的IDE依然是VSCode。 文档结构: ```python - conda.yaml # MLFlow Projects 所需要的conda的yaml文件 - MLproject # MLFlow Projects 所需要的MLproject文件 - requirements.txt # 我们测试代码的时候用到,包含了测试代码需要的依赖库 - main.py # 展示了如何使用tensorflow2/keras进行模型的训练 - READ.md # readme文件 - config.txt # 我们测试代码的时候用到,设置参数的时候方便一些 - wine-quality.csv # 训练数据集,其实不需要,我们直接从网上下载下来 ``` ### 第一种运行方式 1. 在我们的主机(host machine),新建并进入虚拟环境,安装好`requirements.txt`里面的依赖; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-project-basic.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-project-basic`文件夹; 4. `cd mlflow-ex-project-basic`进入文件夹; 5. `python .\main.py`。你应该能看到类似 ```terminal Mode: loop Test Elasticnet model with different alpha and l1_ratio values. Test - alpha: 0.0, l1_ratio: 0.0. Result: RMSE: 0.68, MAE: 0.54, R2: 0.35 Test - alpha: 0.0, l1_ratio: 0.2. Result: RMSE: 0.68, MAE: 0.54, R2: 0.35 Test - alpha: 0.0, l1_ratio: 0.4. Result: RMSE: 0.68, MAE: 0.54, R2: 0.35 ... Test - alpha: 0.8, l1_ratio: 0.8. Result: RMSE: 0.83, MAE: 0.68, R2: 0.03 Best Elasticnet model (alpha=0.800000, l1_ratio=0.800000): Best model - alpha: 0.8, l1_ratio: 0.8. Result: RMSE: 0.8323634286332126, MAE: 0.6841525289534505, R2: 0.026507009052647468 ``` 并且你也会发现,在`mlflow-ex-project-basic`文件夹下面多了一个`mlruns`文件夹。 6. 运行成功。注意,每次运行的时候需要改一下`config.txt`文件里面的`experimentid`值,因为我们每次不能创建相同id的experiment。 ### 第二种运行方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-project-basic.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-project-basic`文件夹; 4. 注意,我们这里没有进入`mlflow-ex-project-basic`文件夹。运行: ```bash mlflow run mlflow-ex-project-basic ``` 5. 如果你是第一次运行,那么系统会给你新建一个虚拟机,然后系统进入这个虚拟机平台,安装好依赖,再运行`main.py`文件。运行完后,你会发现在当前目录下,会新生成`mlruns`文件夹。以下为terminal代码运行后的一部分日志,详细的日志以及代码的解释请参见我的博客:[MLOps极致细节:5. MLFlow Projects 案例代码解读](https://blog.csdn.net/zyctimes/article/details/123312039)。 ```terminal 2022/03/06 15:20:38 INFO mlflow.projects.utils: === Created directory C:\XXX\Temp\tmp4t1upjb_ for downloading remote URIs passed to arguments of type 'path' === 2022/03/06 15:20:38 INFO mlflow.projects.backend.local: === Running command 'conda activate mlflow-5cbba1deec6e564616d0ebee88bd7d510b35ef53 && python main.py 0.5 0.1 loop mlflowProjectExample20' in run with ID '42a6a0faa2f1486c973fecb851193f56' === Mode: loop Test Elasticnet model with different alpha and l1_ratio values. Test - alpha: 0.0, l1_ratio: 0.0. Result: RMSE: 0.64, MAE: 0.51, R2: 0.36 Test - alpha: 0.0, l1_ratio: 0.2. Result: RMSE: 0.64, MAE: 0.51, R2: 0.36 ... Test - alpha: 0.8, l1_ratio: 0.8. Result: RMSE: 0.8, MAE: 0.66, R2: 0.01 Best Elasticnet model (alpha=0.800000, l1_ratio=0.800000): Best model - alpha: 0.8, l1_ratio: 0.8. Result: RMSE: 0.7980985615795877, MAE: 0.661761764937828, R2: 0.010305314500945628 2022/03/06 15:21:57 INFO mlflow.projects: === Run (ID '42a6a0faa2f1486c973fecb851193f56') succeeded === ``` 6. 运行成功。注意,每次运行的时候需要改一下`config.txt`文件里面的`experimentid`值,因为我们每次不能创建相同id的experiment。 ### 第三种运行方式 这种方式最为简洁,直接调git的URI链接,连下载都免了。 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在我们自己选择的某个本地路径下 ```bash mlflow run https://gitee.com/yichaoyyds/mlflow-ex-project-basic.git ``` 3. 你会发现在当前目录下,会新生成`mlruns`文件夹。其实第二种和第三种是一样的,只是第二种方式,我们手动克隆了一下,而第三种方式,mlflow帮我们克隆了一下,保存到了系统的temp路径下。我们来看一下运行后的(部分)日志,就一目了然了: ```terminal 2022/03/06 15:37:12 INFO mlflow.projects.utils: === Fetching project from https://gitee.com/yichaoyyds/mlflow-ex-project-basic.git into C:\XXX\Temp\tmp2my_ysex === 2022/03/06 15:37:16 INFO mlflow.projects.utils: === Created directory C:\XXX\Temp\tmp9c6kybzr for downloading remote URIs passed to arguments of type 'path' === 2022/03/06 15:37:16 INFO mlflow.projects.backend.local: === Running command 'conda activate mlflow-5cbba1deec6e564616d0ebee88bd7d510b35ef53 && python main.py 0.5 0.1 loop mlflowProjectExample1' in run with ID '4cd58e551b114c60b416b41225580b17' === Mode: loop Test Elasticnet model with different alpha and l1_ratio values. Test - alpha: 0.0, l1_ratio: 0.0. Result: RMSE: 0.68, MAE: 0.52, R2: 0.27 Test - alpha: 0.0, l1_ratio: 0.2. Result: RMSE: 0.68, MAE: 0.52, R2: 0.27 ... Test - alpha: 0.8, l1_ratio: 0.8. Result: RMSE: 0.79, MAE: 0.64, R2: 0.03 Best Elasticnet model (alpha=0.800000, l1_ratio=0.800000): Best model - alpha: 0.8, l1_ratio: 0.8. Result: RMSE: 0.7866516565074876, MAE: 0.6435140676671445, R2: 0.03154140821475915 2022/03/06 15:38:29 INFO mlflow.projects: === Run (ID '4cd58e551b114c60b416b41225580b17') succeeded === ```