日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

从FM推演各深度学习CTR预估模型

發(fā)布時(shí)間:2024/1/17 pytorch 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从FM推演各深度学习CTR预估模型 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文的PDF版本、代碼實(shí)現(xiàn)和數(shù)據(jù)可以在我的github取到。

1.引言

點(diǎn)擊率(click-through rate, CTR)是互聯(lián)網(wǎng)公司進(jìn)行流量分配的核心依據(jù)之一。比如互聯(lián)網(wǎng)廣告平臺,為了精細(xì)化權(quán)衡和保障用戶、廣告、平臺三方的利益,準(zhǔn)確的CTR預(yù)估是不可或缺的。CTR預(yù)估技術(shù)從傳統(tǒng)的邏輯回歸,到近兩年大火的深度學(xué)習(xí),新的算法層出不窮:DeepFM, NFM, DIN, AFM, DCN……?
然而,相關(guān)的綜述文章不少,但碎片羅列的居多,模型之間內(nèi)在的聯(lián)系和演化思路如何揭示?怎樣才能迅速get到新模型的創(chuàng)新點(diǎn)和適用場景,快速提高新論文速度,節(jié)約理解、復(fù)現(xiàn)模型的成本?這些都是亟待解決的問題。?
我們認(rèn)為,從FM及其與神經(jīng)網(wǎng)絡(luò)的結(jié)合出發(fā),能夠迅速貫穿很多深度學(xué)習(xí)CTR預(yù)估網(wǎng)絡(luò)的思路,從而更好地理解和應(yīng)用模型

2.本文的思路與方法

  • 我們試圖從原理上進(jìn)行推導(dǎo)、理解各個深度CTR預(yù)估模型之間的相互關(guān)系,知其然也知其所以然。(以下的分析與拆解角度,是一種我們嘗試的理解視角,并不是唯一的理解方式)
  • 推演的核心思路:“通過設(shè)計(jì)網(wǎng)絡(luò)結(jié)構(gòu)進(jìn)行組合特征的挖掘”
  • 具體來說有兩條:其一是從FM開始推演其在深度學(xué)習(xí)上的各種推廣(對應(yīng)下圖的紅線),另一條是從embedding+MLP自身的演進(jìn)特點(diǎn)結(jié)合CTR預(yù)估本身的業(yè)務(wù)場景進(jìn)行推演(對應(yīng)下圖黑線部分)。?


  • 為了便于理解,我們簡化了數(shù)據(jù)案例——只考慮離散特征數(shù)據(jù)的建模,以分析不同神經(jīng)網(wǎng)絡(luò)在處理相同業(yè)務(wù)問題時(shí)的不同思路
  • 同時(shí),我們將各典型論文不同風(fēng)格的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)圖統(tǒng)一按照計(jì)算圖來繪制,以便于對比不同模型
  • 3.FM:降維版本的特征二階組合

    CTR預(yù)估本質(zhì)是一個二分類問題,以移動端展示廣告推薦為例,依據(jù)日志中的用戶側(cè)的信息(比如年齡,性別,國籍,手機(jī)上安裝的app列表)、廣告?zhèn)鹊男畔?#xff08;廣告id,廣告類別,廣告標(biāo)題等)、上下文側(cè)信息(渠道id等),去建模預(yù)測用戶是否會點(diǎn)擊該廣告。?
    FM出現(xiàn)之前的傳統(tǒng)的處理方法是人工特征工程加上線性模型(如邏輯回歸Logistic Regression)。為了提高模型效果,關(guān)鍵技術(shù)是找到到用戶點(diǎn)擊行為背后隱含的特征組合。如男性、大學(xué)生用戶往往會點(diǎn)擊游戲類廣告,因此“男性且是大學(xué)生且是游戲類”的特征組合就是一個關(guān)鍵特征。但這本質(zhì)仍是線性模型,其假設(shè)函數(shù)表示成內(nèi)積形式一般為:

    ?

    ylinear=σ(?w??,x???)ylinear=σ(?w→,x→?)

    ?

    其中x??x→為特征向量,w??w→為權(quán)重向量,σ()σ()為sigmoid函數(shù)。

    但是人工進(jìn)行特征組合通常會存在諸多困難,如特征爆炸、特征難以被識別、組合特征難以設(shè)計(jì)等。為了讓模型自動地考慮特征之間的二階組合信息,線性模型推廣為二階多項(xiàng)式(2d?Polynomial2d?Polynomial)模型:

    ?

    ypoly=σ(?w??,x???+∑i=1n∑j=1nwij?xi?xj)ypoly=σ(?w→,x→?+∑i=1n∑j=1nwij?xi?xj)

    ?

    其實(shí)就是對特征兩兩相乘(組合)構(gòu)成新特征(離散化之后其實(shí)就是“且”操作),并對每個新特征分配獨(dú)立的權(quán)重,通過機(jī)器學(xué)習(xí)來自動得到這些權(quán)重。將其寫成矩陣形式為:

    ?

    ypoly=σ(w??T?x??+x??T?W(2)?x??)ypoly=σ(w→T?x→+x→T?W(2)?x→)

    ?

    其中W(2)W(2)為二階特征組合的權(quán)重矩陣,是對稱矩陣。而這個矩陣參數(shù)非常多,為O(n2)O(n2)。為了降低該矩陣的維度,可以將其因子分解(FactorizationFactorization)為兩個低維(比如n?kn?k)矩陣的相乘。則此時(shí)WW矩陣的參數(shù)就大幅降低,為O(nk)O(nk)。公式如下:

    ?

    W(2)=WT?WW(2)=WT?W

    ?

    這就是RendleRendle等在2010年提出因子分解機(jī)(Factorization Machines,FM)的名字的由來。FM的矩陣形式公式如下:

    ?

    yFM=σ(w??T?x??+x??T?WT?W?x??)yFM=σ(w→T?x→+x→T?WT?W?x→)

    ?

    將其寫成內(nèi)積的形式:?

    yFM=σ(?w??,x???+?W?x??,W?x???)yFM=σ(?w→,x→?+?W?x→,W?x→?)


    利用?∑ni=1ai→,∑ni=1ai→?=∑ni=1∑nj=1?ai→,aj→??∑i=1nai→,∑i=1nai→?=∑i=1n∑j=1n?ai→,aj→?,可以將上式進(jìn)一步改寫成求和式的形式:?

    yFM=σ(?w??,x???+∑i=1n∑j=1n?xi?v??i,xj?v??j?)yFM=σ(?w→,x→?+∑i=1n∑j=1n?xi?v→i,xj?v→j?)


    其中vi→vi→向量是矩陣WW的第ii列。為了去除重復(fù)項(xiàng)與特征平方項(xiàng),上式可以進(jìn)一步改寫成更為常見的FM公式:?

    yFM=σ(?w??,x???+∑i=1n∑j=i+1n?v??i,v??j?xi?xj)yFM=σ(?w→,x→?+∑i=1n∑j=i+1n?v→i,v→j?xi?xj)


    對比二階多項(xiàng)式模型,FM模型中特征兩兩相乘(組合)的權(quán)重是相互不獨(dú)立的,它是一種參數(shù)較少但表達(dá)力強(qiáng)的模型。

    ?

    此處附上FM的TensorFlow代碼實(shí)現(xiàn),完整數(shù)據(jù)和代碼請戳這里。注意FM通過內(nèi)積進(jìn)行無重復(fù)項(xiàng)與特征平方項(xiàng)的特征組合過程使用了一個小trick,就是:?

    ∑i=1n∑j=i+1nxixj=1/2×[(∑i=1nxi)2?∑i=1nx2i]∑i=1n∑j=i+1nxixj=1/2×[(∑i=1nxi)2?∑i=1nxi2]

    ?

    class FM(Model):def __init__(self, input_dim=None, output_dim=1, factor_order=10, init_path=None, opt_algo='gd', learning_rate=1e-2,l2_w=0, l2_v=0, random_seed=None):Model.__init__(self)# 一次、二次交叉、偏置項(xiàng)init_vars = [('w', [input_dim, output_dim], 'xavier', dtype),('v', [input_dim, factor_order], 'xavier', dtype),('b', [output_dim], 'zero', dtype)]self.graph = tf.Graph()with self.graph.as_default():if random_seed is not None:tf.set_random_seed(random_seed)self.X = tf.sparse_placeholder(dtype)self.y = tf.placeholder(dtype)self.vars = init_var_map(init_vars, init_path)w = self.vars['w']v = self.vars['v']b = self.vars['b']# [(x1+x2+x3)^2 - (x1^2+x2^2+x3^2)]/2# 先計(jì)算所有的交叉項(xiàng),再減去平方項(xiàng)(自己和自己相乘)X_square = tf.SparseTensor(self.X.indices, tf.square(self.X.values), tf.to_int64(tf.shape(self.X)))xv = tf.square(tf.sparse_tensor_dense_matmul(self.X, v))p = 0.5 * tf.reshape(tf.reduce_sum(xv - tf.sparse_tensor_dense_matmul(X_square, tf.square(v)), 1),[-1, output_dim])xw = tf.sparse_tensor_dense_matmul(self.X, w)logits = tf.reshape(xw + b + p, [-1])self.y_prob = tf.sigmoid(logits)self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=self.y)) + \l2_w * tf.nn.l2_loss(xw) + \l2_v * tf.nn.l2_loss(xv)self.optimizer = get_optimizer(opt_algo, learning_rate, self.loss)#GPU設(shè)定config = tf.ConfigProto()config.gpu_options.allow_growth = Trueself.sess = tf.Session(config=config)# 圖中所有variable初始化tf.global_variables_initializer().run(session=self.sess)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    4.用神經(jīng)網(wǎng)絡(luò)的視角看FM:嵌入后再進(jìn)行內(nèi)積

    我們觀察FM公式的矩陣內(nèi)積形式:

    ?

    yFM=σ(?w??,x???+?W?x??,W?x???)yFM=σ(?w→,x→?+?W?x→,W?x→?)

    ?

    發(fā)現(xiàn)W?x??W·x→部分就是將離散系數(shù)特征通過矩陣乘法降維成一個低維稠密向量。這個過程對神經(jīng)網(wǎng)絡(luò)來說就叫做嵌入(embedding)。所以用神經(jīng)網(wǎng)絡(luò)視角來看:

  • FM首先是對離散特征進(jìn)行嵌入。
  • 之后通過對嵌入后的稠密向量進(jìn)行內(nèi)積來進(jìn)行二階特征組合
  • 最后再與線性模型的結(jié)果求和進(jìn)而得到預(yù)估點(diǎn)擊率。?
    其示意圖如下。為了表述清晰,我們繪制的是神經(jīng)網(wǎng)絡(luò)計(jì)算圖而不是網(wǎng)絡(luò)結(jié)構(gòu)圖——在網(wǎng)絡(luò)結(jié)構(gòu)圖中增加了權(quán)重WW的位置。?

  • 5.FM的實(shí)際應(yīng)用:考慮領(lǐng)域信息

    廣告點(diǎn)擊率預(yù)估模型中的特征以分領(lǐng)域的離散特征為主,如:廣告類別、用戶職業(yè)、手機(jī)APP列表等。由于連續(xù)特征比較好處理,為了簡化起見,本文只考慮同時(shí)存在不同領(lǐng)域的離散特征的情形。處理離散特征的常見方法是通過獨(dú)熱(one-hot)編碼轉(zhuǎn)換為一系列二值特征向量。然后將這些高維稀疏特征通過嵌入(embedding)轉(zhuǎn)換為低維連續(xù)特征。前面已經(jīng)說明FM中間的一個核心步驟就是嵌入,但這個嵌入過程沒有考慮領(lǐng)域信息。這使得同領(lǐng)域內(nèi)的特征也被當(dāng)做不同領(lǐng)域特征進(jìn)行兩兩組合了。?
    其實(shí)可以將特征具有領(lǐng)域關(guān)系的特點(diǎn)作為先驗(yàn)知識加入到神經(jīng)網(wǎng)絡(luò)的設(shè)計(jì)中去:同領(lǐng)域的特征嵌入后直接求和作為一個整體嵌入向量,進(jìn)而與其他領(lǐng)域的整體嵌入向量進(jìn)行兩兩組合。而這個先嵌入后求和的過程,就是一個單領(lǐng)域的小離散特征向量乘以矩陣的過程。此時(shí)FM的過程變?yōu)?#xff1a;對不同領(lǐng)域的離散特征分別進(jìn)行嵌入,之后再進(jìn)行二階特征的向量內(nèi)積。其計(jì)算圖圖如下所示:?


    這樣考慮其實(shí)是給FM增加了一個正則:考慮了領(lǐng)域內(nèi)的信息的相似性。而且還有一個附加的好處,這些嵌入后的同領(lǐng)域特征可以拼接起來作為更深的神經(jīng)網(wǎng)絡(luò)的輸入,達(dá)到降維的目的。接下來我們將反復(fù)看到這種處理方式。?
    此處需要注意,這與“基于領(lǐng)域的因子分解機(jī)”(Field-aware Factorization Machines,FFM有區(qū)別。FFM也是FM的另一種變體,也考慮了領(lǐng)域信息。但其不同點(diǎn)是同一個特征與不同領(lǐng)域進(jìn)行特征組合時(shí),其對應(yīng)的嵌入向量是不同的。本文不考慮FFM的作用機(jī)制。?
    經(jīng)過這些改進(jìn)的FM終究還是淺層網(wǎng)絡(luò),它的表現(xiàn)力仍然有限。為了增加模型的表現(xiàn)力(model capacity),一個自然的想法就是將該淺層網(wǎng)絡(luò)不斷“深化”

    ?

    6.embedding+MLP:深度學(xué)習(xí)CTR預(yù)估的通用框架

    embedding+MLP是對于分領(lǐng)域離散特征進(jìn)行深度學(xué)習(xí)CTR預(yù)估的通用框架。深度學(xué)習(xí)在特征組合挖掘(特征學(xué)習(xí))方面具有很大的優(yōu)勢。比如以CNN為代表的深度網(wǎng)絡(luò)主要用于圖像、語音等稠密特征上的學(xué)習(xí),以W2V、RNN為代表的深度網(wǎng)絡(luò)主要用于文本的同質(zhì)化、序列化高維稀疏特征的學(xué)習(xí)。CTR預(yù)估的主要場景是對離散且有具體領(lǐng)域的特征進(jìn)行學(xué)習(xí),所以其深度網(wǎng)絡(luò)結(jié)構(gòu)也不同于CNN與RNN。?
    具體來說, embedding+MLP的過程如下:

  • 對不同領(lǐng)域的one-hot特征進(jìn)行嵌入(embedding),使其降維成低維度稠密特征。
  • 然后將這些特征向量拼接(concatenate)成一個隱含層。
  • 之后再不斷堆疊全連接層,也就是多層感知機(jī)(Multilayer Perceptron, MLP,有時(shí)也叫作前饋神經(jīng)網(wǎng)絡(luò))。
  • 最終輸出預(yù)測的點(diǎn)擊率。?
    其示意圖如下:?

  • embedding+MLP的缺點(diǎn)是只學(xué)習(xí)高階特征組合,對于低階或者手動的特征組合不夠兼容,而且參數(shù)較多,學(xué)習(xí)較困難。

    7.FNN:FM與MLP的串聯(lián)結(jié)合

    Weinan Zhang等在2016年提出的因子分解機(jī)神經(jīng)網(wǎng)絡(luò)(Factorisation Machine supported Neural Network,FNN)將考FM與MLP進(jìn)行了結(jié)合。它有著十分顯著的特點(diǎn):

  • 采用FM預(yù)訓(xùn)練得到的隱含層及其權(quán)重作為神經(jīng)網(wǎng)絡(luò)的第一層的初始值,之后再不斷堆疊全連接層,最終輸出預(yù)測的點(diǎn)擊率。
  • 可以將FNN理解成一種特殊的embedding+MLP,其要求第一層嵌入后的各領(lǐng)域特征維度一致,并且嵌入權(quán)重的初始化是FM預(yù)訓(xùn)練好的
  • 不是一個端到端的訓(xùn)練過程,有貪心訓(xùn)練的思路。而且如果不考慮預(yù)訓(xùn)練過程,模型網(wǎng)絡(luò)結(jié)構(gòu)也沒有考慮低階特征組合。?
    其計(jì)算圖如下所示:?

  • 通過觀察FFN的計(jì)算圖可以看出其與embedding+MLP確實(shí)非常像。不過此處省略了FNN的FM部分的線性模塊。這種省略為了更好地進(jìn)行兩個模型的對比。接下來的計(jì)算圖我們都會省略線性模塊。

    此處附上FNN的代碼實(shí)現(xiàn),完整數(shù)據(jù)和代碼請戳這里。:

    class FNN(Model):def __init__(self, field_sizes=None, embed_size=10, layer_sizes=None, layer_acts=None, drop_out=None,embed_l2=None, layer_l2=None, init_path=None, opt_algo='gd', learning_rate=1e-2, random_seed=None):Model.__init__(self)init_vars = []num_inputs = len(field_sizes)for i in range(num_inputs):init_vars.append(('embed_%d' % i, [field_sizes[i], embed_size], 'xavier', dtype))node_in = num_inputs * embed_sizefor i in range(len(layer_sizes)):init_vars.append(('w%d' % i, [node_in, layer_sizes[i]], 'xavier', dtype))init_vars.append(('b%d' % i, [layer_sizes[i]], 'zero', dtype))node_in = layer_sizes[i]self.graph = tf.Graph()with self.graph.as_default():if random_seed is not None:tf.set_random_seed(random_seed)self.X = [tf.sparse_placeholder(dtype) for i in range(num_inputs)]self.y = tf.placeholder(dtype)self.keep_prob_train = 1 - np.array(drop_out)self.keep_prob_test = np.ones_like(drop_out)self.layer_keeps = tf.placeholder(dtype)self.vars = init_var_map(init_vars, init_path)w0 = [self.vars['embed_%d' % i] for i in range(num_inputs)]xw = tf.concat([tf.sparse_tensor_dense_matmul(self.X[i], w0[i]) for i in range(num_inputs)], 1)l = xw#全連接部分for i in range(len(layer_sizes)):wi = self.vars['w%d' % i]bi = self.vars['b%d' % i]print(l.shape, wi.shape, bi.shape)l = tf.nn.dropout(activate(tf.matmul(l, wi) + bi,layer_acts[i]),self.layer_keeps[i])l = tf.squeeze(l)self.y_prob = tf.sigmoid(l)self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=l, labels=self.y))if layer_l2 is not None:self.loss += embed_l2 * tf.nn.l2_loss(xw)for i in range(len(layer_sizes)):wi = self.vars['w%d' % i]self.loss += layer_l2[i] * tf.nn.l2_loss(wi)self.optimizer = get_optimizer(opt_algo, learning_rate, self.loss)config = tf.ConfigProto()config.gpu_options.allow_growth = Trueself.sess = tf.Session(config=config)tf.global_variables_initializer().run(session=self.sess)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    8.DeepFM: FM與MLP的并聯(lián)結(jié)合

    針對FNN需要預(yù)訓(xùn)練的問題,Huifeng Guo等提出了深度因子分解機(jī)模型(Deep Factorisation Machine, DeepFM, 2017)。該模型的特點(diǎn)是:

  • 不需要預(yù)訓(xùn)練。
  • 將考慮領(lǐng)域信息的FM部分與MLP部分并聯(lián)起來(借用初中電路的術(shù)語),其實(shí)就是對兩個模型進(jìn)行聯(lián)合訓(xùn)練
  • 考慮領(lǐng)域信息的FM部分的嵌入向量拼接起來作為MLP部分的輸入特征,也就是是兩個模型共享嵌入后的特征。?
    其計(jì)算圖如下所示:?

  • 通過觀察DeepFM的計(jì)算圖可以看出紅色虛線以上部分其實(shí)就是FM部分,虛線以下就是MLP部分

    此處附上DeepFM的代碼實(shí)現(xiàn),完整數(shù)據(jù)和代碼請戳這里。:

    def model_fn(features, labels, mode, params):"""Bulid Model function f(x) for Estimator."""#------超參數(shù)的設(shè)定----field_size = params["field_size"]feature_size = params["feature_size"]embedding_size = params["embedding_size"]l2_reg = params["l2_reg"]learning_rate = params["learning_rate"]#batch_norm_decay = params["batch_norm_decay"]#optimizer = params["optimizer"]layers = map(int, params["deep_layers"].split(','))dropout = map(float, params["dropout"].split(','))#------權(quán)重------FM_B = tf.get_variable(name='fm_bias', shape=[1], initializer=tf.constant_initializer(0.0))FM_W = tf.get_variable(name='fm_w', shape=[feature_size], initializer=tf.glorot_normal_initializer())# FFM_V = tf.get_variable(name='fm_v', shape=[feature_size, embedding_size], initializer=tf.glorot_normal_initializer())# F * E #------build feaure-------feat_ids = features['feat_ids']feat_ids = tf.reshape(feat_ids,shape=[-1,field_size]) # None * f/K * Kfeat_vals = features['feat_vals']feat_vals = tf.reshape(feat_vals,shape=[-1,field_size]) # None * f/K * K#------build f(x)------with tf.variable_scope("First-order"):feat_wgts = tf.nn.embedding_lookup(FM_W, feat_ids) # None * f/K * Ky_w = tf.reduce_sum(tf.multiply(feat_wgts, feat_vals),1)with tf.variable_scope("Second-order"):embeddings = tf.nn.embedding_lookup(FM_V, feat_ids) # None * f/K * K * Efeat_vals = tf.reshape(feat_vals, shape=[-1, field_size, 1]) # None * f/K * K * 1 ?embeddings = tf.multiply(embeddings, feat_vals) #vij*xi sum_square = tf.square(tf.reduce_sum(embeddings,1)) # None * K * Esquare_sum = tf.reduce_sum(tf.square(embeddings),1)y_v = 0.5*tf.reduce_sum(tf.subtract(sum_square, square_sum),1) # None * 1with tf.variable_scope("Deep-part"):if FLAGS.batch_norm:#normalizer_fn = tf.contrib.layers.batch_norm#normalizer_fn = tf.layers.batch_normalizationif mode == tf.estimator.ModeKeys.TRAIN:train_phase = True#normalizer_params = {'decay': batch_norm_decay, 'center': True, 'scale': True, 'updates_collections': None, 'is_training': True, 'reuse': None}else:train_phase = False#normalizer_params = {'decay': batch_norm_decay, 'center': True, 'scale': True, 'updates_collections': None, 'is_training': False, 'reuse': True}else:normalizer_fn = Nonenormalizer_params = Nonedeep_inputs = tf.reshape(embeddings,shape=[-1,field_size*embedding_size]) # None * (F*K)for i in range(len(layers)):#if FLAGS.batch_norm:# deep_inputs = batch_norm_layer(deep_inputs, train_phase=train_phase, scope_bn='bn_%d' %i)#normalizer_params.update({'scope': 'bn_%d' %i})deep_inputs = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=layers[i], \#normalizer_fn=normalizer_fn, normalizer_params=normalizer_params, \weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='mlp%d' % i)if FLAGS.batch_norm:deep_inputs = batch_norm_layer(deep_inputs, train_phase=train_phase, scope_bn='bn_%d' %i) #放在RELU之后 https://github.com/ducha-aiki/caffenet-benchmark/blob/master/batchnorm.md#bn----before-or-after-reluif mode == tf.estimator.ModeKeys.TRAIN:deep_inputs = tf.nn.dropout(deep_inputs, keep_prob=dropout[i]) #Apply Dropout after all BN layers and set dropout=0.8(drop_ratio=0.2)#deep_inputs = tf.layers.dropout(inputs=deep_inputs, rate=dropout[i], training=mode == tf.estimator.ModeKeys.TRAIN)y_deep = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=1, activation_fn=tf.identity, \weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='deep_out')y_d = tf.reshape(y_deep,shape=[-1])#sig_wgts = tf.get_variable(name='sigmoid_weights', shape=[layers[-1]], initializer=tf.glorot_normal_initializer())#sig_bias = tf.get_variable(name='sigmoid_bias', shape=[1], initializer=tf.constant_initializer(0.0))#deep_out = tf.nn.xw_plus_b(deep_inputs,sig_wgts,sig_bias,name='deep_out')with tf.variable_scope("DeepFM-out"):#y_bias = FM_B * tf.ones_like(labels, dtype=tf.float32) # None * 1 warning;這里不能用label,否則調(diào)用predict/export函數(shù)會出錯,train/evaluate正常;初步判斷estimator做了優(yōu)化,用不到label時(shí)不傳y_bias = FM_B * tf.ones_like(y_d, dtype=tf.float32) # None * 1y = y_bias + y_w + y_v + y_dpred = tf.sigmoid(y)predictions={"prob": pred}export_outputs = {tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: tf.estimator.export.PredictOutput(predictions)}# Provide an estimator spec for `ModeKeys.PREDICT`if mode == tf.estimator.ModeKeys.PREDICT:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,export_outputs=export_outputs)#------bulid loss------loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=y, labels=labels)) + \l2_reg * tf.nn.l2_loss(FM_W) + \l2_reg * tf.nn.l2_loss(FM_V) #+ \ l2_reg * tf.nn.l2_loss(sig_wgts)# Provide an estimator spec for `ModeKeys.EVAL`eval_metric_ops = {"auc": tf.metrics.auc(labels, pred)}if mode == tf.estimator.ModeKeys.EVAL:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,eval_metric_ops=eval_metric_ops)#------bulid optimizer------if FLAGS.optimizer == 'Adam':optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate, beta1=0.9, beta2=0.999, epsilon=1e-8)elif FLAGS.optimizer == 'Adagrad':optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate, initial_accumulator_value=1e-8)elif FLAGS.optimizer == 'Momentum':optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.95)elif FLAGS.optimizer == 'ftrl':optimizer = tf.train.FtrlOptimizer(learning_rate)train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())# Provide an estimator spec for `ModeKeys.TRAIN` modesif mode == tf.estimator.ModeKeys.TRAIN:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,train_op=train_op)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    9.NFM:通過逐元素乘法延遲FM的實(shí)現(xiàn)過程

    我們再回到考慮領(lǐng)域信息的FM,它仍有改進(jìn)的空間。因?yàn)橐陨线@些網(wǎng)絡(luò)的FM部分都是只進(jìn)行嵌入向量的兩兩內(nèi)積后直接求和,沒有充分利用二階特征組合的信息。Xiangnan He等在2017年提出了神經(jīng)網(wǎng)絡(luò)因子分解機(jī)(Neural Factorization Machines,NFM)對此作出了改進(jìn)。其計(jì)算圖如下所示:?

    ?

    NFM的基本特點(diǎn)是:

  • 利用二階交互池化層(Bi-Interaction Pooling)對FM嵌入后的向量兩兩進(jìn)行元素級別的乘法,形成同維度的向量求和后作為前饋神經(jīng)網(wǎng)絡(luò)的輸入。計(jì)算圖中用圈乘??表示逐元素乘法運(yùn)算。
  • NFM與DeepFM的區(qū)別是沒有單獨(dú)的FM的淺層網(wǎng)絡(luò)進(jìn)行聯(lián)合訓(xùn)練,而是將其整合后直接輸出給前饋神經(jīng)網(wǎng)絡(luò)
  • 當(dāng)MLP的全連接層都是恒等變換且最后一層參數(shù)全為1時(shí),NFM就退化成了FM。可見,NFM是FM的推廣,它推遲了FM的實(shí)現(xiàn)過程,并在其中加入了更多非線性運(yùn)算
  • 另一方面,我們觀察計(jì)算圖會發(fā)現(xiàn)NFM與FNN非常相似。它們的主要區(qū)別是NFM?在embedding之后對特征進(jìn)行了兩兩逐元素乘法。因?yàn)橹鹪叵喑说南蛄烤S數(shù)不變,之后對這些向量求和的維數(shù)仍然與embedding的維數(shù)一致。因此輸入到MLP的參數(shù)比起直接concatenate的FNN更少。
  • 此處附上NFM的代碼實(shí)現(xiàn),完整數(shù)據(jù)和代碼請戳這里:

    def model_fn(features, labels, mode, params):"""Bulid Model function f(x) for Estimator."""#------hyperparameters----field_size = params["field_size"]feature_size = params["feature_size"]embedding_size = params["embedding_size"]l2_reg = params["l2_reg"]learning_rate = params["learning_rate"]#optimizer = params["optimizer"]layers = map(int, params["deep_layers"].split(','))dropout = map(float, params["dropout"].split(','))#------bulid weights------Global_Bias = tf.get_variable(name='bias', shape=[1], initializer=tf.constant_initializer(0.0))Feat_Bias = tf.get_variable(name='linear', shape=[feature_size], initializer=tf.glorot_normal_initializer())Feat_Emb = tf.get_variable(name='emb', shape=[feature_size,embedding_size], initializer=tf.glorot_normal_initializer())#------build feaure-------feat_ids = features['feat_ids']feat_ids = tf.reshape(feat_ids,shape=[-1,field_size])feat_vals = features['feat_vals']feat_vals = tf.reshape(feat_vals,shape=[-1,field_size])#------build f(x)------with tf.variable_scope("Linear-part"):feat_wgts = tf.nn.embedding_lookup(Feat_Bias, feat_ids) # None * F * 1y_linear = tf.reduce_sum(tf.multiply(feat_wgts, feat_vals),1)with tf.variable_scope("BiInter-part"):embeddings = tf.nn.embedding_lookup(Feat_Emb, feat_ids) # None * F * Kfeat_vals = tf.reshape(feat_vals, shape=[-1, field_size, 1])embeddings = tf.multiply(embeddings, feat_vals) # vij * xisum_square_emb = tf.square(tf.reduce_sum(embeddings,1))square_sum_emb = tf.reduce_sum(tf.square(embeddings),1)deep_inputs = 0.5*tf.subtract(sum_square_emb, square_sum_emb) # None * Kwith tf.variable_scope("Deep-part"):if mode == tf.estimator.ModeKeys.TRAIN:train_phase = Trueelse:train_phase = Falseif mode == tf.estimator.ModeKeys.TRAIN:deep_inputs = tf.nn.dropout(deep_inputs, keep_prob=dropout[0]) # None * Kfor i in range(len(layers)):deep_inputs = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=layers[i], \weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='mlp%d' % i)if FLAGS.batch_norm:deep_inputs = batch_norm_layer(deep_inputs, train_phase=train_phase, scope_bn='bn_%d' %i) #放在RELU之后 https://github.com/ducha-aiki/caffenet-benchmark/blob/master/batchnorm.md#bn----before-or-after-reluif mode == tf.estimator.ModeKeys.TRAIN:deep_inputs = tf.nn.dropout(deep_inputs, keep_prob=dropout[i]) #Apply Dropout after all BN layers and set dropout=0.8(drop_ratio=0.2)#deep_inputs = tf.layers.dropout(inputs=deep_inputs, rate=dropout[i], training=mode == tf.estimator.ModeKeys.TRAIN)y_deep = tf.contrib.layers.fully_connected(inputs=deep_inputs, num_outputs=1, activation_fn=tf.identity, \weights_regularizer=tf.contrib.layers.l2_regularizer(l2_reg), scope='deep_out')y_d = tf.reshape(y_deep,shape=[-1])with tf.variable_scope("NFM-out"):#y_bias = Global_Bias * tf.ones_like(labels, dtype=tf.float32) # None * 1 warning;這里不能用label,否則調(diào)用predict/export函數(shù)會出錯,train/evaluate正常;初步判斷estimator做了優(yōu)化,用不到label時(shí)不傳y_bias = Global_Bias * tf.ones_like(y_d, dtype=tf.float32) # None * 1y = y_bias + y_linear + y_dpred = tf.sigmoid(y)predictions={"prob": pred}export_outputs = {tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: tf.estimator.export.PredictOutput(predictions)}# Provide an estimator spec for `ModeKeys.PREDICT`if mode == tf.estimator.ModeKeys.PREDICT:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,export_outputs=export_outputs)#------bulid loss------loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=y, labels=labels)) + \l2_reg * tf.nn.l2_loss(Feat_Bias) + l2_reg * tf.nn.l2_loss(Feat_Emb)# Provide an estimator spec for `ModeKeys.EVAL`eval_metric_ops = {"auc": tf.metrics.auc(labels, pred)}if mode == tf.estimator.ModeKeys.EVAL:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,eval_metric_ops=eval_metric_ops)#------bulid optimizer------if FLAGS.optimizer == 'Adam':optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate, beta1=0.9, beta2=0.999, epsilon=1e-8)elif FLAGS.optimizer == 'Adagrad':optimizer = tf.train.AdagradOptimizer(learning_rate=learning_rate, initial_accumulator_value=1e-8)elif FLAGS.optimizer == 'Momentum':optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.95)elif FLAGS.optimizer == 'ftrl':optimizer = tf.train.FtrlOptimizer(learning_rate)train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())# Provide an estimator spec for `ModeKeys.TRAIN` modesif mode == tf.estimator.ModeKeys.TRAIN:return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions,loss=loss,train_op=train_op)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108

    10.AFM: 對簡化版NFM進(jìn)行加權(quán)求和

    NFM的主要創(chuàng)新點(diǎn)是在FM過程中添加了逐元素相乘的運(yùn)算來增加模型的復(fù)雜度。但沒有在此基礎(chǔ)上添加更復(fù)雜的運(yùn)算過程,比如對加權(quán)求和。Jun Xiao等在2017年提出了注意力因子分解模型(Attentional Factorization Machine,AFM)就是在這個方向上的改進(jìn)。其計(jì)算圖如下所示:?

    ?

    AFM的特點(diǎn)是:

  • AFM與NFM都是致力于充分利用二階特征組合的信息,對嵌入后的向量兩兩進(jìn)行逐元素乘法,形成同維度的向量。而且AFM沒有MLP部分。
  • AFM通過在逐元素乘法之后形成的向量進(jìn)行加權(quán)求和,而且權(quán)重是基于網(wǎng)絡(luò)自身來產(chǎn)生的。其方法是引入一個注意力子網(wǎng)絡(luò)(Attention Net)
  • 當(dāng)權(quán)重都相等時(shí),AFM退化成無全連接層的NFM
  • “注意力子網(wǎng)絡(luò)”的主要操作是進(jìn)行矩陣乘法,其最終輸出結(jié)果為softmax,以保證各分量的權(quán)重本身是一個概率分布
  • 11.PNN:通過改進(jìn)向量乘法運(yùn)算延遲FM的實(shí)現(xiàn)過程

    再回到FM。既然AFM、NFM可以通過添加逐元素乘法的運(yùn)算來增加模型的復(fù)雜度,那向量乘法有這么多,可否用其他的方法增加FM復(fù)雜度?答案是可以的。Huifeng Guo等在2016年提出了基于向量積的神經(jīng)網(wǎng)絡(luò)(Product-based Neural Networks,PNN)就是一個典型例子。其簡化計(jì)算圖如下所示:?


    對比之前模型的計(jì)算圖,我們可以發(fā)現(xiàn)PNN的基本特點(diǎn)是:

    ?

  • 利用二階向量積層(Pair-wisely Connected Product Layer)對FM嵌入后的向量兩兩進(jìn)行向量積,形成的結(jié)果作為之后MLP的輸入。計(jì)算圖中用圓點(diǎn)?表示向量積運(yùn)算。PNN采用的向量積有內(nèi)積與外積兩種形式。
  • 需要說明的是,本計(jì)算圖中省略了PNN中向量與常數(shù)1進(jìn)行的乘法運(yùn)算。這部分其實(shí)與FNN類似,不是PNN的主要創(chuàng)新點(diǎn)。故在此圖中省略。
  • 對于內(nèi)積形式的PNN,因?yàn)閮蓚€向量相乘的結(jié)果為標(biāo)量,可以直接把各個標(biāo)量“拼接”成一個大向量,就可以作為MLP的輸入了。
  • 當(dāng)MLP的全連接層都是恒等變換且最后一層參數(shù)全為1時(shí),內(nèi)積形式的PNN就退化成了FM
  • 對于外積形式的PNN,因?yàn)閮蓚€向量相乘相當(dāng)于列向量與行向量進(jìn)行矩陣相乘,得到的結(jié)果為一個矩陣。各個矩陣向之前內(nèi)積形式的操作一樣直接拼接起來維數(shù)太多,論文的簡化方案是直接對各個矩陣進(jìn)行求和,得到的新矩陣(可以理解成之后對其拉長成向量)就直接作為MLP的輸入。
  • 觀察計(jì)算圖發(fā)現(xiàn)外積形式的PNN與NFM很像,其實(shí)就是PNN把NFM的逐元素乘法換成了外積
  • 此處分別附上PNN的內(nèi)積與外積形式代碼,完整數(shù)據(jù)和代碼請戳這里。

    class PNN1(Model):def __init__(self, field_sizes=None, embed_size=10, layer_sizes=None, layer_acts=None, drop_out=None,embed_l2=None, layer_l2=None, init_path=None, opt_algo='gd', learning_rate=1e-2, random_seed=None):Model.__init__(self)init_vars = []num_inputs = len(field_sizes)for i in range(num_inputs):init_vars.append(('embed_%d' % i, [field_sizes[i], embed_size], 'xavier', dtype))num_pairs = int(num_inputs * (num_inputs - 1) / 2)node_in = num_inputs * embed_size + num_pairs# node_in = num_inputs * (embed_size + num_inputs)for i in range(len(layer_sizes)):init_vars.append(('w%d' % i, [node_in, layer_sizes[i]], 'xavier', dtype))init_vars.append(('b%d' % i, [layer_sizes[i]], 'zero', dtype))node_in = layer_sizes[i]self.graph = tf.Graph()with self.graph.as_default():if random_seed is not None:tf.set_random_seed(random_seed)self.X = [tf.sparse_placeholder(dtype) for i in range(num_inputs)]self.y = tf.placeholder(dtype)self.keep_prob_train = 1 - np.array(drop_out)self.keep_prob_test = np.ones_like(drop_out)self.layer_keeps = tf.placeholder(dtype)self.vars = init_var_map(init_vars, init_path)w0 = [self.vars['embed_%d' % i] for i in range(num_inputs)]xw = tf.concat([tf.sparse_tensor_dense_matmul(self.X[i], w0[i]) for i in range(num_inputs)], 1)xw3d = tf.reshape(xw, [-1, num_inputs, embed_size])row = []col = []for i in range(num_inputs-1):for j in range(i+1, num_inputs):row.append(i)col.append(j)# batch * pair * kp = tf.transpose(# pair * batch * ktf.gather(# num * batch * ktf.transpose(xw3d, [1, 0, 2]),row),[1, 0, 2])# batch * pair * kq = tf.transpose(tf.gather(tf.transpose(xw3d, [1, 0, 2]),col),[1, 0, 2])p = tf.reshape(p, [-1, num_pairs, embed_size])q = tf.reshape(q, [-1, num_pairs, embed_size])ip = tf.reshape(tf.reduce_sum(p * q, [-1]), [-1, num_pairs])# simple but redundant# batch * n * 1 * k, batch * 1 * n * k# ip = tf.reshape(# tf.reduce_sum(# tf.expand_dims(xw3d, 2) *# tf.expand_dims(xw3d, 1),# 3),# [-1, num_inputs**2])l = tf.concat([xw, ip], 1)for i in range(len(layer_sizes)):wi = self.vars['w%d' % i]bi = self.vars['b%d' % i]l = tf.nn.dropout(activate(tf.matmul(l, wi) + bi,layer_acts[i]),self.layer_keeps[i])l = tf.squeeze(l)self.y_prob = tf.sigmoid(l)self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=l, labels=self.y))if layer_l2 is not None:self.loss += embed_l2 * tf.nn.l2_loss(xw)for i in range(len(layer_sizes)):wi = self.vars['w%d' % i]self.loss += layer_l2[i] * tf.nn.l2_loss(wi)self.optimizer = get_optimizer(opt_algo, learning_rate, self.loss)config = tf.ConfigProto()config.gpu_options.allow_growth = Trueself.sess = tf.Session(config=config)tf.global_variables_initializer().run(session=self.sess)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    class PNN2(Model):def __init__(self, field_sizes=None, embed_size=10, layer_sizes=None, layer_acts=None, drop_out=None,embed_l2=None, layer_l2=None, init_path=None, opt_algo='gd', learning_rate=1e-2, random_seed=None,layer_norm=True):Model.__init__(self)init_vars = []num_inputs = len(field_sizes)for i in range(num_inputs):init_vars.append(('embed_%d' % i, [field_sizes[i], embed_size], 'xavier', dtype))num_pairs = int(num_inputs * (num_inputs - 1) / 2)node_in = num_inputs * embed_size + num_pairsinit_vars.append(('kernel', [embed_size, num_pairs, embed_size], 'xavier', dtype))for i in range(len(layer_sizes)):init_vars.append(('w%d' % i, [node_in, layer_sizes[i]], 'xavier', dtype))init_vars.append(('b%d' % i, [layer_sizes[i]], 'zero', dtype))node_in = layer_sizes[i]self.graph = tf.Graph()with self.graph.as_default():if random_seed is not None:tf.set_random_seed(random_seed)self.X = [tf.sparse_placeholder(dtype) for i in range(num_inputs)]self.y = tf.placeholder(dtype)self.keep_prob_train = 1 - np.array(drop_out)self.keep_prob_test = np.ones_like(drop_out)self.layer_keeps = tf.placeholder(dtype)self.vars = init_var_map(init_vars, init_path)w0 = [self.vars['embed_%d' % i] for i in range(num_inputs)]xw = tf.concat([tf.sparse_tensor_dense_matmul(self.X[i], w0[i]) for i in range(num_inputs)], 1)xw3d = tf.reshape(xw, [-1, num_inputs, embed_size])row = []col = []for i in range(num_inputs - 1):for j in range(i + 1, num_inputs):row.append(i)col.append(j)# batch * pair * kp = tf.transpose(# pair * batch * ktf.gather(# num * batch * ktf.transpose(xw3d, [1, 0, 2]),row),[1, 0, 2])# batch * pair * kq = tf.transpose(tf.gather(tf.transpose(xw3d, [1, 0, 2]),col),[1, 0, 2])# b * p * kp = tf.reshape(p, [-1, num_pairs, embed_size])# b * p * kq = tf.reshape(q, [-1, num_pairs, embed_size])# k * p * kk = self.vars['kernel']# batch * 1 * pair * kp = tf.expand_dims(p, 1)# batch * pairkp = tf.reduce_sum(# batch * pair * ktf.multiply(# batch * pair * ktf.transpose(# batch * k * pairtf.reduce_sum(# batch * k * pair * ktf.multiply(p, k),-1),[0, 2, 1]),q),-1)## if layer_norm:# # x_mean, x_var = tf.nn.moments(xw, [1], keep_dims=True)# # xw = (xw - x_mean) / tf.sqrt(x_var)# # x_g = tf.Variable(tf.ones([num_inputs * embed_size]), name='x_g')# # x_b = tf.Variable(tf.zeros([num_inputs * embed_size]), name='x_b')# # x_g = tf.Print(x_g, [x_g[:10], x_b])# # xw = xw * x_g + x_b# p_mean, p_var = tf.nn.moments(op, [1], keep_dims=True)# op = (op - p_mean) / tf.sqrt(p_var)# p_g = tf.Variable(tf.ones([embed_size**2]), name='p_g')# p_b = tf.Variable(tf.zeros([embed_size**2]), name='p_b')# # p_g = tf.Print(p_g, [p_g[:10], p_b])# op = op * p_g + p_bl = tf.concat([xw, kp], 1)for i in range(len(layer_sizes)):wi = self.vars['w%d' % i]bi = self.vars['b%d' % i]l = tf.nn.dropout(activate(tf.matmul(l, wi) + bi,layer_acts[i]),self.layer_keeps[i])l = tf.squeeze(l)self.y_prob = tf.sigmoid(l)self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=l, labels=self.y))if layer_l2 is not None:self.loss += embed_l2 * tf.nn.l2_loss(xw)#tf.concat(w0, 0))for i in range(len(layer_sizes)):wi = self.vars['w%d' % i]self.loss += layer_l2[i] * tf.nn.l2_loss(wi)self.optimizer = get_optimizer(opt_algo, learning_rate, self.loss)config = tf.ConfigProto()config.gpu_options.allow_growth = Trueself.sess = tf.Session(config=config)tf.global_variables_initializer().run(session=self.sess)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118

    12.DCN:高階FM的降維實(shí)現(xiàn)

    以上的FM推廣形式,主要是對FM進(jìn)行二階特征組合。高階特征組合是通過MLP實(shí)現(xiàn)的。但這兩種實(shí)現(xiàn)方式是有很大不同的,FM更多是通過向量embedding之間的內(nèi)積來實(shí)現(xiàn),而MLP則是在向量embedding之后一層一層進(jìn)行權(quán)重矩陣乘法實(shí)現(xiàn)。可否直接將FM的過程在高階特征組合上進(jìn)行推廣?答案是可以的。Ruoxi Wang等在2017提出的深度與交叉神經(jīng)網(wǎng)絡(luò)(Deep & Cross Network,DCN)就是在這個方向進(jìn)行改進(jìn)的。DCN的計(jì)算圖如下:?


    DCN的特點(diǎn)如下:

    ?

  • Deep部分就是普通的MLP網(wǎng)絡(luò),主要是全連接。
  • 與DeepFM類似,DCN是由embedding+MLP部分與cross部分進(jìn)行聯(lián)合訓(xùn)練的。Cross部分是對FM部分的推廣。
  • cross部分的公式如下:?

    ?

  • 可以證明,cross網(wǎng)絡(luò)是FM的過程在高階特征組合的推廣。完全的證明需要一些公式推導(dǎo),感興趣的同學(xué)可以直接參考原論文的附錄。
  • 而用簡單的公式證明可以得到一個很重要的結(jié)論:只有兩層且第一層與最后一層權(quán)重參數(shù)相等時(shí)的Cross網(wǎng)絡(luò)與簡化版FM等價(jià)。
  • 此處對應(yīng)簡化版的FM視角是將拼接好的稠密向量作為輸入向量,且不做領(lǐng)域方面的區(qū)分(但產(chǎn)生這些稠密向量的過程是考慮領(lǐng)域信息的,相對全特征維度的全連接層減少了大量參數(shù),可以視作稀疏鏈接思想的體現(xiàn))。而且之后進(jìn)行embedding權(quán)重矩陣W只有一列——是退化成列向量的情形。
  • 與MLP網(wǎng)絡(luò)相比,Cross部分在增加高階特征組合的同時(shí)減少了參數(shù)的個數(shù),并省去了非線性激活函數(shù)
  • 13.Wide&Deep: DeepFM與DCN的基礎(chǔ)框架

    開篇已經(jīng)提到,本文思路有兩條主線。到此為止已經(jīng)將基于FM的主線介紹基本完畢。接下來將串講從embedding+MLP自身的演進(jìn)特點(diǎn)的CTR預(yù)估模型主線,而這條思路與我們之前的FM思路同樣有千絲萬縷的聯(lián)系。?
    Google在2016年提出的寬度與深度模型(Wide&Deep)在深度學(xué)習(xí)CTR預(yù)估模型中占有非常重要的位置,它奠定了之后基于深度學(xué)習(xí)的廣告點(diǎn)擊率預(yù)估模型的框架。?
    Wide&Deep將深度模型與線性模型進(jìn)行聯(lián)合訓(xùn)練,二者的結(jié)果求和輸出為最終點(diǎn)擊率。其計(jì)算圖如下:?


    我們將Wide&Deep的計(jì)算圖與之前的模型進(jìn)行對比可知:

    ?

  • Wide&Deep是前面介紹模型DeepFM與DCN的基礎(chǔ)框架。這些模型均采用神經(jīng)網(wǎng)絡(luò)聯(lián)合訓(xùn)練的思路,對神經(jīng)網(wǎng)絡(luò)進(jìn)行并聯(lián)。
  • DeepFM、DCN與Wide&Deep的Deep部分都是MLP
  • Wide&Deep的Wide部分是邏輯回歸,可以手動設(shè)計(jì)組合特征。
  • DeepFM的Wide部分是FM,DCN的Wide部分是Cross網(wǎng)絡(luò),二者均不強(qiáng)求手動設(shè)計(jì)特征。但此時(shí)都與字面意義上的Wide有一定差異,因?yàn)榫蚕砹私稻S后的嵌入特征
  • 此處附上DeepFM的代碼實(shí)現(xiàn),完整數(shù)據(jù)和代碼請戳這里:

    def get_model(model_type, model_dir):print("Model directory = %s" % model_dir)# 對checkpoint去做設(shè)定runconfig = tf.contrib.learn.RunConfig(save_checkpoints_secs=None,save_checkpoints_steps = 100,)m = None# 寬模型if model_type == 'WIDE':m = tf.contrib.learn.LinearClassifier(model_dir=model_dir,feature_columns=wide_columns)# 深度模型if model_type == 'DEEP':m = tf.contrib.learn.DNNClassifier(model_dir=model_dir,feature_columns=deep_columns,hidden_units=[100, 50, 25])# 寬度深度模型if model_type == 'WIDE_AND_DEEP':m = tf.contrib.learn.DNNLinearCombinedClassifier(model_dir=model_dir,linear_feature_columns=wide_columns,dnn_feature_columns=deep_columns,dnn_hidden_units=[100, 70, 50, 25],config=runconfig)print('estimator built')return m
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    14.Deep Cross: DCN由其殘差網(wǎng)絡(luò)思想進(jìn)化

    由K. He等提出的深度殘差網(wǎng)絡(luò)能夠大大加深神經(jīng)網(wǎng)絡(luò)的深度,同時(shí)不會引起退化的問題,顯著提高了模型的精度。Ying Shan等將該思路應(yīng)用到廣告點(diǎn)擊率預(yù)估模型中,提出深度交叉模型(DeepCross,2016DeepCross,2016)。Deep Cross的計(jì)算圖如下:?


    將Deep Cross與之前的模型對比,可以發(fā)現(xiàn)其特點(diǎn)是:

    ?

  • 對embedding+MLP的改進(jìn)主要是MLP部分增加跳躍連接成為殘差網(wǎng)絡(luò)
  • Deep Cross?與傳統(tǒng)的殘差網(wǎng)絡(luò)的區(qū)別主要是沒有采用卷積操作。其中一個原因是在廣告點(diǎn)擊率預(yù)估領(lǐng)域,特征不具備平移不變性
  • DCN其實(shí)是從Deep Cross進(jìn)化出來的版本。DCN相對Deep Cross的主要貢獻(xiàn)是解耦了Deep 與Cross(特征交叉)部分
  • 因此DCN中的Cross部分可以理解為殘差網(wǎng)絡(luò)的變體:其將Deep Cross的跨越鏈接縮短為只有一層,而全連接部分改為與權(quán)重向量和輸入向量的內(nèi)積。
  • 15.DIN:對同領(lǐng)域歷史信息引入注意力機(jī)制的MLP

    以上神經(jīng)網(wǎng)絡(luò)對同領(lǐng)域離散特征的處理基本是將其嵌入后直接求和,這在一般情況下沒太大問題。但其實(shí)可以做得更加精細(xì)。比如對于歷史統(tǒng)計(jì)類特征。以用戶歷史瀏覽的商戶id為例,假設(shè)用戶歷史瀏覽了10個商戶,這些商戶id的常規(guī)處理方法是作為同一個領(lǐng)域的特征嵌入后直接求和得到一個嵌入向量。但這10個商戶只有一兩個商戶與當(dāng)前被預(yù)測的廣告所在的商戶相似,其他商戶關(guān)系不大。增加這兩個商戶在求和過程中的權(quán)重,應(yīng)該能夠更好地提高模型的表現(xiàn)力。而增加求和權(quán)重的思路就是典型的注意力機(jī)制思路。?
    由?Bahdanau et al. (2015)?引入的現(xiàn)代注意力機(jī)制,本質(zhì)上是加權(quán)平均(權(quán)重是模型根據(jù)數(shù)據(jù)學(xué)習(xí)出來的),其在機(jī)器翻譯上應(yīng)用得非常成功。受注意力機(jī)制的啟發(fā),Guorui Zhou等在2017年提出了深度興趣網(wǎng)絡(luò)(Deep Interest Network,DIN)。DIN主要關(guān)注用戶在同一領(lǐng)域的歷史行為特征,如瀏覽了多個商家、多個商品等。DIN可以對這些特征分配不同的權(quán)重進(jìn)行求和。其網(wǎng)絡(luò)結(jié)構(gòu)圖如下:?

    ?

  • 此處采用原論文的結(jié)構(gòu)圖,表示起來更清晰。
  • DIN考慮對同一領(lǐng)域的歷史特征進(jìn)行加權(quán)求和,以加強(qiáng)其感興趣的特征的影響。
  • 用戶的每個領(lǐng)域的歷史特征權(quán)重則由該歷史特征及其對應(yīng)備選廣告特征通過一個子網(wǎng)絡(luò)得到。即用戶歷史瀏覽的商戶特征與當(dāng)前瀏覽商戶特征對應(yīng),歷史瀏覽的商品特征與當(dāng)前瀏覽商品特征對應(yīng)。
  • 權(quán)重子網(wǎng)絡(luò)主要包括特征之間的元素級別的乘法、加法和全連接等操作
  • AFM也引入了注意力機(jī)制。但是AFM是將注意力機(jī)制與FM同領(lǐng)域特征求和之后進(jìn)行結(jié)合,DIN直接是將注意力機(jī)制與同領(lǐng)域特征求和之前進(jìn)行結(jié)合
  • 16.多任務(wù)視角:信息的遷移與補(bǔ)充

    對于數(shù)據(jù)驅(qū)動的解決方案而言,數(shù)據(jù)和模型同樣重要,數(shù)據(jù)(特征)通常決定了效果的上限,各式各樣的模型會以不同的方式去逼近這個上限。而所有算法應(yīng)用的老司機(jī)都知道很多場景下,如果有更多的數(shù)據(jù)進(jìn)行模型訓(xùn)練,效果一般都能顯著得到提高。廣告也是一樣的場景,在很多電商的平臺上會有很多不同場景的廣告位,每個場景蘊(yùn)含了用戶的不同興趣的表達(dá),這些信息的匯總與融合可以帶來最后效果的提升。但是將不同場景的數(shù)據(jù)直接進(jìn)行合并用來訓(xùn)練(ctr/cvr)模型,結(jié)果很多時(shí)候并不是很樂觀,仔細(xì)想想也是合理的,不同場景下的樣本分布存在差異,直接對樣本累加會影響分布導(dǎo)致效果負(fù)向。?


    而深度學(xué)習(xí)發(fā)展,使得信息的融合與應(yīng)用有了更好的進(jìn)展,用Multi?taskMulti?task?learning(MTL)learning(MTL)的方式可以很漂亮的解決上面提到的問題。我們不直接對樣本進(jìn)行累加和訓(xùn)練,而是像上圖所示,把兩個場景分為兩個task,即分為兩個子網(wǎng)絡(luò)。對單個網(wǎng)絡(luò)而言,底層的embedding層的表達(dá)受限于單場景的數(shù)據(jù)量,很可能學(xué)習(xí)不充分。而上圖這樣的網(wǎng)絡(luò)結(jié)合,使得整個訓(xùn)練過程有了表示學(xué)習(xí)的共享(Shared Lookup Table),這種共享有助于大樣本的子任務(wù)幫助小樣本的子任務(wù),使得底層的表達(dá)學(xué)習(xí)更加充分。?DeepFM和DCN也用到了這個思路!只是它們是對同一任務(wù)的不同模型進(jìn)行結(jié)合,而多任務(wù)學(xué)習(xí)是對不同任務(wù)的不同模型進(jìn)行結(jié)合。而且,我們可以玩得更加復(fù)雜。?
    Multi-task learning(MTL)整個結(jié)構(gòu)的上層的不同的task的子網(wǎng)絡(luò)是不一樣的,這樣每個子網(wǎng)絡(luò)可以各自去擬合自己task對應(yīng)的概念分布。并且,取決于問題與場景的相似性和復(fù)雜度,可以把底層的表達(dá)學(xué)習(xí),從簡單的共享embedding到共享一些層次的表達(dá)。極端的情況是我們可以直接共享所有的表達(dá)學(xué)習(xí)(representation learning)部分,而只接不同的網(wǎng)絡(luò)head來完成不一樣的任務(wù)。這樣帶來的另外一個好處是,不同的task可以共享一部分計(jì)算,從而實(shí)現(xiàn)計(jì)算的加速。?
    值得一提的另一篇paper是阿里媽媽團(tuán)隊(duì)提出的“完整空間多任務(wù)模型”(Entire Space Multi-Task Model,ESMM),也是很典型的多任務(wù)學(xué)習(xí)和信息補(bǔ)充思路,這篇paper解決的問題不是ctr(點(diǎn)擊率)預(yù)估而是cvr(轉(zhuǎn)化率)預(yù)估,傳統(tǒng)CVR預(yù)估模型會有比較明顯的樣本選擇偏差(sample selection bias)和訓(xùn)練數(shù)據(jù)過于稀疏(data sparsity )的問題,而ESMM模型利用用戶行為序列數(shù)據(jù),在完整的樣本數(shù)據(jù)空間同時(shí)學(xué)習(xí)點(diǎn)擊率和轉(zhuǎn)化率(post-view clickthrough&conversion rate,CTCVR),在一定程度上解決了這個問題。?
    在電商的場景下,用戶的決策過程很可能是這樣的,在觀察到系統(tǒng)展現(xiàn)的推薦商品列表后,點(diǎn)擊自己感興趣的商品,進(jìn)而產(chǎn)生購買行為。所以用戶行為遵循這樣一個決策順序:impression → click → conversion。CVR模型旨在預(yù)估用戶在觀察到曝光商品進(jìn)而點(diǎn)擊到商品詳情頁之后購買此商品的概率,即pCVR = p(conversion|click,impression)。?
    預(yù)估點(diǎn)擊率pCTR,預(yù)估點(diǎn)擊下單率pCVR和預(yù)估點(diǎn)擊與下單率pCTCVR關(guān)系如下。?

    ?

    傳統(tǒng)的CVR預(yù)估任務(wù)通常采用類似于CTR預(yù)估的技術(shù)進(jìn)行建模。但是不同于CTR預(yù)估任務(wù)的是,這個場景面臨一些特有的挑戰(zhàn):1) 樣本選擇偏差;2) 訓(xùn)練數(shù)據(jù)稀疏;3) 延遲反饋等。?


    ESMM模型提出了下述的網(wǎng)絡(luò)結(jié)構(gòu)進(jìn)行問題建模?


    EMMS的特點(diǎn)是:

    ?

  • 在整個樣本空間建模。pCVR 可以在先估計(jì)出pCTR 和pCTCVR之后計(jì)算得出,如下述公式。從原理上看,相當(dāng)于分別單獨(dú)訓(xùn)練兩個模型擬合出pCTR 和pCTCVR,進(jìn)而計(jì)算得到pCVR 。?


    注意到pCTR 和pCTCVR是在整個樣本空間上建模得到的,pCVR 只是一個中間變量。因此,ESMM模型是在整個樣本空間建模,而不像傳統(tǒng)CVR預(yù)估模型那樣只在點(diǎn)擊樣本空間建模。
  • 特征表示層共享。ESMM模型借鑒遷移學(xué)習(xí)和multi-task learning的思路,在兩個子網(wǎng)絡(luò)的embedding層共享特征表示詞典。embedding層的表達(dá)參數(shù)占了整個網(wǎng)絡(luò)參數(shù)的絕大部分,參數(shù)量大,需要大量的訓(xùn)練樣本才能學(xué)習(xí)充分。顯然CTR任務(wù)的訓(xùn)練樣本量要大大超過CVR任務(wù)的訓(xùn)練樣本量,ESMM模型中特征表示共享的機(jī)制能夠使得CVR子任務(wù)也能夠從只有展現(xiàn)沒有點(diǎn)擊的樣本中學(xué)習(xí),從而在一定程度上緩解訓(xùn)練數(shù)據(jù)稀疏性問題。
  • 17.各種模型的對比和總結(jié)

    前面介紹了各種基于深度學(xué)習(xí)的廣告點(diǎn)擊率預(yù)估算法模型,針對不同的問題、基于不同的思路,不同的模型有各自的特點(diǎn)。各個模型具體關(guān)系比較如下表1所示:?

    表 1. 各模型對比

    ?

    Embedding+MLPFMAttentionResnet
    Wide&Deep××
    FNN×
    DeepFM×
    NFM×
    DIN×
    AFM×
    Deep Cross××
    DCN×

    本文從開篇就說明這些模型推演的核心思路是“通過設(shè)計(jì)網(wǎng)絡(luò)結(jié)構(gòu)進(jìn)行組合特征的挖掘”,其在各個模型的實(shí)現(xiàn)方式如下:

  • FM其實(shí)是對嵌入特征進(jìn)行兩兩內(nèi)積實(shí)現(xiàn)特征二階組合;FNN在FM基礎(chǔ)上引入了MLP;
  • DeepFM通過聯(lián)合訓(xùn)練、嵌入特征共享來兼顧FM部分與MLP部分不同的特征組合機(jī)制;
  • NFM、PNN則是通過改造向量積的方式來延遲FM的實(shí)現(xiàn)過程,在其中添加非線性成分來提升模型表現(xiàn)力;
  • AFM更進(jìn)一步,直接通過子網(wǎng)絡(luò)來對嵌入向量的兩兩逐元素乘積進(jìn)行加權(quán)求和,以實(shí)現(xiàn)不同組合的差異化,也是一種延遲FM實(shí)現(xiàn)的方式;
  • DCN則是將FM進(jìn)行高階特征組合的方向上進(jìn)行推廣,并結(jié)合MLP的全連接式的高階特征組合機(jī)制;
  • Wide&Deep是兼容手工特征組合與MLP的特征組合方式,是許多模型的基礎(chǔ)框架;
  • Deep Cross是引入殘差網(wǎng)絡(luò)機(jī)制的前饋神經(jīng)網(wǎng)絡(luò),給高維的MLP特征組合增加了低維的特征組合形式,啟發(fā)了DCN;
  • DIN則是對用戶側(cè)的某歷史特征和廣告?zhèn)鹊耐I(lǐng)域特征進(jìn)行組合,組合成的權(quán)重反過來重新影響用戶側(cè)的該領(lǐng)域各歷史特征的求和過程;
  • 多任務(wù)視角則是更加宏觀的思路,結(jié)合不同任務(wù)(而不僅是同任務(wù)的不同模型)對特征的組合過程,以提高模型的泛化能力。
  • 當(dāng)然,廣告點(diǎn)擊率預(yù)估深度學(xué)習(xí)模型還有很多,比如Jie Zhu提出的基于決策樹的神經(jīng)網(wǎng)絡(luò)(Deep Embedding Forest)將深度學(xué)習(xí)與樹型模型結(jié)合起來。如果數(shù)據(jù)特征存在圖像或者大量文本相關(guān)特征,傳統(tǒng)的卷積神經(jīng)網(wǎng)絡(luò)、循環(huán)神經(jīng)網(wǎng)絡(luò)均可以結(jié)合到廣告點(diǎn)擊率預(yù)估的場景中。各個深度模型都有相應(yīng)的特點(diǎn),限于篇幅,我們就不再贅述了。

    18.后記

    目前深度學(xué)習(xí)的算法層出不窮,看論文確實(shí)有些應(yīng)接不暇。我們的經(jīng)驗(yàn)有兩點(diǎn):要有充分的生產(chǎn)實(shí)踐經(jīng)驗(yàn),同時(shí)要有扎實(shí)的算法理論基礎(chǔ)。很多論文的亮點(diǎn)其實(shí)是來自于實(shí)際做工程的經(jīng)驗(yàn)。也辛虧筆者一直都在生產(chǎn)一線并帶領(lǐng)算法團(tuán)隊(duì)進(jìn)行工程研發(fā)(當(dāng)然也因此荒廢了近2年的博客,T△T ),積淀了一些特征工程、模型訓(xùn)練的經(jīng)驗(yàn),才勉強(qiáng)跟得上新論文。比如DIN“對用戶側(cè)的某領(lǐng)域歷史特征基于廣告?zhèn)鹊耐I(lǐng)域特征進(jìn)行加權(quán)求和”的思想,其實(shí)與傳統(tǒng)機(jī)器學(xué)習(xí)對強(qiáng)業(yè)務(wù)相關(guān)特征進(jìn)行針對性特征組合的特征工程思路比較相似。另一方面,對深度學(xué)習(xí)的經(jīng)典、前沿方法的熟悉也很重要。從前面我們的串講也能夠看出,CTR預(yù)估作為一個業(yè)務(wù)特點(diǎn)很強(qiáng)的場景,在應(yīng)用深度學(xué)習(xí)的道路上,也充分借鑒了注意力機(jī)制、殘差網(wǎng)絡(luò)、聯(lián)合訓(xùn)練、多任務(wù)學(xué)習(xí)等經(jīng)典的深度學(xué)習(xí)方法。了解博主的朋友也知道我們一直推崇理論與實(shí)踐相結(jié)合的思路,我們自身對這條經(jīng)驗(yàn)也非常受用。當(dāng)然,計(jì)算廣告是一個很深的領(lǐng)域,自己研究尚淺,串講難免存在紕漏。歡迎大家指出問題,共同交流學(xué)習(xí)。

    參考文獻(xiàn)

  • 陳巧紅,余仕敏,賈宇波. 廣告點(diǎn)擊率預(yù)估技術(shù)綜述[J]. 浙江理工大學(xué)學(xué)報(bào). 2015(11).
  • 紀(jì)文迪,王曉玲,周傲英. 廣告點(diǎn)擊率估算技術(shù)綜述[J]. 華東師范大學(xué)學(xué)報(bào)(自然科學(xué)版). 2013(03).
  • Rendle S. Factorization machines. Data Mining (ICDM), 2010 IEEE 10th International Conference on. 2010.
  • Heng-Tze Cheng and Levent Koc. Wide & deep learning for recommender systems. In Proceedings of the 1st Workshop on Deep Learning for Recommender Systems, pages 7–10. ACM, 2016.
  • Weinan Zhang, Tianming Du, and Jun Wang. Deep learning over multi-field categorical data - - A case study on user response prediction. In ECIR, 2016.
  • Huifeng Guo, Ruiming Tang, Yunming Ye, Zhenguo Li, and Xiuqiang He. DeepFM: A Factorization-Machine based Neural Network for CTR Prediction. arXiv preprint arXiv:1703.04247 (2017).
  • Xiangnan He and Tat-Seng Chua. Neural Factorization Machines for Sparse Predictive Analytics SIGIR. 355–364. 2017.
  • Guorui Zhou, Chengru Song, Xiaoqiang Zhu, Xiao Ma, Yanghui Yan, Xingya Dai, Han Zhu, Junqi Jin, Han Li, and Kun Gai. 2017. Deep Interest Network for Click-Through Rate Prediction. arXiv preprint arXiv:1706.06978 (2017).
  • J. Xiao, H. Ye, X. He, H. Zhang, F. Wu, and T.-S. Chua. Attentional factorization machines: Learning the weight of feature interactions via attention networks. In IJCAI, 2017.

  • Ying Shan, T Ryan Hoens, Jian Jiao, Haijing Wang, Dong Yu, and JC Mao. 2016. Deep Crossing: Web-Scale Modeling without Manually Cra ed Combinatorial Features. In Proceedings of the 22nd ACM SIGKDD International Conference on Knowledge Discovery and Data Mining. ACM, 255–262.

  • Wang, R., Fu, B., Fu, G., Wang, M.: Deep & cross network for ad click predictions. In: Proceedings of the ADKDD 17. pp. 12:1–12:7 (2017).
  • Ying Shan, T Ryan Hoens, et al. Deep crossing: Web-scale modeling without manually crafted combinatorial features. KDD ’16. ACM, 2016.
  • Paul Covington, Jay Adams, and Emre Sargin. Deep neural networks for youtube recommendations. In Proceedings of the 10th ACM Conference on Recommender Systems, pages 191–198. ACM, 2016.
  • Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. 2015. Deep residual learning for image recognition. arXiv preprint arXiv:1512.03385 (2015).
  • 總結(jié)

    以上是生活随笔為你收集整理的从FM推演各深度学习CTR预估模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    国产精品18久久久久久首页狼 | 免费黄色av电影 | 国产一性一爱一乱一交 | 天天爱天天操天天干 | 免费进去里的视频 | 久久免费视频3 | a黄色影院 | 天天综合入口 | www黄com| 色综合a| 久久一区91 | 天天操天天摸天天爽 | www.色婷婷.com| 高清av网站 | 999国产 | 久久精品中文字幕免费mv | 欧美日韩中文在线观看 | av超碰免费在线 | 日韩久久精品 | 欧美性春潮 | 在线观看国产麻豆 | 欧美精品一区二区免费 | 国产精品入口66mio女同 | 久久人人爽视频 | 日韩有码网站 | 丁香免费视频 | www.99热精品 | 天天se天天cao天天干 | 国产精品在线看 | 在线国产片 | 在线播放国产一区二区三区 | 在线观看亚洲成人 | 国产a精品 | 日韩久久午夜一级啪啪 | 综合天天久久 | 狠狠色狠狠色综合日日小说 | 国产一级片毛片 | 91福利国产在线观看 | 久久久久国产成人免费精品免费 | 天天干夜夜夜操天 | 五月综合| av看片网 | 国产视频手机在线 | 日韩三级久久 | 国产vs久久 | 六月天综合网 | 国产精品久久久毛片 | 国产精品自产拍在线观看网站 | 日日夜夜精品视频 | 国产日韩精品一区二区三区 | 亚洲人毛片 | 在线观看视频中文字幕 | 欧美精品二区 | 欧美91精品国产自产 | 国产在线国产 | 91在线视频免费观看 | 天天爱天天射 | 久久理论电影网 | 久草视频免费在线观看 | 日本成人中文字幕在线观看 | 亚洲欧美日韩国产精品一区午夜 | 九九热久久免费视频 | 日韩av播放在线 | 国产97在线视频 | 中文字幕黄色网址 | 韩国av电影在线观看 | 国产专区在线 | 久草| 久久久久久久久久久电影 | 蜜桃视频在线观看一区 | 人人爽人人澡 | 欧美视频日韩视频 | 欧美日韩久 | 日韩精品久久一区二区 | 中文在线字幕免 | 国产又黄又硬又爽 | 久久久精品在线观看 | 国产97超碰| 免费色视频在线 | 国产一二三在线视频 | 午夜精品久久久久久久99热影院 | 国产精品久久久久久久99 | 麻豆一区二区 | 久久综合亚洲鲁鲁五月久久 | av丝袜天堂| 国产成人黄色在线 | 国产视频资源在线观看 | 特级xxxxx欧美 | 超碰人人在 | 五月婷婷一区 | 日日干夜夜操视频 | 一级精品视频在线观看宜春院 | 国产精品自产拍在线观看桃花 | 亚洲成av片人久久久 | 久久久色 | 国产成本人视频在线观看 | 在线观看国产亚洲 | 中中文字幕av在线 | 1024手机在线看 | 中文字幕在线观看的网站 | 超碰成人av| 一区二区三区免费在线观看视频 | 99视频网站 | av在观看 | 91视频一8mav | 国产丝袜美腿在线 | 91在线网址 | av免费在线观 | 91免费观看国产 | 91av视频免费在线观看 | 国产午夜精品一区二区三区欧美 | 国产1区2区3区精品美女 | 一区二区三区四区精品视频 | 色av婷婷 | 超碰在线天天 | 高清国产在线一区 | 色播五月婷婷 | 69xx视频| 九九热久久免费视频 | 国产在线观看网站 | 久久综合影音 | 日韩在线第一区 | 一区在线免费观看 | 99久国产| 黄色com| 成人在线观看免费视频 | 狠狠操狠狠干天天操 | 国产小视频在线观看免费 | 欧美性生活久久 | 精品亚洲男同gayvideo网站 | 婷婷电影在线观看 | av免费网站观看 | 国产五月天婷婷 | 99热高清| 手机av电影在线 | 亚洲欧美国产精品 | 欧美日韩99| 91麻豆.com| 天天插狠狠干 | 国产成人黄色网址 | 成人在线免费看视频 | 亚洲精品国产成人 | 国产99在线免费 | 亚洲国产三级 | 亚洲一区二区三区在线看 | 久久精品一二三区白丝高潮 | 欧美激情精品久久久久久免费印度 | 不卡av在线 | 天天爱天天射天天干天天 | 视频一区在线免费观看 | 国产日韩欧美在线播放 | 在线观看你懂的网站 | 国产黄免费在线观看 | 国产小视频免费在线网址 | 黄色在线看网站 | 欧美精品久久99 | 亚洲欧洲国产视频 | 欧美一区二区精美视频 | 91香蕉视频黄色 | 在线高清一区 | 亚洲极色| 成人午夜剧场在线观看 | 国产亚洲精品久久网站 | 国产资源在线视频 | 日韩最新理论电影 | 日韩一级电影在线观看 | 精品国产观看 | 久久成人精品电影 | 色资源网免费观看视频 | 国产精品一区二区三区视频免费 | 狠狠激情中文字幕 | 国产精品久久久久久久av电影 | 国产乱码精品一区二区蜜臀 | av电影免费 | 欧美精品一区二区三区四区在线 | 日韩经典一区二区三区 | 99国产一区二区三精品乱码 | 在线观看深夜福利 | 国产日韩精品在线观看 | 免费在线观看视频一区 | 精品一区二区电影 | 欧美韩国日本在线观看 | 国产精品v a免费视频 | 亚洲精品在线视频观看 | 国产一区二区在线精品 | 欧美精品一区二区三区一线天视频 | 亚洲精品在线免费观看视频 | 女人18片毛片90分钟 | 国产精品爽爽久久久久久蜜臀 | 久久久久久久久久久久影院 | 亚洲色图 校园春色 | 97超在线 | 精品国产乱码久久久久久久 | 久久一区二区三区四区 | 99精品视频在线观看视频 | 奇人奇案qvod| 精品在线观看国产 | 一区二区三区高清在线 | 中文字幕在线影视资源 | 久久久久久久久久久黄色 | 色99之美女主播在线视频 | 香蕉视频91 | 亚洲欧美日韩精品久久久 | 国产精品 日韩 | 久久xx视频 | 91最新中文字幕 | 国产精品白虎 | 麻花天美星空视频 | 久久99精品久久久久久三级 | 欧美日韩在线第一页 | 国产高清av在线播放 | 久久综合九色综合欧美就去吻 | 国产精成人品免费观看 | 天天射天天操天天 | 精品美女久久久久 | 美女搞黄国产视频网站 | 亚洲国产婷婷 | 成人久久影院 | 二区视频在线 | 国产精品手机在线 | 精品一区二区在线免费观看 | 久久影院亚洲 | 精品久久影院 | 精品主播网红福利资源观看 | 色婷婷狠狠五月综合天色拍 | 激情五月***国产精品 | 黄色精品久久 | www.97视频 | 狠狠色免费| 少妇搡bbbb搡bbb搡忠贞 | 二区在线播放 | 国内一级片在线观看 | 久久激情小说 | 天天激情在线 | 亚洲激情小视频 | 在线观看亚洲免费视频 | 久久综合九色综合久久久精品综合 | 国产精品久久久电影 | 精品一区二区电影 | 麻豆一区在线观看 | 丁香综合网 | 波多野结衣电影一区 | 精品国产伦一区二区三区观看方式 | 97超碰国产在线 | 免费精品在线观看 | 国产一级做a爱片久久毛片a | 亚洲天堂色婷婷 | 人人爱人人射 | 欧美色图亚洲图片 | 97成人资源 | 成人在线观看资源 | 久久九九精品 | 亚洲精品动漫在线 | 人人爽久久涩噜噜噜网站 | 91av视频| 91亚洲狠狠婷婷综合久久久 | 奇米影视在线99精品 | 美女福利视频一区二区 | 色网站在线 | 久久久影视 | 国产成人在线综合 | 国产精品一区二区免费视频 | 免费看一级黄色 | 久久一区国产 | 中文字幕中文字幕在线中文字幕三区 | 极品中文字幕 | 狠狠操狠狠插 | 久久理伦片 | 日韩美精品视频 | 精品久久精品久久 | www.天天色 | 中文字幕中文字幕 | av线上免费看 | 最近中文字幕高清字幕免费mv | 久久精品久久精品 | 黄网站免费大全入口 | 日韩视频在线不卡 | 国产系列 在线观看 | 日韩欧美精品在线观看视频 | 国产二区免费视频 | 最新国产在线 | 日韩理论| 美女国产网站 | 国产流白浆高潮在线观看 | 天天摸天天舔 | 国产在线a不卡 | 欧美成人在线网站 | 一级a性色生活片久久毛片波多野 | 波多野结衣日韩 | 欧美精品久久人人躁人人爽 | 日产乱码一二三区别在线 | 国产视频日韩视频欧美视频 | 18网站在线观看 | 99精品一区 | 九九电影在线 | 久久视频精品在线 | 国产综合小视频 | 精品国产免费久久 | 亚洲精品av中文字幕在线在线 | 亚洲一级片在线观看 | 麻豆视频免费在线 | 一区 在线 影院 | 久久久久久久99精品免费观看 | 91大神在线观看视频 | 91精品成人久久 | 日韩久久一区二区 | 中文字幕在线电影 | 久久综合久久综合九色 | 久久久久久久久久久久久影院 | 亚洲理论电影 | 在线观av | 国产拍揄自揄精品视频麻豆 | 在线免费黄色片 | 国产午夜一区二区 | 国色综合| 免费福利在线视频 | 国产看片 色 | 国产午夜精品视频 | 黄色亚洲大片免费在线观看 | 日韩成人精品在线观看 | 丝袜+亚洲+另类+欧美+变态 | 国产视频在线播放 | 伊人狠狠色丁香婷婷综合 | 欧美国产日韩一区二区三区 | 一区精品久久 | 亚洲精品久久久蜜臀下载官网 | 国产在线播放观看 | www国产亚洲精品久久麻豆 | 国产青春久久久国产毛片 | 亚洲婷婷综合色高清在线 | 人人讲下载 | 国产在线不卡 | 国产精品福利久久久 | 97超碰人人澡人人爱 | 亚洲午夜久久久影院 | 96亚洲精品久久 | 超碰个人在线 | 在线黄色国产 | 日韩免费成人 | 婷香五月| 人人爽人人看 | 久久区二区 | 久久久久久综合网天天 | 国产亚洲成人网 | 日韩欧美在线免费观看 | 伊人干综合 | 国产小视频国产精品 | 国产精品美女久久久久久久久久久 | 婷婷精品在线视频 | 久久99爱视频 | 中文字幕日本在线观看 | 中国一级片在线 | 国产区精品区 | 日韩精品在线免费播放 | 黄网站www | 在线国产一区二区三区 | 中文字幕在线观看三区 | 欧美少妇bbwhd | 久久久国际精品 | av电影不卡在线 | 亚洲免费婷婷 | 久草综合视频 | 国产麻豆精品一区二区 | 日韩av成人在线 | 日韩免费一区二区三区 | 午夜精品99久久免费 | 国产福利在线不卡 | 国产破处在线视频 | 国产精品视频久久久 | 奇米影视在线99精品 | 美女性爽视频国产免费app | 亚洲精品在线观看av | av免费看网站 | 欧美午夜激情网 | 欧美日韩精品二区第二页 | 国产精品久久久久久久妇 | 亚洲欧美视频一区二区三区 | 国产精品精品久久久久久 | 亚洲最新精品 | 激情久久小说 | 国产亚洲精品久久久久久 | 夜夜躁日日躁 | 深爱五月网 | 欧美日本国产在线观看 | 成人教育av | 国产高清在线a视频大全 | 国产亚洲精品久 | 成人一区二区三区在线 | 五月婷婷激情 | 999久久久免费视频 午夜国产在线观看 | 综合色狠狠 | 97超碰成人在线 | 欧美日韩高清不卡 | 麻豆精品国产传媒 | 日本电影黄色 | 精品免费 | 丁香在线观看完整电影视频 | 成人黄色在线电影 | 天天色播| 久久电影中文字幕视频 | 久久视频精品在线观看 | 亚洲精品ww | 91超级碰碰 | 黄色www| 午夜精品久久久久久 | 91麻豆精品国产91久久久久 | 日韩av一区二区三区 | 九九热精品在线 | 亚洲开心色| 成年性视频 | 91豆花在线观看 | 三级av小说 | 久久激五月天综合精品 | 免费在线观看av不卡 | 久久国产区 | 国产精品久久久久久影院 | 日韩一级成人av | 欧美激情视频一二区 | 天天操天天拍 | 日日夜夜婷婷 | 日韩在线免费 | 婷婷av综合 | 欧美性久久久 | 色婷婷综合久色 | 久久久久久久久久国产精品 | 成人av影视 | 国产精品高潮呻吟久久av无 | 日韩网站一区 | 麻豆视频入口 | 亚洲国产精彩中文乱码av | 日日碰狠狠添天天爽超碰97久久 | 久久最新| 91麻豆精品一区二区三区 | 中文字幕免费在线 | 国产麻豆视频网站 | 亚洲最快最全在线视频 | 久草精品网 | 五月开心激情 | 美女网站一区 | 九精品 | 日韩毛片精品 | 国产视频精品久久 | 2021国产在线 | 中文字幕网站视频在线 | 91在线网址 | 国产精品一区二区在线 | 亚洲一区二区精品在线 | 免费看v片网站 | 91精品国产福利 | 99久久精品久久久久久清纯 | 国产一级一级国产 | 米奇四色影视 | 黄色毛片视频免费观看中文 | 天天操人 | 国产精品久久久久久久久久久久午夜 | 欧美日韩精品在线观看 | 综合色伊人 | 少妇搡bbbb搡bbb搡忠贞 | 日本aa在线 | 国产主播99 | 亚洲自拍偷拍色图 | 成片视频免费观看 | 黄色大片免费网站 | 日韩av在线资源 | 欧美狠狠操 | 国产一级精品绿帽视频 | 婷婷精品在线视频 | 最近更新好看的中文字幕 | 国产手机av | 国产精品精品国产婷婷这里av | 成人a级免费视频 | 69欧美视频| 中文字幕亚洲在线观看 | 成人影视免费看 | 久久久在线免费观看 | 久久国内精品视频 | 婷婷色综合网 | 91网免费看 | 亚洲精品2区 | 国产视频资源 | 日韩欧美xxxx| 久久五月天婷婷 | 91麻豆精品国产 | 久久天天躁狠狠躁亚洲综合公司 | 国产96av | 天天射天天做 | 精品一区二区影视 | 日韩免费二区 | 久久人人爽人人人人片 | 色中色亚洲 | 香蕉网站在线观看 | 黄色大全免费观看 | 免费精品国产 | 日本亚洲国产 | 69热国产视频 | 奇米网网址 | 99精品久久精品一区二区 | 久久婷婷精品视频 | 成人av在线亚洲 | 久久99精品国产91久久来源 | 国产亚洲精品成人av久久影院 | 久久久久免费电影 | 91av电影在线观看 | 四虎影视成人永久免费观看亚洲欧美 | 国产精品久久久久影视 | 国产精品亚洲综合久久 | 欧美巨乳波霸 | 韩国精品在线观看 | 国产九九九九九 | 国产乱老熟视频网88av | 黄色av一区二区 | a在线免费 | 午夜的福利 | 五月天丁香亚洲 | 欧美乱淫视频 | 国产视频精品在线 | 午夜少妇一区二区三区 | 天天插天天操天天干 | 久久99亚洲精品久久 | 成人在线免费av | 麻豆免费视频观看 | 九九九九精品 | 香蕉久草 | 欧美999| 超碰在线97免费 | 免费看色的网站 | 久久久91精品国产一区二区三区 | 欧美精品在线观看免费 | 欧美日韩精 | 国产精品久久久久久久久久久免费看 | 99久e精品热线免费 99国产精品久久久久久久久久 | 97人人澡人人添人人爽超碰 | 911在线 | 国产99久久精品 | 麻豆视频国产精品 | 国内精品久久久精品电影院 | 中文字幕在线成人 | 欧美日韩在线视频观看 | 亚洲aⅴ乱码精品成人区 | 91亚色视频在线观看 | 日韩午夜小视频 | 91激情视频在线 | 国产精品一区二区在线观看免费 | 日韩综合视频在线观看 | 精品色999 | 久久99深爱久久99精品 | 国产精品免费在线 | 成人啪啪18免费游戏链接 | 日本中文字幕一二区观 | 色小说在线 | 永久免费精品视频 | 91社区国产高清 | 天天av综合网| 久久久久久久久久久综合 | 日韩av在线网站 | 亚洲激情在线视频 | 日日爽 | 菠萝菠萝蜜在线播放 | 日韩欧美视频一区二区三区 | 玖玖玖在线观看 | 一级免费黄色 | 欧美日韩在线精品一区二区 | 青青河边草免费直播 | 四虎影视成人精品 | av噜噜噜在线播放 | 国产手机在线播放 | 国产美腿白丝袜足在线av | 久久激情视频网 | 一级黄色大片在线观看 | 亚洲视频 中文字幕 | 激情五月激情综合网 | 2023亚洲精品国偷拍自产在线 | 精品国产一区二区三区在线 | 中文字幕在线观看的网站 | 久av在线| 中文在线www | 99精品一级欧美片免费播放 | 欧美极品xxxx| 美女视频黄在线观看 | 美女露久久 | 在线观看www视频 | 黄色一级片视频 | 婷婷六月网 | 久久久在线免费观看 | 91精品网站在线观看 | 香蕉视频网址 | 国产成人精品一区二区三区在线观看 | 久久精品一区二区三区中文字幕 | 一区二区三区高清 | 成人亚洲精品国产www | 免费在线观看av电影 | 日韩欧在线 | 国产在线不卡视频 | 成人av电影在线 | 最新国产中文字幕 | 99情趣网视频| 亚洲精品免费在线观看 | 成人av电影免费在线播放 | 中文网丁香综合网 | 日韩在线一级 | 99久久99久久精品 | 亚洲免费在线观看视频 | 亚洲人成在 | 中文字幕在线日本 | 久久久久久久免费 | adn—256中文在线观看 | 色噜噜在线观看 | 国产亚洲婷婷 | 欧美a级成人淫片免费看 | 综合久久精品 | 日韩中文字幕免费看 | 精品国产1区2区 | 国产精品v欧美精品 | 国产美女在线精品免费观看 | 日韩精品一区二 | 色婷婷在线播放 | 精品国偷自产国产一区 | 激情久久伊人 | 九九热久久免费视频 | 国产免费黄色 | 久久电影国产免费久久电影 | 美女视频国产 | 91探花国产综合在线精品 | 久草精品视频在线播放 | 欧洲一区二区在线观看 | 天天天综合| 日韩亚洲欧美中文字幕 | 国内精品久久天天躁人人爽 | 久久久穴 | 欧美精品资源 | 天天做日日做天天爽视频免费 | 日日夜夜天天干 | av电影中文字幕在线观看 | 久久久久久久久久久综合 | 国产成人一区二区在线观看 | 九色免费视频 | 久久国产精品网站 | 亚洲尺码电影av久久 | 精品久久一级片 | 91成熟丰满女人少妇 | 国内视频在线 | 久久人人爽爽人人爽人人片av | 久久精品2 | 午夜精品视频福利 | 国产日韩在线视频 | 中文字幕日韩国产 | 欧美一区二区在线免费观看 | 日韩一区二区在线免费观看 | 成人播放器 | 中文字幕一区二区三区四区 | 久久久福利 | 国产精品一区二区三区观看 | 国产欧美日韩视频 | 久久综合久久久 | 国产精品嫩草影院9 | 国产精品国产三级在线专区 | 日韩毛片精品 | 狠狠的日日 | 久草在线免费色站 | 精品一区二区在线播放 | 免费高清在线视频一区· | 久久久久久久久久久影视 | 丁香婷婷深情五月亚洲 | 91九色蝌蚪视频 | 日韩精品一区二区三区免费观看视频 | 国产日本亚洲高清 | 亚洲男男gaygay无套同网址 | 婷婷丁香狠狠爱 | 国产专区精品 | 91免费高清视频 | 蜜臀av在线一区二区三区 | 亚洲精品国内 | 国模一二三区 | 中文字幕乱码日本亚洲一区二区 | 天天爱天天操天天射 | 色无五月 | 久久夜色精品国产欧美乱 | 国产精品aⅴ | 深夜免费小视频 | 欧美日韩国产一区二 | 国产黄色片久久 | 中文字幕欧美日韩va免费视频 | 久久在线免费观看 | 91精品视频在线免费观看 | 亚洲视频每日更新 | 国产一区电影在线观看 | 精品一区免费 | 麻豆国产精品一区二区三区 | 在线看片一区 | 区一区二在线 | www亚洲国产 | 奇米影音四色 | 亚洲精品国产成人 | 九九热在线精品 | 国产精品系列在线观看 | 黄色三级久久 | 成人av高清 | 又湿又紧又大又爽a视频国产 | 天天躁天天操 | 久久久久亚洲精品男人的天堂 | 免费人成网ww44kk44 | 久久精品视频网址 | 午夜私人影院 | 精品美女久久久久久免费 | 国产精品99久久久久久久久久久久 | 中文字幕第 | 国产精品毛片久久久久久久久久99999999 | 免费看久久久 | 色婷婷www| 亚洲欧美国产日韩在线观看 | 久久久男人的天堂 | 人人添人人澡人人澡人人人爽 | 人人干,人人爽 | 在线免费观看的av网站 | 亚洲综合五月天 | 麻豆 videos | 波多野结衣视频一区 | 精品999在线观看 | 亚洲涩涩网站 | 亚洲精品色婷婷 | 国产视频精品久久 | 国产精品免费久久久久影院仙踪林 | 久久在线看 | 天天玩天天操天天射 | 91日韩精品视频 | 日韩欧美一区二区在线播放 | 国产精品18久久久久久不卡孕妇 | 精品国产99 | 青青河边草免费视频 | 天天爱天天舔 | 丁香五月网久久综合 | 91精品免费| 五月综合婷 | 在线免费看片 | 一区二区不卡 | 中文字幕在线高清 | 中国老女人日b | 久久高清免费 | 欧美aaaxxxx做受视频 | 欧美作爱视频 | 精品美女在线视频 | 成人免费视频视频在线观看 免费 | 久久久www成人免费毛片 | 天天综合入口 | 在线观看中文字幕 | 婷婷激情综合 | 91粉色视频 | 在线观看你懂的网址 | 亚洲涩涩网| 在线导航av | 国产精品久久久久久久av大片 | 911免费视频 | 久久综合影视 | 亚洲理论在线观看电影 | 国产在线观看av | 亚洲综合爱| 九九综合久久 | 欧美人人| 美女黄频在线观看 | 97狠狠干 | 久久成人精品电影 | 高清不卡一区二区在线 | 六月丁香激情综合色啪小说 | 香蕉网在线播放 | 国产成人精品区 | 一区二区三区中文字幕在线 | 精品国产视频在线观看 | 又长又大又黑又粗欧美 | 在线免费黄 | 日本少妇久久久 | 国产精品久久9 | 日韩天天操 | 国产精品 999| 麻豆视频在线免费 | 日本久久视频 | 天天草夜夜 | 激情影院在线观看 | 色妞久久福利网 | av观看在线观看 | 日韩av免费一区二区 | 韩国av一区二区三区 | 99久久日韩精品视频免费在线观看 | se婷婷 | 国产成人黄色片 | 中文字幕在线观看视频一区二区三区 | 久久国产欧美日韩 | 亚洲狠狠干 | 91网在线观看 | 五月天色综合 | 亚洲欧洲一区二区在线观看 | 国产精品美女久久久久久久久 | 中文字幕资源在线 | 久久成年人 | 亚州精品成人 | 国产超碰在线观看 | 99久久久久久久 | 999精品 | 中文字幕制服丝袜av久久 | 久久综合射 | 精品国产伦一区二区三区观看方式 | 97福利社| 99久久精品免费看国产 | 香蕉视频啪啪 | 精品国产诱惑 | 日韩理论片在线 | 久久99久国产精品黄毛片入口 | 五月婷婷av | 色天天天| 精品极品在线 | 99热官网| 国产亚洲精品久久久网站好莱 | 91视频免费观看 | 五月天婷亚洲天综合网精品偷 | 亚洲精品国产欧美在线观看 | 久久精品免费 | 亚洲激情 欧美激情 | 中文字幕一区二区三区四区久久 | 国产精品精品国产色婷婷 | 久久成人国产精品 | 中文字幕日本在线 | 欧美久久久久久 | 国产亚洲午夜高清国产拍精品 | 99爱视频在线观看 | 网站在线观看日韩 | 91麻豆精品国产午夜天堂 | 色多多污污 | 蜜臀久久99精品久久久无需会员 | 日韩高清网站 | 久久久久久久久久久影视 | 成年人黄色免费视频 | 日本精品久久久久 | 怡红院成人在线 | 九九精品视频在线观看 | 青草视频在线看 | 欧美伊人网 | 日韩av不卡在线观看 | 热久久这里只有精品 | 韩国精品在线 | 插插插色综合 | 国产精品毛片一区视频播不卡 | 久久看毛片 | 狠狠色丁香婷婷综合久小说久 | 日韩成人免费观看 | 麻豆视频一区 | 欧美一区二区在线免费观看 | 中文字幕一区二区三区四区 | 色综合久 | 97精品国产97久久久久久春色 | 午夜影院先 | 欧美日韩在线视频一区 | 在线观看免费av网 | 国产精品美女免费看 | 日本超碰在线 | 精品国产伦一区二区三区观看体验 | 狠狠干激情 | 国产精品一区二区三区久久久 | 福利av影院| 欧美 激情 国产 91 在线 | 国产色在线观看 | 欧美一级专区免费大片 | 精品久操| 精品免费久久久久 | 久久国产精品免费 | 中文av网站 | 久久精品国产一区 | 一区二区久久 | 国产精品日韩欧美一区二区 | 黄色av电影一级片 | 中文字幕一区2区3区 | 国产精品久久一区二区无卡 | 激情五月播播久久久精品 | 九色91在线 | 欧美看片| 久久综合九色 | 色网站在线免费观看 | 美女免费电影 | 国产成人精品一区二区三区免费 | www成人精品 | 最近中文字幕 | 久久a免费视频 | 日本特黄一级片 | 一区视频在线 | 韩国三级av在线 | 麻豆国产视频 | 欧美在线18 | 久射网| 午夜黄色影院 | 久久精品日产第一区二区三区乱码 | 日韩久久精品一区二区 | 97视频免费观看 | 超碰97免费| 婷婷久久网 | av免费试看| 久久99亚洲精品久久 | 婷婷丁香五 | 亚洲一级在线观看 | 夜夜躁狠狠燥 | 天堂av影院| 欧美在线观看视频免费 | 999久久国精品免费观看网站 | 日韩亚洲在线视频 | 欧美91片| 亚洲视频 一区 | 一区二区中文字幕在线 | 久久久国产精品成人免费 | 免费久久精品视频 | 一级片视频在线 | 国产中文字幕免费 | 欧美99精品 | 在线免费看黄网站 | 香蕉网址 | 97视频资源 | 毛片视频网址 | 中文字幕在线观看视频一区 | 日本精品二区 | 中文字幕之中文字幕 | 亚洲国产无 | 国产成人av一区二区三区在线观看 | 丁香五婷 | 欧美日韩一区二区三区在线免费观看 | 国产亚洲精品xxoo | 国产精品第 | 久久成人午夜视频 | 久久99免费观看 | 国产人成在线视频 | 国产免费一区二区三区最新 | 日韩在线视频网 | 久草在线综合网 | 天天天在线综合网 | 欧美大jb | 国产精品成人在线观看 | 精品免费视频. | 免费在线播放黄色 | 亚洲精品视频在线观看免费视频 | 黄色免费看片网站 | 少妇视频一区 | 在线视频手机国产 | 综合色狠狠 | 久热免费在线 | 欧美精品一区二区免费 | 美女视频国产 | 国产成人免费观看 | 色婷婷综合久久久 | 免费av在 | 免费日韩 精品中文字幕视频在线 | 国产亚洲欧美精品久久久久久 | 国产91成人在在线播放 | 成人免费在线观看入口 | 公开超碰在线 | 五月天婷婷综合 | 国产在线高清精品 | 久久亚洲影院 | 亚洲伊人天堂 | 午夜av电影院 | 五月综合色| 久久久国产成人 | 91麻豆免费版 | 免费色婷婷 | 色资源二区在线视频 | 中文字幕色网站 | 天无日天天操天天干 | 91精品视频在线播放 | 久久婷婷综合激情 | 一区视频在线 | 国产无区一区二区三麻豆 | 香蕉视频色 | 精品亚洲视频在线 | 欧美国产日韩一区二区三区 | 伊人亚洲精品 | 久久这里只精品 | 国产男男gay做爰 | 久久精品欧美日韩精品 | 国产又黄又硬又爽 | 中文字幕亚洲情99在线 | 在线免费观看视频一区 | 国产91精品在线播放 | 网站免费黄色 | 日本精品视频在线观看 | 一区二区三区中文字幕在线 | 亚洲视频免费在线看 | 在线免费观看视频 | 九九热re | 中文字幕影片免费在线观看 | 五月天天av | 500部大龄熟乱视频 欧美日本三级 | 久久免费99| 亚洲无吗天堂 | 亚洲精品99久久久久中文字幕 | 国产成人精品免费在线观看 | 日韩精品一区二区三区免费观看视频 | 久久久亚洲国产精品麻豆综合天堂 | 久久国产免费看 | 国产精品2018 | 日韩a在线 | 日韩精品一区二区三区在线播放 | 免费av高清| 黄色免费视频在线观看 | 香蕉手机在线 |