[譯] 自然語言處理真是有趣!

計算機如何理解人類的語言

計算機擅長處理結構化的數據,像電子表格和數據庫表之類的。但是我們人類的日常溝通是用詞匯來表達的,而不是表格,對計算機而言,這真是件棘手的事。

[譯] 自然語言處理真是有趣!的圖1

遺憾的是,我們并不是生活在處處都是結構化數據的時代。

這個世界上的許多信息都是非結構化的 —— 不僅僅是英語或者其他人類語言的原始文本。我們該如何讓一臺計算機去理解這些非結構化的文本并且從中提取信息呢?

[譯] 自然語言處理真是有趣!的圖2

自然語言處理,簡稱 NLP,是人工智能領域的一個子集,目的是為了讓計算機理解并處理人類語言。讓我們來看看 NLP 是如何工作的,并且學習一下如何用 Python 寫出能夠從原始文本中提取信息的程序。

注意:如果你不關心 NLP 是如何工作的,只想剪切和粘貼一些代碼,直接跳過至“用 Python 處理 NLP 管道”部分。

計算機能理解語言嗎?

自從計算機誕生以來,程序員們就一直嘗試去寫出能夠理解像英語這樣的語言的程序。這其中的原因顯而易見 —— 幾千年來,人類都是用寫的方式來記錄事件,如果計算機能夠讀取并理解這些數據將會對人類大有好處。

目前,計算機還不能像人類那樣完全了解英語 —— 但它們已經能做許多事了!在某些特定領域,你能用 NLP 做到的事看上去就像魔法一樣。將 NLP 技術應用到你的項目上能夠為你節約大量時間。

更好的是,在 NLP 方面取得的最新進展就是可以輕松地通過開源的 Python 庫比如 spaCy、textacy 和 neuralcoref 來進行使用。你需要做的只是寫幾行代碼。

從文本中提取含義是很難的

讀取和理解英語的過程是很復雜的 —— 即使在不考慮英語中的邏輯性和一致性的情況下。比如,這個新聞的標題是什么意思呢?

環境監管機構盤問了非法燒烤的業主。(“Environmental regulators grill business owner over illegal coal fires.”)

環境監管機構就非法燃燒煤炭問題對業主進行了詢問?或者按照字面意思,監管機構把業主烤了?正如你所見,用計算機來解析英語是非常復雜的一件事。

在機器學習中做一件復雜的事通常意味著建一條管道。這個辦法就是將你的問題分成細小的部分,然后用機器學習來單獨解決每一個細小的部分。再將多個相互補充的機器學習模型進行鏈接,這樣你就能搞定非常復雜的事。

而且這正是我們將要對 NLP 所使用的策略。我們將理解英語的過程分解為多個小塊,并觀察每個小塊是如何工作的。

一步步構建 NLP 管道

讓我們看一段來自維基百科的文字:

倫敦是英格蘭首都,也是英國的人口最稠密的城市。倫敦位于英國大不列顛島東南部泰晤士河畔,兩千年來一直是一個主要定居點。它是由羅馬人建立的,把它命名為倫蒂尼恩。(London is the capital and most populous city of England and the United Kingdom. Standing on the River Thames in the south east of the island of Great Britain, London has been a major settlement for two millennia. It was founded by the Romans, who named it Londinium.)

(來源:維基百科“倫敦”

這段文字包含了幾個有用的信息。如果電腦能夠閱讀這段文字并且理解倫敦是一個由羅馬人建立的,位于英國的城市等等,那就最好不過了。但是要達到這個要求,我們需要先將有關書面知識的最基本的概念傳授給電腦,然后不斷深入。

步驟一:語句分割

在管道中所要做的第一件事就是將這段文字分割成獨立的句子,由此我們可以得到:

  1. “倫敦是英國的首都,也是英格蘭和整個聯合王國人口最稠密的城市。(London is the capital and most populous city of England and the United Kingdom.)”

  2. “位于泰晤士河流域的倫敦,在此后兩個世紀內為這一地區最重要的定居點之一。(Standing on the River Thames in the south east of the island of Great Britain, London has been a major settlement for two millennia.)”

  3. 它由羅馬人建立,取名為倫蒂尼恩。(It was founded by the Romans, who named it Londinium.)”

我們假設每一個句子都代表一個獨立的想法。那么相較于能理解整篇文章的程序而言,我們可以更加容易地寫出能夠理解獨立語句的程序。

創建一個語句分割模型就像使用標點符號來分割語句一樣簡單。但是現代 NLP 管道通常需要更加復雜的技術來解決文檔排版不整齊的情況。

第二步:文字符號化

現在我們已經把文檔分割成了句子,我們可以一步一步地處理這些句子,讓我們從文檔中的第一個句子開始:

“London is the capital and most populous city of England and the United Kingdom.”

下一步就是在管道中將這個句子分割成獨立的詞語或符號。這就稱作分詞。接下來看看對這個句子分詞的結果:

“London”, “is”, “ the”, “capital”, “and”, “most”, “populous”, “city”, “of”, “England”, “and”, “the”, “United”, “Kingdom”, “.”

分詞在英語中是容易完成的。我們只要分割那些空格分隔的詞語。我們也將標點符號作為單詞,因為它們也具有含義。

第三步:猜測每個詞的屬性

接下來,我們需要猜測一下每一個詞的屬性 —— 名詞,動詞和形容詞等等。知道每個詞在句子中所扮演的角色之后,就能夠幫助我們推斷句子的含義。

要知道詞的屬性,我們可以將每個詞(包括一些上下文的詞)提供給預先訓練的詞性分類模型:


Y(6PQ{CAAI8QSN7CRYD0]}I.png

詞性分類模型在最初通過數百萬個英語句子的訓練,這些句子中每個詞的屬性都已經被標記,并以此讓模型學會復制這種標記的行為。

記住,這個模型是基于統計數據的 —— 它并不是以和人類一樣的方式理解詞的含義。它所知道的只是如何依靠之前標記的類似單詞和句子來猜測語句的含義。

在處理完整個句子之后,我們會得出這樣的結果:

[譯] 自然語言處理真是有趣!的圖4

根據這些信息,我們已經能夠開始搜集一些非?;A的含義。比如,這個句子中的名詞包括“倫敦”和“首都”,所以這個句子極有可能是與倫敦有關的。

第四步:文本詞形還原

在英語(以及其它大多數語言)中,詞語以不同的形式出現。來看看下面這兩個句子:

I had a pony.

I had two ponies.

兩句話都講到了名詞小馬 (pony),但是它們有著不同的詞形變化。知道詞語的基本形式對計算機處理文本是有幫助的,這樣你就能知道兩句話在討論同一個概念。否則,“pony” 和 “ponies” 對于電腦來說就像兩個完全不相關的詞語。

在 NLP 中,我們稱這個過程為詞形還原 —— 找出句子中每一個詞的最基本的形式或詞元。

對于動詞也一樣。我們也能夠通過尋找動詞最初的非結合形式來進行詞形還原。所以 “I had two ponies” 變為 “I [have] two [pony]”。

詞形還原一般是通過具有基于其詞性的詞匯形式的查找表來完成工作的,并且可能具有一些自定義的規則來處理之前從未見過的詞語。

這就是經過詞形還原添加動詞最初形式的句子:

[譯] 自然語言處理真是有趣!的圖5

唯一變化的地方就是將 “is” 變為 “be”。

第五步:識別終止詞

接下來,我們需要考慮句子中的每個單詞的重要性。英語有很多頻繁出現的填充詞比如 “and”、“the” 和 “a”。 在對文本進行統計的時候,隨著這些詞出現頻率的升高,將會出現很多歧義。一些 NLP 管道將這些詞語標記為“終止詞” —— 在進行任何分析之前需要過濾掉的詞語。

這就是將終止詞過濾掉之后的句子:

[譯] 自然語言處理真是有趣!的圖6

終止詞的識別通常是由查詢一個硬編碼的已知終止詞列表來完成。但是不存在對于所有應用來說通用的標準終止詞列表。這個列表極大程度上是由你的應用所決定的。

舉個例子,如果你正在建立一個與搖滾樂隊有關的搜索引擎,需要確保你沒有忽略單詞 “The”。不僅是因為這個單詞出現在很多樂隊名中,而且還有一個 80 年代的著名搖滾樂隊叫做 The The!

第六步:依存語法解析

下一步就是找出句子中的每一個詞之間的依存關系,這就做依存語法解析。

目標就是構建一棵樹,為句子中的每一個詞賦予一個父類詞語。樹的根是句子中的主要動詞。根據這個句子構造的解析樹的開頭就是這個樣子:

[譯] 自然語言處理真是有趣!的圖7

但我們還可以做的更多。為了識別每一個詞的父類詞,我們還可以預測這兩個詞之間存在的關系:

[譯] 自然語言處理真是有趣!的圖8

這顆解析樹為我們展示了這個句子的主體是名詞倫敦,而且它和首都之間有著 be 關系。我們最終發現了一些有用的信息 —— 倫敦是一個首都!如果我們遵循著這個句子的整顆解析樹(不僅是圖示信息),甚至能夠發現倫敦是英國的首都。

就像我們早前使用機器學習模型來預測詞性那樣,以將詞語輸入機器學習模型并輸出結果的方式來完成依存語法分析。 但是分析依存語法是一項十分復雜的任務,它需要用一整篇文章來作為分析某些細節的上下文。 如果你很好奇它是如何工作的,有一篇作者為 Matthew Honnibal 的優秀文章值得一讀 用 500 行 Python 代碼來解析英語 (Parsing English in 500 Lines of Python)。

但是盡管這位作者在 2015 年發表了一條說明稱這種方法現在已成為標準,但它已經過時甚至不再被作者使用過。在 2016 年,谷歌推出了一種新的依存語法分析方法,稱為 Parsey McParseface,它采用了一種新的深度學習方法,超越了之前的表現,并在業界內快速流傳。一年之后,他們又發布了新的模型,稱為 ParseySaurus,對某些方面做了進一步改善。換句話說,解析技術依舊是搜索領域的一項熱門技術,并且在不斷地變化和改進。

很多英語語句是十分模糊且難以解析的,這一點需要牢記在心。在那些例子中,模型會根據之前解析過的最相似的句子來進行猜測,但這并不完美,有時這個模型會產生令人尷尬的錯誤。但隨著時間的推移,我們的 NLP 模型將會繼續以合理的方式更好地解析文本。

想要在你自己的句子上試一試依存語法解析嗎?這是來自 spaCy 團隊的一個很棒的互動演示。

第六步(下):查找名詞短語

到現在為止,我們將句子中的每一個詞語都作為一個獨立的實體。但有時將一些詞語連接起來能夠更加合理地表達一個想法或事件。我們能夠用依存關系解析樹中的信息來自動地將所有闡述相同事物的詞語組合在一起。

舉個例子,比如這一個:

[譯] 自然語言處理真是有趣!的圖9

我們可以將名詞短語組合在一起達到這樣的結果:

[譯] 自然語言處理真是有趣!的圖10

我們要根據最終目標來決定是否要進行這一步。但是如果我們并不需要得到哪些詞是形容詞這些額外細節而是更關注抽取句子中的完整含義,這通常是簡化句子一個簡單的方法。

第七步:命名實體識別(NER)

現在我們已經完成所有困難的工作,終于可以拋棄書面的語法并開始動手實現想法了。

在我們的句子中,有著以下名詞:

[譯] 自然語言處理真是有趣!的圖11

這些名詞中,有一部分與實際意義相同。比如說“倫敦”、“英格蘭”和“英國”代表了地圖上的物理位置。如果能檢測到這些那真是太棒了!有了這些信息,我們就能夠使用 NLP 在自動地提取一個在文檔中提及的真實世界地理位置列表。

命名實體識別NER)的目標就是為了檢測和標記這些代表真實世界中某些事物的名詞。在使用我們的 NER 標記模型對句子中的每個詞語進行處理之后,句子就變成這樣:

[譯] 自然語言處理真是有趣!的圖12

但 NER 系統并不只是做這些簡單的查找字典的工作。而是使用某個詞語在句子中的上下文以及統計模型來猜測某個詞語代表哪種類型的名詞。一個優秀的 NER 系統能夠根據上下文線索辨別出人名 “Brooklyn Decker” 和 地名 “Brooklyn”。

這些是經典的 NER 系統能夠標記的事物:

  • 人名

  • 公司名

  • 地理位置(物理位置和政治位置)

  • 產品名稱

  • 日期和時間

  • 金額

  • 事件名稱

自從 NER 能夠幫助輕易地從文本中獲取結構化數據,便被廣泛使用。它是從 NLP 管道中獲得結果的最便捷途徑之一。

想自己試一試專名識別技術嗎?這是來自 spaCy 團隊的另一個很棒的互動演示。

第八步:共指解析

在此刻,我們已經對句子有了充分的了解。我們了解了每個詞語的詞性、詞語之間的依存關系以及哪些詞語是代表命名實體的。

可是,我們還需要解決一個大問題。英語中存在著大量的代詞 —— 比如、。這些是我們對在句子中反復出現的名稱的簡化。人們能夠根據上下文來得到這些詞代表的內容。但是我們的 NLP 模型并不知道這些代詞的含義,因為它每次只檢查一個句子。

來看看我們的文檔中的第三個句子:

“It was founded by the Romans, who named it Londinium.”

如果我們用 NLP 管道解析這個句子,我們就能知道“它”是由羅馬人建立的。但如果能知道“倫敦”是由羅馬人建立的那會更有用。

當人們讀這個句子時,能夠很容易得出“它”代表“倫敦”。共指解析的目的是根據整個句子中的代詞來找出這種相同的映射。我們是想要找出所有指向同一實體的詞語。

這就是在我們的文檔中對“倫敦”使用共指解析的結果:

[譯] 自然語言處理真是有趣!的圖13

將共指信息、解析樹和命名實體信息結合在一起,我們就能夠從這個文檔中提取出很多信息!

共指解析是我們正在進行工作的管道中的最艱難步驟之一。它甚至比語句解析還要困難。深度學習的最新進展帶來更精確的方法,但它還不夠完美。如果你想多了解一下它是如何工作的,從這里開始。

想要參與協作共指解析?看看這個來自 Hugging Face 的協作共指解析演示。

用 Python 來構建 NLP 管道

這是我們的完整 NLP 管道的概覽:

[譯] 自然語言處理真是有趣!的圖14

共指解析是一項并不總要完成的可選步驟。

哎呀,有好多步驟啊!

注意:在我們往下看之前,值得一提的是,這些都是構建傳統 NLP 管道的步驟,你可以根據你的目的以及如何實現你的 NLP 庫來決定是跳過還是重復某些步驟。舉個例子,一些像 spaCy 這樣的庫,是先使用依存語法解析,得出結果后再進行語句分割。

那么,我們該如何構建這個管道?多謝像 spaCy 這樣神奇的 python 庫,管道的構建工作已經完成!所有的步驟都已完成,時刻準備為你所用。

首先,假設你已經安裝了 Python 3,你可以按如下步驟來安裝 spaCy:

# 安裝 spaCy  pip3 install -U spacy # 下載針對 spaCy 的大型英語模型 python3 -m spacy download en_core_web_lg # 安裝同樣大有用處的 textacy pip3 install -U textacy 復制代碼

在一段文檔中運行 NLP 管道的代碼如下所示:

import spacy # 加載大型英語模型 nlp = spacy.load('en_core_web_lg') # 我們想要檢驗的文本 text = """London is the capital and most populous city of England and  the United Kingdom.  Standing on the River Thames in the south east  of the island of Great Britain, London has been a major settlement  for two millennia. It was founded by the Romans, who named it Londinium. """ # 用 spaCy 解析文本. 在整個管道運行. doc = nlp(text) # 'doc' 現在包含了解析之后的文本。我們可以用它來做我們想做的事! # 比如,這將會打印出所有被檢測到的命名實體: for entity in doc.ents:     print(f"{entity.text} ({entity.label_})") 復制代碼

如果你運行了這條語句,你就會得到一個關于文檔中被檢測出的命名實體和實體類型的表:

London (GPE)   England (GPE)   the United Kingdom (GPE)   the River Thames (FAC)   Great Britain (GPE)   London (GPE)   two millennia (DATE)   Romans (NORP)   Londinium (PERSON) 復制代碼

你可以查看每一個實體代碼的含義

需要注意的是,它誤將 “Londinium” 作為人名而不是地名。這可能是因為在訓練數據中沒有與之相似的內容,不過它做出了最好的猜測。如果你要解析具有專業術語的文本,命名實體的檢測通常需要做一些微調。

讓我們把這實體檢測的思想轉變一下,來做一個數據清理器。假設你正在嘗試執行新的 GDPR 隱私條款并且發現你所持有的上千個文檔中都有個人身份信息,例如名字。現在你的任務就是移除文檔中的所有名字。

如果將上千個文檔中的名字手動去除,需要花上好幾年。但如果用 NLP,事情就簡單了許多。這是一個移除檢測到的名字的數據清洗器:

 import spacy # 加載大型英語 NLP 模型 nlp = spacy.load('en_core_web_lg') # 如果檢測到名字,就用 "REDACTED" 替換 def replace_name_with_placeholder(token):     if token.ent_iob != 0 and token.ent_type_ == "PERSON":         return "[REDACTED] "     else:         return token.string # 依次解析文檔中的所有實體并檢測是否為名字 def scrub(text):     doc = nlp(text)     for ent in doc.ents:         ent.merge()     tokens = map(replace_name_with_placeholder, doc)     return "".join(tokens) s = """ In 1950, Alan Turing published his famous article "Computing Machinery and Intelligence". In 1957, Noam Chomsky’s  Syntactic Structures revolutionized Linguistics with 'universal grammar', a rule based system of syntactic structures. """ print(scrub(s)) 復制代碼

如果你運行了這個,就會看到它如預期般工作:

In 1950, [REDACTED] published his famous article "Computing Machinery and Intelligence". In 1957, [REDACTED]    Syntactic Structures revolutionized Linguistics with 'universal grammar', a rule based system of syntactic structures. 復制代碼

信息提取

開箱即用的 spaCy 能做的事實在是太棒了。但你也可以用 spaCy 解析的輸出來作為更復雜的數據提取算法的輸入。這里有一個叫做 textacy 的 python 庫,它實現了多種基于 spaCy 的通用數據提取算法。這是一個良好的開端。

它實現的算法之一叫做半結構化語句提取。我們用它來搜索解析樹,查找主體為“倫敦”且動詞是 “be” 形式的簡單語句。這將會幫助我們找到有關倫敦的信息。

來看看代碼是怎樣的:

import spacy import textacy.extract # 加載大型英語 NLP 模型 nlp = spacy.load('en_core_web_lg') # 需要檢測的文本 text = """London is the capital and most populous city of England and  the United Kingdom.   Standing on the River Thames in the south east of the island of Great Britain,  London has been a major settlement  for two millennia.  It was founded by the Romans,  who named it Londinium. """ # 用 spaCy 來解析文檔 doc = nlp(text) # 提取半結構化語句 statements = textacy.extract.semistructured_statements(doc, "London") # 打印結果 print("Here are the things I know about London:") for statement in statements:     subject, verb, fact = statement     print(f" - {fact}") 復制代碼

它打印出了這些:

Here are the things I know about London:  - the capital and most populous city of England and the United Kingdom.   - a major settlement for two millennia. 復制代碼

也許這不會太令人印象深刻。但如果你將這段代碼用于維基百科上關于倫敦的整篇文章上,而不只是這三個句子,就會得到令人印象十分深刻的結果:

Here are the things I know about London:  - the capital and most populous city of England and the United Kingdom    - a major settlement for two millennia    - the world's most populous city from around 1831 to 1925    - beyond all comparison the largest town in England    - still very compact    - the world's largest city from about 1831 to 1925    - the seat of the Government of the United Kingdom    - vulnerable to flooding    - "one of the World's Greenest Cities" with more than 40 percent green space or open water    - the most populous city and metropolitan area of the European Union and the second most populous in Europe    - the 19th largest city and the 18th largest metropolitan region in the world    - Christian, and has a large number of churches, particularly in the City of London    - also home to sizeable Muslim, Hindu, Sikh, and Jewish communities    - also home to 42 Hindu temples    - the world's most expensive office market for the last three years according to world property journal (2015) report    - one of the pre-eminent financial centres of the world as the most important location for international finance    - the world top city destination as ranked by TripAdvisor users    - a major international air transport hub with the busiest city airspace in the world    - the centre of the National Rail network, with 70 percent of rail journeys starting or ending in London    - a major global centre of higher education teaching and research and has the largest concentration of higher education institutes in Europe    - home to designers Vivienne Westwood, Galliano, Stella McCartney, Manolo Blahnik, and Jimmy Choo, among others    - the setting for many works of literature    - a major centre for television production, with studios including BBC Television Centre, The Fountain Studios and The London Studios    - also a centre for urban music    - the "greenest city" in Europe with 35,000 acres of public parks, woodlands and gardens    - not the capital of England, as England does not have its own government 復制代碼

現在事情變得有趣了起來!我們自動收集了大量的信息。

為了讓事情變得更有趣,試試安裝 neuralcoref 庫并且添加共指解析到你的管道。這將為你提供更多的信息,因為它會捕捉含有“它”的而不是直接表示“倫敦”的句子。

我們還能做什么?

看看這個 spaCy 文檔和 textacy 文檔,你會發現很多能夠用于解析文本的方法示例。目前我們所看見的只是一個小示例。

這里有另外一個實例:想象你正在構建一個能夠向用戶展示我們在上一個例子中提取出的全世界城市的信息的網站。

如果你的網站有搜索功能,能像谷歌那樣能夠自動補全常規的查詢就太好了:

[譯] 自然語言處理真是有趣!的圖15

谷歌對于“倫敦”的自動補全建議

如果這么做,我們就需要一個可能提供給用戶的建議列表。我們可以使用 NLP 來快速生成這些數據。

這是從文檔中提取常用名詞塊的一種方式:

import spacy import textacy.extract # 加載大型英語 NLP 模型 nlp = spacy.load('en_core_web_lg') # 需要檢測的文檔 text = """London is the capital and most populous city of England and  the United Kingdom.   Standing on the River Thames in the south east of the island of Great Britain,  London has been a major settlement  for two millennia.  It was founded by the Romans,  who named it Londinium. """ # 用 spaCy 解析文檔 doc = nlp(text) # 提取半結構化語句 statements = textacy.extract.semistructured_statements(doc, "London") # 打印結果 print("Here are the things I know about London:") for statement in statements:     subject, verb, fact = statement     print(f" - {fact}") 復制代碼

如果你用這段代碼來處理維基百科上關于倫敦的文章,就會得到如下結果:

westminster abbey   natural history museum   west end   east end   st paul's cathedral   royal albert hall   london underground   great fire   british museum   london eye .... etc .... 復制代碼

更進一步

這只是你可以用 NLP 做到的事中的一個小示例。在以后的文章中,我們將會談論一些其他的應用,例如文本分類或亞馬遜 Alexa 系統是如何解析問題的。

但目前要做的事,就是安裝 spaCy 并使用它。如果你不是 Python 程序員并且使用不同的 NLP 庫,這種想法應該也能奏效。

登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP