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

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

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

遺憾的是,咱們並非生活在到處都是結構化數據的時代。前端

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

天然語言處理,簡稱 NLP,是人工智能領域的一個子集,目的是爲了讓計算機理解並處理人類語言。讓咱們來看看 NLP 是如何工做的,而且學習一下如何用 Python 寫出可以從原始文本中提取信息的程序。android

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

計算機能理解語言嗎?

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

目前,計算機還不能像人類那樣徹底瞭解英語 —— 但它們已經能作許多事了!在某些特定領域,你能用 NLP 作到的事看上去就像魔法同樣。將 NLP 技術應用到你的項目上可以爲你節約大量時間。程序員

更好的是,在 NLP 方面取得的最新進展就是能夠輕鬆地經過開源的 Python 庫好比 spaCytextacyneuralcoref 來進行使用。你須要作的只是寫幾行代碼。github

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

讀取和理解英語的過程是很複雜的 —— 即便在不考慮英語中的邏輯性和一致性的狀況下。好比,這個新聞的標題是什麼意思呢?web

環境監管機構盤問了非法燒烤的業主。(「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」, 「.」

分詞在英語中是容易完成的。咱們只要分割那些空格分隔的詞語。咱們也將標點符號做爲單詞,由於它們也具備含義。

第三步:猜想每一個詞的屬性

接下來,咱們須要猜想一下每個詞的屬性 —— 名詞,動詞和形容詞等等。知道每一個詞在句子中所扮演的角色以後,就可以幫助咱們推斷句子的含義。

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

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

記住,這個模型是基於統計數據的 —— 它並非以和人類同樣的方式理解詞的含義。它所知道的只是如何依靠以前標記的相似單詞和句子來猜想語句的含義。

在處理完整個句子以後,咱們會得出這樣的結果:

根據這些信息,咱們已經可以開始蒐集一些很是基礎的含義。好比,這個句子中的名詞包括「倫敦」和「首都」,因此這個句子極有多是與倫敦有關的。

第四步:文本詞形還原

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

I had a pony.

I had two ponies.

兩句話都講到了名詞小馬 (pony),可是它們有着不一樣的詞形變化。知道詞語的基本形式對計算機處理文本是有幫助的,這樣你就能知道兩句話在討論同一個概念。不然,「pony」 和 「ponies」 對於電腦來講就像兩個徹底不相關的詞語。

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

對於動詞也同樣。咱們也可以經過尋找動詞最初的非結合形式來進行詞形還原。因此 「I had two ponies」 變爲 「I [have] two [pony]」。

詞形還原通常是經過具備基於其詞性的詞彙形式的查找表來完成工做的,而且可能具備一些自定義的規則來處理以前從未見過的詞語。

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

惟一變化的地方就是將 「is」 變爲 「be」。

第五步:識別終止詞

接下來,咱們須要考慮句子中的每一個單詞的重要性。英語有不少頻繁出現的填充詞好比 「and」、「the」 和 「a」。 在對文本進行統計的時候,隨着這些詞出現頻率的升高,將會出現不少歧義。一些 NLP 管道將這些詞語標記爲「終止詞」 —— 在進行任何分析以前須要過濾掉的詞語。

這就是將終止詞過濾掉以後的句子:

終止詞的識別一般是由查詢一個硬編碼的已知終止詞列表來完成。可是不存在對於全部應用來講通用的標準終止詞列表。這個列表極大程度上是由你的應用所決定的。

舉個例子,若是你正在創建一個與搖滾樂隊有關的搜索引擎,須要確保你沒有忽略單詞 「The」。不只是由於這個單詞出如今不少樂隊名中,並且還有一個 80 年代的著名搖滾樂隊叫作 The The

第六步:依存語法解析

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

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

但咱們還能夠作的更多。爲了識別每個詞的父類詞,咱們還能夠預測這兩個詞之間存在的關係:

這顆解析樹爲咱們展現了這個句子的主體是名詞倫敦,並且它和首都之間有着 be 關係。咱們最終發現了一些有用的信息 —— 倫敦是一個首都!若是咱們遵循着這個句子的整顆解析樹(不只是圖示信息),甚至可以發現倫敦是英國的首都。

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

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

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

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

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

到如今爲止,咱們將句子中的每個詞語都做爲一個獨立的實體。但有時將一些詞語鏈接起來可以更加合理地表達一個想法或事件。咱們可以用依存關係解析樹中的信息來自動地將全部闡述相同事物的詞語組合在一塊兒。

舉個例子,好比這一個:

咱們能夠將名詞短語組合在一塊兒達到這樣的結果:

咱們要根據最終目標來決定是否要進行這一步。可是若是咱們並不須要獲得哪些詞是形容詞這些額外細節而是更關注抽取句子中的完整含義,這一般是簡化句子一個簡單的方法。

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

如今咱們已經完成全部困難的工做,終於能夠拋棄書面的語法並開始動手實現想法了。

在咱們的句子中,有着如下名詞:

這些名詞中,有一部分與實際意義相同。好比說「倫敦」、「英格蘭」和「英國」表明了地圖上的物理位置。若是能檢測到這些那真是太棒了!有了這些信息,咱們就可以使用 NLP 在自動地提取一個在文檔中說起的真實世界地理位置列表。

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

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

這些是經典的 NER 系統可以標記的事物:

  • 人名
  • 公司名
  • 地理位置(物理位置和政治位置)
  • 產品名稱
  • 日期和時間
  • 金額
  • 事件名稱

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

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

第八步:共指解析

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

但是,咱們還須要解決一個大問題。英語中存在着大量的代詞 —— 好比。這些是咱們對在句子中反覆出現的名稱的簡化。人們可以根據上下文來獲得這些詞表明的內容。可是咱們的 NLP 模型並不知道這些代詞的含義,由於它每次只檢查一個句子。

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

「It was founded by the Romans, who named it Londinium.」

若是咱們用 NLP 管道解析這個句子,咱們就能知道「它」是由羅馬人創建的。但若是能知道「倫敦」是由羅馬人創建的那會更有用。

當人們讀這個句子時,可以很容易得出「它」表明「倫敦」。共指解析的目的是根據整個句子中的代詞來找出這種相同的映射。咱們是想要找出全部指向同一實體的詞語。

這就是在咱們的文檔中對「倫敦」使用共指解析的結果:

將共指信息、解析樹和命名實體信息結合在一塊兒,咱們就可以從這個文檔中提取出不少信息!

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

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

用 Python 來構建 NLP 管道

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

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

哎呀,有好多步驟啊!

注意:在咱們往下看以前,值得一提的是,這些都是構建傳統 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 文檔,你會發現不少可以用於解析文本的方法示例。目前咱們所看見的只是一個小示例。

這裏有另一個實例:想象你正在構建一個可以向用戶展現咱們在上一個例子中提取出的全世界城市的信息的網站。

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

谷歌對於「倫敦」的自動補全建議

若是這麼作,咱們就須要一個可能提供給用戶的建議列表。咱們可使用 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 庫,這種想法應該也能奏效。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索