1. 程式人生 > 其它 >基於 Nebula Graph 構建圖學習能力

基於 Nebula Graph 構建圖學習能力

本文首發於 Nebula Graph Community 公眾號

經常看技術文章的小夥伴可能會留意到除了正在閱讀的那篇文章,在文章頁面的正文下方或者右側區域會有若干同主題、同作者的文章等你閱讀;經常逛淘寶、京東的小夥伴可能發現了,一旦你購買或者檢視過某個商品之後,猜你喜歡的推薦商品會貼近你剛拔草的商品…這些日常生活中常遇到的事情,可能是由一個名叫圖學習的“傢伙”提供技術支援。

圖學習,顧名思義是基於圖的機器學習,按照本期專案介紹的參賽隊伍——圖學習興趣小隊隊長楊鑫的話就是,圖學習是一個通過深度學習方法,基於圖的結構與屬性生成一個向量作為點、邊或者整個圖的表徵。

在之前 Nebula Hackathon 2021 年的參賽專案中,圖學習興趣小隊“豪氣”地說要讓 Nebula Graph 具備支援圖學習的能力,在本文接下來的內容中,你將瞭解到他們是怎麼實現這一目標的。

圖學習小課堂

在講述專案實現之前,專案負責人楊鑫先給大家上了一課“圖解圖學習”。

以獲取頂點的向量表徵為例來講解下圖學習過程,第一步需要對圖中頂點鄰居進行取樣拿到鄰居的拓撲結構以及屬性;第二步便是通過自定義的聚合函式聚合鄰居頂點蘊含的資訊進行計算;最後一步基於聚合資訊得到圖中各頂點的向量表示。

楊鑫表示,衡量一個圖學習演算法的好壞是通過生成向量中包含圖中頂點屬性及拓撲結構的豐富程度來判斷的。

故事的開始

在選擇圖學習框架時,圖學習興趣小隊有自己的一套選型標準:首先它是開源元件,方便二次開發,其次它支援分散式,最後框架本身和圖資料庫的耦合程度要低方便定製化開發。經過深入調研,由於 DGL(連結:

https://www.dgl.ai/)同底層的圖資料庫耦合過高,PYG(連結:https://pytorch-geometric.readthedocs.io/en/latest/)不支援分散式,最終他們採用了 Euler(GitHub 地址:https://github.com/alibaba/euler),而在 Nebula Hackathon 2021 中,圖學習興趣小隊的重點工作便是用 Nebula Graph 替換 Euler 原生圖資料庫,讓社群使用者可以基於 Nebula Graph 低成本嘗試圖學習能力。

設計思路

在方案設計上,架構分為三層:底層是 Nebula Graph 圖資料庫,中間層是圖取樣運算元層,為上層 Euler 圖演算法提供多種取樣圖資料的能力。圖取樣運算元則是他們本次工作的重點——重寫 22 個 TF 取樣運算元、6 種 nGQL 取樣語法。

高強度的開發量

以全域性帶權取樣語法設計為例,

這裡採用了預計算(離線)+ 計算下推(實時)的方式來實現全域性取樣,主要過程為(上圖 1-4)

  1. graphd 提交非同步構建任務給 metad;
  2. metad 下發任務給各個 storaged 節點進行計算;
  3. storaged 將計算結果上報給 metad 彙總;
  4. metad 通過心跳將結果同步給 graphd。

詳細展開來講,在圖學習訓練過程中,資料取樣是一個非常高頻的操作,取樣效能好壞對圖學習訓練耗時影響很大。

在這裡,楊鑫他們採用別名取樣演算法作為全域性帶權取樣語法的核心演算法,它的基本原理是首先對進行取樣的全部資料根據各自的權重計算出一份取樣表,取樣表由行號(sid)、vid1、取樣概率(prob)、vid2 四部分組成,其中行號是從 0 開始的編號,vid1、vid2 表示可以被取樣的某個頂點的 vid;取樣流程是首先在表中隨機選擇一行,然後再隨機生成一個 0~1 之間的值 p,如果 p < prob,則本次取樣的資料是 vid1,否則取樣 vid2。

目前圖學習是基於靜態圖資料訓練,因此我們可以通過預計算的方式離線生成一份別名取樣表,而實時取樣過程簡化為基於預計算的取樣表做兩次隨機取樣,時間複雜度由 O(n) 降到 O(1),可以極大地提高取樣效率。

下面是基於 Nebula Graph 實現的全域性帶權取樣具體實現,跟 Nebula Graph 的索引重建邏輯很相似。

  1. Graph 服務呼叫 Meta 服務啟動一個非同步構建取樣表任務,並支援非同步任務的狀態查詢。
  2. Meta 服務的作用是控制非同步任務的執行,包括分配每個 Storage 節點需要處理的資料(根據 partition 的 leader 分佈決定)、非同步觸發各個 Storage 節點進行取樣表的計算、記錄任務的執行狀態、記錄全域性資訊(點、邊權重和)、通過心跳邏輯將全域性資訊快取在 Graph 服務中。
  3. Storage 服務的任務是生成所負責資料的取樣表。取樣表的計算是整個流程中的核心邏輯,計算過程需要對所有點、邊編號,並根據權重大小對點、邊進行分類,很顯然這些資料是無法全部儲存在記憶體中的,所以我們在 Storage 中增加了一個取樣統計資訊 RocksDB 例項來儲存取樣表、點邊總數、點邊權重、計算中間變數等資料。以計算某一類點的取樣表的過程為例:

第一步遍歷全圖來統計這一類點的權重和數量,同時為了給生成取樣表做準備,將點的序號(點的讀取順序)、vid、權重等資料儲存在了圖中(B1)結構中。其中 key 的資料結構是 type + tagid + sid,type 標識了資料是 B1 型別,tagid 就是點的 tag,sid 是點的序號,跟取樣表的 key 結構相同。

第二步將資料分類,根據權重值以點的總數的倒數為界將所有的點分成兩部分,分別以(B2)、(B3)的結構儲存,key 的組成與 (B1) 結構相比就是type 值不同。

第三步分別遍歷(B2)、(B3),根據別名取樣演算法的理論來計算每個點的取樣概率 prob。這裡每個點是用 sid 來標識的,也就是說實際上是在計算第 sid 個點的取樣概率,概率值作為取樣表的一部分會更新到(B1)結構中。

第四步將中間變數(B2)、(B3)結構刪除掉,釋放磁碟空間。

利用取樣表進行實時取樣的過程就比較簡單了。完成取樣表的預計算後會將點、邊權重的統計資訊上報到 Meta 服務儲存,然後通過心跳通知 Graph 服務將這些資料快取在本地。根據這些資料可以計算出點、邊在各 Storage 服務上所佔的權重比例,將使用者指定的取樣數量按比例分配到各 Storage 服務,然後在 Storage 服務上通過兩次的隨機數操作取樣到足夠數量的資料後返回,最後在 Graph 服務上進行資料聚合,這樣就完成了一次帶權取樣。

另外為了提高非同步任務的健壯性,還實現了失敗重試、任務重複限制、重建取樣表後髒資料清理、匯出取樣表等功能。

提到專案設計以及重寫其他運算元過程中遇到的問題,圖學習興趣小隊隊長楊鑫表示因為 Nebula Graph 的資料都儲存在磁碟中,要用 Nebula Graph 替換 Euler 原生記憶體圖資料庫,改造後的 Euler 在取樣效率上肯定要低於原生 Euler,因此怎麼保證改造後 Euler 的圖學習訓練耗時儘可能接近原生 Euler 是要解決的首要問題,至少得保證兩者取樣效能不能有資料級上的差距

原生 Euler 中的圖學習演算法由 Python 實現,通過 TensorFlow 的 OP 機制來呼叫 C++ 實現的取樣運算元,然後在取樣運算元內直接呼叫記憶體圖資料庫獲取資料,這樣就完成了一次資料取樣。

圖興趣小隊最初的方案是將取樣運算元用 Python 實現,這樣一次資料取樣過程就變成了圖學習演算法直接呼叫取樣運算元,然後在取樣運算元內則通過 Nebula Graph 的 Python 客戶端執行取樣語法獲取資料。這樣改造後的系統會有更清晰的處理流程,但是經過測試他們發現其訓練耗時要遠大於原生 Euler,具體到訓練過程中的每次資料取樣上,其耗時是原生 Euler 的幾十倍,這樣的結果顯然是不能滿足要求的。通過分析各階段執行耗時他們發現,資料取樣的耗時要遠大於取樣語法的執行耗時,所以他們認為是 Python 客戶端在反序列化上消耗了大量時間。因此圖興趣小隊進行了第一次優化,使用 fbthrift fastproto 替換 Nebula Graph 原生客戶端的序列化元件,優化後的效能提高了一倍,整體訓練耗時確實有所降低,但是這樣的結果卻仍然無法滿足他們的使用要求。

這時候用上了第二個方案,重寫 C++ 版本的取樣運算元,在取樣運算元中通過 Nebula Graph 的 C++ 客戶端執行取樣語法獲取資料,相比第一個方案多了一些適配工作,運算元的重寫主要是適配 C++ 客戶端的輸入輸出,另外改造了 C++ 客戶端以便取樣運算元的呼叫。

這也是他們最終的方案,這樣改造後的 Euler 雖然在訓練耗時上仍然高於原生 Euler,但是差距控制在了二倍以內,符合預期。

有意思的 Hackathon

當談到本次有什麼值得圖學習興趣小隊留意的專案時,隊長楊鑫表示比較關注的是大油條東北虎隊伍的專案——如何吊打 Nebula 的深度查詢,這個專案的優化思路對他們很有借鑑意義。

因為在實際使用中,圖興趣小隊所在團隊的業務方有很多的多跳查詢需求,包括 GO 查詢、FINDPATH 查詢等。這本應該是 Nebula Graph 所擅長的部分,在大部分場景下也確實如此,但是在遇到出度很大的頂點的時候,查詢效能會急劇惡化。其主要原因還是基於目前 Nebula Graph 的架構,多跳查詢只能先將一跳的結果集彙總到 Graph 服務後才能進行下一跳計算,完全不能將多跳計算下推。而這個專案正好給他們提供了一個解決這個難題的思路。

附:圖學習興趣小隊專案設計文稿:https://docs.qq.com/doc/DVnZQUVBzd1dmS0lS


交流圖資料庫技術?加入 Nebula 交流群請先填寫下你的 Nebula 名片,Nebula 小助手會拉你進群~~

關注公眾號