Wide&Deep learning
最近調試了幾天WDL,留個筆記。
WDL是Google在2016年的paper,目標是用於自己Google play中的app推薦。
推薦系統
推薦系統主要分為兩個部分,檢索系統(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

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