本文已纳入学习路径:Watson Machine Learning Accelerator 入门系列。
主题 | 类型 |
---|---|
Watson Machine Learning Accelerator 简介 | 文章 |
加速深度学习和机器学习 | 文章 + Notebook |
Watson Machine Learning Accelerator 中的 Elastic Distributed Training | 文章 + Notebook |
使用 Watson Machine Learning Accelerator 超参数优化来加快零售价格预测 | 教程 |
推动更高的 GPU 利用率和吞吐量 | 教程 |
使用 Watson Machine Learning Accelerator 对图像进行分类 | 文章 + Notebook |
随着越来越多的行业领导者了解到数据和机器学习模型可以给他们的业务带来价值,各行各业已经开始逐步采用人工智能 (AI)。AI 可以给许多经济部门带来优势,其中包括:通过过程自动化来降低运营成本、通过提升生产效率和用户体验来增加收入、改善合规性并增强了安全性。
特别是,在零售行业中使用 AI,可以在优化、自动化和规模化方面提供优势。现如今,零售商都是使用数据来了解客户并改进现有产品,从而让他们的产品能够在竞争中脱颖而出。他们还可以更好地了解购物行为数据,预测客户的需求和个人偏好,利用个性化的报价和体验作出响应,从而增强促销效果并提高销售量。
每个零售商都需要完成的一项主要工作是优化价格,例如,确定特定商品的合适报价。借助 AI,他们便可以根据多种因素对各种商品进行优化。使用 AI 模型,可以根据季节性数据以及库存水平、竞争产品和价格的实时输入来确定每件商品的最佳价格。AI 还可以向零售商展示不同定价策略可能产生的结果,以便他们可以确立最佳促销优惠,吸引更多客户,从而提高销售量。
要实现这些潜在优势的关键是要设计和部署适当的机器学习模型,以最高的准确性预测每件商品的最佳价格。众所周知,梯度提升机 (GBM) 现在是最强大的机器学习模型之一,它可以为涉及表格化数据集的大多数任务提供最高泛化准确性。因此,本教程将重点介绍 GBM 机器学习模型,因为它是价格优化任务的理想之选。我们将使用 Mercari 价格优化竞争方案(Kaggle 提供的一个公共数据集)。然后,我们将使用大家喜爱的 GBM 模型 XGBoost。要使用 XGBoost 实现理想的泛化准确性,我们需要执行超参数调整 (HPT),即尝试不同的超参数集并选择在验证数据集中提供最佳准确性的超参数集。为此,我们将使用 Watson Machine Learning Accelerator 套件,此套件既是资源编排器,也是任务调度程序,它可以在一系列节点和 GPU 之间无缝分配 HPT 任务。
在本教程中,了解 Watson Machine Learning Accelerator 的易用性以及在执行分布式机器学习作业时的高资源效率,并了解 HPT 流程的强大功能,此流程建立的 XGBoost 模型在预测未见过的数据时也能提供较高的泛化准确性。
准备要用于提交 HPO 作业的集群:创建 conda 环境(在所有节点上)
要准备 POWER 集群:
创建一个 conda 环境,并以 egoadmin 用户身份安装预先构建的 XGBoost 库。
conda create --name dli-xgboost python=3.6 py-xgboost-gpu
要准备 x86 集群:
编译 XGBoost。
git clone --recursive https://github.com/dmlc/xgboost cd xgboost/ mkdir build cd build PATH=/opt/wmla-ig/anacondapowerai161-1/anaconda/pkgs/cudatoolkit-dev-10.1.168-513.g7069ee4/bin:$PATH cmake3 ..-DUSE_CUDA=ON make -j
创建一个 conda 环境,并在其中安装 XGBoost。
conda create --name dli-xgboost --yes pip python=3.7 conda activate dli-xgboost conda install numpy scikit-learn scipy python setup.py install source deactivate
创建 XGBoost BYOF 插件(仅在管理节点上)
要创建插件:
export DLI_EGO_TOP=/opt/ibm/spectrumcomputing
检查
DL_NFS_PATH
的值。$ cat $DLI_EGO_TOP/dli/conf/dlpd/dlpd.conf | grep DL_NFS_PATH "DL_NFS_PATH": "/dlishared",
export DL_NFS_PATH=/dlishared
创建一个名为
Xgboost.conf
的文件并在其中包含以下内容。{ "desc" : [{" ": "XGboost.Currently in development phase."}, {" ": "Examples:"}, {" ": "$ python dlicmd.py --exec-start XGboost <connection-options> --ig <ig> --model-main XGboost_Main.py"} ], "deployMode Desc": "Optional", "deployMode": "cluster", "appName Desc" : "This is required", "appName": "dlicmdXGboost", "numWorkers Desc": "Optional number of workers", "numWorkers": 1, "maxWorkers Desc": "User can't specify more than this number", "maxWorkers": 1, "maxGPUPerWorker Desc": "User can't specify more than this number", "maxGPUPerWorker": 10, "egoSlotRequiredTimeout Desc": "Optional", "egoSlotRequiredTimeout": 120, "workerMemory Desc" : "Optional", "workerMemory": "2G", "frameworkCmdGenerator Desc": "", "frameworkCmdGenerator": "XGboostCmdGen.py" }
将该文件移至以下目录。
sudo mv XGboost.conf $DLI_EGO_TOP/dli/conf/dlpd/dl_plugins
创建一个名为 Xgboost_wrapper.sh` 的文件并在其中包含以下内容。
#!/bin/sh source activate dli-xgboost python $@
创建一个名为
XGboostCmdGen.py
的文件并在其中包含以下内容。#!/usr/bin/env python2 import os.path, sys from os import environ """ """ def main(): cmd = "" if "DLI_SHARED_FS" in os.environ: print (environ.get('DLI_SHARED_FS')) cmd = environ.get('DLI_SHARED_FS') + "/tools/spark_tf_launcher/launcher.py" else: print("Error: environment variable DLI_SHARED_FS must be defined") sys.exit() if "APP_NAME" in os.environ: cmd = cmd + " --sparkAppName=" + environ.get('APP_NAME') else: print("Error: environment variable APP_NAME must be defined") sys.exit() if "MODEL" in os.environ: cmd = cmd + " --model=" + environ.get('MODEL') else: print("Error: environment variable MODEL must be defined") sys.exit() if "REDIS_HOST" in os.environ: cmd = cmd + " --redis_host=" + environ.get('REDIS_HOST') else: print("Error: environment variable REDIS_HOST must be defined") sys.exit() if "REDIS_PORT" in os.environ: cmd = cmd + " --redis_port=" + environ.get('REDIS_PORT') else: print("Error: environment variable REDIS_PORT must be defined") sys.exit() if "GPU_PER_WORKER" in os.environ: cmd = cmd + " --devices=" + environ.get('GPU_PER_WORKER') else: print("Error: environment variable GPU_PER_WORKER must be defined") sys.exit() cmd = cmd + " --work_dir=" + os.path.dirname(environ.get('MODEL')) cmd = cmd + " --app_type=executable" cmd = cmd + " --model=" + environ.get('DLI_SHARED_FS') + "/tools/dl_plugins/XGboost_wrapper.sh --" cmd = cmd + " " + environ.get('MODEL') # adding user args for i in range(1, len(sys.argv)): cmd += " " + sys.argv[i] # Expected result in json print('{"CMD" : "%s"}' % cmd) if __name__ == "__main__": sys.exit(main())
移动这些文件并使其成为可执行文件。
sudo mv XGboost_wrapper.sh $DL_NFS_PATH/tools/dl_plugins sudo mv XGboostCmdGen.py $DL_NFS_PATH/tools/dl_plugins sudo chmod +x $DL_NFS_PATH/tools/dl_plugins/XGboost_wrapper.sh sudo chmod +x $DL_NFS_PATH/tools/dl_plugins/XGboostCmdGen.py
下载并准备数据集
mkdir $DL_NFS_PATH/data sets/higgs
cd $DL_NFS_PATH/datasets/higgs
wget --no-check-certificate https://archive.ics.uci.edu/ml/machine-learning-databases/00280/HIGGS.csv.gz
gunzip HIGGS.csv.gz
mkdir train
mkdir val
mkdir test
在当前文件夹中创建以下 Python 脚本 (
preprocess.py
)。import pandas as pd from sklearn.model_selection import train_test_split import xgboost as xgb df = pd.read_csv("HIGGS.csv", header=None) data = df.values y = data[:,0] X = data[:,1:] X_tmp, X_test, y_tmp, y_test = train_test_split(X,y, random_state=42) X_train, X_val, y_train, y_val = train_test_split(X_tmp,y_tmp, random_state=42) print("Number of features: %d" % (X_train.shape[1])) print("Number of training examples: %d" % (X_train.shape[0])) print("Number of validation examples: %d" % (X_val.shape[0])) print("Number of test examples: %d" % (X_test.shape[0])) dx_train = xgb.DMatrix(X_train, y_train) dx_val = xgb.DMatrix(X_val, y_val) dx_test = xgb.DMatrix(X_test, y_test) dx_train.save_binary("train/HIGGS_train.dmatrix") dx_val.save_binary("val/HIGGS_val.dmatrix") dx_test.save_binary("test/HIGGS_test.dmatrix")
执行预处理脚本以生成数据文件。
conda activate dli-xgboost conda install pandas python preprocess.py
您会看到以下输出:
Number of features: 28 Number of training examples: 6187500 Number of validation examples: 2062500 Number of test examples: 2750000
检查
DLI_DATA_FS
的值。$ cat $DLI_EGO_TOP/dli/conf/dlpd/dlpd.conf | grep DLI_DATA_FS "DLI_DATA_FS": "/dlidata/",
将训练和验证数据集复制到
'DLI_DATA_FS'
。$ pwd /dlidata/dataset/price_prediction $ ll -lt -rw-rw-r-- 1 egoadmin egoadmin 210025976 Nov 7 14:38 pp_val.dmatrix -rw-rw-r-- 1 egoadmin egoadmin 630075452 Nov 7 14:38 pp_train.dmatrix
使用默认参数运行 XGBoost
创建
train_xgb_default.py
文件。from sklearn.metrics import roc_auc_score import xgboost as xgb import argparse CLI=argparse.ArgumentParser() CLI.add_argument("--trainFile", type=str, default="") CLI.add_argument("--valFile", type=str, default="") CLI.add_argument("--testFile", type=str, default="") args = CLI.parse_args() # Set params params = { 'tree_method': 'gpu_hist', 'max_bin': 64, 'objective': 'binary:logistic', } # Load data dtrain = xgb.DMatrix(args.trainFile) ddev = xgb.DMatrix(args.valFile) dtest = xgb.DMatrix(args.testFile) # Get labels y_train = dtrain.get_label() y_dev = ddev.get_label() y_test = dtest.get_label() # Train gbm = xgb.train(params, dtrain) # Inference p1_train = gbm.predict(dtrain) p1_dev = gbm.predict(ddev) p1_test = gbm.predict(dtest) # Evaluate auc_train = roc_auc_score(y_train, p1_train) auc_dev = roc_auc_score(y_dev, p1_dev) auc_test = roc_auc_score(y_test, p1_test) print("auc_test: %f, auc_val: %f, auc_test: %f" % (auc_train, auc_dev, auc_test))
使用默认参数运行模型(与以前一样使用
dli-xgboost
环境)。
(dli-xgboost)# python train_xgb_default.py --trainFile /dlidata/dataset/price_prediction/pp_train.dmatrix --testFile /dlidata/dataset/price_prediction/pp_val.dmatrix
[04:16:57] 833433x93 matrix with 77509269 entries loaded from /dlidata/dataset/price_prediction/pp_train.dmatrix
[04:16:57] 277812x93 matrix with 25836516 entries loaded from /dlidata/dataset/price_prediction/pp_val.dmatrix
mse_test: 1231.55
使用 Watson Machine Learning Accelerator 超参数优化来调优 XGboost
我们来看看使用 Watson Machine Learning Accelerator 超参数优化是否可以做得更好。
通过运行 runbook 的步骤 1 – 4 来安装和配置 Watson Machine Learning Accelerator。
下载 05_tuning_xgboost_with_hpo.ipynb notebook,然后使用您的首选工具来打开该 notebook。
利用该文件夹下载模型:xgb-model/main.py。
更新 notebook 的第一个单元:
- hostname - username, password - protocol (http or https) - http or https port - sigName - Dataset location
更新 notebook 的第二个单元:
- maxJobNum: total number of tuning jobs to be running - maxParalleJobNum: total number of tuning jobs running in parallel, which is equivalent to total number of GPUs available in the cluster
在此 notebook 中,我们将调优 XGBoost 模型的五个参数。运行 notebook 以启动并行模型调优作业。
运行第四个单元以监视作业进度。将返回建议的最佳参数集(具有最佳指标)。
.... Hpo task Admin-hpo-83966261958354 state RUNNING progress 56% Hpo task Admin-hpo-83966261958354 completes with state FINISHED { "best": { "appId": "Admin-84189701779622-1370733872", "driverId": "driver-20191108160851-0342-bacfbcb3-ed76-4f70-92f5-65062f92d1cb", "endTime": "2019-11-08 16:11:07", "hyperParams": [ { "dataType": "double", "fixedVal": "0.9597590292372464", "name": "learning_rate", "userDefined": false }, { "dataType": "int", "fixedVal": "565", "name": "num_rounds", "userDefined": false }, { "dataType": "int", "fixedVal": "13", "name": "max_depth", "userDefined": false }, { "dataType": "double", "fixedVal": "1584.7191653582931", "name": "lambda", "userDefined": false }, { "dataType": "double", "fixedVal": "0.47", "name": "colsample_bytree", "userDefined": false } ], "id": 6, "maxiteration": 0, "metricVal": 1036.0960693359375, "startTime": "2019-11-08 16:08:51", "state": "FINISHED" }, ......
使用从调优作业返回的参数来创建
train_xgb_tuned.py
文件。import xgboost as xgb import argparse import numpy as np from sklearn.metrics import mean_squared_error CLI=argparse.ArgumentParser() CLI.add_argument("--trainFile", type=str, default="") CLI.add_argument("--testFile", type=str, default="") args = CLI.parse_args() # Set params as found by WML-A HPO params = { 'tree_method': 'gpu_hist', 'learning_rate': 0.9597590292372464, 'num_rounds': 565, 'max_depth': 13, 'lambda': 1584.7191653582931, 'colsample_bytree': 0.47 } # Load training and test data dtrain = xgb.DMatrix(args.trainFile) dtest = xgb.DMatrix(args.testFile) # Training gbm = xgb.train(params, dtrain, params['num_rounds']) # Evaluate true_price = np.expm1(dtest.get_label()) pred_price = np.expm1(gbm.predict(dtest)) mse_test = mean_squared_error(true_price, pred_price) # Output print("mse_test: %.2f" % (mse_test))
使用已调优的参数运行 XGBoost
通过以下代码,使用已调优的参数运行 XGBoost。
(dli-xgboost)# python train_xgb_tuned.py --trainFile /dlidata/dataset/price_prediction/pp_train.dmatrix --testFile /dlidata/dataset/price_prediction/pp_val.dmatrix
[04:23:26] 833433x93 matrix with 77509269 entries loaded from /dlidata/dataset/price_prediction/pp_train.dmatrix
[4:23:26] 277812x93 matrix with 25836516 entries loaded from /dlidata/dataset/price_prediction/pp_val.dmatrix
mse_test: 1036.10
结束语
均方误差 (MSE) 用于衡量误差平方的平均值,即估计值与实际值之间的平均平方差。MSE 值越小,近似误差就越小,泛化准确性就越好。在我们的实验中,使用 Watson Machine Learning Accelerator 超参数优化调整参数的 MSE 值是 1036.10,与 MSE 值 1231.55 的默认参数相比,它提供了较高的泛化准确性。
在本教程中,我们展示了 Watson Machine Learning Accelerator 的易用性以及在自动执行并行超参数调整作业时的效率,并说明了它如何以更精确的 XGBoost 模型泛化精度提供更准确的零售价格预测。
本文翻译自:Expedite retail price prediction with Watson Machine Learning Accelerator hyperparameter optimization(2020-10-21)