推薦系統(tǒng)遇上深度學(xué)習(xí)(五)--Deep&Cross Network模型理論和實(shí)踐

推薦系統(tǒng)遇上深度學(xué)習(xí)系列:
推薦系統(tǒng)遇上深度學(xué)習(xí)(一)--FM模型理論和實(shí)踐:http://www.reibang.com/p/152ae633fb00
推薦系統(tǒng)遇上深度學(xué)習(xí)(二)--FFM模型理論和實(shí)踐:http://www.reibang.com/p/781cde3d5f3d
推薦系統(tǒng)遇上深度學(xué)習(xí)(三)--DeepFM模型理論和實(shí)踐:
http://www.reibang.com/p/6f1c2643d31b
推薦系統(tǒng)遇上深度學(xué)習(xí)(四)--多值離散特征的embedding解決方案:http://www.reibang.com/p/4a7525c018b2

1一睁、原理

Deep&Cross Network模型我們下面將簡(jiǎn)稱(chēng)DCN模型:

一個(gè)DCN模型從嵌入和堆積層開(kāi)始,接著是一個(gè)交叉網(wǎng)絡(luò)和一個(gè)與之平行的深度網(wǎng)絡(luò)逾礁,之后是最后的組合層颜武,它結(jié)合了兩個(gè)網(wǎng)絡(luò)的輸出邑退。完整的網(wǎng)絡(luò)模型如圖:

嵌入和堆疊層
我們考慮具有離散和連續(xù)特征的輸入數(shù)據(jù)。在網(wǎng)絡(luò)規(guī)模推薦系統(tǒng)中,如CTR預(yù)測(cè)仍源,輸入主要是分類(lèi)特征,如“country=usa”舔涎。這些特征通常是編碼為獨(dú)熱向量如“[ 0,1,0 ]”笼踩;然而,這往往導(dǎo)致過(guò)度的高維特征空間大的詞匯亡嫌。

為了減少維數(shù)嚎于,我們采用嵌入過(guò)程將這些離散特征轉(zhuǎn)換成實(shí)數(shù)值的稠密向量(通常稱(chēng)為嵌入向量):

然后掘而,我們將嵌入向量與連續(xù)特征向量疊加起來(lái)形成一個(gè)向量:

拼接起來(lái)的向量X0將作為我們Cross Network和Deep Network的輸入

Cross Network
交叉網(wǎng)絡(luò)的核心思想是以有效的方式應(yīng)用顯式特征交叉。交叉網(wǎng)絡(luò)由交叉層組成于购,每個(gè)層具有以下公式:

一個(gè)交叉層的可視化如圖所示:

可以看到袍睡,交叉網(wǎng)絡(luò)的特殊結(jié)構(gòu)使交叉特征的程度隨著層深度的增加而增大。多項(xiàng)式的最高程度(就輸入X0而言)為L(zhǎng)層交叉網(wǎng)絡(luò)L + 1肋僧。如果用Lc表示交叉層數(shù)女蜈,d表示輸入維度。然后色瘩,參數(shù)的數(shù)量參與跨網(wǎng)絡(luò)參數(shù)為:d * Lc * 2 (w和b)

交叉網(wǎng)絡(luò)的少數(shù)參數(shù)限制了模型容量伪窖。為了捕捉高度非線(xiàn)性的相互作用,模型并行地引入了一個(gè)深度網(wǎng)絡(luò)居兆。

Deep Network

深度網(wǎng)絡(luò)就是一個(gè)全連接的前饋神經(jīng)網(wǎng)絡(luò)覆山,每個(gè)深度層具有如下公式:

Combination Layer

鏈接層將兩個(gè)并行網(wǎng)絡(luò)的輸出連接起來(lái),經(jīng)過(guò)一層全鏈接層得到輸出:

如果采用的是對(duì)數(shù)損失函數(shù)泥栖,那么損失函數(shù)形式如下:

總結(jié)
DCN能夠有效地捕獲有限度的有效特征的相互作用簇宽,學(xué)會(huì)高度非線(xiàn)性的相互作用,不需要人工特征工程或遍歷搜索吧享,并具有較低的計(jì)算成本魏割。
論文的主要貢獻(xiàn)包括:

1)提出了一種新的交叉網(wǎng)絡(luò),在每個(gè)層上明確地應(yīng)用特征交叉钢颂,有效地學(xué)習(xí)有界度的預(yù)測(cè)交叉特征钞它,并且不需要手工特征工程或窮舉搜索。
2)跨網(wǎng)絡(luò)簡(jiǎn)單而有效殊鞭。通過(guò)設(shè)計(jì)遭垛,各層的多項(xiàng)式級(jí)數(shù)最高,并由層深度決定操灿。網(wǎng)絡(luò)由所有的交叉項(xiàng)組成锯仪,它們的系數(shù)各不相同。
3)跨網(wǎng)絡(luò)內(nèi)存高效趾盐,易于實(shí)現(xiàn)庶喜。
4)實(shí)驗(yàn)結(jié)果表明,交叉網(wǎng)絡(luò)(DCN)在LogLoss上與DNN相比少了近一個(gè)量級(jí)的參數(shù)量救鲤。

這個(gè)是從論文中翻譯過(guò)來(lái)的久窟,哈哈。

2蜒简、實(shí)現(xiàn)解析

本文的代碼根據(jù)之前DeepFM的代碼進(jìn)行改進(jìn)瘸羡,我們只介紹模型的實(shí)現(xiàn)部分,其他數(shù)據(jù)處理的細(xì)節(jié)大家可以參考我的github上的代碼:
https://github.com/princewen/tensorflow_practice/tree/master/Basic-DCN-Demo

數(shù)據(jù)下載地址:https://www.kaggle.com/c/porto-seguro-safe-driver-prediction

不去下載也沒(méi)關(guān)系搓茬,我在github上保留了幾千行的數(shù)據(jù)用作模型測(cè)試犹赖。

模型輸入

模型輸入

模型的輸入主要有下面幾個(gè)部分:

self.feat_index = tf.placeholder(tf.int32,
                                 shape=[None,None],
                                 name='feat_index')
self.feat_value = tf.placeholder(tf.float32,
                               shape=[None,None],
                               name='feat_value')

self.numeric_value = tf.placeholder(tf.float32,[None,None],name='num_value')

self.label = tf.placeholder(tf.float32,shape=[None,1],name='label')
self.dropout_keep_deep = tf.placeholder(tf.float32,shape=[None],name='dropout_deep_deep')

可以看到队他,這里與DeepFM相比,一個(gè)明顯的變化是將離散特征和連續(xù)特征分開(kāi)峻村,連續(xù)特征不在轉(zhuǎn)換成embedding進(jìn)行輸入麸折,所以我們的輸入共有五部分。
feat_index是離散特征的一個(gè)序號(hào)粘昨,主要用于通過(guò)embedding_lookup選擇我們的embedding垢啼。feat_value是對(duì)應(yīng)離散特征的特征值。numeric_value是我們的連續(xù)特征值张肾。label是實(shí)際值芭析。還定義了兩個(gè)dropout來(lái)防止過(guò)擬合。

權(quán)重構(gòu)建

權(quán)重主要包含四部分吞瞪,embedding層的權(quán)重馁启,cross network中的權(quán)重,deep network中的權(quán)重以及最后鏈接層的權(quán)重芍秆,我們使用一個(gè)字典來(lái)表示:

def _initialize_weights(self):
weights = dict()

#embeddings
weights['feature_embeddings'] = tf.Variable(
    tf.random_normal([self.cate_feature_size,self.embedding_size],0.0,0.01),
    name='feature_embeddings')
weights['feature_bias'] = tf.Variable(tf.random_normal([self.cate_feature_size,1],0.0,1.0),name='feature_bias')


#deep layers
num_layer = len(self.deep_layers)
glorot = np.sqrt(2.0/(self.total_size + self.deep_layers[0]))

weights['deep_layer_0'] = tf.Variable(
    np.random.normal(loc=0,scale=glorot,size=(self.total_size,self.deep_layers[0])),dtype=np.float32
)
weights['deep_bias_0'] = tf.Variable(
    np.random.normal(loc=0,scale=glorot,size=(1,self.deep_layers[0])),dtype=np.float32
)


for i in range(1,num_layer):
    glorot = np.sqrt(2.0 / (self.deep_layers[i - 1] + self.deep_layers[I]))
    weights["deep_layer_%d" % i] = tf.Variable(
        np.random.normal(loc=0, scale=glorot, size=(self.deep_layers[i - 1], self.deep_layers[i])),
        dtype=np.float32)  # layers[i-1] * layers[I]
    weights["deep_bias_%d" % i] = tf.Variable(
        np.random.normal(loc=0, scale=glorot, size=(1, self.deep_layers[i])),
        dtype=np.float32)  # 1 * layer[I]

for i in range(self.cross_layer_num):

    weights["cross_layer_%d" % i] = tf.Variable(
        np.random.normal(loc=0, scale=glorot, size=(self.total_size,1)),
        dtype=np.float32)
    weights["cross_bias_%d" % i] = tf.Variable(
        np.random.normal(loc=0, scale=glorot, size=(self.total_size,1)),
        dtype=np.float32)  # 1 * layer[I]

# final concat projection layer

input_size = self.total_size + self.deep_layers[-1]

glorot = np.sqrt(2.0/(input_size + 1))
weights['concat_projection'] = tf.Variable(np.random.normal(loc=0,scale=glorot,size=(input_size,1)),dtype=np.float32)
weights['concat_bias'] = tf.Variable(tf.constant(0.01),dtype=np.float32)

return weights

計(jì)算網(wǎng)絡(luò)輸入
這一塊我們要計(jì)算兩個(gè)并行網(wǎng)絡(luò)的輸入X0惯疙,我們需要將離散特征轉(zhuǎn)換成embedding,同時(shí)拼接上連續(xù)特征:

# model
self.embeddings = tf.nn.embedding_lookup(self.weights['feature_embeddings'],self.feat_index) # N * F * K
feat_value = tf.reshape(self.feat_value,shape=[-1,self.field_size,1])
self.embeddings = tf.multiply(self.embeddings,feat_value)

self.x0 = tf.concat([self.numeric_value,
                     tf.reshape(self.embeddings,shape=[-1,self.field_size * self.embedding_size])]
                    ,axis=1)

Cross Network
根據(jù)論文中的計(jì)算公式妖啥,一步步計(jì)算得到cross network的輸出:

# cross_part
self._x0 = tf.reshape(self.x0, (-1, self.total_size, 1))
x_l = self._x0
for l in range(self.cross_layer_num):
    x_l = tf.tensordot(tf.matmul(self._x0, x_l, transpose_b=True),
                        self.weights["cross_layer_%d" % l],1) + self.weights["cross_bias_%d" % l] + x_l

self.cross_network_out = tf.reshape(x_l, (-1, self.total_size))

Deep Network
這一塊就是一個(gè)多層全鏈接神經(jīng)網(wǎng)絡(luò):

self.y_deep = tf.nn.dropout(self.x0,self.dropout_keep_deep[0])

for i in range(0,len(self.deep_layers)):
    self.y_deep = tf.add(tf.matmul(self.y_deep,self.weights["deep_layer_%d" %i]), self.weights["deep_bias_%d"%I])
    self.y_deep = self.deep_layers_activation(self.y_deep)
    self.y_deep = tf.nn.dropout(self.y_deep,self.dropout_keep_deep[i+1])

Combination Layer
最后將兩個(gè)網(wǎng)絡(luò)的輸出拼接起來(lái)霉颠,經(jīng)過(guò)一層全鏈接得到最終的輸出:

# concat_part
concat_input = tf.concat([self.cross_network_out, self.y_deep], axis=1)

self.out = tf.add(tf.matmul(concat_input,self.weights['concat_projection']),self.weights['concat_bias'])

定義損失
這里我們可以選擇logloss或者mse,并加上L2正則項(xiàng):

# loss
if self.loss_type == "logloss":
    self.out = tf.nn.sigmoid(self.out)
    self.loss = tf.losses.log_loss(self.label, self.out)
elif self.loss_type == "mse":
    self.loss = tf.nn.l2_loss(tf.subtract(self.label, self.out))
# l2 regularization on weights
if self.l2_reg > 0:
    self.loss += tf.contrib.layers.l2_regularizer(
        self.l2_reg)(self.weights["concat_projection"])
    for i in range(len(self.deep_layers)):
        self.loss += tf.contrib.layers.l2_regularizer(
            self.l2_reg)(self.weights["deep_layer_%d" % I])
    for i in range(self.cross_layer_num):
        self.loss += tf.contrib.layers.l2_regularizer(
            self.l2_reg)(self.weights["cross_layer_%d" % I])

剩下的代碼就不介紹啦荆虱!

好啦蒿偎,本文只是提供一個(gè)引子,有關(guān)DCN的知識(shí)大家可以更多的進(jìn)行學(xué)習(xí)呦克伊。

參考文章:

1酥郭、https://blog.csdn.net/roguesir/article/details/79763204
2、論文:https://arxiv.org/abs/1708.05123

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愿吹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子惜姐,更是在濱河造成了極大的恐慌犁跪,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歹袁,死亡現(xiàn)場(chǎng)離奇詭異坷衍,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)条舔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)枫耳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人孟抗,你說(shuō)我怎么就攤上這事迁杨∽晷模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵铅协,是天一觀(guān)的道長(zhǎng)捷沸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)狐史,這世上最難降的妖魔是什么痒给? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮骏全,結(jié)果婚禮上苍柏,老公的妹妹穿的比我還像新娘。我一直安慰自己姜贡,他們只是感情好试吁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著鲁豪,像睡著了一般潘悼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爬橡,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天治唤,我揣著相機(jī)與錄音,去河邊找鬼糙申。 笑死宾添,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的柜裸。 我是一名探鬼主播缕陕,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼疙挺!你這毒婦竟也來(lái)了扛邑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铐然,失蹤者是張志新(化名)和其女友劉穎蔬崩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體搀暑,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沥阳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了自点。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桐罕。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出功炮,到底是詐尸還是另有隱情溅潜,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布死宣,位于F島的核電站伟恶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏毅该。R本人自食惡果不足惜博秫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望眶掌。 院中可真熱鬧挡育,春花似錦、人聲如沸朴爬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)召噩。三九已至母赵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間具滴,已是汗流浹背凹嘲。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留构韵,地道東北人周蹭。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像疲恢,于是被迫代替她去往敵國(guó)和親凶朗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容