社群推薦算法在騰訊游戲的實踐
本次分享的題目是社群推薦在騰訊游戲中的應用。第一部分將回答什么是社群推薦,為什么要進行社群推薦,以及如何進行社群推薦。第二部分將講解如何解決社群推薦冷啟問題,我們提出了一個自適應的社群檢測算法,相關論文已發表于 KDD 2024。第三部分將介紹一個有約束的社群推薦算法,主要解決騰訊游戲社群推薦數據稀疏的問題,相關論文發表在 KDD 2023。最后一部分是對我們團隊的簡單介紹。
一、社群推薦簡介
1. 社交網絡中的社群
社交網絡的定義是由節點(個人)和節點之間的社會關系(親人、同事、朋友等)組成的網絡結構。社交網絡中的節點通常就是獨立的個人,部分節點集合構成社群,一個社群通常由聯系緊密的人組成,社交網絡中通常有多個社群。
2. 為什么需要社群推薦
再來簡單介紹下社群推薦任務的 motivation,我們希望通過社群推薦方式,為游戲內玩家推薦合適的社群,從而提升游戲內用戶活躍度和付費率。
研究表明,游戲社交網絡中的社群其實是游戲社區繁榮的體現,游戲社群對提升玩家付費活躍有正向作用。舉個簡單例子,同一個社群內玩家可能有高活躍度玩家,也有低活躍度玩家,他們都在一個社群就會產生一些交互,比如對局、組隊等行為。通過社群內玩家的交互,可以使高活帶低活,從而提升社群內玩家總體活躍度。
下面兩幅圖展示的是有社群玩家和無社群玩家的付費率,以及他們的游戲時間。可以發現有社群玩家游戲時間和付費率遠高于無社群游戲玩家。所以我們希望通過為這些無社群玩家推薦社群,鼓勵他們加入社群,來提升最終社群內用戶活躍度和付費率。
除此之外,需要社群推薦還有一個原因,游戲內社群數量非常龐大,我們的一個游戲可能有幾百萬甚至幾千萬的社群數量,用戶在真實情況下去選擇想要加入的社群時,就會存在信息過載的問題。因此我們希望用 data-driven 或者 model driven 方法,去為每一個玩家挑選推薦更適合以及更可能加入的社群。
3. 在騰訊游戲中應用社群算法
社群推薦面臨諸多挑戰。首先,游戲內用戶和社群的交互極其稀疏。在極端情況下,比如游戲產品剛剛上線,可能大部分用戶都沒有跟任何社群交互過,對社群而言,里面存在的玩家數量非常少,在這種冷啟動的情況下我們會結合一些社群發現算法通過 unsupervised learning 方式給玩家推薦一些潛在社群,推動玩家去構成一些新社群。
除此之外,游戲社交網絡也是一個典型無標度網絡,其規模非常巨大。在不同場景下,社交網絡規模可能是幾億甚至十幾億節點的超大規模圖。如何把 graph learning 的方法用到真實世界巨大規模的圖上也是一個很有挑戰性的事情。
這里就介紹一下我們怎么樣在真實的騰訊游戲應用場景群中用社群推薦算法。首先給定一個游戲社交網絡節點,玩家邊代表玩家間的交互。社交網絡是社群推薦算法的輸入,我們通過算法和 data-driven 方式去挖掘關系緊密以及興趣相似的玩家群體。然后給他們推薦相應的社群,或者鼓勵他們去形成新社群。
在這里我們列了兩個應用場景,一個是騰訊游戲中話題圈子推薦。顧名思義,話題圈子和社團其實都是由一部分玩家、一部分用戶去所構成的子群體,我們要以一個群體為單位,將其當作一個 item 去推薦給不同的玩家,來鼓勵他們加入到對應圈子或者社團中。
除此之外,還有好友和組隊推薦等場景,我們也傾向于給同一個社群內的玩家去推薦好友,鼓勵他們完成一系列組隊或對局等活躍任務,通過社群內玩家高活拉低活的方式,提升社群內總體用戶活躍度。
接下來將具體介紹我們研發的兩個社群推薦算法。
二、自適應 K-Free 社群檢測算法
1. 真實業務痛點
首先是自適應 K-Free 社群檢測算法,我們的目標是發現社交網絡中潛在的社群,從而解決社群推薦冷啟動問題。
在設計算法之前,我們首先對真實業務中遇到的痛點問題進行了抽象,將其形式化為科學問題(算法問題)。
社群檢測算法在業務場景中的兩個痛點為:
- 兼顧社群的語義屬性(玩家屬性: 玩法偏好,付費,活躍......),網絡結構(好友關系鏈的緊密程度)
- 確定社群的數目和分布
當前算法無法同時解決兩個痛點。傳統算法(如 Louvain)不需要社群數目先驗,但是無法感知節點和社群的語義屬性。深度學習算法(深度圖聚類)可以聯合學習語義屬性,但需要社群數目先驗。
這兩種算法都沒有辦法解決我們的業務問題,所以我們提出了 K-free 社群檢測問題。這個問題就是在真實社群數目 k 未知的前提下,挖掘同時有網絡結構信息和語義結構特點的社群結構。
以傳統的算法為例,其優化目標為模塊度,即社群網絡結構的緊密程度,以模塊度為目標優化出來的社群,其實是同一個社群內連邊盡量稠密,社群間連邊盡量稀疏。
但我們只考慮模塊度指標是不夠的,還要去考慮一些語義的 semantic 指標。比如衡量社群內節點語義屬性的相似性,也有一些算法去針對這些指標做一些單獨的優化。同時我們在真實社群中往往要權衡兩類優化目標,正所謂物以類聚人以群分,我們希望最終的社群 modularity 和 semantic 指標都高。
我們在真實實驗中發現,像 Louvain 這種算法檢測出來的社群數量比真實數值要高很多。比如左邊這張圖,我們以圖上節點分類數據集為例,coral 數據集,我們發現它真實類別數是 7,但是如果用 Louvain 算法劃分社群則能分成 105 個,遠高于我們真實想得到的理想 k 值。但用 k-means 的話,雖然能剛好分成 7 個 cluster,但是它的 modularity 又非常低,可能僅僅是語義程度上相似,但是結構上完全不相似(圖上距離非常遠)。
也有一些方法是用了現在比較火的圖神經網絡這種深度學習方法去做深度圖聚類,圖神經網絡是聚合圖中鄰居信息,來更新當前節點的表示,這一方式可同時進行圖上結構和屬性信息的聯合學習,雖然解決了痛點一,但有一個限制,它要跟現有的聚類方法結合,比如像 k-means,要有一個先驗 k。真實業務情況下,我們不知道 k 到底是多少,所以這類算法實踐起來會有一定困難。
那么一定要有 k 嗎?如果把深度圖聚類中 k-means 聚類換一種聚類方式,比如密度聚類 DBSCAN 是不是就可以了呢?我們通過真實實驗發現這其實是不可以的,因為 DBSCAN 也有一些比較強的先驗參數,像搜索半徑,而且它真實劃分出來節點的一些特征空間分布會有一定崩潰問題。比如像下圖展示的,Coral 數據集其實是有 7 個真實類別,DBSCAN 容易將其劃分為 3 個 cluster,并不是理想的情況。
那么使用 k-means,通過遍歷 k,選模塊度最高的 k 是不是就可以呢?這是可以的,但它的缺點就是比較低效。首先我們要確定候選 k 的搜索范圍,再去窮舉或者搜索嘗試,因此比較低效。
既然這些方法都沒有辦法同時解決我們的痛點問題,我們就希望通過聯合學習的方式,既兼顧特征與結構與語義信息,同時又自適應地確定劃分社群數量。我們提出了深度自適應的生成式的 K-Free Community Detection 算法,簡稱 DAG。
DAG 主要由兩個模塊構成,這兩個模塊分別解決了前文的兩個痛點。
- DAG 首先用 Mask AutoEncoder (MAE) 作為節點 embedding 模塊,并通過預訓練模型讓節點 embedding 包含自身拓撲鄰居的語義信息。這解決了痛點一。
- DAG 用 Community Affiliation Network (CAN)建模社交網絡的生成,這樣無需聚類,直接得出每個節點社群 id,在此基礎上,DAG 將搜索 K 轉化成了可微分的社群選擇。這解決了痛點二。
接下來詳細介紹一下這兩個模塊是怎么工作的。在預訓練階段我們會用 mask attribute reconstruction 鏈目標,隨機采樣一組節點,將對應屬性替換為 mask token。然后通過 graph auto encoder 將其解碼,得到重建后的 attribute,使重建后的 attribute 和真實未 mask 前的 attribute 盡量接近。
第一步輸入一個 input graph 即臨界點矩陣 A,以及圖屬性矩陣■(~@X)。第二步隨機 mask 一組 NODE 的對應屬性,然后輸入到 GNN encoder 里,再經過一層二重 mask,得到基于 mask 特征的節點表示。第三步通過 GNN decoder 得到重建后屬性表示,最后計算 construction loss,這里是通過 GNN 聚合鄰居消息的方式去恢復某節點被 mask 掉的屬性信息。
通過預訓練 loss,我們既捕捉了節點的結構屬性,又捕捉了節點的語義屬性。接下來我們通過 readout 函數將節點劃分成合適 k 值,通過 readout 函數得到每個節點對應的社群 ID,readout 是一個神經網絡,它的輸出是一個高維稀疏向量。這個高維向量里面只有稀疏的 k 個維度被激活,這 k 個維度對應該節點屬于的社群。
如何保證模型訓練得到高維稀疏矩陣的同時又能學到社群數量呢?
我們通過鏈路預測任務去捕捉網絡中的結構屬性,計算節點的 BPR loss,從而讓網絡中相鄰的節點 embedding 更接近,不相鄰節 embedding 會更遠一些。
介紹到這里,這個 loss 其實只能得到一個效果,就是讓這個 community application 的 result 函數進一步得到圖結構的信息。
但如何保證稀疏性呢?當 k-searching 搜索社群數量時,加入一組稀疏約束。通過 readout 函數輸出的是每一個 NODE 屬于的社群 ID 向量。我們會對這個向量做稀疏約束,比如對列做 L2 norm,同時對行做 L1 norm,L1 norm 是很強的吸入性約束。這樣輸出的 ID 向量分布概率在某一維比較大,其他維比較小,是一個橫向稀疏向量。同時我們在列方向加 L2 norm 稀疏性約束,這會使得 readout 函數輸出比較高維向量,但其實只有少數 k 維度對應的社群 ID 激活值比較高。
這樣我們就無法把確定屬性節點應該被劃分成多少個社群的一個 case,通過稀疏約束方式,得到 readout hold,這個節點所屬的授權 ID,同時保證社群數量適中,最終要保證預訓練 loss,以及社群隸屬 readout 函數 BPR loss 都比較低。再配合組稀疏 loss 就可以自適應地得到 k 個社群。
除了模型外,我們還提出了社交網絡劃分社群質量的評價指標,稱為 EDGE Metric。這個指標解決了傳統指標例如 modularity、模塊度或者語義相似性難以衡量網絡結構和語義相似度的權衡。我們在原始論文中也做了一系列 theoretical 和 empirical study,去支撐指標的優勢。
在真實的評估過程中,用戶真實社群標簽是未知的,訓練雖然是 unsupervised learning,但評估其實還是需要用到少量人工標注的真實標簽作為 Label,當標簽比較少時,現在常用的解決方法可能是把一些分類數據集里樣本的類別當作社群標簽。
我們發現在曝光轉化率這個線上指標上,我們的 model 相比于 baseline 提升大概在 4% 到 9%,像 DGC model,它的提升就比較一般,甚至產生了負向增益。而我們的模型有著比較穩定的提升。
三、有約束的大規模社群推薦算法 ComRec
我們想解決的另一個問題,就是在不知道社群數量k 的情況下去劃分適當數量的社群,同時兼顧結構和語義屬性。服務的場景為,針對一些剛起步不久的騰訊游戲做冷啟動的社群推薦時,可以無監督地發現一些社群。但如果游戲已經是比較成熟的產品了,已經積累了一定用戶和社群 item 的交互歷史,利用這部分信息再結合一些傳統推薦算法,可能會達到更好效果。基于此 motivation,我們又進一步做了有約束的大規模社群推薦算法 ComRec。這篇 paper 也同樣發表在 KDD 會議上。
游戲場景中社群推薦約束問題中的約束該怎么理解呢?
不同于傳統社群,社交網絡中社群,每一個用戶在同一時刻只能加入一個社群,也就是說他不能同時加入兩個社群。在傳統的社交網絡里,一個用戶可能是屬于多個社群,不同社群之間存在 overlap。但在我們的 problem setting 限制下,有很強的 Constraint,用戶在同一時刻只能在一個社群里面,用戶只能從一個社群退出后,才能加入另一個社群。
社群推薦場景主要有兩大挑戰:
- 交互數據稀疏:極度稀疏的 user-item 交互數據
- 社群信息受限:游戲內社團沒有額外的 side information,傳統的推薦 item 可能有很豐富的 side information,比如 title description 或非結構化信息商品圖片等。
我們的社群推薦算法主要分為三個模塊,一是標簽模塊機制-labeling agenda,它描述的是約束,同一個 NODE 在同一時刻只能加入一個社群。除此之外我們通過一個圖神經網絡模塊去得到對應的 user item 表示。為了兼顧大規模圖上的信息,及局部社群推薦,我們做了一系列的優化,將其分成了 global propagation 和 local propagation。
社群標簽機制是我們要用向量表示節點,它是否屬于某一社群是比較簡單的表示方式,比如有 k 個社群,就用 K 維 one-hot 向量表示該節點是不是屬于其中一個社群。但是這樣會有一個問題,我們的社群可能是百萬甚至千萬級別的數量,one-hot 向量維度會很高,會給模型 learning 過程造成困難。在實際設計中我們做了一定的約束放松,只會維護一個一維標簽標注 NODE 是不是隸屬于某一社群,而不區分它具體屬于哪個社群。
基于 label 機制,我們的核心目的是希望標注 NODE 是否屬于某一社群,還是不屬于任何社群。我們要進一步思考圖神經網絡是如何做消息傳遞的。傳統的圖神經網絡在做消息傳遞時,每一個節點在每一輪更新都會聚合所有鄰居信息,把鄰居信息特征聚合后,通過一個圖卷集合,比如均值聚合得到一個向量,下一步就是通過聚合后的信息去更新當前節點向量表示。但在我們的 setting 下,面臨大規模圖挑戰,同時需要做社群推薦,因此我們希望同社群內節點的表示更接近。
我們的做法是,將其分成 global feature propagation 和 local feature propagation。Global feature propagation 是 column-wised propagation,比如維護一個 nd 維用戶 feature embedding 表示矩陣,要在 column 維度上做一個 propagation,不同于傳統的圖神經網絡,每一次都會用所有鄰居特征更新所有節點。我們做了一系列優化,把原本 n^n 的復雜度變成了亞線性。
圖上節點不是每一輪都會更新節點表示,而是會有一定延遲,我們的更新機制是每一個節點在累積接收 message 到一定程度下,才會去更新節點表示。在具體實現上,考慮到我們是應用到一些工業場景,核心的計算代碼是用 C++ 實現的,這提升了很多效率。
最終效果,在 2000 萬節點的圖上,只需要 30 秒就可以完成一次快速計算。除了通過 global propagation 在整個圖級別捕捉鄰居節點信息和結構信息,以及結鄰居分布的語義信息,還通過 local propagation 進一步增強社群表示,因為我們的模型是用來做社群推薦的,社群其實是一個子圖,local propagation 可以理解為是一個 subgraph 級別的 propagation,下圖紅圈圈出來的節點屬于同一個社群,我們就在同一個社群里進行消息傳遞,或者說進行 feature 的平滑,讓同一個社群節點 feature embedding 更加接近,相似度更高。屬于不同社群的節點,相似度更低一些。
通過分階段 propagation,我們在兼顧高效率的同時增強了社群信息的語義結構學習。
我們在大量數據集上進行了實驗。首先是離線數據集的 setting,我們在四個騰訊游戲的內社交網絡數據集上做了實驗,這幾個數據集都是百萬節點及千萬節點邊的 setting。同時我們也對比了像傳統的網絡嵌入方法 (network embedding),以及僅使用屬性特征的像 MLP 推薦模型,特征交叉的 learning model AutoIntCL,還對比了一些基于頻率的協同過濾推薦算法,比如 LightGCN 和 LightGCN-E,以及 social recommendation 的 model,比如 GraphRec。
最終 ComRec 相比于 baseline 方法都有 3.5%~5% 以上比較可觀的提升。模型的離線效果是通過 hit rate 和 NDCG 等一些排序指標進行評估的。
我們也把模型部署到了真實線上環境-游戲內社群推薦。真實世界中圖的規模是比較大的,其中有 2000 萬節點,28 萬社群數量,1.6 億條邊,我們在這樣一個大規模圖上去進行線上實驗,評價指標也換成了線上評價指標。比如 user item 點擊率,以及把社群列表曝光給玩家之后的曝光通過率,即玩家點擊社群,然后申請加入社群的比例是多少。我們的模型在線上指標上相比于 baseline model 也有著比較可觀的提升。同時我們也對比了不同模型的運行時間,我們的模型在保留了更好的推薦效果的同時運行時間也是最少的。
感興趣的同學也可以搜索我們的論文,相關代碼也是開源的,歡迎大家來與我們做進一步交流。
四、About Us
最后簡單介紹一下我們的團隊。我們是騰訊互娛 CDP 數據科學中心社交算法組,致力于研發高效且有效的社交網絡算法和技術,通過挖掘海量圖數據服務于游戲社交推薦的相關場景,比如前文中介紹的戰隊推薦、社群推薦、游戲內好友推薦,以及社交傳播影響力最大化和社交營銷等多種場景,希望助力于游戲場景提升用戶活躍度和付費率。歡迎感興趣的同學加入我們來共同探索社交算法在騰訊游戲中的無限可能。
五、Q&A
Q1:第一個算法聚類是 unsupervised 聚類還是 supervised 聚類?
A1:第一個算法是 unsupervised 算法。我們第一階段的優化目標,是 feature reconstruction 優化目標,也就是只需要知道節點的特征,我們是沒有任何的節點標簽的,優化目標其實是純無監督目標。
第二階段社群隸屬模塊 learning 部分,它的一部分優化目標是 link prediction,即拿到一個圖結構后 mask 其中一部分 edge,然后預測這些 edge 存在的概率,也可以認為是一個 unsupervised 的過程,這個過程是 Nodewise 任務,但是并不涉及任何 Nodewise 標簽,后面加入的 group sparsity 約束,是在 learning 出來的 representation 矩陣上做稀疏性約束,只需要算 L1 norm、L2 norm 和 optimization 相關 loss。整體算法流程是 unsupervised 過程,最終應用也是在無監督場景解決一些冷啟問題。
Q2:前面提到的 BGC 算法能否用異質圖解決?
A2:當然是可以的。像 DGC 算法,它是先通過圖神經網絡去學習節點級別表示,每一個樣本都有對應向量,基于向量再去做聚類,比如通過 k-means 聚類成 k 個 cluster。我們真實的業務場景中是一個異質圖,可能是多關系網絡,只需要改變前面 encoder 模塊,如果網絡關系是同質圖就選擇同質圖 GNN,如果是異質圖只需換成 heterogeneous GNN。
后面聚類時,因為 heterogeneous graph 可能會存在多種類型節點和邊,可能只能錨定其中某一類型節點,比如用戶節點,在用戶節點表示上做聚類,更準確地說是在同種可比的類型節點上做聚類。同質圖和異質圖不同就是 encoder 以及最后聚類邏輯上會有一點不同。
Q3:預訓練任務和真實推薦任務是否有偏?
A3:預訓練任務和推薦任務確實有偏差,比如像 DAG 這篇 paper,我們主要解決的是冷啟動問題。當我們沒有 user item 交互歷史的時候,我們沒有辦法根據他的歷史交互序列去精準捕捉用戶意圖,但是我們知道一些其他信息,比如用戶在社交網絡里親密關系信息、他在具體下游任務當中的親密關系。我們可以通過這些信息彌補這種偏差。但如果要完全消除這種偏差,后面介紹的 ComRec 算法還是要利用用戶歷史的 community 的交互序列,根據他的歷史交互行為才能更精準刻畫用戶對社群偏好程度,才能做完全無偏推薦。