构建无服务器机器学习模型

本文介绍如何在 Google Cloud Platform (GCP) 上以无服务器方式构建自定义机器学习任务,并说明 AI Platform 相比于 Perception API 所具备的优势。具体涵盖以下主题:

  • 了解如何构建机器学习模型
  • 提升模型质量
  • 从玩具问题转向可扩缩的环境

本文紧接无服务器机器学习模型架构一文,在前文中,您已了解如何以无服务器方式使用 Firebase、Cloud Functions、Natural Language API 和 AI Platform 来丰富支持服务工单。

了解构建步骤

在 GCP 中,机器学习任务主要有两种执行方式:

  • 使用 GCP 提供的预建且经过训练的 RESTful Perception API,例如 Cloud Vision APICloud Speech API。这些预训练模型可用于进行情感分析和自动标记(这些内容已在本解决方案的第一部分中提及)。
  • 构建或重复使用模型。您可以通过 TensorFlow 和 AI Platform 使用自己的自定义数据训练这些模型。如需预测解决时间和优先级,最好使用这种方法(请参阅本解决方案的第一部分)。

下图展示的是第二种方法,在这种方法中,您需要收集和存储数据集、整理数据,然后设计、训练并部署模型。

机器学习任务

收集和存储数据

为了生成令人信服的模型,关键在于数据。提供的数据越多,模型预测效果通过训练得到提升的可能性就越大(但前提是您提供的是有用并且整洁有序的数据)。如需了解详情,请参阅提升模型质量部分。

在某些情况下,获取数据可能十分简单;但如果一些数据集只包含几百个样本,那么获取数据可能就并非易事。对于支持服务工单,您会获得几十万个历史样本,这应该足以训练出一个出色的模型。

在使用客户关系管理 (CRM) 系统或其他任何工单处理系统时,您可能可通过导出或运行查询来获取自产品发布后创建的所有工单。这样做的目的是获取工单字段。通常,这些字段包含工单 ID、客户 ID、类别、优先级、解决时间、代理 ID、客户的产品使用体验等信息。此类导出操作的输出一般是 CSV 文件:

t0,Patrick Blevins,12,3-Advanced,Performance,Request,4-Critical,P1,5
t1,Kaitlyn Ruiz,3,2-Experienced,Technical,Issue,1-Minor,P4,6
t2,Chelsea Martin,11,2-Experienced,Technical,Request,4-Critical,P1,2
t3,Richard Arnold,8,2-Experienced,Performance,Request,1-Minor,P3,5
...

在收集数据时,请务必牢记以下几点事项:

  • 如果您执行的是二元分类,请勿只收集正例。建议同时收集负例。
  • 概括来说,为各类别找到的样本数量应尽量保持均衡。否则,您将需要应对代码中的任何不平衡问题。
  • 寻找更多的离群值样本。这些样本属于真实用例,因此系统应该能够对其进行预测。

在本教程中,历史数据已收集完毕,并在 Cloud Storage 中以单个 CSV 文件形式提供。

对数据进行预处理

在训练模型之前,您需要对数据进行预处理,此环节至关重要。所涉及的工作量和选用的技术主要取决于以下两个决定因素:

  • 数据质量:如果您的数据包含不相关的字段,或者数据需要进行清理或特征组合,请务必先解决这些问题,然后再发送数据进行训练。
  • 数据大小:如果您的数据过大,或者数据因采用独热编码而变得过大,那么单个实例可能无法处理该数据。

如需详细了解预处理方面的最佳做法,请参阅从玩具问题转向可扩缩的解决方案部分。

Cloud Datalab 可以直接从其界面中运行 gcloud 命令,并可在代管式环境中运行 Jupyter Notebook,因此是一个非常好的数据准备工具。Cloud Datalab 带有 ML Workbench 库,可以简化与 TensorFlow 的互动。

Cloud Datalab 还可用作一个互动式编排系统:

  • 如果数据足够小,您可以通过互动方式使用 Pandas 等库。
  • 如果内存无法满足数据的需求,您可以使用 Apache Beam 等工具在 Cloud Datalab 外部处理数据。但您仍然可以通过互动方式使用结果。

以下是您可能需要执行的一些任务:

  • 过滤掉预测时不可用的输入列。 例如:代理 ID
  • 确保您的标签已正确转换并且可用。 例如:删除空值
  • 消除异常,或寻找更多样本(前提是这些样本不是异常,而是重复事件)。 例如:不存在的类别文本
  • 按某一比例将数据拆分用于训练、评估和测试。 例如:80%、10%、10%
  • 将输入和标签转换为实用的特征。 例如:解决时间 =(结束时间 - 创建时间)
  • 移除重复行

下表展示了一些给出的输入:

字段名称 保留 原因 类型
Ticket ID 该值对于每个工单都是独一无二的,并且对于训练预测算法不会有任何帮助。 不适用
Customer ID 不确定 取决于客户是否属于重复客户。 离散
Category 可能影响工单复杂性。 分类
Agent ID 在用户提交工单时,此为未知值。

注意:一个有用的用例是通过分类方案预测该值。
不适用
Years of product experience 可能影响工单复杂性。 连续

选择完输入列后,您至少需要创建两个不同的数据集(最好创建三个),这些数据集不能重叠并且都对应一定比例的数据。

训练集
对应总数据集的约 80% 数据。您的模型使用该数据集来调整各种参数(称为模型权重),以尽可能接近真实情况(即标签)。为此,模型会最大限度地降低损失函数的值,该函数用于计算模型的预测结果与真实情况之间的差距(也就是当前误差)。最终的预测模型会选用一组最佳权重。
评估集
通常对应数据集 10% 到 20% 的数据。该数据集可防止模型出现过拟合现象。如果模型在训练集上表现良好,只产生了一个小错误,但无法对新数据或未知数据做出良好的预测,则说明模型发生了过拟合。 换句话说,该模型本身过拟合到了数据中。如果一个模型训练过度,那么它只能学会如何提取训练集中的特定特征,而无法学会如何提取给定类型数据中的一般特征。
测试集
通常对应 10% 到 15% 的数据。测试集用于验证模型的泛化能力。由于训练期间使用的是评估集,因此模型可能存在隐性偏差。为了评估模型的效果,您必须衡量该模型在不同测试集上的表现情况。

可采用以下任一方式来划分数据:

  • 随机重排数据。
  • 使用生成器种子重排数据。
  • 使用列的哈希值来确定某个样本是归入训练集、评估集还是测试集。

建议使用哈希值,因为在提取数据集的更新版本时哈希值不会受到影响。此外,这种方法还可以确保测试集始终保持不变。

设计模型

解决时间和优先级预测属于监管机器学习任务。这意味着输入数据会带有标签。相关的数据字段分为两类:

输入
工单 ID、资历、使用体验、类别、类型、影响
标签
解决时间和优先级

在监督式学习环境中,实用的训练样本是与标签相关的输入。这些类型的标签反映了有待模型发现的真实情况。预测模型的目标是使用输入来预测未知标签。为此,模型需要使用有效样本来进行训练。在此用例中,预测涉及到以下内容:

解决时间
如果支持服务代理看到的值较高,那么可能说明需要更多资源来处理未知问题。
优先级
有助于代理按照既定流程确定工单和资源的优先级。

为了设计模型,您需要先构建具体问题,从而确定应使用哪个模型进行预测。此用例存在两个不同的监管机器学习问题:

回归
解决时间是一个连续的数值。它可以定义为回归问题,该模型的预测结果为连续值。
分类
优先级可以有若干个值,例如 P1、P2、P3 和 P4。多分类模型可以有效地解决此问题。 该模型会针对每个优先级类别输出一个概率,并且所有概率的总和为 1。分配概率后,您便可以确定为哪个工单指定哪个优先级。例如,如果 P1 = 10%、P2 = 20%、P3 = 60% 且 P4 = 10%,则为支持服务工单分配 P3 优先级。

在利用 TensorFlow 和 AI Platform 时,对于上述两个问题而言,模型开发流程是类似的,并且向其中一个 Estimator API 提供的特点也是相同的。从分类切换到回归只需更改几行代码即可。

确定输入并获得一些有效数据集后,您现在需要将数据转换为可在 TensorFlow 图中使用的实体(包括非数字值)。

字段名称 类型 说明
Category 分类 您知道完整词汇(所有可能值)。
Product experience 连续 要保留的数值。每年的 Product experience 都很重要。

ML Workbench 提供了一种将这些输入转换为可供 TensorFlow 使用的实体的简单方法。ML Workbench 会对每种字段类型都使用 TensorFlow 特征列函数

features:
  ticketid:
    transform: key
  seniority:
    transform: identity
  category:
    transform: one_hot
  [...]
  priority:
    transform: target

此外,机器学习 Workbench 还提供一个用于分析和准备模型数据的函数:

%%ml analyze [--cloud]
output: [OUTPUT_ANALYSIS]
data: $[CREATED_DATASET]
features:
...

生成模型

对于本文中的用例,您拥有的工单足以让模型提供相当不错的预测,但不足以应对数据大小的需求,因此您可以使用本地训练程序。请注意,只需使用 --cloud 参数即可方便地从本地训练切换到云端训练。

%%ml train [--cloud]
output: [OUTPUT_TRAIN]
analysis: [OUTPUT_ANALYSIS]
data: $[CREATED_DATASET]
  model_args:
    model: dnn_regression
    max-steps: 2000
    hidden-layer-size1: 32
    hidden-layer-size2: 8
    train-batch-size: 100
    eval-batch-size: 100
    learning-rate: 0.001

如需详细了解 hidden-layer-sizeXmax-steps 参数,请参阅调整超参数部分。

部署模型

在开发应用时,关键环节是在 TensorFlow 中构建一个图并将其移植到 AI Platform 进行训练。但是,如果一个功能强大的预测模型只可供数据科学家使用,那有何意义呢?当前用例旨在为您的支持服务台提供实时预测结果。为此,需要能够通过使用 Node.js 编写的 Cloud Functions 函数访问模型。该模型是用 Python 构建和编写的。

AI Platform 可以将模型部署为 RESTful API;这样一来,无论您是只有一个用户还是拥有着数百万个用户,该模型均可提供大规模预测服务。如需部署该模型,只需使用简易命令行,并将模型名称和存储分区分别替换为 [MODEL_NAME][BUCKET] 即可。

gcloud ml-engine models create [MODEL_NAME]
DEPLOYMENT_SOURCE=[BUCKET]
gcloud ml-engine versions create "version_name" --model [MODEL_NAME] --origin $DEPLOYMENT_SOURCE

该模型可用于在线预测和离线预测。在下一部分中,您将学习如何通过无服务器方式使用 Cloud Functions 函数来调用该模型。

以无服务器方式丰富数据

部署模型后,即可通过 RESTful API 对其进行调用,这是使用 AI Platform 的优势之一。该 API 可将模型提供给所有类型的客户端(包括 Cloud Functions 函数)。在本解决方案的用例中,Firebase 数据库在记录工单后会触发 Cloud Functions 函数,以使用 Natural Language API 和自定义模型来丰富数据。下图演示了这一模型。

以无服务器方式丰富数据

以下两个示例通过 Cloud Functions 函数调用 Natural Language API 和自定义模型。

  • Natural Language API:

    const text = ticket.description;
    const document = language.document({content: text});
    
    document.detectSentiment()
     .then((results) => {
        const sentiment = results[1].documentSentiment;
        admin.database().ref(`/tickets/${key}/pred_sentiment`).set(sentiment.score);
     })
     .catch((err) => {
        console.error('ERROR detectSentiment:', err);
     });
  • 解决时间回归模型:

    ml.projects.predict({
      name: `projects/${MDL_PROJECT_NAME}/models/${RESOLUTION_TIME_MODEL_NAME}`,
      resource: {
        name: `projects/${MDL_PROJECT_NAME}/models/${RESOLUTION_TIME_MODEL_NAME}`,
        instances: [
          `${key},${ticket.seniority},${ticket.experience},${ticket.category},
          ${ticket.type},${ticket.impact}`
        ]
      }
    },

提升模型质量

本部分简要介绍了一些有助于改进模型的额外措施。

数据准备

在开始训练模型之前,您需要先准备好数据:

收集样本
无论是您的数据包含离群值,还是您有多个需要预测的类别,都请务必收集所有用例的样本。
清理数据
清理操作非常简单,只需删除重复项即可;执行此操作可以避免训练集和评估集中含有相同样本,或者说,可以确保所有值都有意义(例如,资历年数不小于零)。
运用人类的洞察能力
在使用合适特征的情况下,机器学习模型可以表现得更出色。最佳做法是使用 TensorFlow 提供的 cross_function 来组合特征。例如,若要预测出租车费用,此函数可以通过组合经度和纬度来提升模型质量。或者,在支持服务用例中,该函数可以组合资历与产品使用体验。
创建数据桶
借助 TensorFlow bucketized_column 之类的函数,可以将输入离散化并提升性能,尤其是在样本数量不是很多的极端情况下。

调整超参数

一些训练参数值很难找到,但它们却对成功构建模型至关重要。使用合适的组合可以大大提升模型性能。通常需要调整以下值:

  • 隐藏层的大小(用于神经网络)
  • 神经元的数量(用于神经网络)
  • 训练步数
  • 分类输入桶的大小(如果您没有完整字典)(例如:origin city)

您选择的任何值都可以作为超参数。 可通过以下几种方式找到合适的组合:

  • 使用“For”循环进行网格搜索。

    您可以设置不同的值,循环遍历所有组合,并重点关注最佳结果。这种方式可能非常耗时,并且计算开销很大,具体取决于超参数的数量及其范围大小。

  • 首选方法是使用 AI Platform 调整超参数。 AI Platform 会根据声明性 YAML 设置自动调整超参数。在所有训练步骤完成之前,该系统会快速跳转到最佳参数组合并停止运行,这有助于节省时间、计算资源和资金。

增加样本数量

模型在训练时使用的数据越多,它看到的用例就越多,其预测效果也会越好。如果向模型提供的样本有数百万个,那么可能很难在本地进行训练。一种解决方案是使用 ML Workbench,它可以利用以下服务:

  • TensorFlow:用于分发训练任务并分批运行各步。
  • BigQuery:用于分析训练数据
  • AI Platform:用于在可扩缩的“按需使用”基础架构上运行训练和预测

下图演示了在用例和训练数据较多的情况下,模型是如何改善预测效果的。

数据和用例

请注意,与 MapReduce 不同,机器学习训练不是高度并行问题。也就是说,优化梯度下降法等操作需要占用参数服务器上的共享内存。您的机器学习平台必须支持这种方法。

从玩具问题转向可扩缩的环境

前一部分介绍了一些有助于提升模型质量的最佳做法。其中一些任务可以通过对数据集进行采样或加以限制轻松实现。但在训练高性能模型时,由于需要使用大量数据,因此这些任务可能颇具挑战性。

下图展示了一种可扩缩的方法。

以无服务器方式丰富数据

使用 BigQuery 和 Cloud Datalab 探索数据

建议使用 BigQuery 存储和查询数据。BigQuery 是一个专为大数据而构建的列式数据库,可让用户在短短几秒钟内对数 TB 的数据运行临时查询。

通过 Cloud Datalab 和 BigQuery,您可以执行以下操作:

  • 通过 Cloud Datalab,利用 BigQuery 探索和直观呈现数 TB 的数据。
  • 过滤可能对预测没有太大影响的输入。
  • 创建一组代表性数据样本以开始创建模型。
  • 有可能拆分数据,用于训练、评估和测试。

使用 Cloud Dataprep 和 Cloud Dataflow 预处理数据

大多数情况下,输入数据并不是现成可用的。它们通常需要经过处理才能成为有用的特征,例如:

  • 清除诸如 None 和 Null 之类的值,它们将变为 Unknown 值。
  • 拆分数据集以进行训练、评估和测试。
  • 将数据转换为 tfRecord 文件(推荐与 TensorFlow 结合使用的一种格式)。

Cloud Dataprep 是一种可视化工具,可以在编程开销有限的情况下执行大规模数据准备和清理。Cloud Dataprep 在后台使用 Apache Beam,但得益于其简单易用的界面,可以省去大量样板代码。

Apache Beam 可以在 Cloud Dataflow 上运行。 Cloud Dataflow 可助力您开发和执行各种各样的数据处理模式。 这些模式包括 ETL(提取、转换和加载)、批量计算和连续计算。

使用 tf.Transform 和 Dataflow 大规模减少偏差

开发者通常需要编写预处理训练代码。有时,为了迎合在分布式环境中运行的需求,他们需要调整此代码,但同时还要为传入的预测数据编写既相似又不同的代码。这种做法可能会导致以下两个主要问题:

  • 两个代码库可能需要由不同的团队来维护。
  • 更重要的是,训练与推理之间可能会产生偏差。

tf.Transform 可让您编写同时适用于训练和预测的通用代码,因此可以解决这两个问题。此外,它可以使用 Apache Beam 在分布式环境中运行代码。

在 Google Cloud Platform 上利用带有 tf.Transform 的 TensorFlow

前文所述的部分功能也同属于 TensorFlow(因此它们是开源的),但对于 AI Platform,运行 TensorFlow 还会带来以下关键优势:

  • 在无服务器环境中运行机器学习任务
  • 更加轻松地调整超参数
  • 将模型作为 RESTful API 托管,从而可通过异构客户端(不限于 Python)进行访问

下图展示了 TensorFlow 的使用方法。

利用 TensorFlow

请注意,利用 tf.Transform(一个 TensorFlow 库),您可以限制训练和预测之间的潜在偏差,因为它们可以使用相同的代码库。

后续步骤