深度學習模型交叉特征建模不理想违诗?試試DCNv2[論文筆記&源碼解讀]

論文介紹

DCN-v2優(yōu)化了DCN的cross layer漱凝,權(quán)重參數(shù)w由原來的vector變?yōu)榉疥噈atrix,增加了網(wǎng)絡層的表達能力较雕;同時碉哑,為了保證線上應用的耗時不會因為cross layer參數(shù)量的增加而增加挚币。觀察到cross layer的matrix具有低秩性亮蒋,使用矩陣分解,將方陣matrix轉(zhuǎn)換為兩個低維的矩陣妆毕、最后在低秩空間內(nèi)慎玖,利用MoE多專家系統(tǒng),對特征交叉做非線性變化笛粘,進一步增加對交叉特征的建模趁怔。vector -> matrix; moe

設想:DCNv2是不是可以結(jié)合多任務學習、MMoE架構(gòu)薪前,設計一個新的點擊率润努、轉(zhuǎn)換率模型。效果會不會很好呢示括?不過铺浇,這種方法對訓練樣本量可能要求比較高《庀ィ可以嘗試一下鳍侣。

構(gòu)建推薦系統(tǒng)的關鍵點在于學習有效的交叉特征。特征的交叉一般通過哈達瑪積來表示吼拥,比如x1表示性別倚聚,男、女凿可;x2表示是否喜歡體育惑折;x1&x2聯(lián)合特征太惠,會有4種取值。通過特征交叉婴梧,可以給模型帶來一定的非線性表示蔓倍。DCN在實際應用中,當處理十億級別的訓練數(shù)據(jù)樣本時敞咧,其Cross網(wǎng)絡部分在建模特征交叉時表達能力受限棘捣。盡管,交叉特征建模在學術上已經(jīng)提出了很多新的技術方法休建, 但在實際工程中乍恐,許多深度學習模型仍然是通過傳統(tǒng)的前饋神經(jīng)網(wǎng)絡來實現(xiàn)特征交叉建模。

通盤考慮DCN網(wǎng)絡的優(yōu)缺點以及交叉特征的建模方式测砂,這里提出了一種新模型架構(gòu)DCNv2:優(yōu)化DCN的Cross部分茵烈,豐富其對交叉特征的建模能力。

我們直接對比DCN砌些、DCNv2的網(wǎng)絡架構(gòu)呜投。、

dcn
DCN-v2

兩者的差別在于Cross網(wǎng)絡的建模方式存璃。

DCN Cross layer:


cross layer-vector

DCNv2 Cross layer:


cross layer-matrix

網(wǎng)絡層權(quán)重參數(shù)由原來的vector變?yōu)閙atrix仑荐。DCN網(wǎng)絡的cross layer的建模是element-wise;DCNv2 cross layer可以實現(xiàn)element-wise和feature-wise的特征交叉纵东。


待理解

我們先回歸一下DCN網(wǎng)絡模型粘招。DCN借鑒Google的Wide&Deep模型結(jié)構(gòu),Deep部分是一個N的MLP偎球,用于學習隱性高階交叉特征洒扎;Cross網(wǎng)絡通過顯性的交叉公式建模高階交叉特征。cross網(wǎng)絡的參數(shù)為兩個d維度的向量:w和b衰絮。通過公式優(yōu)化袍冷,可以簡化運算,不會影響模型的線上耗時猫牡。這是DCN網(wǎng)絡的優(yōu)點胡诗。

但是,DCN網(wǎng)絡的Cross網(wǎng)絡镊掖、Deep網(wǎng)絡的參數(shù)量不平衡乃戈,Deep部分的參數(shù)占據(jù)DCN總參數(shù)的絕大部分。


eg

舉例來說亩进,對于1層cross和1層deep的DCN網(wǎng)絡輸入經(jīng)過embedding和stack處理后維度為d症虑,Cross部分網(wǎng)絡參數(shù)為2d,Deep為d*d归薛,當MLP的層數(shù)增多時谍憔,deep部分的參數(shù)量也急速增加匪蝙。DCN網(wǎng)路的絕大部分參數(shù)都用于對隱性交叉特征進行建模。Cross部分的表達能力反而受限习贫。

DCN-v2優(yōu)化了cross網(wǎng)絡的建模方式逛球,增加了cross網(wǎng)絡部分的表達能力;deep部分保持不變苫昌。下面主要就Cross網(wǎng)絡進行詳細介紹颤绕。

cross layer-matrix

從原來的向量變?yōu)榫仃嚒S捎诰€上應用對模型的耗時祟身、資源占用要求很高奥务。原來的DCN的網(wǎng)絡正是由于Cross網(wǎng)絡既能對交叉特征進行顯性建模,而且對模型的耗時影響忽略不計袜硫。如果改進后的cross layer直接應用到線上氯葬,cross網(wǎng)絡雖然會增加模型的表達能力,但是cross部分的權(quán)重參數(shù)會給模型的耗時帶來影響婉陷。所以帚称,為了能進一步減少cross網(wǎng)絡的模型耗時,論文通過實驗發(fā)現(xiàn)了cross layer的權(quán)重參數(shù)具有低秩性秽澳。

低秩性

我們可以對cross layer的權(quán)重參數(shù)進行矩陣分解闯睹,將原來[d,d]的W方陣,分解為兩個矩陣U肝集,V瞻坝,[d,r], r << d. 這樣就可以實現(xiàn)cross layer的參數(shù)縮減蛛壳,同時也增加了cross網(wǎng)絡的表達能力杏瞻。

矩陣分解

通過上面的公式,我們可以發(fā)現(xiàn):

  1. cross在低維空間進行交叉特征的建模衙荐;
  2. 我們將輸入x從維度d映射到r捞挥,然后又映射會維度d。[d >> r].

低維空間的交叉特征建模使得我們可以利用MoE忧吟。MoE由兩部分組成:experts專家和gating門(一個關于輸入x的函數(shù))砌函。我們可以使用多個專家,每個專家學習不同的交叉特征溜族,最后通過gating將各個專家的學習結(jié)果整合起來讹俊,作為輸出。這樣就又能進一步增加對交叉特征的建模能力煌抒。

MoE
continue

同時仍劈,我們也可以對低緯映射空間中做更多的非線性變化,進一步增加模型的表達能力寡壮。

通過實驗發(fā)現(xiàn)贩疙,對比其他模型讹弯,DCN-v2表現(xiàn)更好。

image-20210101121920940
試驗結(jié)果

其他这溅,需要注意的是组民。論文提出,deep和cross的結(jié)合方式悲靴,選用并行or串行結(jié)構(gòu)臭胜,與訓練數(shù)據(jù)密切相關。不同的數(shù)據(jù)分布癞尚,應該選擇不同的處理方式庇楞,并行結(jié)構(gòu)并不是通用的。

源碼閱讀

Cross Layer

將DCN的Cross layer和不使用MoE結(jié)構(gòu)的cross layer否纬。兩者的區(qū)別在于交叉特征的建模方式吕晌,權(quán)重參數(shù)一個是向量,一個是矩陣临燃。

[圖片上傳失敗...(image-801292-1609475511103)]

DCN-v2
class CrossNet(nn.Module):
    """The Cross Network part of Deep&Cross Network model,
    which leans both low and high degree cross feature.
      Input shape
        - 2D tensor with shape: ``(batch_size, units)``.
      Output shape
        - 2D tensor with shape: ``(batch_size, units)``.
      Arguments
        - **in_features** :輸入特征維度
        - **input_feature_num**: Positive integer, shape(Input tensor)[-1]
        - **layer_num**: cross網(wǎng)絡的網(wǎng)絡層數(shù)
        - **parameterization**: "vector"  or "matrix" ,表示網(wǎng)絡層的建模方式
        - **l2_reg**: 正則系數(shù)
        - **seed**: 隨機種子
    """

    def __init__(self, in_features, layer_num=2, parameterization='vector', seed=1024, device='cpu'):
        super(CrossNet, self).__init__()
        self.layer_num = layer_num
        self.parameterization = parameterization
        # 參數(shù)聲明
        if self.parameterization == 'vector': # DCN
            # weight in DCN.  (in_features, 1)
            self.kernels = torch.nn.ParameterList([nn.Parameter(nn.init.xavier_normal_(torch.empty(in_features, 1))) for i in range(self.layer_num)])
        elif self.parameterization == 'matrix': # DCNv2
            # weight matrix in DCN-M.  (in_features, in_features)
            self.kernels = torch.nn.ParameterList([nn.Parameter(nn.init.xavier_normal_(torch.empty(in_features, in_features))) for i in range(self.layer_num)])
        else:  # error
            raise ValueError("parameterization should be 'vector' or 'matrix'")

        self.bias = torch.nn.ParameterList([nn.Parameter(nn.init.zeros_(torch.empty(in_features, 1))) for i in range(self.layer_num)])
        self.to(device)

    def forward(self, inputs):
        x_0 = inputs.unsqueeze(2)
        x_l = x_0
        for i in range(self.layer_num):
            if self.parameterization == 'vector':
            # x0 * (xl.T * w )+ b + xl
                xl_w = torch.tensordot(x_l, self.kernels[i], dims=([1], [0]))
                dot_ = torch.matmul(x_0, xl_w)
                x_l = dot_ + self.bias[i]
            elif self.parameterization == 'matrix':
            # x0 * (Wxl + bl) + xl
                dot_ = torch.matmul(self.kernels[i], x_l)  # W * xi  (bs, in_features, 1)
                dot_ = dot_ + self.bias[i]  # W * xi + b
                dot_ = x_0 * dot_  # x0 · (W * xi + b)  Hadamard-product
            else:  # error
                print("parameterization should be 'vector' or 'matrix'")
                pass
            x_l = dot_ + x_l
        x_l = torch.squeeze(x_l, dim=2)
        return x_l

Cross Network + MoE

公式

計算每個專家的輸出睛驳,然后通過gating將多個專家的輸出進行加權(quán)平均。

class CrossNetMix(nn.Module):
    """DCN-Mix:
      1 添加MoE膜廊,學習不同子空間內(nèi)的交叉特征
      2 在低維空間增加更多的非線性變換
      Input shape
        - 2D tensor with shape: ``(batch_size, units)``.
      Output shape
        - 2D tensor with shape: ``(batch_size, units)``.
      Arguments
        - **in_features** : 輸入特征維度
        - **low_rank** : 低維度空間的維度
        - **num_experts** : 專家數(shù)目.
        - **layer_num**: cross網(wǎng)路層數(shù)
        - **device**:"cpu" or "cuda:0"
    """

    def __init__(self, in_features, low_rank=32, num_experts=4, layer_num=2, device='cpu'):
        super(CrossNetMix, self).__init__()
        self.layer_num = layer_num
        self.num_experts = num_experts

        # 參數(shù)聲明
        # U: (in_features, low_rank)
        self.U_list = torch.nn.ParameterList([nn.Parameter(nn.init.xavier_normal_(
            torch.empty(num_experts, in_features, low_rank))) for i in range(self.layer_num)])
        # V: (in_features, low_rank)
        self.V_list = torch.nn.ParameterList([nn.Parameter(nn.init.xavier_normal_(
            torch.empty(num_experts, in_features, low_rank))) for i in range(self.layer_num)])
        # C: (low_rank, low_rank)
        self.C_list = torch.nn.ParameterList([nn.Parameter(nn.init.xavier_normal_(
            torch.empty(num_experts, low_rank, low_rank))) for i in range(self.layer_num)])
        self.gating = nn.ModuleList([nn.Linear(in_features, 1, bias=False) for i in range(self.num_experts)])

        self.bias = torch.nn.ParameterList([nn.Parameter(nn.init.zeros_(
            torch.empty(in_features, 1))) for i in range(self.layer_num)])
        self.to(device)

    def forward(self, inputs):
        x_0 = inputs.unsqueeze(2)  # (bs, in_features, 1)
        x_l = x_0
        for i in range(self.layer_num):# 逐個網(wǎng)絡層
            output_of_experts = []
            gating_score_of_experts = []
            for expert_id in range(self.num_experts): # 每個的若干個專家
                # 針對每個專家乏沸,計算gating score,output
                # (1) G(x_l)
                # 根據(jù)輸入計算gating值爪瓜,最后softmax計算權(quán)重系數(shù)
                gating_score_of_experts.append(self.gating[expert_id](x_l.squeeze(2)))
                # (2) E(x_l)
                # 計算每個專家的輸出
                # 2.1 將輸入映射到低維空間
                v_x = torch.matmul(self.V_list[i][expert_id].t(), x_l)  # (bs, low_rank, 1)

                # 2.2 在低維空間進行非線性變換
                v_x = torch.tanh(v_x)
                v_x = torch.matmul(self.C_list[i][expert_id], v_x)
                v_x = torch.tanh(v_x)

                # 2.3 從低維空間映射回高維度
                uv_x = torch.matmul(self.U_list[i][expert_id], v_x)  # (bs, in_features, 1)

                dot_ = uv_x + self.bias[i]
                # 哈達瑪積:逐元素乘法
                dot_ = x_0 * dot_  # Hadamard-product

                output_of_experts.append(dot_.squeeze(2))# [bs, d]

            # (3) 專家輸出結(jié)果加權(quán)平均蹬跃,得到這一層網(wǎng)絡的輸出內(nèi)容
            output_of_experts = torch.stack(output_of_experts, 2)  # (bs, in_features, num_experts)
            gating_score_of_experts = torch.stack(gating_score_of_experts, 1)  # (bs, num_experts, 1)
            moe_out = torch.matmul(output_of_experts, gating_score_of_experts.softmax(1))
            x_l = moe_out + x_l  # (bs, in_features, 1)

        x_l = x_l.squeeze()  # (bs, in_features)
        return x_l

進一步思考:將DCN-V2和MTL多任務學習結(jié)合起來效果會怎么樣呢?

后續(xù)打算铆铆,參考PyTorch實現(xiàn)蝶缀,寫一版TensorFlow版本的DCN-v2。

Reference

DCN-v2

pytoch實現(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末薄货,一起剝皮案震驚了整個濱河市翁都,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谅猾,老刑警劉巖柄慰,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異税娜,居然都是意外死亡坐搔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門敬矩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來概行,“玉大人,你說我怎么就攤上這事谤绳≌季猓” “怎么了袒哥?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長消略。 經(jīng)常有香客問我堡称,道長,這世上最難降的妖魔是什么艺演? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任却紧,我火速辦了婚禮,結(jié)果婚禮上胎撤,老公的妹妹穿的比我還像新娘晓殊。我一直安慰自己,他們只是感情好伤提,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布巫俺。 她就那樣靜靜地躺著,像睡著了一般肿男。 火紅的嫁衣襯著肌膚如雪介汹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天舶沛,我揣著相機與錄音嘹承,去河邊找鬼。 笑死如庭,一個胖子當著我的面吹牛叹卷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坪它,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼骤竹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哟楷?” 一聲冷哼從身側(cè)響起瘤载,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卖擅,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體墨技,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡惩阶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扣汪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片断楷。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖崭别,靈堂內(nèi)的尸體忽然破棺而出冬筒,到底是詐尸還是另有隱情恐锣,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布舞痰,位于F島的核電站土榴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏响牛。R本人自食惡果不足惜玷禽,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呀打。 院中可真熱鬧矢赁,春花似錦、人聲如沸贬丛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽豺憔。三九已至蜒蕾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間焕阿,已是汗流浹背咪啡。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暮屡,地道東北人撤摸。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像褒纲,于是被迫代替她去往敵國和親准夷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

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