机器学习与结构化数据 (2-1):训练模型

这篇文章中,您将使用 TensorFlow 的 high-level Estimator API 创建一个宽且深的机器学习预测模型。您可以透过上一篇文章:数据分析和准备中所创建的 CSV 文件在 Cloud ML Engine 上训练模型。

架构

这篇文章将使用下图中虚线内的元件:

成本

这篇文章将会使用到以下需付费的元件,包含:

  • Compute Engine
  • Persistent Disk
  • Cloud Storage
  • Cloud ML Engine

根据这个定价计算器,假设您花一天使用这些元件来实作这篇文章,预计会花 1.57 美元。

开始之前

在开始之前,您必须完成本系列的第一部分 “资料分析和准备“。

透过 notebook

您可以按照前一篇文章中所下载的 Cloud Datalab notebook 说明,来了解建立机器学习模型的 end-to-end 流程。这篇文章是 notebook 的第二部分,将提供一些概要和补充的内容。

使用 Estimator API 创建 TensorFlow 模型

在第一篇文章中,您探索了原始数据集并选择了与婴儿体重相关的特征。您还使用 Cloud Dataflow 将数据集转换为 CSV 文件,将它们分成 training set evaluation set

选择一个合适的模型

TensorFlow 在建构模型时提供了几个抽象级别 (levels of abstraction)。较底层的 API提供了强大功能以及很高的灵活性,如果您是开发新机器学习技术的研究人员,较底层的 API 对你而言将非常实用。然而,估算婴儿体重是一个直接、具明确定义的问题,high-level 的 Estimator API 则会是实作机器学习解决方案的最佳选择。

Estimator API:

  • 附带内建估算器 (estimator) 或类别 (class),您可以透过实例化来解决常见的机器学习问题。
  • 与其将您限制在一台机器上,它允许您在一组机器上训练模型。 Estimator API提供了一个很方便的方式去实作分布式训练。

对于 Natality 数据集,notebook 使用tf.estimator.DNNLinearCombinedRegressor 回归器。此回归器允许您使用具有嵌入图层和多个隐藏图层的前馈神经网络创建一个一般化的模型,该模型具有深度及稀疏特征的逻辑回归。

下面的图片概述了三种主要的模型类型:宽、深、宽且深:

宽模型通常对基于分类特征的训练很有用。在 Natality 数据集中,以下特征适用于宽模型:

  • is_male, plurality

若要将数值特征应用于宽模型,则必须将连续值拆分为 buckets of value ranges(就是对其进行分段),将其转换为分类特征。在这种情况下,您可以将此技术应用于以下特征:

  • mother_age, gestation_weeks

特征组合透过连接 (concatenate) 一对特征 (is_male, plurality)来产生新特征,并将该连接作为 input,以便让模型学习。例如:双胞胎男孩往往比双胞胎女孩具有更高的体重。您可以将特征组合直接应用在分类特征,并且可以在将数值特征首先离散为数据特征时,将其应用于数值特征。
深层模型最适合数字特征。婴儿体重预测问题中特征符合以下标准:

  • mother_age, gestation_weeks

您也可以在深层模型中使用嵌入层。嵌入层将大量分类特征转换成较低维的数字特征。缺点是特征组合会大大增加特征的总数,如果提供给深度网络,则会增加过度拟合的风险。您可以通过使用嵌入层来缓解这种风险。

在 Natality 数据集中,您可以获取数值资料,将它们切割成几个区块,透过特征组合产生其他分类特征,然后使用嵌入图层。该嵌入层是深层模型的附加输入。

总而言之,某些数据特征适用于宽模型,其他特征可以通过深模型更好地工作:

宽模型 分类特征和分段数值特征 is_male, plurality, mother_age (bucketized),gestation_weeks (bucketized)
深模型 数值特征 mother_age, gestation_weeks
深模型加上嵌入层 透过特征组合产生分类特征 在宽模型中组合特征

为了解决不同类型特征带来的问题,开发了广且深的模型。它是以前两种模型的组合。您可以指定在配置 Estimator 对象时由哪个模型使用哪些特征。
以下是一个广且深的架构:

读取资料的函数

Estimator API 要求您提供一个名为input_fn的函数,该函数会在每次调用时从训练集中返回一批范例。您可以使用笔记本中的 read_dataset 函数透过指定 CSV 文件的档案名称模式来创建 input_fnfunction。

在内部,input_fn  函数使用存储在变量 filename_queue 中的文件名队列对像作为排队机制。它会在索引范例之前,识别与档名及模式相匹配的档案并对其进行洗牌。从CSV文件读取一行后, tf.decode_csv 将列值转换为TensorFlow常量对象列表。  DEFAULTS 列表用于标识值类型。

例如,如果 DEFAULTS的第一个元素是 [0.0],则第一列中的值将视为实数。  input_fn函数还提供默认值以补充CSV文件中的空单元格;这些空单元被称为缺失值。最后,使用CSV_COLUMNS 值作为键将列表转换为Python字典。input_fn函数返回特征字典和相应的标签值。在这种情况下,标签是婴儿的体重。

值的转换

从CSV文件读取值后,您可以对其应用其他转换。例如, is_malefield包含字符串 TrueFalse。然而,将这些字符串用作直接模型输入是没有意义的,因为数学模型并不像人类那样解释字面表达式的含义。通常的做法是对分类特征使用单热编码。在这种情况下,TrueFalse 分别映射到两个二进制列[1, 0][0, 1]

如前一部分所述,您还必须将数值分段 (bucketization),特征组合和嵌入技术应用于原始输入。

TensorFlow 提供了一个名为”特征列”的辅助方法来自动执行这些转换,这些方法可以Estimator 物件一起使用。例如,在以下代码中,tf.feature_column.categorical_column_with_vocabulary_list 将one-hot编码应用于 is_male。您可以使用返回值作为Estimator物件的输入。

tf.feature_column.categorical_column_with_vocabulary_list('is_male',      ['True', 'False', 'Unknown'])  

在以下代码中,您可以应用 tf.feature_column.bucketized_column 来对数值列(例如mother_age)进行分段 (bucketize)。

age_buckets = tf.feature_column.bucketized_column(mother_age,      boundaries=np.arange(15,45,1).tolist())  

boundaries选项指定分段的大小。在前面的例子中,除了“小于15”和“超过45”之外,它还为15至44岁之间的每个年龄层建立分段。

以下代码将特征组合和嵌入图层也应用于每一个宽列。

crossed = tf.feature_column.crossed_column(wide, hash_bucket_size=20000)  embed = tf.feature_column.embedding_column(crossed, 3)

tf.feature_column.embedding_column 的第二个参数定义了嵌入层的维数,在这种情况下为 case 3。

定义宽且深的特征

您必须区分用于宽部份和深部份的特征。应用转换后,您可以定义名为 wide 的特征列表作为宽部分的输入,以及名为 deep 的特征列表作为深部份的输入。以下代码中的变量(is_male, plurality等)是特征列的返回值 (return values)。

wide = [is_male,          plurality,          age_buckets,          gestation_buckets]    deep = [mother_age,          gestation_weeks,          embed]  

延伸阅读:

机器学习与结构化数据 (1):数据分析和准备

(原文翻译自 Google Cloud。)

 


连络“GCP 专门家”
想在手机阅读更多周边设备资讯?下载【香港硅谷】Android应用
分享到Facebook
技术平台: Nasthon Systems