<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【論文解讀】DeepFM論文總結(jié)

          共 10069字,需瀏覽 21分鐘

           ·

          2020-12-07 07:45

          本次要總結(jié)分享的是 推薦/CTR 領(lǐng)域內(nèi)著名的deepfm[1] 論文,參考的代碼tensorflow-DeepFM[2],該論文方法較為簡(jiǎn)單,實(shí)現(xiàn)起來也比較容易,該方法在工業(yè)界十分常用。

          「建議在非深色主題下閱讀本文,pc端閱讀點(diǎn)擊文末左下角“原文鏈接”,體驗(yàn)更佳」

          @

          • 論文動(dòng)機(jī)及創(chuàng)新點(diǎn)

          • 模型結(jié)構(gòu)

            • 輸入數(shù)據(jù)

            • FM 部分

            • Deep 部分

          • 代碼分析

            • 數(shù)據(jù)預(yù)處理

            • 定義 DeepFM 模型超參數(shù)

            • 構(gòu)圖

          • 總結(jié)


          論文動(dòng)機(jī)及創(chuàng)新點(diǎn)

          • 在 deepfm 提出之前,現(xiàn)有的模型很難很好的提取低階和高階的交互特征,或者需要足夠豐富的人工特征工程才能進(jìn)行。
          • 一些特性交互很容易理解,可以由專家(對(duì)業(yè)務(wù)邏輯很了解的人)設(shè)計(jì)。然而,大多數(shù)其他的特征交互都隱藏在數(shù)據(jù)中,難以識(shí)別先驗(yàn)信息(例如,經(jīng)典的關(guān)聯(lián)規(guī)則“尿布和啤酒”是從數(shù)據(jù)中挖掘出來的,而不是由專家發(fā)現(xiàn)),這只能通過機(jī)器學(xué)習(xí)自動(dòng)獲取。即使對(duì)于易于理解的交互特征,專家似乎也不太可能對(duì)它們進(jìn)行窮盡式的建模,尤其是當(dāng)特征數(shù)量很大的時(shí)候。
          ?

          所以對(duì)于許多數(shù)據(jù)挖掘類比賽,特征工程的工作量幾乎占到工作量的 95%以上,大部分甚至一些優(yōu)秀選手,首先一股腦的把所能想到的特征都使用上,然后根據(jù)效果做些適當(dāng)特征選擇。當(dāng)選取的特征效果的確很好時(shí),把構(gòu)建這些特征的思路包裝成某一個(gè)聽起來很高逼格的”方法論“。

          ?
          • 很容易想到,有沒有什么辦法,能讓模型能端到端的進(jìn)行特征學(xué)習(xí)呢?從而避免繁雜的人工特征工程過程。deepfm 論文里就是基于這一動(dòng)機(jī),將 fm 模型和 DNN 模型聯(lián)合起來進(jìn)行訓(xùn)練,其中 fm 模型可能捕捉到一些低階的交互特征,而 DNN 模型捕捉一些高階模型。該聯(lián)合模型可以進(jìn)行端到端的訓(xùn)練學(xué)習(xí)。
          • Deepfm 模型中的 Deep 部分和 fm 部分共享 embedding,極大減少了需要學(xué)習(xí)的參數(shù),使其訓(xùn)練過程很有效率。
          • 和以往的 CTR 模型相比,Deepfm 模型效果最好。

          模型結(jié)構(gòu)

          在這里插入圖片描述

          上圖為 DeepFM 的網(wǎng)絡(luò)結(jié)構(gòu)圖,由左邊的 FM 模型和右邊的 DNN 模型組成,兩個(gè)子模型共享下方的輸入 embedding。

          輸入數(shù)據(jù)

          假定有 個(gè)樣本,每個(gè)樣本由 組成,其中

          • 個(gè)特征組成,其中包含了 「類別」型特征 和 「數(shù)值」型特征組成,每個(gè)特征可理解為一個(gè)
          ?

          其中 類別 型特征可用 one-hot 編碼表示,數(shù)值型特征用其本身數(shù)值或者離散化在 one-hot 表示

          ?
          • 這里定義 表示特征個(gè)數(shù); 表示 (數(shù)值特征個(gè)數(shù)+類別特征「取值」個(gè)數(shù)); 表示
          ?

          類別特征 one-hot 后向量長(zhǎng)度即為取值個(gè)數(shù)

          ?

          FM 部分

          這里定義兩個(gè)參數(shù)矩陣

          • feature_bias:shape 為 的一階參數(shù)矩陣
          • feature_embeddings:shape 為 的二階參數(shù)矩陣
          • <> 表示內(nèi)積不得不說:這篇論文里面的網(wǎng)絡(luò)圖都畫的好丑

          上式中 第一項(xiàng) 表示提取一階特征,第二項(xiàng)表示提取二階交叉特征;每個(gè)樣本在類別型 特征上只有一個(gè)取值。

          • d 表示 ,第二項(xiàng)是在不同 field 之間做二階交叉特征計(jì)算。

          • 對(duì)于一階特征中的參數(shù) 表示從 feature_bias 參數(shù)矩陣中 lookup 得到一個(gè)參數(shù),樣本中每個(gè)特征都能得到一個(gè)對(duì)應(yīng)向量(長(zhǎng)度為 1)。

          • 二階特征中, 分別表示 的隱向量,可以從 feature_embeddings 參數(shù)矩陣中 lookup 得到(長(zhǎng)度為 k)。

            在這里插入圖片描述
          ?

          這里可以理解將數(shù)值特征也embedding成向量,一個(gè)數(shù)值特征只對(duì)應(yīng)一個(gè)embedding向量,而一個(gè)類別特征的不同取值則對(duì)應(yīng)不同向量,但向量長(zhǎng)度均為k,對(duì)應(yīng)論文里說:即使不同的field長(zhǎng)度不一樣(one-hot向量長(zhǎng)度不一樣),但是都能embedding成度相同的向量。

          ?

          二階交叉特征推導(dǎo):

          上式中, 表示 表示隱向量從 feature*embeddings (shape 為[feature_size,k]) 參數(shù)矩陣中 lookup 得到的參數(shù),那么對(duì)于第 個(gè) ,其得到的 shape 為 ,因此 表示 個(gè)分量,對(duì)于類別型特征, 非 0 即 1。

          由上面分析可知,每個(gè)輸入特征都有對(duì)應(yīng)的 參數(shù)向量對(duì)應(yīng)。

          Deep 部分

          這部分更容易理解了,就是個(gè) DNN 網(wǎng)絡(luò),模型輸入為上圖中的 Dense_Embeddings:

          注意:FM 與 Deep 部分共享輸入的 embedding feature,也就是他們共同影響 Dense_Embeddings。

          代碼分析

          這部分參考的是 tensorflow-DeepFM[3]

          數(shù)據(jù)預(yù)處理

          該部分對(duì)數(shù)據(jù)集中特征進(jìn)行了編號(hào),一個(gè)連續(xù)特征用一個(gè)編號(hào),類別特征不同取值用不同編號(hào)

          def?gen_feat_dict(self):
          ?????if?self.dfTrain?is?None:
          ?????????dfTrain?=?pd.read_csv(self.trainfile)
          ?????else:
          ?????????dfTrain?=?self.dfTrain
          ?????if?self.dfTest?is?None:
          ?????????dfTest?=?pd.read_csv(self.testfile)
          ?????else:
          ?????????dfTest?=?self.dfTest
          ?????df?=?pd.concat([dfTrain,?dfTest])
          ?????self.feat_dict?=?{}
          ?????tc?=?0
          ?????for?col?in?df.columns:
          ?????????if?col?in?self.ignore_cols:
          ?????????????continue
          ?????????if?col?in?self.numeric_cols:
          ?????????????#?map?to?a?single?index
          ?????????????self.feat_dict[col]?=?tc
          ?????????????tc?+=?1
          ?????????else:
          ?????????????us?=?df[col].unique()
          ?????????????self.feat_dict[col]?=?dict(zip(us,?range(tc,?len(us)+tc)))
          ?????????????tc?+=?len(us)
          ?????self.feat_dim?=?tc

          由上述代碼可以看出 feat_dim 就是我們前面定義的 feature_size

          ?def?parse(self,?infile=None,?df=None,?has_label=False):
          ?????assert?not?((infile?is?None)?and?(df?is?None)),?"infile?or?df?at?least?one?is?set"
          ?????assert?not?((infile?is?not?None)?and?(df?is?not?None)),?"only?one?can?be?set"
          ?????if?infile?is?None:
          ?????????dfi?=?df.copy()
          ?????else:
          ?????????dfi?=?pd.read_csv(infile)
          ?????if?has_label:
          ?????????y?=?dfi["target"].values.tolist()
          ?????????dfi.drop(["id",?"target"],?axis=1,?inplace=True)
          ?????else:
          ?????????ids?=?dfi["id"].values.tolist()
          ?????????dfi.drop(["id"],?axis=1,?inplace=True)
          ?????#?dfi?for?feature?index
          ?????#?dfv?for?feature?value?which?can?be?either?binary?(1/0)?or?float?(e.g.,?10.24)
          ?????dfv?=?dfi.copy()
          ?????for?col?in?dfi.columns:
          ?????????if?col?in?self.feat_dict.ignore_cols:
          ?????????????dfi.drop(col,?axis=1,?inplace=True)
          ?????????????dfv.drop(col,?axis=1,?inplace=True)
          ?????????????continue
          ?????????if?col?in?self.feat_dict.numeric_cols:
          ?????????????dfi[col]?=?self.feat_dict.feat_dict[col]
          ?????????else:
          ?????????????dfi[col]?=?dfi[col].map(self.feat_dict.feat_dict[col])
          ?????????????dfv[col]?=?1.

          ?????#?list?of?list?of?feature?indices?of?each?sample?in?the?dataset
          ?????Xi?=?dfi.values.tolist()
          ?????#?list?of?list?of?feature?values?of?each?sample?in?the?dataset
          ?????Xv?=?dfv.values.tolist()
          ?????if?has_label:
          ?????????return?Xi,?Xv,?y
          ?????else:
          ?????????return?Xi,?Xv,?ids

          由上面代碼可以看出:dfi 表示特征的編號(hào),對(duì)于一個(gè)類別特征,不同取值其編號(hào)不同;dfv 表示該特征值,對(duì)于數(shù)值型特征就是該值本身,類別特征全是 1(表示取到了該編號(hào)的類別值)。

          定義 DeepFM 模型超參數(shù)

          class?DeepFM(BaseEstimator,?TransformerMixin):
          ????def?__init__(self,?feature_size,?field_size,
          ?????????????????embedding_size=8,?dropout_fm=[1.0,?1.0],
          ?????????????????deep_layers=[32,?32],?dropout_deep=[0.5,?0.5,?0.5],
          ?????????????????deep_layers_activation=tf.nn.relu,
          ?????????????????epoch=10,?batch_size=256,
          ?????????????????learning_rate=0.001,?optimizer_type="adam",
          ?????????????????batch_norm=0,?batch_norm_decay=0.995,
          ?????????????????verbose=False,?random_seed=2016,
          ?????????????????use_fm=True,?use_deep=True,
          ?????????????????loss_type="logloss",?eval_metric=roc_auc_score,
          ?????????????????l2_reg=0.0,?greater_is_better=True)
          :

          ????????assert?(use_fm?or?use_deep)
          ????????assert?loss_type?in?["logloss",?"mse"],?\
          ????????????"loss_type?can?be?either?'logloss'?for?classification?task?or?'mse'?for?regression?task"

          ????????self.feature_size?=?feature_size????????#?M=數(shù)值型特征個(gè)數(shù)+類別型特征取值個(gè)數(shù),就是feat_dim
          ????????self.field_size?=?field_size????????????#?F=特征個(gè)數(shù)
          ????????self.embedding_size?=?embedding_size????#?K=embedding_size

          ????????self.dropout_fm?=?dropout_fm
          ????????self.deep_layers?=?deep_layers
          ????????self.dropout_deep?=?dropout_deep
          ????????self.deep_layers_activation?=?deep_layers_activation
          ????????self.use_fm?=?use_fm
          ????????self.use_deep?=?use_deep
          ????????self.l2_reg?=?l2_reg

          ????????self.epoch?=?epoch
          ????????self.batch_size?=?batch_size
          ????????self.learning_rate?=?learning_rate
          ????????self.optimizer_type?=?optimizer_type

          ????????self.batch_norm?=?batch_norm
          ????????self.batch_norm_decay?=?batch_norm_decay

          ????????self.verbose?=?verbose
          ????????self.random_seed?=?random_seed
          ????????self.loss_type?=?loss_type
          ????????self.eval_metric?=?eval_metric
          ????????self.greater_is_better?=?greater_is_better
          ????????self.train_result,?self.valid_result?=?[],?[]

          ????????self._init_graph()

          構(gòu)圖

          feature_bias:shape 為 的一階參數(shù)矩陣 feature_embeddings:shape 為 的二階參數(shù)矩陣

          def?_init_graph(self):
          ????self.graph?=?tf.Graph()
          ????with?self.graph.as_default():

          ????????tf.set_random_seed(self.random_seed)

          ????????self.feat_index?=?tf.placeholder(tf.int32,?shape=[None,?None],
          ?????????????????????????????????????????????name="feat_index")??#?None?*?F
          ????????self.feat_value?=?tf.placeholder(tf.float32,?shape=[None,?None],
          ?????????????????????????????????????????????name="feat_value")??#?None?*?F
          ????????self.label?=?tf.placeholder(tf.float32,?shape=[None,?1],?name="label")??#?None?*?1
          ????????self.dropout_keep_fm?=?tf.placeholder(tf.float32,?shape=[None],?name="dropout_keep_fm")
          ????????self.dropout_keep_deep?=?tf.placeholder(tf.float32,?shape=[None],?name="dropout_keep_deep")
          ????????self.train_phase?=?tf.placeholder(tf.bool,?name="train_phase")

          ????????self.weights?=?self._initialize_weights()

          ????????#?model
          ????????self.embeddings?=?tf.nn.embedding_lookup(self.weights["feature_embeddings"],
          ?????????????????????????????????????????????????????????self.feat_index)??#?None?*?F?*?K
          ????????feat_value?=?tf.reshape(self.feat_value,?shape=[-1,?self.field_size,?1])
          ????????self.embeddings?=?tf.multiply(self.embeddings,?feat_value)?##?供下面的FM和Deep部分使用

          ????????#?----------?first?order?term?----------
          ????????self.y_first_order?=?tf.nn.embedding_lookup(self.weights["feature_bias"],?self.feat_index)?#?None?*?F?*?1
          ????????self.y_first_order?=?tf.reduce_sum(tf.multiply(self.y_first_order,?feat_value),?2)??#?None?*?F
          ????????self.y_first_order?=?tf.nn.dropout(self.y_first_order,?self.dropout_keep_fm[0])?#?None?*?F

          ????????#?----------?second?order?term?---------------
          ????????#?sum_square?part
          ????????self.summed_features_emb?=?tf.reduce_sum(self.embeddings,?1)??#?None?*?K
          ????????self.summed_features_emb_square?=?tf.square(self.summed_features_emb)??#?None?*?K

          ????????#?square_sum?part
          ????????self.squared_features_emb?=?tf.square(self.embeddings)
          ????????self.squared_sum_features_emb?=?tf.reduce_sum(self.squared_features_emb,?1)??#?None?*?K

          ????????#?second?order
          ????????self.y_second_order?=?0.5?*?tf.subtract(self.summed_features_emb_square,?self.squared_sum_features_emb)??#?None?*?K
          ????????self.y_second_order?=?tf.nn.dropout(self.y_second_order,?self.dropout_keep_fm[1])??#?None?*?K

          ????????#?----------?Deep?component?----------
          ????????self.y_deep?=?tf.reshape(self.embeddings,?shape=[-1,?self.field_size?*?self.embedding_size])?#?None?*?(F*K)
          ????????self.y_deep?=?tf.nn.dropout(self.y_deep,?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["layer_%d"?%i]),?self.weights["bias_%d"%i])?#?None?*?layer[i]?*?1
          ????????????if?self.batch_norm:
          ????????????????self.y_deep?=?self.batch_norm_layer(self.y_deep,?train_phase=self.train_phase,?scope_bn="bn_%d"?%i)?#?None?*?layer[i]?*?1
          ????????????self.y_deep?=?self.deep_layers_activation(self.y_deep)
          ????????????self.y_deep?=?tf.nn.dropout(self.y_deep,?self.dropout_keep_deep[1+i])?#?dropout?at?each?Deep?layer

          ????????#?----------?DeepFM?----------
          ????????if?self.use_fm?and?self.use_deep:
          ????????????concat_input?=?tf.concat([self.y_first_order,?self.y_second_order,?self.y_deep],?axis=1)
          ????????elif?self.use_fm:
          ????????????concat_input?=?tf.concat([self.y_first_order,?self.y_second_order],?axis=1)
          ????????elif?self.use_deep:
          ????????????concat_input?=?self.y_deep
          ????????self.out?=?tf.add(tf.matmul(concat_input,?self.weights["concat_projection"]),?self.weights["concat_bias"])

          這里需要注意:本實(shí)現(xiàn)代碼中,「也對(duì)連續(xù)特征也直接做了 embedding」,用的時(shí)候也可以把連續(xù)特征改為 deep 側(cè)的直接輸入,另外針對(duì)多值離散特征這里也沒有處理。

          總結(jié)

          • 該方法將 FM(捕捉低級(jí)特征)和 Deep(捕捉高級(jí)特征)進(jìn)行端到端的聯(lián)合訓(xùn)練,并且共享輸入 embedding,這是現(xiàn)在非常常見的做法。
          • 論文講到該方法可以一定程度避免人工特征工程,從模型看的確做到了無(wú)腦交叉,模型自動(dòng)學(xué)習(xí)各種交叉的權(quán)重。

          Reference

          [1]

          deepfm: https://arxiv.org/abs/1703.04247

          [2]

          tensorflow-DeepFM: https://github.com/ChenglongChen/tensorflow-DeepFM

          [3]

          tensorflow-DeepFM: https://github.com/ChenglongChen/tensorflow-DeepFM

          往期精彩回顧





          獲取本站知識(shí)星球優(yōu)惠券,復(fù)制鏈接直接打開:

          https://t.zsxq.com/qFiUFMV

          本站qq群704220115。

          加入微信群請(qǐng)掃碼:

          瀏覽 34
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲AV成人无码精品区 | 欧美操妣免费看 | 波多野结衣中文视频 | 99re6热在线精品视频播放 | 天天躁日日躁狠狠躁av |