從文本到知識:Neo4j 圖數據庫 + NLP (自然語言處理) 實現案例

        我們現在處於“大數據時代”,而在浩繁的“大數據”中,絕大多數是文本形式的非結構化數據。圖其實可以非常靈活和有效地表示和處理文本內容中的詞語、概念、依存關係,並用作知識推理、情感分析、智能問答等豐富的應用中。

        本文以百度雲的自然語言處理API服務爲例,介紹怎樣將文本分析的結果保存到Neo4j圖數據庫中。

1、準備

        Neo4j圖數據庫3.5.*。

        APOC擴展包。關於如何安裝APOC,請參見這裏。我們要用到APOC中訪問RESTful API的過程。關於APOC的介紹,請參見這篇文章

        一個百度雲賬號,並可以訪問百度智能雲

 

2、創建百度雲NLP應用

       在百度雲控制檯中選擇並創建一個“自然語言應用”:

        對於有限的NLP API調用是免費的。把上面頁面中的AppID和 API Key的內容保存下來,我們後面要用到。

 

3、從Neo4j中訪問百度NLP API

3.1 概述

       Neo4j的APOC擴展包提供豐富的過程和函數。要調用任何API,可以使用下面的過程:

  • apoc.load.json:最簡單的URL訪問,請求不帶參數。URL可以是遠程的,也可以是文件。
  • apoc.load.jsonParams:帶參數/payload的API調用過程,還可以指定JSON Path對結果進行過濾。這是我們下面要用的過程。
  • apoc.load.jsonArray:與apoc.load.json類似,內容中可以包含JSON Array。
  • apoc.import.json:導入由apoc.export.json導出的JSON數據文件。

        關於相關過程的詳細文檔,請參見Neo4j文檔

3.2 獲取Access Token

       首先需要向授權服務地址https://aip.baidubce.com/oauth/2.0/token發送請求(推薦使用POST),並在URL中帶上以下參數:

  • grant_type: 必須參數,固定爲client_credentials
  • client_id: 必須參數,應用的API Key;(參見第2部分)
  • client_secret: 必須參數,應用的Secret Key(參見第2部分)。

      例如:

https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=??????&client_secret=???????

       在返回的JSON數據中可以看到access_token,例如:

      "access_token":"24.1170ea9dfdfe1edbce3830b78e92b4a0.2592000.1592653389.282335-19996420",

3.3 對句子進行詞法分析

      詞法分析對文本內容進行分詞、詞性標註和專名識別;該操作識別出文本串中的基本詞彙(分詞),對這些詞彙進行重組、標註組合後詞彙的詞性,並進一步識別出命名實體。

       可以先測試一下,看看返回的分詞結果是怎樣的(注意:請使用你自己的access_token替換下面的access_toekn參數值):

'{"text": "Neo4j是全球領先的圖數據庫軟件"}', null, {}) YIELD value
RETURN value
 
       上面我們使用了apoc.load.jsonParams(urlOrKey :: STRING?, headers :: MAP?, payload :: STRING?, path = :: STRING?, config = {} :: MAP?) :: (value :: MAP?))。該過程除了指定API的URL外,還可以將HTTP Header,payload和jsonpath作爲參數傳遞給調用操作。
 
       返回的結果保存在value變量中,內容格式如下:
 
{
  "log_id": 4752890392005512214,
  "items": [
    {
      "formal": "",
      "loc_details": [],
      "item": "Neo4j",
      "pos": "nz",
      "ne": "",
      "basic_words": [
        "Neo4j"
      ],
      "byte_length": 5,
      "byte_offset": 0,
      "uri": ""
    },
    {
      "formal": "",
      "loc_details": [],
      "item": "是",
      "pos": "v",
      "ne": "",
      "basic_words": [
        "是"
      ],
      "byte_length": 3,
      "byte_offset": 5,
      "uri": ""
    },
    ... ... 
}

       結果中,每個詞語及其屬性包含在items列表中返回。在Cypher中可以使用諸如value.items[0].item的形式訪問詞語的內容。

       下面是調用百度詞法分析API對兩個句子進行分析的完整Cypher查詢: 

// ***************** 開始 ************************
// 初始化文本內容數組
WITH ["Neo4j是全球領先的圖數據庫軟件", "Neo4j於2007年在瑞典創建"] AS sentences
UNWIND sentences AS sentence
// 使用百度雲NLP對句子進行分詞,然後創建句子和詞的關係圖譜
CALL apoc.load.jsonParams(
'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token=24.1170ea9dfdfe1edbce3830b78e92b4a0.2592000.1592653389.282335-19996420', {},
'{"text": "'+sentence + '"}', null, {}) YIELD value
WITH value
CREATE (s:Sentence{text:value.text})
WITH value, s, value.items AS items
UNWIND items AS item
// 過濾掉助詞如'的'
WITH s, item WHERE item.pos <> 'u'
MERGE (a:Word{word:item.item})
  SET a.pos = item.pos, a.byte_offset = item.byte_offset, a.ne = item.ne, a.formal = item.formal, a.uri = item.uri
CREATE (s) <-[:IN_SENTENCE]- (a)
RETURN a
// ***************** 結束 ************************

        對於創建的Word節點,我們根據它們在句子中的位置(byte_offset屬性),創建先後關係: 

// 創建同一個句子的詞語之間的先後關係
MATCH (s:Sentence) <-[:IN_SENTENCE]- (w:Word)
WITH w ORDER BY w.byte_offset ASC
WITH collect (w) AS words
// 創建一個數組it, 其元素類型是整數序列,元素個數是所有詞的個數-1。該數組用作循環次數控制。
WITH words, range(0,size(words) - 2) AS it
UNWIND it AS i
WITH words[i] AS w1, words[i+1] AS w2
MERGE (w1) <-[:AFTER]- (w2)
RETURN w1, w2

        這裏,UNWIND語句的作用逐一取出it數組中的元素,以循環執行後面的語句,其作用類似於FOR EACH i IN it DO ...。執行完成後,我們可以得到下面的包含句子(Sentence)和詞語(Word)的圖:

 

3.4 對句子進行句法分析

        依存句法分析接口可自動分析文本中的依存句法結構信息,利用句子中詞與詞之間的依存關係來表示詞語的句法結構信息(如“主謂”、“動賓”、“定中”等結構關係),並用樹狀結構來表示整句的結構(如“主謂賓”、“定狀補”等)。有了依存結構信息,我們可以掌握詞語在句子中的作用,以及關於句子含義更豐富的描述。

        因爲我們的句子已經保存在Sentence節點中,這裏我們直接讀取、並運行句法分析。

// ***************** 開始 ************************
// 使用百度雲NLP對句子中的詞進行依存關係分析,然後創建句子和詞的關係圖譜
MATCH (s:Sentence)
WITH s
CALL apoc.load.jsonParams('https://aip.baidubce.com/rpc/2.0/nlp/v1/depparser?charset=UTF-8&access_token=24.1170ea9dfdfe1edbce3830b78e92b4a0.2592000.1592653389.282335-19996420', {},
'{"text": "'+ s.text +'","mode":1}', null, {}) YIELD value
WITH s, value, value.items AS items
UNWIND items AS item
// 更新詞的屬性。
// 這裏過濾掉助詞如'的'。注意這裏返回結果中代表詞性的屬性名是postag。
WITH s, item WHERE item.postag <> 'u'
MATCH (a:Word{word:item.word})
  SET a.id = item.id, a.head = item.head, a.deprel = item.deprel
WITH s  
// 根據分析結果創建詞之間的依存關係,該關係包含一個屬性代表依存關係類型
MATCH (s) <-[:IN_SENTENCE]- (w)  
WITH s,w WHERE w.head <> 0
MATCH (s) <-[:IN_SENTENCE]- (w1)
WHERE w.head = w1.id
MERGE (w) -[:DEPENDS_ON{type:w.deprel}]-> (w1)
RETURN w
// ***************** 結束 ************************

       再看看文本分析的結果圖:

       圖中關係舉例如下:

       (Neo4j) -[:DEPENDS_ON{type:'SBV'}]-> ('是') <-[:DEPENDS_ON{type:'VOB'}]- ('軟件') 

       SBV表示“主謂關係”,VOB表示“動賓關係”。當我們擁有這樣的關係結構,就可以回答簡單的問題例如“Neo4j是什麼”?“Neo4j什麼時候創建的?”。關於所有34種詞語依賴關係的說明,請參見百度自然語言處理文檔

      

4、總結

       百度的自然語言API提供豐富的處理功能,除了詞法分析和句法分析,還包括詞的向量表示、短語相似度分析、文本的情感分析等。通過與 Neo4j的有機結合,可以創建語義豐富的知識圖譜,實現內容推理、文本分類、聊天機器人等新穎的應用。

 

注:由於web文本編輯器的限制,上面的Cyher代碼中可能有不可見字符從而造成執行錯誤。請訪問Github下載正確的代碼。

 

https://github.com/Joshua-Yu/baidu-neo4j-nlp 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章