# mlflow-ex-hyperparametertunning **Repository Path**: yichaoyyds/mlflow-ex-hyperparametertunning ## Basic Information - **Project Name**: mlflow-ex-hyperparametertunning - **Description**: 在这个章节中,我们将详细提供一个案例,基于keras的深度学习框架对`winequality-white`数据进行quanlity的预测。此章节的代码基于[MLFlow官网GitHub链接](https://github.com/mlflow/mlflow/tree/master/examples/hyperparam)。 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-03-05 - **Last Updated**: 2022-08-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MLFlow 超参数调参案例: 综述 在这个博客中,我们将详细提供一系列案例,基于mlflow和keras的深度学习框架对`winequality-white`数据进行quanlity预测的端到端流程,以及通过随机选择和Hyperopt优化进行调整超参数。此博客的代码基于[MLFlow官网GitHub链接](https://github.com/mlflow/mlflow/tree/master/examples/hyperparam)改写。 - 平台:Win10。 - IDE:Visual Studio Code - 需要预装:Anaconda3。 目录 - [MLFlow 超参数调参案例: 综述](#mlflow-超参数调参案例-综述) - [背景介绍](#背景介绍) - [案例1:基于keras的端到端深度学习流程](#案例1基于keras的端到端深度学习流程) - [案例1:第一种方式](#案例1第一种方式) - [案例1:第二种方式](#案例1第二种方式) - [案例1:第三种方式](#案例1第三种方式) - [案例2:超参数的随机调整](#案例2超参数的随机调整) - [案例2:第一种方式](#案例2第一种方式) - [案例2:第二种方式](#案例2第二种方式) - [案例2:第三种方式](#案例2第三种方式) - [案例3:超参数的Hyperopt调整](#案例3超参数的hyperopt调整) - [案例3:第一种方式](#案例3第一种方式) - [案例3:第二种方式](#案例3第二种方式) - [案例3:第三种方式](#案例3第三种方式) - [对比这三种方式](#对比这三种方式) - [参考](#参考) ## 背景介绍 超参数(hyperparameter)是控制模型训练的参数,与其他参数(如节点权重)不同,它们不会被学习。这些参数的例子包括学习速率(Learning Rate)或神经网络中的层数(nural layer)。 为这些超参数选择正确的值对于良好的训练至关重要,但仅仅猜测它们并不容易。超参数调整(或优化)是优化超参数以最大化目标(例如验证集上的模型精度)的过程。为此,可以使用不同的方法: - 网格搜索(Grid Search),包括尝试集合中所有可能的值 - 随机搜索(Random Search),从一个范围中随机选取值 - 贝叶斯优化(Bayesian optimization):另一种尝试选择最佳值的迭代方法 在这个案例中,我们尝试了手动选择超参数,随机搜索,以及hyperopt方法去寻找最优的超参数:`learning-rate`以及`momentum`以获得最优地`RMSE`值。 输入数据集被分为三个部分:训练集、验证集和测试集。训练数据集用于拟合模型,验证数据集用于选择最佳超参数值,测试集用于评估性能,并验证我们没有过度拟合特定的训练和验证组合。这三个指标都记录在MLflow中,我们可以使用MLflow UI检查它们在不同超参数值之间的变化。 文档结构: ```python - conda.yaml # MLFlow Projects 所需要的conda的yaml文件 - conda.yamlbk # 原yaml文件,由于我暂时不知道如何在conda.yaml文件中对pip加源,所以我对原文件做了修改 - MLproject # MLFlow Projects 所需要的MLproject文件,包含了对`train`, `search_random`以及`search_hyperopt`的调用 - requirements.txt # 我们测试代码的时候用到,包含了测试代码需要的依赖库 - search_hyperopt.py # 使用Hyperopt方法去优化超参数 - search_random.py # 使用随机搜索的方法去优化超参数 - train.py # 展示了如何使用tensorflow2/keras进行模型的训练 - READ.md # readme文件 ``` 在运行起代码之前,我们还是需要在我们的主机(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-hyperparametertunning.git`。然后进入`mlflow-ex-hyperparametertunning`文件夹,在terminal中运行py文件,比如`python train.py`; 2. 我们把此案例相关代码克隆到本地:`git clone https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。然后再按照下面章节的步骤运行`mlrun`指令(在terminal中); 3. 不用把代码克隆到本地。mlflow也支持直接跑git上的代码。下面章节会做具体描述。 一个建议:在通过`MLFlow Projects`的方式运行代码前,如果我们对mlflow不了解,我们还是先按照比较原始的方式先把代码跑起来,比如`python train.py`。这也是为什么我们依旧在代码中包含了`requirements.py`的原因。和之前的案例一样,我们先进入之前创建的虚拟环境,然后激活,比如:`conda activate mlFlowEx`(`mlFlowEx`是我们之前创建的虚拟环境)。然后,我们在虚拟环境中下载好相关依赖:`pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple`。和之前一样,这个案例我们选用的IDE依然是VSCode。 ## 案例1:基于keras的端到端深度学习流程 `train.py`案例展示了我们如何使用tensorflow2/keras进行模型的训练。这里我们只介绍三种运行代码的方式。代码的详细解释请参见博客[MLFlow 超参数调参案例: 基于keras的端到端深度学习流程](./mlflow-hyperparam-1.md)。 ### 案例1:第一种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-hyperparametertunning`文件夹; 4. `cd mlflow-ex-hyperparametertunning`进入文件夹; 5. `python .\train.py`。你应该能看到类似 ```terminal Epoch 99/100 173/173 [==============================] - 1s 6ms/step - loss: 0.4339 - val_loss: 0.5356 ``` 6. 运行成功后,你会在当前路径下看到一个新生成的文件夹:`mlruns`; ### 案例1:第二种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-hyperparametertunning`文件夹; 4. 我们需要在创建一个experiment。注意,我们这里没有进入`mlflow-ex-hyperparametertunning`文件夹: ```bash mlflow experiments create -n new_run ``` 5. 你会发现在当前目录下,会新生成`mlruns`文件夹。terminal会返回experiment ID。然后我们输入: ```bash mlflow run -e train --experiment-id ./mlflow-ex-hyperparametertunning/ ``` 你应该可以看到类似 ```terminal Epoch 99/100 173/173 [==============================] - 1s 6ms/step - loss: 0.4339 - val_loss: 0.5356 ``` 6. 运行成功; ### 案例1:第三种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 我们需要在创建一个experiment,在我们自己选择的某个本地路径下 ```bash mlflow experiments create -n new_run ``` 3. 你会发现在当前目录下,会新生成`mlruns`文件夹。terminal会返回experiment ID。然后我们输入: ```bash mlflow run -e train --experiment-id https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git ``` 你应该可以看到类似 ```terminal Epoch 99/100 173/173 [==============================] - 1s 6ms/step - loss: 0.4339 - val_loss: 0.5356 ``` 4. 运行成功; 在尝试这三种运行方式的时候,可以注意一下terminal的日志,从日志中我们可以明显看到其中的运行逻辑。 ## 案例2:超参数的随机调整 `search_random.py`随机对`lr`以及`momentum`进行取值,然后运行模型的训练。这里我们只介绍三种运行代码的方式。代码的详细解释请参见博客[MLFlow 超参数调参案例:随机搜索调参](./mlflow-hyperparam-2.md)。 ### 案例2:第一种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-hyperparametertunning`文件夹; 4. `cd mlflow-ex-hyperparametertunning`进入文件夹; 5. `python .\search_random.py`。需要注意,需要检查一下`search_random.py`中,`mlflow.projects.run`中的`uri`参数需要设置为`https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。如运行成功,你应该能看到类似 ```terminal Epoch 49/50 173/173 [==============================] - 0s 1ms/step - loss: 0.4805 - val_loss: 0.5160 ``` 6. 运行成功后,你会在当前路径下看到一个新生成的文件夹:`mlruns`。需要注意,运行时间时间上,案例2肯定要比案例1长,因为案例二会首先随机选取`lr`以及`momentum`的值,然后再运行案例1的代码。 ### 案例2:第二种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-hyperparametertunning`文件夹; 4. 我们需要在创建一个experiment。注意,我们这里没有进入`mlflow-ex-hyperparametertunning`文件夹: ```bash mlflow experiments create -n new_run ``` 5. 你会发现在当前目录下,会新生成`mlruns`文件夹。terminal会返回experiment ID。在进行下一步操作之前,注意需要检查一下`search_random.py`中,`mlflow.projects.run`中的`uri`参数需要设置为`.`。然后我们输入: ```bash mlflow run -e random --experiment-id ./mlflow-ex-hyperparametertunning/ ``` 你应该可以看到类似 ```terminal Epoch 49/50 173/173 [==============================] - 0s 1ms/step - loss: 0.4805 - val_loss: 0.5160 ``` 6. 运行成功; ### 案例2:第三种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 我们需要在创建一个experiment,在我们自己选择的某个本地路径下 ```bash mlflow experiments create -n new_run ``` 3. 你会发现在当前目录下,会新生成`mlruns`文件夹。terminal会返回experiment ID。在进行下一步操作之前,注意需要检查一下`search_random.py`中,`mlflow.projects.run`中的`uri`参数需要设置为`.`。然后我们输入: ```bash mlflow run -e random --experiment-id https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git ``` 4. 运行成功; ## 案例3:超参数的Hyperopt调整 `search_hyperopt.py`通过`hyperopt`对`lr`以及`momentum`进行优化取值,然后运行模型的训练。随机选择方法是随机选择`lr`以及`momentum`的值,而`hyperopt`相当于计算cost function的最优解的方式通过迭代优化对这两个超参数取值,而这个cost function就是(或者说成正比)验证集的差值。这里我们只介绍三种运行代码的方式。代码的详细解释请参见博客[MLFlow 超参数调参案例: hyperopt优化调参](./mlflow-hyperparam-3.md)。 ### 案例3:第一种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-hyperparametertunning`文件夹; 4. `cd mlflow-ex-hyperparametertunning`进入文件夹; 5. `python .\search_hyperopt.py`。需要注意,需要检查一下`search_hyperopt.py`中,`mlflow.projects.run`中的`uri`参数需要设置为`https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`; 6. 运行成功后,你会在当前路径下看到一个新生成的文件夹:`mlruns`。需要注意,运行时间时间上,案例2肯定要比案例1长,因为案例二会首先随机选取`lr`以及`momentum`的值,然后再运行案例1的代码。 ### 案例3:第二种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 在VSCode,terminal中,选择你想克隆代码的本地路径; 3. 克隆代码:`git clone https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git`。此时,如果你在terminal输入`ls`,应该可以看到`mlflow-ex-hyperparametertunning`文件夹; 4. 我们需要在创建一个experiment。注意,我们这里没有进入`mlflow-ex-hyperparametertunning`文件夹: ```bash mlflow experiments create -n new_run ``` 5. 你会发现在当前目录下,会新生成`mlruns`文件夹。terminal会返回experiment ID。在进行下一步操作之前,注意需要检查一下`search_hyperopt.py`中,`mlflow.projects.run`中的`uri`参数需要设置为`.`。然后我们输入: ```bash mlflow run -e hyperopt --experiment-id ./mlflow-ex-hyperparametertunning/ ``` 6. 运行成功; ### 案例3:第三种方式 1. 在我们的主机(host machine),新建并进入虚拟环境; 2. 我们需要在创建一个experiment,在我们自己选择的某个本地路径下 ```bash mlflow experiments create -n new_run ``` 3. 你会发现在当前目录下,会新生成`mlruns`文件夹。terminal会返回experiment ID。在进行下一步操作之前,注意需要检查一下`search_hyperopt.py`中,`mlflow.projects.run`中的`uri`参数需要设置为`.`。然后我们输入: ```bash mlflow run -e hyperopt --experiment-id https://gitee.com/yichaoyyds/mlflow-ex-hyperparametertunning.git ``` 4. 运行成功; ## 对比这三种方式 最后,让我们来对比一下使用固定超参数,随机搜索超参数,以及Hyperopt优化搜索超参数的结果: ![mlflow ui](./img/4_compareall1.png) ![mlflow ui](./img/4_compareall2.png) 其实我们并没有很明显地感受到后两种搜索方式的不同,很可能是因为这个网络本身很小,我们再怎么调参数也不会对网络本身的性能带来很大的改变。实际上,我觉得Hyperopt优化调参是要比随机搜索要效果好一些的。固定超参数毫无疑问就是碰运气了。 ## 参考 - [一种超参数优化技术-Hyperopt](https://www.cnblogs.com/panchuangai/p/13939492.html#:~:text=%E4%BB%80%E4%B9%88%E6%98%AFHyperopt.%20Hyperopt%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BC%BA%E5%A4%A7%E7%9A%84python%E5%BA%93%EF%BC%8C%E7%94%A8%E4%BA%8E%E8%B6%85%E5%8F%82%E6%95%B0%E4%BC%98%E5%8C%96%EF%BC%8C%E7%94%B1jamesbergstra%E5%BC%80%E5%8F%91%E3%80%82.%20Hyperopt%E4%BD%BF%E7%94%A8%E8%B4%9D%E5%8F%B6%E6%96%AF%E4%BC%98%E5%8C%96%E7%9A%84%E5%BD%A2%E5%BC%8F%E8%BF%9B%E8%A1%8C%E5%8F%82%E6%95%B0%E8%B0%83%E6%95%B4%EF%BC%8C%E5%85%81%E8%AE%B8%E4%BD%A0%E4%B8%BA%E7%BB%99%E5%AE%9A%E6%A8%A1%E5%9E%8B%E8%8E%B7%E5%BE%97%E6%9C%80%E4%BD%B3%E5%8F%82%E6%95%B0%E3%80%82.%20%E5%AE%83%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%A4%A7%E8%8C%83%E5%9B%B4%E5%86%85%E4%BC%98%E5%8C%96%E5%85%B7%E6%9C%89%E6%95%B0%E7%99%BE%E4%B8%AA%E5%8F%82%E6%95%B0%E7%9A%84%E6%A8%A1%E5%9E%8B%E3%80%82.%20Hyperopt%E7%9A%84%E7%89%B9%E6%80%A7.,Hyperopt%E5%8C%85%E5%90%AB4%E4%B8%AA%E9%87%8D%E8%A6%81%E7%9A%84%E7%89%B9%E6%80%A7%EF%BC%8C%E4%BD%A0%E9%9C%80%E8%A6%81%E7%9F%A5%E9%81%93%EF%BC%8C%E4%BB%A5%E4%BE%BF%E8%BF%90%E8%A1%8C%E4%BD%A0%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E4%BC%98%E5%8C%96%E3%80%82.%20%EF%BC%88a%EF%BC%89%20%E6%90%9C%E7%B4%A2%E7%A9%BA%E9%97%B4.%20hyperopt%E6%9C%89%E4%B8%8D%E5%90%8C%E7%9A%84%E5%87%BD%E6%95%B0%E6%9D%A5%E6%8C%87%E5%AE%9A%E8%BE%93%E5%85%A5%E5%8F%82%E6%95%B0%E7%9A%84%E8%8C%83%E5%9B%B4%EF%BC%8C%E8%BF%99%E4%BA%9B%E6%98%AF%E9%9A%8F%E6%9C%BA%E6%90%9C%E7%B4%A2%E7%A9%BA%E9%97%B4%E3%80%82.%20%E9%80%89%E6%8B%A9%E6%9C%80%E5%B8%B8%E7%94%A8%E7%9A%84%E6%90%9C%E7%B4%A2%E9%80%89%E9%A1%B9%EF%BC%9A.) - [Hyperparameter Tuning with MLflow and HyperOpt](https://dzlab.github.io/ml/2020/08/16/mlflow-hyperopt/) - [Hyperparameter Tuning with MLflow, Apache Spark MLlib and Hyperopt](https://databricks.com/blog/2019/06/07/hyperparameter-tuning-with-mlflow-apache-spark-mllib-and-hyperopt.html) - [Hyperopt: Distributed Hyperparameter Optimization](https://github.com/hyperopt/hyperopt) - [MLFlow Hyperparameter Tuning Example](https://github.com/mlflow/mlflow/tree/master/examples/hyperparam) - [Keras中的回调函数Callbacks详解](https://blog.csdn.net/wf592523813/article/details/95027246) - [python __enter__ 与 __exit__的作用,以及与 with 语句的关系](https://www.cnblogs.com/lipijin/p/4460487.html) - [Python命令行工具-Click基础](https://zhuanlan.zhihu.com/p/346106422) - [Keras中文文档,回调函数使用](https://keras.io/zh/callbacks/) - [Numpy.random.seed()的用法](https://blog.csdn.net/weixin_41571493/article/details/80549833)