知識圖譜和Neo4j實戰

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

一.什麼是知識圖譜

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

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

知識圖譜可以表示成一個實體關係網絡圖,實體就是一個包含信息的個體,畫出來叫節點;關係是兩個實體之間的聯繫,畫出來叫邊。借用上面的例子“達觀數據是一家人工智能公司”,“達觀數據”和“人工智能公司”就是兩個實體,“是”即這兩個實體之間的關係。所以這句話用知識圖譜可以表示成下圖。

知識圖譜和Neo4j實戰

二.知識圖譜的應用場景

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

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

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

知識圖譜和Neo4j實戰

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

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

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

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

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

知識圖譜和Neo4j實戰

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

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

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

三.知識圖譜的構建

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

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

1.算法抽取方式:

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

2.程序抽取方式:

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

四.知識圖譜的存儲以及neo4j的性能測試

知識圖譜是基於圖的數據結構,通常用圖數據庫進行存儲,我們先來看一下圖數據庫排行

知識圖譜和Neo4j實戰

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

測試環境:

1.操作系統: Mac OS X 10.10.5

2.內存: 8G

3.cpu參數: 8核8線程

4. 編程語言: python 2.7

5.Neo4j 版本: 3.3.0

6.服務器節點數: 單點

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

知識圖譜和Neo4j實戰

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

知識圖譜和Neo4j實戰

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

五.neo4j圖數據庫優化

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

1.高可用架構:

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. MATCH (n) OPTIONAL MATCH (n)-[r]->() RETURN count(n.prop) + count(r.prop);

2. MATCH (n) OPTIONAL MATCH (n)-[r]->() RETURN count(*) + count(*);

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

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

知識圖譜和Neo4j實戰

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

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 數據庫關聯的值設置索引。

總結與展望

知識圖譜和Neo4j還有很多有趣的特性,鑑於篇幅這裡不再贅述。自Google在2012年推出知識圖譜技術以來,知識圖譜迎來了飛速的發展。由於知識圖譜在關係“理解”方面的優勢,目前已經在各大互聯網公司和傳統企業的項目中落地,並取得了良好的效果。正是由於知識圖譜對數據理解和傳統方式不一致,給傳統的數據挖掘算法帶來了挑戰。相信隨著人們對知識圖譜的關注度越來越高,在知識圖譜領域將會湧現更多更成熟的構建、存儲和挖掘理念,相信在不遠的將來知識圖譜將會在更廣泛的領域內為大家服務。

轉自:https://zhuanlan.zhihu.com/p/36404872


分享到:


相關文章: