在回归模型或分类模型中创建嵌套

描述

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

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

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

在本文中,我会向您展示如何:

在回归模型或分类模型中创建嵌套

以不同方法表示分类变量

使用特征列进行数学计算

分发嵌套及原始模型的输出

您可以在 GitHub 上找到本文中的完整代码,其中包含更多上下文。在这里,我只向您展示关键代码段。

用模型来预测自行车需求

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

数据集

模型的输入如下:

星期几(1–7 的整数)

租赁站 ID(由于不知道完整词汇,这里我们使用哈希存储分区。该数据集有大约 650 个唯一值。我们会使用一个很大的哈希存储分区,但之后会将其嵌入到较低维度中)

是否下雨(真/假)

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

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

注:BigQuery 链接

https://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 模型中有分类变量,可以试试从这些模型中分配嵌套。也许他们会带来新的数据分析!

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分