DeepFM理論與其應用

DeepFM[1]是哈工大Guo博士在華爲諾亞實驗室實習期間,提出的一種深度學習方法,它基於Google的經典論文Wide&Deep learning 基礎上,通過將原論文的wide部分--LR部分替換成FM[4],從而改進了原模型依然需要人工特徵工程的缺點,得到一個end to end 的深度學習模型。DeepFM在企業數據集(華爲應用商店)和公開數據集(criteo)上都取得不錯的效果,目前該方法在不少互聯網公司的推薦、廣告系統中得到了較爲廣泛的應用。

1. CTR預估中的特徵分析

在CTR預測中,挖掘用戶行爲中的隱藏特徵以及它們之間的交叉特徵已經成爲推薦算法中最核心的一部分。華爲通過對自己應用市場的用戶進行行爲分析,得到以下兩個重要的結論。

  1. 用戶喜歡在等待外賣送達的時段下載APP。它說明時間和APP類別的二維特徵交叉是一個有效的特徵輸入信號。
  2. 青少年的男性用戶喜歡下載射擊或者RPG遊戲APP。它則說明年齡、性別、APP類別的三維特徵交叉也是一個有效的輸入信號。

我們可以看到,CTR預估中主要挑戰是有效對特徵交互建模,有些特徵交互可以很容易理解,因此特徵工程的專家可以人工設計出來。然而,絕大部分特徵都是隱藏在數據背後,難以形成專家的先驗知識,只能通過機器學習自動生成。由於實際應用中使用到的特徵非常多(原始特徵經常有幾十到上百維),就算是簡單的特徵交互,專家其實也無法對全部特徵交叉進行有效建模。

廣義線性模型實現簡單、性能好,但是缺乏學習特徵交叉的能力,通常在工業實踐中會人工做特徵工程來解決這個問題。FM採用隱向量(latent vector)的內積作爲對特徵交叉的建模方法,具有很好的效果,FM在深度學習時代之前是CTR預估最爲廣泛應用的一種算法,它在實踐中通常只會利用二維的特徵交叉。

總而言之,用戶行爲的特徵維度是高度複雜的,無論是低維還是高維的特徵交叉都會起到重要的作用。根據Google wide&deep model,它在建模過程中同時考慮了低維和高維的特徵交叉,以提升模型的效果。

2.深度學習在CTR預估的進展

Google的Wide & Deep Learning for Recommender Systems[2]是深度學習應用於推薦、廣告等CTR領域的重要論文。過去幾年,神經網絡已經在圖像、音頻等領域得到廣泛應用,而由於推薦、廣告等領域由於數據的稀疏性、離散性,無法直接套用傳統的深度學習模型。

基於深度學習的思想,Google 提出一種深度模塊和廣度模塊結合的神經網絡模型。Wide端使用常見的LR(FTRL[5]實現)模型,將常見的離散特徵、低維特徵組合作爲輸入,實現了模型的記憶能力。換句話說,模型能夠很好記住用戶的喜好,給用戶推薦 常見喜好 的內容。Deep端將離散特徵通過embedding方法轉化成稠密特徵向量輸入,實際上實現了tag向量的模糊查詢,擴充了模型的泛化能力。換句話說,模型能夠更好理解用戶-物品之間內在的高維關係,給用戶推薦 罕見但是可能喜好 的內容,破解“信息繭房”的問題。

2.1 稀疏特徵的優點:

  • LR, DNN在底層還是一個線性模型,但是現實生活中,標籤y與特徵x之間較少存在線性關係,而往往是分段的。以"點擊率 ~ 歷史曝光次數" 之間的關係爲例,之前曝光過1、2次的時候,“點擊率 ~ 歷史曝光次數”之間一般是正相關的,再多曝光1、2次,用戶由於好奇,沒準就點擊了;但是,如果已經曝光過8、9次了,由於用戶已經失去了新鮮感,越多曝光,用戶越不可能再點,這時“點擊率 ~ 歷史曝光次數”就表現出負相關性。因此,categorical特徵相比於numeric特徵,更加符合現實場景。
  • 推薦、搜索一般都是基於用戶、商品的標籤畫像系統,而標籤天生就是categorical的
  • 稀疏的類別/ID類特徵,可以稀疏地存儲、傳輸、運算,提升運算效率。

2.2 稀疏特徵的缺點:

  • 稀疏的categorical/ID類特徵,也有着單個特徵表達能力弱、特徵組合爆炸、分佈不均勻導致受訓程度不均勻的缺點。
  • FTRL 充分輸入的稀疏性在線更新模型,訓練出的模型也是稀疏的,便於快速預測。
  • Parameter Server,充分利用特徵的稀疏性,不必在各機器之間同步全部模型,而讓每臺機器“按需”同步自己所需要的部分模型權重,“按需”上傳這一部分權重的梯度。
  • TensorFlow Feature Column類,除了一個numeric_column是處理實數特徵的,其實的都是圍繞處理categorical特徵的,封裝了常見的分桶、交叉、哈希等操作。

總而言之:

  • Wide for Memorization,wide側記住的是歷史數據中那些常見、高頻的模式。根據人工經驗、業務背景,將有價值的、顯而易見的特徵及特徵組合輸入wide側。

  • Deep for Generation,deep側通過embedding將tag向量化,變tag的精確匹配,爲tag向量的模糊查詢,因而模型具備良好的“擴展”能力。

Wide & Deep模型應用Google Play的數據,它包含超過10億活躍用戶以及上百萬的app行爲。在線實驗顯示Wide& Deep model 有效提升了App的購買率。代碼開源集成到了TensorFlow內,調用DNNLinearCombinedClassifier 這個estimator就可以。

estimator = DNNLinearCombinedClassifier(
    # wide側設置
    linear_feature_columns=[categorical_feature_a_x_categorical_feature_b],
    linear_optimizer=tf.train.FtrlOptimizer(...),
    # deep側設置
    dnn_feature_columns=[
        categorical_feature_a_emb, categorical_feature_b_emb,
        numeric_feature],
    dnn_hidden_units=[1000, 500, 100],
    dnn_optimizer=tf.train.ProximalAdagradOptimizer(...),
    # warm-start 設置
    warm_start_from="/path/to/checkpoint/dir")

除了Wide and Deep 以外還有數篇文章探索深度學習在CTR預估領域的應用,其中包括採用FM對特徵做初始化處理的FNN[3]。FNN通過
它的模型如下圖所示:


它主要缺點在於,embedding 後的特徵可能會被FM模型過度影響。使用FM對特徵做預處理的做法,可能影響了模型的性能和效率。它只能刻畫高維的特徵交互,而不像Wide & Deep那樣高維和低維特徵交叉都能刻畫到。

3.DeepFM核心思想

DeepFM將Wide and Deep 模型中的Wide側的LR替換成FM,克服了原有模型依然需要對低維特徵做特徵工程的缺點,實現了一個無需任何人工特徵工程的end to end 模型。DeepFM在wide側和deep側共享了embedding的特徵向量。

可以看到DeepFM的數學形式化:
y=sigmod(yFM +yDNN)

yFM 是FM組件的輸出,yDNN是深度組件的輸出結果。FM組件能夠捕獲一維特徵的同時,還能很好捕獲二維稀疏組合特徵。如下圖所示:

yDNN旨在學習高維特徵組合,和圖像、音頻的稠密數值張量不同的是,在推薦系統中DNN模型的數據輸入通常都是非常稀疏的張量,所以在技術上一般會採用embedding層來壓縮數據空間維度。

DeepFM 在企業數據集(華爲應用商店)和公開數據集(criteo)進行多次實驗,採用AUC和LogLoss來評估效果。具體效果如下圖所示:


DeepFM在公開數據上,比LR&DNN AUC提升了一百多個基點,是一個非常好的改進。

4. DeepFM重要參數

這篇文章有趣的部分是探索與分享整個模型的多個超參,從而分析如何得到一個更好效果的模型。

4.1 激活函數

relu 函數和 tanh 函數比sigmod函數效果更好。

4.2 Dropout

下圖效果顯示:採用適合的隨機性能夠加強模型的魯棒性,建議採用dropout比率在0.6~0.9之間。

4.3 每層神經元個數

建議採用200~400個神經元能夠給模型更好效果。

4.4 隱含層數量

增加隱含層的數量能夠一定程度提升模型效果,但是要注意過擬合的情況。建議3~5個隱藏層爲妙。

4.5 網絡結構

文章中測試了四種深度網絡結構,不變型(constant),增長型(increasing),衰減型(decreasing),鑽石型(diamond)。文章保證四種網絡結構神經元總量一致,採用三層隱藏層,從而四種形狀具體爲:constant (200-200-200), increasing (100- 200-300), decreasing (300-200-100), and diamond (150-300- 150).
如下圖所示,constant型效果更好。這點比較有意思,因爲在Wide & Deep Model中,採用的是decreasing型。網絡結構的效果也取決於實驗數據本身。

5. DeepFM的實現

DeepCTR[6]是一個實現了多種深度CTR預估模型的python庫,下面引用它基於criteo數據,所實現的DeepFM樣例代碼

import pandas as pd
from sklearn.metrics import log_loss, roc_auc_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, MinMaxScaler

from deepctr.models import DeepFM
from deepctr.utils import SingleFeat

if __name__ == "__main__":
    data = pd.read_csv('./criteo_sample.txt')

    #拆分稀疏和稠密特徵
    sparse_features = ['C' + str(i) for i in range(1, 27)]
    dense_features = ['I' + str(i) for i in range(1, 14)]

    data[sparse_features] = data[sparse_features].fillna('-1', )
    data[dense_features] = data[dense_features].fillna(0, )
    target = ['label']

    # 1.類別特徵的編碼與稠密特徵做歸一化
    for feat in sparse_features:
        lbe = LabelEncoder()
        data[feat] = lbe.fit_transform(data[feat])
    mms = MinMaxScaler(feature_range=(0, 1))
    data[dense_features] = mms.fit_transform(data[dense_features])

    # 2.統計稀疏特徵類別特徵個數,記錄稠密特徵類目
    sparse_feature_list = [SingleFeat(feat, data[feat].nunique())
                           for feat in sparse_features]
    dense_feature_list = [SingleFeat(feat, 0,)
                          for feat in dense_features]

    # 3.生成模型輸入特徵

    train, test = train_test_split(data, test_size=0.2)
    train_model_input = [train[feat.name].values for feat in sparse_feature_list] + \
                        [train[feat.name].values for feat in dense_feature_list]
    test_model_input = [test[feat.name].values for feat in sparse_feature_list] + \
                       [test[feat.name].values for feat in dense_feature_list]

    # 4.定義模型、預測、評估模型
    model = DeepFM({"sparse": sparse_feature_list,
                    "dense": dense_feature_list}, task='binary')
    model.compile("adam", "binary_crossentropy",
                  metrics=['binary_crossentropy'], )

    history = model.fit(train_model_input, train[target].values,
                        batch_size=256, epochs=10, verbose=2, validation_split=0.2, )
    pred_ans = model.predict(test_model_input, batch_size=256)
    print("test LogLoss", round(log_loss(test[target].values, pred_ans), 4))
    print("test AUC", round(roc_auc_score(test[target].values, pred_ans), 4))

引用

[1] Guo, Huifeng, et al. "DeepFM: a factorization-machine based neural network for CTR prediction." arXiv preprint arXiv:1703.04247 (2017).
[2] Cheng, Heng-Tze, et al. "Wide & deep learning for recommender systems." Proceedings of the 1st workshop on deep learning for recommender systems. ACM, 2016.
[3] Zhang, Weinan, Tianming Du, and Jun Wang. "Deep learning over multi-field categorical data." European conference on information retrieval. Springer, Cham, 2016.
[4] Rendle, Steffen. "Factorization machines." 2010 IEEE International Conference on Data Mining. IEEE, 2010.
[5] McMahan, H. Brendan. "Follow-the-regularized-leader and mirror descent: Equivalence theorems and l1 regularization." (2011).
[6] DeepCTR https://github.com/shenweichen/DeepCTR

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章