[ML] Wide&Deep learning

Wide&Deep learning

最近调试了几天WDL,留个笔记。
WDL是Google在2016年的paper,目标是用于自己Google play中的app推荐。

官方介绍
paper download
图片描述

推荐系统

推荐系统主要分为两个部分,检索系统(Retrieval)排序系统(Ranking)
首先用检索的方法对大数据集进行初步筛选,返回一个query list。这里retrieval通常会结合采用机器学习模型和人工定义规则两种方法。
得到query list后,再使用排序系统对每个item进行打分和排序。

分数值P(y|x), y是采取的行为,x是特征,一般包括
User feature
Contextual feature
Impression feature

memorization & generalization

推荐系统重要问题之一,解决memorization(记忆)和generalization(归纳)。
memorization主要是基于历史数据 学习频繁共同出现的item,并且探索他们之间的相关性,也就是根据历史行为数据,推荐相关的item(topical),由wide作为主导;
generalization主要是基于相关性之间的传递, 探索历史上没有出现的新的特征的组合,也就是实现了推荐的多样性问题(diversity),deep作为主导。

wide model

wide model主要采用逻辑回归(LR),LR的特征一般是二值且稀疏的,这里采用one-hot编码。特征组合(cross-product transformation),只有当变量同时满足时才会取值为1,否则为0。但是这存在局限,当训练集里没有出现过query-item pair,就不能进行泛化。
Linear model:。其中特征x包括原始的输入特征以及组合特征。
cross-product transformation特征表示为:

是一个bool变量,如果第i个特征是第k个transformation 的一部分,那么值就是1,否则就是0。

deep model

deep就是deep learning了,模型输入包括类型特征(embedding)+连续特征。
对于特殊兴趣或者小众用户,query-item matrix非常稀疏,dense embedding的方法可以得到对所有query-item pair非零的预测,但是容易过度泛化over-generalize,这点正好和LR互补。
每一个隐层(hidden-layer):
f激活函数(default=ReLu), l是层数。

Joint Training

在论文实验中,训练部分,wide使用Follow-the-regularized-learder(FTRL)+L1正则, deep使用了AdaGrad。 ![图片描述](https://i.loli.net/2017/09/07/59b0e0bbc986f.jpg)

TensorFlow实现

没自己实现过的东西理解就是不深。代码实现这块google在github给出了DEMO and myself code
不过在自己套用时就会出现问题,毕竟应用场景不同了。
首先是特征维度这块,DEMO中的维度较少,全list出来还能接受,如果是一个上百维或者千维的,那就崩了。。。。
将所有列定义为连续(continuous)或者分类(categorical)。categorical_columns,有限集的一部分(eg:sex,name)。
对于类别较多的categorical_columns,使用哈希值作为键值。continuous_columns使用的是真实值。
continuous_columns,连续范围内的任何数值(eg:money or age)。
Bucketization(桶化),将连续值分组看待,而不是将所有的作为一个大整体,提高准确性。

def csv_head():
    categorical_columns = ["C"+str(i) for i in range(1,6)] #这里是5-dims, not 6-dims
    continuous_columns = ["I"+str(i) for i in range(1,5)]
    label_column = ["label"]
    feature_columns = categorical_columns + continuous_columns
    CSV_COLUMNS = feature_columns + label_column
    return feature_columns, label_column, CSV_COLUMNS
def process_feature():
    wide_columns = []
    for name in categorical_columns:
        wide_columns.append(tf.feature_column.categorical_column_with_hash_bucket(
            name, hash_bucket_size=1000))
    deep_columns = []
    for name in continuous_columns:
        deep_columns.append(tf.feature_column.numeric_column(name))
    for col in wide_columns:
        deep_columns.append(tf.feature_column.embedding_column(
            col, dimension=8))
    price_buckets = []
    for i in range(7):
        price_buckets.append( tf.feature_column.bucketized_column(deep_columns[i],
            boundaries=[10, 20, 30, 40, ]))
    wide_columns.extend(price_buckets)
    cross = [["C3", "C4"], ["C4", "C5"], ["C3","C4","C5"]]
    crossed_columns = []
    for name in cross:
        crossed_columns.append(tf.feature_column.crossed_column(name,hash_bucket_size=50))
    return wide_columns, deep_columns, crossed_columns

然后就是.predict那步。输入特征x就好,不需要label,在input_fn的返回值处去掉y就好。返回结果是一个generator的格式,需要使用for来读取,而且在DNNLinearCombinedRegressor和DNNLinearCombinedClassifier的输出内容是不一样的,需要自己打印出来看需要的是什么。
其他部分按照官方DEMO 来就行,还是给的挺好的。

最后预警一个TF的坑吧,也是很多人不用TF的一个重要原因,没事乱改借口,并且相同功能的函数有好几个,对之前版本的兼容性就更谈不上了,只能两个字回馈,任性!!!
在R1.3版本中,tf.contrib.learn.下的estimator很多都被remove了,在使用的时候会输出很多没用的log信息告诉你这玩意在哪个时间被移除了。所以推荐在使用的时候该用tf.estimator这个模块下的内容。官方github上的DEMO也是这个模块下的版本。强烈推荐!

Reference

https://github.com/tensorflow/tensorflow/blob/r1.3/tensorflow/examples/learn/wide_n_deep_tutorial.py
https://github.com/yufengg/widendeep/blob/master/trainer/task.py
[译] 简明 TensorFlow 教程 — 第二部分:混合学习
论文笔记 - Wide and Deep Learning for Recommender Systems
tensorflow学习笔记(六):TF.contrib.learn大杂烩
https://www.tensorflow.org/extend/estimators
tensorflow线性模型以及Wide deep learning
《Wide & Deep Learning for Recommender Systems 》笔记
http://blog.sina.com.cn/s/blog_61c463090102wjdc.html

posted @ 2017-09-07 14:31  战侠歌1994  阅读(6724)  评论(0编辑  收藏  举报