如何提供使用估算器训练的嵌套?

文 / Google Cloud Platform 技术负责人 Lak Lakshmanan

原文链接:mp.weixin.qq.com/s/MhadSlQER…

如果您有一个稀疏分类变量(可以有多个可能的值的变量),将该变量嵌入到较低维度可能会非常有用。这种最广为人知的嵌入形式就是词嵌套(例如 word2vec 或 Glove 嵌套),即语言中的所有词汇都用一个包含约 50 个元素的向量表示。其理念是相似的词汇在 50 维空间中距离很近。您可以使用分类变量进行相同操作,即使用一个问题训练嵌套,然后再次使用该嵌套,而非对相关问题中的分类变量进行独热编码。嵌套的较低维度空间是连续的,所以该嵌套还可以充当聚类算法的输入 — 您可以找到分类变量的自然分组。

嵌套可以帮助您看到森林,而不仅仅是树木

要提供使用估算器训练的嵌套,您可以连同普通预测输出一起,发出分类变量的较低维度表征。嵌套权重保存在 SavedModel 中,并且有一个分享文件本身的选项。或者,您也可以为机器学习团队的客户端按需提供嵌套,这些客户端现在只是松散耦合到您选择的模型架构,所以这样可能更容易维护。每次有更新更好的版本替代您的模型时,客户端都会获得更新后的嵌套。

在本文中,我会向您展示如何: 在回归模型或分类模型中创建嵌套 以不同方法表示分类变量 使用特征列进行数学计算 分发嵌套及原始模型的输出

您可以在 GitHub 上找到本文中的完整代码,其中包含更多上下文。在这里,我只向您展示关键代码段。 注: GitHub 链接 github.com/GoogleCloud…

用模型来预测自行车需求 我们来构建一个简单的需求预测模型,在已知星期几和当天是否下雨的前期下,预测自行车租赁站的租车数量。所需数据来自纽约市自行车租赁和 NOAA 气象数据的公开数据集:

模型的输入如下: 星期几(1–7 的整数) 租赁站 ID(由于不知道完整词汇,这里我们使用哈希存储分区。该数据集有大约 650 个唯一值。我们会使用一个很大的哈希存储分区,但之后会将其嵌入到较低维度中) 是否下雨(真/假)

我们想要预测的标签为 num_trips。

我们可以通过在 BigQuery 中运行这个查询来创建数据集,从而加入自行车和天气数据集,并进行必要的聚合: 注:BigQuery 链接 cloud.google.com/bigquery/

1    #standardsql    
2    WITH bicycle_rentals AS (    
3        SELECT    
4            COUNT(starttime) as num_trips,    
5            EXTRACT(DATE from starttime) as trip_date,   
6            MAX(EXTRACT(DAYOFWEEK from starttime)) as day_of_week,    
7            start_station_id    
8    FROM `bigquery-public-data.new_york.citibike_trips`    
9    GROUP BY trip_date, start_station_id    
10    ),    
11
12    rainy_days AS    
13    (    
14    SELECT    
15    date,    
16    (MAX(prcp) > 5) AS rainy    
17    FROM (    
18    SELECT    
19        wx.date AS date,    
20        IF (wx.element = 'PRCP', wx.value/10, NULL) AS prcp    
21    FROM    
22        `bigquery-public-data.ghcn_d.ghcnd_2016` AS wx    
23        WHERE    
24            wx.id = 'USW00094728'    
25    )    
26    GROUP BY    
27      date    
28     )    
29
30    SELECT    
31        num_trips,    
32        day_of_week,    
33        start_station_id,    
34        rainy    
35    FROM bicycle_rentals AS bk    
36    JOIN rainy_days AS wx    
37    ON wx.date = bk.trip_date    

复制代码

使用估算器编写模型 要编写模型,我们需要在 TensorFlow 中使用自定义估算器。虽然这只是一个线性模型,但我们不能使用 LinearRegressor,因为 LinearRegressor 会隐藏所有底层特征列运算。我们需要访问中间层输出(嵌套特征列的输出),这样我们就可以清晰地编写线性模型。

要使用自定义估算器,您需要编写一个模型函数,并将其传递给估算器构造函数:

1 ef train_and_evaluate(output_dir, nsteps):
2 estimator = tf.estimator.Estimator(
3 model_fn = model_fn,
4 model_dir = output_dir)

自定义估算器中的模型函数包括下列 5 个部分:

1.定义模型:

1    def model_fn(features, labels, mode):    
2        # linear model    
3        station_col = tf.feature_column.categorical_column_with_hash_bucket('start_station_id', 5000, tf.int32)    
4        station_embed = tf.feature_column.embedding_column(station_col, 2)  # embed dimension    
5        embed_layer = tf.feature_column.input_layer(features, station_embed)  6
7        cat_cols = [    
8            tf.feature_column.categorical_column_with_identity('day_of_week', num_buckets = 8),    
9            tf.feature_column.categorical_column_with_vocabulary_list('rainy', ['false', 'true'])    
10        ]    
11        cat_cols = [tf.feature_column.indicator_column(col) for col in cat_cols]    
12        other_inputs = tf.feature_column.input_layer(features, cat_cols)    
13
14        all_inputs = tf.concat([embed_layer, other_inputs], axis=1)    
15        predictions = tf.layers.dense(all_inputs, 1)  # linear model    
复制代码

我们将选取租赁站列,并根据其哈希代码将其放入一个存储分区。使用这个技巧可以避免构建完整词汇。纽约只有大约 650 个自行车租赁站,所以拥有 5000 个哈希存储分区,我们就可以大大减少冲突的几率。然后,将租赁站 ID 嵌入到少数维度中,我们还会了解到哪些租赁站彼此相似,至少在雨天租车的情况下相似。最后,用二维向量表示每个租赁站的 ID。数字 2 控制较低维度空间代表分类变量中信息的准确程度。这里我随意选择了 2,但实际上,我们需要调节此超参数,以实现最佳性能。

其他两个分类列均使用其实际词汇创建,然后进行了独热编码(指示器列对数据进行了独热编码)。

这两组输入都经过级联,以创建一个宽输入层,然后通过一个输出节点传递到某个密集层。这样,您就在较低层级编写了一个线性模型。这相当于编写了一个 LinearRegressor,如下所示:

1    station_embed = 
2            tf.feature_column.embedding_column(    
tf.feature_column.categorical_column_with_hash_bucket('start_station_id', 5000, tf.int32), 2)    
3    feature_cols = [    
4        tf.feature_column.categorical_column_with_identity('day_of_week', num_buckets = 8),    
5        station_embed,    
6        tf.feature_column.categorical_column_with_vocabulary_list('rainy', ['false', 'true'])    
7    ]    
8        estimator = tf.estimator.LinearRegressor(    
9                            model_dir = output_dir,    
10                          feature_columns = feature_cols)    
复制代码

请注意,LinearRegressor 会将 input_layer、indicator_column 等全部隐藏起来。但是,我想访问租赁站的嵌套,所以将其显示了出来。

2.使用回归模块设置估算器规范 对于回归问题,我们可以使用 Ftrl 优化器将均方误差最小化( LinearRegressor 默认使用此优化器,所以我也使用这个):

1    my_head = tf.contrib.estimator.regression_head()    
2    spec = my_head.create_estimator_spec(    
3        features = features, mode = mode,    
4        labels = labels, logits = predictions,    
5        optimizer = tf.train.FtrlOptimizer(learning_rate = 0.1)  
6    )    

3 — 4.创建输出字典
通常情况下,我们只会发送预测,但在这个例子中,我们想回送预测和嵌套:

1    # 3. Create predictions    
2    predictions_dict = {    
3        "predicted": predictions,    
4        "station_embed": embed_layer    
5    }    
6    
7    # 4. Create export outputs    
8    export_outputs = {    
9        "predict_export_outputs": tf.estimator.export.PredictOutput(outputs = predictions_dict)    
10    }    
复制代码

这里,我们使用自定义估算器的另一个原因在于它能够更改 export_outputs。

5.回送带有预测结果的 EstimatorSpec,并导出替换过的输出:

1    # 5. Return EstimatorSpec    
2    return spec._replace(predictions = predictions_dict,  
3                            export_outputs = export_outputs)    
复制代码

现在,我们照常训练模型。

调用预测 然后,可以使用 TensorFlow Serving 提供导出的模型,或者可以选择将其部署到 Cloud ML Engine(实际是托管的 TF Serving),随后调用进行预测。您也可以使用 gcloud 调用本地模型(它可以针对此用途提供比 saved_model_cli 更方便的界面):

1    EXPORTDIR=./model_trained/export/exporter/
2    MODELDIR=$(ls $EXPORTDIR | tail -1)
3    gcloud ml-engine local predict --model-dir=${EXPORTDIR}/${MODELDIR} --json-instances=./test.json
复制代码

test.json 中有什么? {“day_of_week”: 4, “start_station_id”: 435, “rainy”: “true”} {“day_of_week”: 4, “start_station_id”: 521, “rainy”: “true”} {“day_of_week”: 4, “start_station_id”: 3221, “rainy”: “true”} {“day_of_week”: 4, “start_station_id”: 3237, “rainy”: “true”}

正如您看到的,我发送了 4 个实例,分别对应租赁站 435、521、3221 和 3237。

前面两个站位于曼哈顿,这一区域的租赁活动非常频繁(既为通勤族也为游客提供租赁服务)。后面两个站位于长岛,这个区域的自行车租赁并不普及(可能只在周末提供服务)。产生的输出包含预测的旅行数量(我们的标签)和租赁站的嵌套:

在本例中,嵌套的第一个维度在全部情况下几乎为零。所以,我们只需要一个维度嵌套。查看第二个维度,非常清楚地显示曼哈顿站有正值 (0.0081, 0.0011),而长岛站有负值 (-0.0025, -0.0031)。

这是我们单纯通过机器学习模型得到的信息,仅考察这两个地点在不同日期的自行车租赁情况!如果您的 TensorFlow 模型中有分类变量,可以试试从这些模型中分配嵌套。也许他们会带来新的数据分析!

欢迎关注 Google 官方微信公众号 TensorFlow !

未经允许,谢绝转载!侵权必究!

猜你喜欢

转载自juejin.im/post/5b84ad2ee51d4538d42ad26a