日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

SDNE: 阿里应用深度学习进行图嵌入,构造凑单算法模型

發布時間:2023/12/19 pytorch 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SDNE: 阿里应用深度学习进行图嵌入,构造凑单算法模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文介紹 Structural Deep Network Embedding ,以下簡稱 SDNE,以半監督的方式用深度神經網絡來做圖嵌入。

模型解讀

論文指出學習網絡表示具有三大難點:

  • 高度非線性:網絡結構是高度非線性的,使用淺層網絡無法捕捉高度非線性的網絡結構。
  • 結構捕捉:同時捕捉到局部結構與全局結構。
  • 稀疏性:大部分真實的網絡都是稀疏的,僅僅利用網絡中的部分連接關系建模效果還不夠好。
  • SDNE 的目標是設計一個可以學習到一階相似度與二階相似度的模型。一階相似度與二階相似度的概念與之前博客【圖嵌入】Graph Embedding 方法之 LINE 原理解讀中描述的相同:

    • 一階相似度:描述邊相連的節點對之間具有的相似性。
    • 二階相似度:擁有共同鄰居但是不直接向相連的兩個節點具有的相似性。

    也就是說一階相似度主要反映了 Graph 的局部特征, 二階相似度反映了 Graph 的全局特征。

    為此,作者設計的模型如下圖所示:

    二階相似度學習(無監督學習部分)

    先看圖中的左半部分:

    其輸入是 xix_ixi? 輸出是 x^i\hat x_ix^i? ,這實際上是一種自編碼器,其目標是學習一種函數映射:
    f(x)≈xf(x) \approx x f(x)x
    自編碼器沒有標簽數據,所以是一種非監督學習,前半部分為編碼器,后半部分為解碼器。在實際應用中通常會使用自編碼器的前半部分,即輸入 xix_ixi? 到得到 yi(K)y_i^{(K)}yi(K)? 的部分,此部分的公式為:
    yi(1)=σ(W(1)xi+b(1))yi(k)=σ(W(k)yi(k?1)+b(k)),k=2,...,Ky_i^{(1)}=\sigma{(W^{(1)}x_i+b^{(1)})} \\ y_i^{(k)}=\sigma{(W^{(k)}y_i^{(k-1)}+b^{(k)})}, k=2,...,K yi(1)?=σ(W(1)xi?+b(1))yi(k)?=σ(W(k)yi(k?1)?+b(k)),k=2,...,K
    其中,xix_ixi? 為輸入值,本質是節點 iii 的鄰接矩陣(后面會解釋)。上面公式中的 yi(k)y_i^{(k)}yi(k)? 為第 kkk 層的第 iii 個節點的輸出值,而 W(k)W^{(k)}W(k) 為第 k 層的參數矩陣,bkb^{k}bk 為第 k 層的偏置項。最終經過編碼得到節點的 Embedding 向量 yi(K)y_i^{(K)}yi(K)?之后,再經過與編碼器對稱的網絡結構得到輸出值 x^i\hat x_ix^i? 。

    自編碼器的目標是最小化輸入與輸出的重構誤差,所以損失函數為:
    L=∑i=1n∣∣xi^?xi∣∣22\mathcal{L}=\sum_{i=1}^n{||\hat{x_i}-x_i||^2_2} L=i=1n?xi?^??xi?22?
    這里存在的一個問題是由于圖的稀疏性,鄰接矩陣S中的非零元素是遠遠少于零元素的,那么對于神經網絡來說只要全部輸出0也能取得一個不錯的效果,這不是我們想要的。文章給出的一個方法是使用帶權損失函數,對于非零元素具有更高的懲罰系數:
    L2nd=∑i=1n∣∣(xi^?xi)⊙bi∣∣22\mathcal{L_{2nd}}=\sum_{i=1}^n||(\hat{x_i}-x_i)\odot{b_i}||^2_2 L2nd?=i=1n?(xi?^??xi?)bi?22?
    公式中 ⊙\odot 為哈馬達乘積,表示對應位置元素相乘。bi={bi,j}j=1nb_i=\{b_{i,j}\}^n_{j=1}bi?={bi,j?}j=1n?,鄰接矩陣中的 0 元素對應 b=1b=1b=1,非 0 元素的 b>1b>1b>1,這意味著如果將非 0 元素預測錯了,將面臨更大的懲罰。

    講到這還有個問題,輸入的數據 xix_ixi? 到底是什么?假設用 S 表示鄰接矩陣集合:
    S={s1,s2,...,sn}si={sij}j=1n,sij>0S = \{ s_1, s_2,...,s_n \} \\ s_i = \{ s_{ij}\}^n_{j=1}, s_{ij}>0 S={s1?,s2?,...,sn?}si?={sij?}j=1n?,sij?>0
    其中,n 表示節點的個數,sis_isi? 表示 {si1,si2,...,sin}\{s_{i1},s_{i2},...,s_{in} \}{si1?,si2?,...,sin?} 中與節點 iii 相鄰的節點的邊的集合。令最終輸入的 xi=six_i = s_ixi?=si?,則輸入每一個 xix_ixi? 都包含了頂點 iii 的鄰居結構信息。因此結構相似的頂點可以學習到相似的 embedding 向量,不斷優化代價函數來捕捉全局結構特征,即二階相似度。

    一階相似度學習(有監督部分)

    一開始文章提到 SDNE 是半監督學習模型,那么監督學習的部分體現在何處?再來觀察整個網絡的結構:

    模型的兩側的輸入了有邊相連的節點 i,ji, ji,j 的信息可以學習全局特征,但是這還不夠,相連的兩個節點具有一階相似性,即節點 i,ji, ji,j 應該有相似的向量表示。于是借用拉普拉斯特征映射的思想(在圖中相連的點,在降維后的空間中盡可能的靠近。 ),定義如下損失函數:
    L1st=∑i,j=1nsi,j∣∣yi(K)?yj(K)∣∣22=∑i.j=1nsi,j∣∣yi?yj∣∣22\begin{aligned} \mathcal{L_{1st}}&=\sum_{i,j=1}^n{s_{i,j}||y_i^{(K)}-y_j^{(K)}||^2_2}\\ &=\sum_{i.j=1}^n{s_{i,j}||y_i-y_j||^2_2} \end{aligned} L1st??=i,j=1n?si,j?yi(K)??yj(K)?22?=i.j=1n?si,j?yi??yj?22??

    該損失函數可以利用邊的約束作用使得相鄰頂點保持一階相似度,當相似的頂點在嵌入空間中映射得很遠時,就會產生懲罰。

    補充:

    論文對這個損失函數進行了進一步的變換,根據拉普拉斯矩陣的性質有(參考:拉普拉斯矩陣,譜聚類方法推導和對拉普拉斯矩陣的理解):
    L1st=∑i.j=1nsi,j∣∣yi?yj∣∣22=2tr(YTLY)\begin{aligned} \mathcal{L_{1st}}&=\sum_{i.j=1}^n{s_{i,j}||y_i-y_j||^2_2} \\ &=2tr(Y^TLY) \end{aligned} L1st??=i.j=1n?si,j?yi??yj?22?=2tr(YTLY)?

    L=D?SL = D - S L=D?S

    其中,Y 表示節點的 embedding 向量,L為拉普拉斯矩陣,D是節點的度,S是鄰接矩陣。

    最終整個模型的的損失函數定義如下:
    Lmix=L2nd+αL1st+νLreg=∑i=1n∣∣(xi^?xi)⊙bi∣∣22+α∑i.j=1nsi,j∣∣yi?yj∣∣22+νLreg\begin{aligned} \mathcal{L_{mix}}&=\mathcal{L_{2nd}+\alpha{\mathcal{L_{1st}}}}+\nu{\mathcal{L_{reg}}} \\ &=\sum_{i=1}^n||(\hat{x_i}-x_i)\odot{b_i}||^2_2+\alpha{\sum_{i.j=1}^n{s_{i,j}||y_i-y_j||^2_2}}+\nu{\mathcal{L_{reg}}} \end{aligned} Lmix??=L2nd?+αL1st?+νLreg?=i=1n?(xi?^??xi?)bi?22?+αi.j=1n?si,j?yi??yj?22?+νLreg??

    其中 α,ν\alpha, \nuα,ν 為超參數,LregL_{reg}Lreg?L2L_2L2? 正則項用于防止過擬合:

    Lreg=12∑k=1k(∣∣W(k)∣∣F2+∣∣W^k∣∣F2)\mathcal{L_{reg}}=\frac{1}{2}\sum_{k=1}^k({||W^{(k)}||^2_F+||\hat{W}^{k}||_F^2}) Lreg?=21?k=1k?(W(k)F2?+W^kF2?)

    在模型優化方面,SDNE 使用反向傳播來更新網絡參數,但由于模型高度非線性,參數空間中可能存在許多局部最優。因此,為了得到全局最優,作者使用深度信念網絡(Deep Belief Network,以下簡稱 DBN)對參數進行預訓練。

    關鍵源碼解讀

    這部分主要參考了https://github.com/xiaohan2012/sdne-keras。

    損失函數定義

    定義函數 build_reconstruction_loss 作為二階相似度對應的損失函數,參數 beta 控制非零元素的懲罰力度。

    def build_reconstruction_loss(beta):def reconstruction_loss(true_y, pred_y):diff = K.square(true_y - pred_y)weight = true_y * (beta - 1) + 1weighted_diff = diff * weightreturn K.mean(K.sum(weighted_diff, axis=1)) # mean sqaure errorreturn reconstruction_loss

    定義函數 edge_wise_loss 作為一階相似度對應的損失函數,參數 true_y 并未使用,embedding_diff 表示相鄰的節點iii 與節點 jjj 的 embedding 向量的差值,此函數就是利用差值求均方誤差。

    def edge_wise_loss(true_y, embedding_diff):return K.mean(K.sum(K.square(embedding_diff), axis=1)) # mean sqaure error

    模型定義

    關鍵代碼如下:

    # INPUT # 邊的一個頂點 a input_a = Input(shape=(1,), name='input-a', dtype='int32') # 邊的另一個頂點 b input_b = Input(shape=(1,), name='input-b', dtype='int32') edge_weight = Input(shape=(1,), name='edge_weight', dtype='float32')# 定義編碼器、解碼器的層數組 encoding_layers = [] decoding_layers = []# 用 embedding_layer 保持鄰接矩陣 embedding_layer = Embedding(output_dim=self.N, input_dim=self.N,trainable=False, input_length=1, name='nbr-table') # if you don't do this, the next step won't work embedding_layer.build((None,)) embedding_layer.set_weights([self.adj_mat])encoding_layers.append(embedding_layer) encoding_layers.append(Reshape((self.N,)))# 構造編碼器 encoding_layer_dims = [encode_dim]for i, dim in enumerate(encoding_layer_dims):layer = Dense(dim, activation='sigmoid',kernel_regularizer=regularizers.l2(l2_param),name='encoding-layer-{}'.format(i))encoding_layers.append(layer)# 構造解碼器 decoding_layer_dims = encoding_layer_dims[::-1][1:] + [self.N] for i, dim in enumerate(decoding_layer_dims):activation = 'sigmoid'layer = Dense(dim, activation=activation,kernel_regularizer=regularizers.l2(l2_param),name='decoding-layer-{}'.format(i))decoding_layers.append(layer)# 構造整個網絡 all_layers = encoding_layers + decoding_layers# 取出節點 a 與節點 b 的 embedding 向量 # reduce 函數將 input_a 作為數組 encoding_layers 中每一個 Layer 的輸入 # 然后將每個 layer 的輸出值作為下一個 layer 的輸入,直到編碼器層結束 encoded_a = reduce(lambda arg, f: f(arg), encoding_layers, input_a) encoded_b = reduce(lambda arg, f: f(arg), encoding_layers, input_b)# 得到節點的重構矩陣 decoded_a = reduce(lambda arg, f: f(arg), all_layers, input_a) decoded_b = reduce(lambda arg, f: f(arg), all_layers, input_b)# 將兩個節點的 embedding 向量做減法 embedding_diff = Subtract()([encoded_a, encoded_b])# 為差值添加權重 embedding_diff = Lambda(lambda x: x * edge_weight)(embedding_diff)# 構建模型 self.model = Model([input_a, input_b, edge_weight],[decoded_a, decoded_b, embedding_diff])# 構建損失函數 reconstruction_loss = build_reconstruction_loss(beta)# 構建模型 self.model.compile(optimizer='adadelta',loss=[reconstruction_loss, reconstruction_loss, edge_wise_loss],loss_weights=[1, 1, alpha]) # 損失函數權重 # 構建模型 self.encoder = Model(input_a, encoded_a)# 構建模型 self.decoder = Model(input_a, decoded_a) self.decoder.compile(optimizer='adadelta',loss=reconstruction_loss)

    關于 reduce 的更多說明如下:

    reduce(function, sequence[, initial]) -> value

    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5). If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.

    行業應用

    在購物的過程中,經常遇到滿減活動,例如滿400減50,當購物車商品金額不足400時,就需要進行湊單。在2018年的時候,阿里公開了他們的湊單算法:

    阿里的湊單算法框架圖如上圖所示,其中一部分就用到了 SDNE 模型。比較傳統的協同過濾算法也能發掘共同購買關系,為什么還需要構造 graph?

    由于 graph 具有傳播能力,它不僅能有效的提取出來節點之間的直接關聯,而且可以通過游走策略,挖掘出來二度、三度的關系。朋友的朋友,也是朋友,也存在一定的弱關聯,有效的利用這種傳播能力,能解決購買數據的稀疏性,達到提升覆蓋的效果。

    整個算法流程的步驟大致如下:

    (1)構建 Graph

    基于用戶購買行為構建 graph,節點是商品,邊是商品間同時購買的行為,權重是可以是兩個商品同時購買的次數、時間、金額等。

    為什么需要帶權重的Graph?商品的數量繁多,絕大多數是冷門商品。在對圖進行采樣的過程中,如果使用 random walk 策略,那么采樣出來的序列就包含很多冷門商品。但是在引入權重后,可以基于邊的權重進行游走(weighted walk),這樣采樣出來的序列就能包含更受用戶歡迎的熱門商品。

    (2)采樣

    假如有了下圖所示的帶權商品圖:

    假設游走2步,從節點A出發,隨機取下一個鄰居節點時,如果是random walk算法,它會等概率的游走到B或C節點,但是weighted walk算法會以7/8的概率取節點C,再會以8/12的概率游走到節點D,最終很大概率上會采出來一條序walk=(A,C,D),對于原始graph,A和D是沒有關聯的,但是通過weighted walk,能夠有效的挖掘出A和D的關系。

    (3)嵌入

    將基于weighted walk采出來的序,構造成item-item的pair對,送給embedding模型:

    每一對商品都輸出一個 score,上線之后,取出 topN 個 score 較高的關聯商品進行推薦。

    參考文章:

    【論文筆記】Structural Deep Network Embedding

    SDNE:《Structral Deep Network Embedding》閱讀筆記

    【Embedding】SDNE:深度學習在圖嵌入領域的應用

    大話深度信念網絡(DBN)

    阿里湊單算法首次公開!基于Graph Embedding的打包購商品挖掘系統解析

    總結

    以上是生活随笔為你收集整理的SDNE: 阿里应用深度学习进行图嵌入,构造凑单算法模型的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。