【轉載】KG-知識圖譜初探

轉載:項目實戰–知識圖譜初探

項目實戰:如何構建知識圖譜
實踐了下怎麼建一個簡單的知識圖譜,兩個版本,一個從 0 開始(start from scratch),一個在 CN-DBpedia 基礎上補充,把 MySQL,PostgreSQL,Neo4j 數據庫都嘗試了下。自己跌跌撞撞摸索可能踩坑了都不知道,歡迎討論。

PS:這篇文章寫很不錯,闡釋了知識圖譜的整個構建過程,對於剛入門的同學幫助很大,包括我自己在內。希望你也能從中有所收穫!


1.CN-DBpedia 構建流程

知識庫可以分爲兩種類型,一種是以 Freebase,Yago2 爲代表的 Curated KBs,主要從維基百科和 WordNet 等知識庫中抽取大量的實體及實體關係,像是一種結構化的維基百科。另一種是以 Stanford OpenIE,和我們學校 Never-Ending Language Learning (NELL) 爲代表的 Extracted KBs,直接從上億個非結構化網頁中抽取實體關係三元組。

與 Freebase 相比,這樣得到的知識更加多樣性,但同時精確度要低於 Curated KBs,因爲實體關係和實體更多的是自然語言的形式,如“奧巴馬出生在火奴魯魯。” 可以被表示爲(“Obama”, “was also born in”, “ Honolulu”)。

下面以 CN-DBpedia 爲例看下知識圖譜大致是怎麼構建的。

這裏寫圖片描述

這裏寫圖片描述

上圖分別是 CN-DBpedia 的構建流程和系統架構。知識圖譜的構建是一個浩大的工程,從大方面來講,分爲知識獲取、知識融合、知識驗證、知識計算和應用幾個部分,也就是上面架構圖從下往上走的一個流程,簡單來走一下這個流程。


2.數據支持層

最底下是知識獲取及存儲,或者說是數據支持層,首先從不同來源、不同結構的數據中獲取知識,CN-DBpedia 的知識來源主要是通過爬取各種百科知識這類半結構化數據。

至於數據存儲,要考慮的是選什麼樣的數據庫以及怎麼設計 schema。選關係數據庫還是NoSQL 數據庫?要不要用內存數據庫?要不要用圖數據庫?這些都需要根據數據場景慎重選擇。

CN-DBpedia 實際上是基於 mongo 數據庫,參與開發的謝晨昊提到,一般只有在基於特定領域纔可能會用到圖數據庫,就知識圖譜而言,基於 json (bson) 的 mongo 就足夠了。用到圖查詢的領域如徵信,一般是需要要找兩個公司之間的關聯交易,會用到最短路徑/社區計算等。

schema 的重要性不用多說,高質量、標準化的 schema 能有效降低領域數據之間對接的成本。我們希望達到的效果是,對於任何數據,進入知識圖譜後後續流程都是相同的。換言之,對於不同格式、不同來源、不同內容的數據,在接入知識圖譜時都會按照預定義的 schema 對數據進行轉換和清洗,無縫使用已有元數據和資源。


3.知識融合層

我們知道,目前分佈在互聯網上的知識常常以分散、異構、自治的形式存在,另外還具有冗餘、噪音、不確定、非完備的特點,清洗並不能解決這些問題,因此從這些知識出發,通常需要融合和驗證的步驟,來將不同源不同結構的數據融合成統一的知識圖譜,以保證知識的一致性。

所以數據支持層往上一層實際上是融合層,主要工作是對獲取的數據進行標註、抽取,得到大量的三元組,並對這些三元組進行融合,去冗餘、去衝突、規範化。

第一部分 SPO 三元組抽取,對不同種類的數據用不同的技術提取:

從結構化數據庫中獲取知識:D2R

難點:複雜表數據的處理

從鏈接數據中獲取知識:圖映射

難點:數據對齊

從半結構化(網站)數據中獲取知識:使用包裝器

難點:方便的包裝器定義方法,包裝器自動生成、更新與維護

從文本中獲取知識:信息抽取

難點:結果的準確率與覆蓋率

尤其是純文本數據會涉及到的實體識別、實體鏈接、實體關係識別、概念抽取 等,需要用到許多自然語言處理的技術,包括但不僅限於分詞、詞性標註、分佈式語義表達、篇章潛在主題分析、同義詞構建、語義解析、依存句法、語義角色標註、語義相似度計算等等。

第二部分纔到融合,目的是將不同數據源獲取的知識進行融合構建數據之間的關聯。包括實體對齊、屬性對齊、衝突消解、規範化等,這一部分很多都是 dirty work,更多的是做一個數據的映射、實體的匹配,可能還會涉及的是本體的構建和融合。最後融合而成的知識庫存入上一部分提到的數據庫中。如有必要,也需要如 Spark 等大數據平臺提供高性能計算能力,支持快速運算。

知識融合的四個難點:

實現不同來源、不同形態數據的融合

海量數據的高效融合

新增知識的實時融合

多語言的融合


4.知識驗證

再往上一層主要是驗證,分爲補全、糾錯、外鏈、更新各部分,確保知識圖譜的一致性和準確性。

一個典型問題是,知識圖譜的構建不是一個靜態的過程,當引入新知識時,需要判斷新知識是否正確,與已有知識是否一致,如果新知識與舊知識間有衝突,那麼要判斷是原有的知識錯了,還是新的知識不靠譜?這裏可以用到的證據可以是權威度、冗餘度、多樣性、一致性等。如果新知識是正確的,那麼要進行相關實體和關係的更新。


5.知識計算和應用

這一部分主要是基於知識圖譜計算功能以及知識圖譜的應用。知識計算主要是根據圖譜提供的信息得到更多隱含的知識,像是通過本體或者規則推理技術可以獲取數據中存在的隱含知識;通過鏈接預測預測實體間隱含的關係;通過社區計算在知識網絡上計算獲取知識圖譜上存在的社區,提供知識間關聯的路徑……通過知識計算知識圖譜可以產生大量的智能應用如專家系統、推薦系統、語義搜索、問答等。

知識圖譜涉及到的技術非常多,每一項技術都需要專門去研究,而且已經有很多的研究成果。Anyway 這章不是來論述知識圖譜的具體技術,而是講怎麼做一個 hello world 式的行業知識圖譜。

這裏講兩個小 demo,一個是爬蟲+mysql+d3 的小型知識圖譜,另一個是基於 CN-DBpedia+爬蟲+PostgreSQL+d3 的”增量型”知識圖譜,要實現的是某行業上市公司與其高管之間的關係圖譜。


6.數據獲取

第一個重要問題是,我們需要什麼樣的知識?需要爬什麼樣的數據?

一般在數據獲取之前會先做個知識建模,建立知識圖譜的數據模式,可以採用兩種方法:一種是自頂向下的方法,專家手工編輯形成數據模式;另一種是自底向上的方法,基於行業現有的標準進行轉換或者從現有的高質量行業數據源中進行映射。數據建模都過程很重要,因爲標準化的 schema 能有效降低領域數據之間對接的成本。

作爲一個簡單的 demo,我們只做上市公司和高管之間的關係圖譜,企業信息就用公司註冊的基本信息,高管信息就用基本的姓名、出生年、性別、學歷這些。

然後開始寫爬蟲,爬蟲看着簡單,實際有很多的技巧,怎麼做優先級調度,怎麼並行,怎麼屏蔽規避,怎麼在遵守互聯網協議的基礎上最大化爬取的效率,有很多小的 trick,之前博客裏也說了很多,就不展開了,要注意的一點是,高質量的數據來源是成功的一半!

來扯一扯爬取建議:

從數據質量來看,優先考慮權威的、穩定的、數據格式規整且前後一致、數據完整的網頁

從爬取成本來看,優先考慮免登錄、免驗證碼、無訪問限制的頁面

爬下來的數據務必保存好爬取時間、爬取來源(source)或網頁地址(url)

source 可以是新浪財經這類的簡單標識,url 則是網頁地址,這些在後續數據清洗以及之後的糾錯(權威度計算)、外鏈和更新中非常重要

企業信息可以在天眼查、啓信寶、企查查各種網站查到,信息還蠻全的,不過有訪問限制,需要註冊登錄,還有驗證碼的環節,當然可以過五關斬六將爬到我們要的數據,然而沒這個必要,換別個網站就好。

推薦兩個數據來源: 中財網數據引擎和巨潮資訊,其中巨潮資訊還可以同時爬取高管以及公告信息。

看一下數據:

這裏寫圖片描述

這裏寫圖片描述

換句話說,我們直接能得到規範的實體(公司、人),以及規範的關係(高管),當然也可以把高管展開,用下一層關係,董事長、監事之類,這就需要做進一步的清洗,也可能需要做關係的對齊。

這裏爬蟲框架我用的是 scrapy+redis 分佈式,每天可以定時爬取,爬下來的數據寫好自動化清洗腳本,定時入庫。


7.數據存儲

數據存儲是非常重要的一環,第一個問題是選什麼數據庫,這裏作爲 starter,用的是關係型數據庫 MySQL。設計了四張表,兩張實體表分別存公司(company)和人物(person)的信息,一張關係表存公司和高管的對應關係(management),最後一張 SPO 表存三元組。

爲什麼爬下來兩張表,存儲卻要用 4 張表?

一個考慮是知識圖譜裏典型的一詞多義問題,相同實體名但有可能指向不同的意義,比如說 Paris 既可以表示巴黎,也可以表示人名,怎麼辦?讓作爲地名的 “Paris” 和作爲人的 “Paris” 有各自獨一無二的ID。“Paris1”(巴黎)通過一種內在關係與埃菲爾鐵塔相聯,而 “Paris2”(人)通過取消關係與各種真人秀相聯。

這裏也是一樣的場景,同名同姓不同人,需要用 id 做唯一性標識,也就是說我們需要對原來的數據格式做一個轉換,不同的張三要標識成張三1,張三2… 那麼,用什麼來區別人呢?

拍腦袋想用姓名、生日、性別來定義一個人,也就是說我們需要一張人物表,需要(name, birth, sex)來作 composite unique key 表示每個人。公司也是相同的道理,不過這裏只有上市公司,股票代碼就可以作爲唯一性標識。

Person 表和 company 表是多對多的關係,這裏需要做 normalization,用 management 這張表來把多對多轉化爲兩個一對多的關係,(person_id, company_id)就表示了這種映射。

management 和 spo 表都表示了這種映射,爲什麼用兩張表呢?是出於實體對齊的考慮。management 保存了原始的關係,”董事”、監事”等,而 spo 把這些關係都映射成”高管”,也就是說 management 可能需要通過映射才能得到 SPO 表,SPO 纔是最終成型的表。

我們知道知識庫裏的關係其實有兩種,一種是屬性(property),一種是關係(relation)。那麼還有一個問題是 SPO 需不需要存儲屬性?

最初的想法是實體歸實體,屬性歸屬性,SPO 只存實體間的關係,屬性由實體表檢索得到,然而這樣的話需要多表 JOIN,屬性增加時擴展性也很差。因此把屬性也存到 SPO 表中。在 SPO 表中多加一列 type,來區分這關係是實體間關係還是實體與屬性的關係,便於之後的可視化。

這裏寫圖片描述

最後要注意的一點是,每條記錄要保存創建時間以及最後更新時間,做一個簡單的版本控制。


8.數據可視化

Flask 做 server,d3 做可視化,可以檢索公司名/人名獲取相應的圖譜,如下圖。之後會試着更新有向圖版本。

這裏寫圖片描述


9.Start from CN-DBpedia

把 CN-DBpedia 的三元組數據,大概 6500 萬條,導入數據庫,這裏嘗試了 PostgreSQL。然後檢索了 112 家上市公司的註冊公司名稱,只有 69 家公司返回了結果,屬性、關係都不是很完善,說明了通用知識圖譜有其不完整性。

也有可能需要先做一次 mention2entity,可能它的標準實體並不是註冊信息的公司名稱,不過 API 小範圍試了下很多是 Unknown Mention。

做法也很簡單,把前面 Start from scratch 中得到的 SPO 表插入到這裏的 SPO 表就好了。這麼簡單?因爲這個場景下不用做實體對齊和關係對齊。


10.拓展

這只是個 hello world 項目,在此基礎上可以進行很多有趣的拓展,最相近的比如說加入企業和股東的關係,可以進行企業最終控制人查詢(e.g.,基於股權投資關係尋找持股比例最大的股東,最終追溯至自然人或國有資產管理部門)。再往後可以做企業社交圖譜查詢、企業與企業的路徑發現、企業風險評估、反欺詐等等等等。

具體來說:

重新設計數據模型 引入”概念”,形成可動態變化的“概念—實體—屬性—關係”數據模型,實現各類數據的統一建模;

擴展多源、異構數據,結合實體抽取、關係抽取等技術,填充數據模型;

展開知識融合(實體鏈接、關係鏈接、衝突消解等)、驗證工作(糾錯、更新等)。

最後補充一下用 Neo4j 方式產生的可視化圖,有兩種方法。

一是把上面說到的 MySQL/PostgreSQL 裏的 company 表和 person 表存成 node,node 之間的關係由 spo 表中 type == relation 的 record 中產生;

二是更直接的,從 spo 表中,遇到 type == property 就給 node(subject) 增加屬性 ({predicate:object}),遇到 type == relation 就給 node 增加關係 ((Nsubject) - [r:predicate]-> node(Nobject)),得到下面的圖,移動鼠標到相應位置就可以在下方查看到關係和節點的屬性。

這裏寫圖片描述

作者丨徐阿衡

學校丨卡耐基梅隆大學碩士

研究方向丨QA系統

發佈了201 篇原創文章 · 獲贊 672 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章