1. 程式人生 > >達觀資料技術實踐:知識圖譜和Neo4j淺析

達觀資料技術實踐:知識圖譜和Neo4j淺析

在當前大資料行業中, 隨著演算法的升級, 特別是機器學習的加入,“找規律”式的演算法所帶來的“紅利”正在逐漸地消失,進而需要一種可以對資料進行更深一層挖掘的方式,這種新的方式就是知識圖譜。

下面我們來聊一下知識圖譜以及知識圖譜在達觀資料中的實踐。

 

NO.1 什麼是知識圖譜

知識圖譜(Knowledge Graph)是一種用點來代替實體,用邊代替實體之間關係的一種語義網路。通俗來說,知識圖譜就是把所有不同種類的資訊(Heterogeneous Information)連線在一起而得到的一個關係網路,它提供了站在關係的角度去分析問題的視角。站在這個角度我們可以從“找規律”的維度上升到“理解”的維度, 這也就是為什麼有人說知識圖譜是 AI 的未來。

“達觀資料是一家人工智慧公司”這句話在機器看來只不過是一連串的字元, 但是在我們人看來卻可以分成主謂賓三部分,即主語“達觀資料”謂語“是”賓語“人工智慧公司”。 那麼有沒有一種資料的組織形式讓機器看到這句話時不再是一個字串, 而是一個具有類似主謂賓可以“理解”的結構呢?當然,這就是知識圖譜要乾的事情。

知識圖譜可以表示成一個實體關係網路圖,實體是包含資訊的個體,畫出來叫節點;關係是兩個實體間的聯絡,畫出來叫邊。借用上面的例子“達觀資料是一家人工智慧公司”,“達觀資料”和“人工智慧公司”是兩個實體,“是”即這兩個實體之間的關係。

圖 1 知識圖譜表示實體關係網路圖

NO.2 應用場景

知道了什麼是知識圖譜,那麼知識圖譜有什麼用處呢?這裡我舉兩個例子:知識圖譜在搜尋引擎中的作用以及在銀行風控系統中的應用。

1 知識圖譜在搜尋引擎中的應用

有時候我們在使用搜索引擎時, 我們的搜尋詞(Query)往往看起來更像是一個問題,比如“張三是從哪裡畢業的”,這時我們需要搜尋引擎直接給出我想要的結果,而不是一個網頁排名(page rank) 。比如我在 google 中搜索“扎克伯格的妻子是誰”, 我需要是扎克伯格的妻子普莉希拉・陳的詳細資訊而不是一些包含了她資訊的網頁。我們先看下 google 的結果:

圖 2 google 中搜索“扎克伯格的妻子是誰”

 

那麼Google是怎麼做到的呢?其實早在2012年Google 就已經在搜尋中加入了知識圖譜,使用者可以通過Google 構建的知識圖譜直接查詢到結果,這種方式極大地提升了使用者體驗。然而對於 Google 來說處理起來也比較便捷,首先將“扎克伯格的妻子是誰” 這個 Query通過自然語言處理技術(NLP)處理成“扎克伯格”實體和”has_wife" 的關係,從已經構建好的知識圖譜中查詢, 然後將查詢結果返回給使用者。

然而就是這樣的一個改動,從使用者使用的角度來看已經從普通的搜尋引擎變成了智慧問答的系統,使用者體驗上升了一個層次。

2 知識圖譜在隱含關係挖掘中的應用

馬克斯·韋伯曾說“人是懸掛在自我編織的意義之網上的動物”,這句話從側面說明人與人之間的關係是很複雜的,我們是否可以將複雜的人際關係進行一次挖掘呢?

首先人際關係實際形如一張網, 既然是網那麼它一定具有一個特性,即網上兩個相鄰節點之間的路徑損壞,並不一定影響整張網。比如 一張網(無向圖)中相鄰的 A 節點到 B 節點的路徑“壞了”, 有極大可能找到另一條從 A 到 B 的路徑,而不影響整張網。那麼網的這個特性應該怎樣應用到資料探勘上來呢?我們來看一個知識圖譜在銀行風控系統中的例子

圖 3 知識圖譜在銀行風控系統中的應用

我們可以根據借款人借款時填寫的關係構建知識圖譜, 如圖借款人跟張三是朋友關係,跟李四是父子關係。當我們試圖把借款人的資訊新增到知識圖譜裡的時候,“一致性驗證”引擎會觸發。引擎首先會去讀取張三和李四的關係,從而去驗證這個“三角關係”是否正確。很顯然,朋友的朋友不是父子關係,所以存在著明顯的風險。這裡的隱含關係挖掘可以借用通用的關係挖掘引擎,也可以自己實現隱含關係的挖掘引擎。通用關聯關係的挖掘由於其通用性,通常難以保證對關係挖掘的正確性,通常是自己配置規則來確保關係挖掘的準確性。對隱含關係的挖掘技術目前是知識圖譜研究的前沿方向, 如果有興趣,可以查閱相關論文。

知識圖譜在銀行風控中的作用還有很多,比如對失聯借款人兩度,甚至多度的關係挖掘來找到借款人等。 由此可見在“關係”越複雜的情況下,知識圖譜越是能發揮它的作用。

知識圖譜還有很多其他應用場景,這裡就不一一列舉了,如果您感興趣的話,參見《知識圖譜的應用》。

NO.3 圖譜的構建

既然知識圖譜這麼有用,那麼怎樣才能構建自己的知識圖譜,怎樣將傳統的資料轉化成知識圖譜呢?

傳統資料主要分成兩種,格式化資料和非格式化資料。格式化資料轉化成知識圖譜時需要將格式化的資料對映成實體關係組,從而構建知識圖譜。而非格式化的資料轉化時比較複雜,通常採用演算法抽取和程式抽取兩種方式。

1 演算法抽取方式

通過自然語言處理(NLP)技術對文字進行命名實體識別(NER),從非格式化的文字中識別出專有名詞和有意義的短語並進行分類。比如上例中從“達觀資料是一家人工智慧公司”這段文字中識別出”達觀資料”和“人工智慧公司”這兩個實體以及“是”這個從屬關係,這樣我們就可以通過”達觀資料” “是” “人工智慧公司” 這個實體組來構建知識圖譜。由於目前NER識別技術還不夠成熟,通常我們會對NER 識別的實體進行人工矯正,確保所識別實體的準確性。

2 程式抽取方式

在處理實體識別非格式化資料的過程中我們經常會碰到半格式化的資料,比如一段簡歷的文字,文字中經常會包含,姓名:XXX,公司名:XXX 等格式,遇到這樣的半格式化文字,我們也可以採用正則等方式來抽取,確保知識圖譜構建的完整性和準確性。

NO.4 儲存與效能

知識圖譜是基於圖的資料結構,通常用圖資料庫進行儲存,我們先來看一下圖資料庫排行(部分)。

圖 4 知識圖譜的儲存以及neo4j 的效能測試

通過排行榜可以看出 Neo4j 資料庫遙遙領先,實際上neo4j 已經是當前業界分析知識圖譜的主流資料庫。那麼怎樣將 neo4j 圖資料庫應用到專案中去,以及怎樣優化 neo4j 圖資料庫呢?首先我們來看一下 neo4j 的效能表現:

測試內容: 節點數分別在1萬, 10萬, 100萬,1000萬情況下,在節點設定索引和不設定索引的情況下查詢節點的平均延時。測試結果如下:

圖 5 查詢節點平均延時的測試結果

通過上面的測試可以看出,當節點(Node)的數量超過1000萬時,在不設定索引的情況下,平均查詢延時已經超過了6秒,說明此時 neo4j 已經明顯“吃不消”了,顯然這樣的延時這在實際的專案應用中是完全不可接受的。但是我們發現設定索引之後查詢時間明顯降下來了,那麼是不是設定的索引越多越好呢?我們看下在1000萬節點的情況下有索引和無索引插入延時測試:

圖 6 1000萬節點情況下有索引和無索引的插入測試結果

由上圖測試結果可以看出: 在千萬級資料的情況下有索引插入比無索引插入要慢30%, 所以索引並不是越多越好, 那麼除此之外 neo4j 還有哪些地方可以優化呢?

NO.5 資料庫優化

neo4j 不使用schema,所以從理論上來說 neo4j 可以儲存任何形式的資料。但由於neo4j 是通過鍵值對(Key-Value) 的雙向列表來儲存節點和關係的屬性值,所以neo4j僅適用於儲存實體關係和實體簡單的屬性。在實際應用中一個實體通常會包含眾多的屬性,如果將這些屬性全部儲存到 neo4j 中,neo4j 的查詢將變得異常的慢, 而在實際的應用場景下,經常會遇到高併發的情況。這時候單節點的 neo4j 就會顯得力不從心。那麼在專案實戰中怎樣更好的利用 neo4j 來抵禦高併發呢?

1 高可用架構

neo4j HA(High Availability)即neo4j 的高可用特性,不過這個特徵只能在neo4j 企業版中可用。neo4j HA使用多臺neo4j從資料庫設定替代單臺neo4j主資料庫的容錯架構,這種架構可以在一臺實體機故障的情況下使資料庫具備完善讀寫操作的能力,由於 neo4j HA 採用主從資料同步, 而且寫操作也可以在從庫中執行(經測試這種方式不如主節點寫入可靠)因此採用neo4j HA 比單臺neo4j資料庫擁有更多的讀取負載處理能力。

如果你使用的不是 neo4j 企業版,那麼你可能需要自己動手來構建 neo4j 叢集以此來實現高可用架構了。當然你可以採用Neo4j+DRBD(Distributed Replicated Block Device)+ Keepalived 方式來構建自己的neo4j 叢集, 通過 DRBD 來備份單點上的 neo4j 相簿資料,通過Keepalived 來管理你的叢集。除此之外你還可以通過 zookeeper 來管理你的叢集節點,自己實現將主節點資料修改的Cypher 語句元操作同步到從節點(類似 MySQL 的binlog)來實現主從同步,從而達到讀寫分離。當然不管你採用方式一還是方式二,都會增大開發和維護成本。

2 增加快取

應用快取:在實際應用的過程中讀寫相簿時經常會遇到查詢一些不常修改的資料, 比如需要頻繁查詢使用者所屬的國家資訊,而國家的屬性更改的頻率比較低,而且使用者的國籍資訊不會經常變動,這時我們可以通過新增應用快取(如:redis, leveldb等),將查詢的結果快取起來,減少直接訪問相簿的頻次,減小相簿的讀取壓力。

資料庫快取:由於neo4j 執行一次查詢操作之後,會將資料快取到記憶體中,執行相同的查詢操作 neo4j 直接返回記憶體中快取的資料結果。如果是執行隨機查詢,則後一次結果會覆蓋前一次的查詢資料,記憶體快取的配置可以通過修改配置檔案中dbms.query_cache_size引數進行調整。所以說執行語句時儘可能的利用已有資料的快取,減少 Cache-Miss 情況的發生。

3 索引查詢優化

查詢優化:由於 neo4j 會將查詢結果快取到記憶體中,所以不需要的查詢結果儘量不要放到記憶體,比如 下面的cypher 語句:

語句1比語句2 更好,因為後者會將所有的節點和關係的屬性載入到記憶體,然後計算 count 值,而前者只會將必要的屬性載入到記憶體求count值。

索引優化:我們知道資料庫索引實際上是在資料之外維護了特定演算法的資料結構(如 B+Tree),比如圖7為了加快 Col2的查詢構建一個二叉樹,使原來的“順序”查詢,變成“二分查詢”,從而將查詢複雜度降低為 o(logn),而且索引還會利用訪問區域性性原理,充分利用作業系統的頁快取,加快查詢的速度。

圖 7 資料庫索引原理介紹

由於增加索引會讓相簿維護在維護資料的同時還會維護一份額外的資料結構,更新資料時會造成額外的開銷,這也印證了上面測試的插入資料時無索引比有索引快的結論。

Neo4j 1.4以後的版本引入了自動索引(automatic index),可以在config/neo4j.properties中配置自動建立索引,也可以通過語句CREATE INDEX ON :Label(PropertyName)手動建立索引,從而提高查詢的效率。 

4 Neo4j和KV(Key Value)資料庫聯合使用

由於 neo4j 的節點和關係的屬性是通過Key-Value 的雙向列表來儲存的,所以這種資料結決定了 neo4j 中儲存的節點不能包含太多的屬性值。但是在實際應用中經常會碰到一些實體擁有大量的屬性,必要時還需要通過這些屬性的值來查詢實體進而查詢實體擁有的關係。這時候可以將 neo4j 資料庫和KV 資料庫(如:MongoDB)進行聯合使用,比如在 neo4j 節點的屬性中儲存MongoDB 中的 objectId。

這樣既可以充分利用 neo4j 的特性來進行關係查詢又可以通過 KV 資料庫的特性來進行屬性到實體的查詢。通常在相簿和 KV 資料庫聯合使用時, 特別是經常需要通過屬性來查詢實體時需要設定 neo4j schema Index,即將neo4j中與 KV 資料庫關聯的值設定索引。

NO.5 總結與展望

知識圖譜和Neo4j還有很多有趣的特性,鑑於篇幅這裡不再贅述。自Google在2012年推出知識圖譜技術以來,知識圖譜迎來了飛速的發展。由於知識圖譜在關係“理解”方面的優勢,目前已經在各大網際網路公司和傳統企業的專案中落地,並取得了良好的效果。

正是由於知識圖譜對資料理解和傳統方式不一致,給傳統的資料探勘演算法帶來了挑戰。相信隨著人們對知識圖譜的關注度越來越高,在知識圖譜領域將會湧現更多更成熟的構建、儲存和挖掘理念,相信在不遠的將來知識圖譜將會在更廣泛的領域內為大家服務。