【NLP】NLP中的消歧
作者 | Nesrine Sfar
作者 | Nesrine Sfar
編譯 | VK
來源 | Towards Data Science
如果你點(diǎn)開這篇文章,這意味著你有足夠的好奇心去學(xué)習(xí)關(guān)于NLP/NLU中解決歧義的不同方法。
背景信息是機(jī)器產(chǎn)生歧義的原因。這種模棱兩可的信息來源于人類在交流中使用的自然語言。將這種語言“翻譯”時(shí)可能會產(chǎn)生歧義。這可以用人類語言本身固有的不正式和模棱兩可來解釋。
傳統(tǒng)的方法是基于詞向量化。這里顯示的替代方法是基于知識圖。
本教程將通過一個(gè)簡單方便的應(yīng)用程序,即自然語言API(nl api),重點(diǎn)介紹一些可以用來解決這個(gè)問題的方法。

機(jī)器無法解釋或理解文本;要解決語言歧義,就需要對文本進(jìn)行多層次的語言分析。處理歧義的現(xiàn)象稱為“消歧”。這是幫助機(jī)器檢測文本意義(語義)的過程。詞義的確定要考慮語境、句法和詞語之間的關(guān)系。
下面的文章將強(qiáng)調(diào)不同的方法,可以用來幫助機(jī)器減少歧義,如詞形還原,詞性標(biāo)注等。
這項(xiàng)工作將基于一個(gè)名為expert.ai NL的API。
Expert.ai NL API
Expert.ai NL API是一個(gè)能夠通過幾行代碼在文本中提供多層次信息的應(yīng)用程序。
為了構(gòu)建NLP模塊,API提供了深入的語言處理技術(shù)。它可以進(jìn)行深層語言分析,例如token化、詞形還原、詞性標(biāo)注、形態(tài)/句法/語義分析。
除此之外,該庫還可以解決命名實(shí)體識別、實(shí)體間的語義關(guān)系和情感分析等問題。
1.如何使用Expert.ai NL API for Python?
庫的安裝
首先,你需要使用以下命令安裝客戶端庫:
pip install expertai-nlapi
一旦你在developer.expert.ai網(wǎng)站上創(chuàng)建了賬號,API就可用了。Python客戶端代碼將開發(fā)人員帳戶指定為環(huán)境變量:
Linux操作系統(tǒng):
export EAI_USERNAME=YOUR_USER
export EAI_PASSWORD=YOUR_PASSWORD
windows:
SET EAI_USERNAME=YOUR_USER
SET EAI_PASSWORD=YOUR_PASSWORD
你的用戶是你在注冊期間指定的電子郵件地址。
你還可以在代碼中定義:
import os
os.environ["EAI_USERNAME"] = 'YOUR_USER'
os.environ["EAI_PASSWORD"] = 'YOUR_PASSWORD'
2.深層語言分析
語言學(xué)把語言分析分成不同的部分。所有這些分支都是相互依存的,語言中的一切都是相互聯(lián)系的。
對文檔進(jìn)行多級文本分析;每一個(gè)文本被分成句子,這些句子被解析成token、詞形和詞性,尋找句法成分和謂詞之間的關(guān)系,并解釋語法以構(gòu)建完整的依賴樹。
要檢索這些信息,首先要導(dǎo)入庫的client:
from expertai.nlapi.cloud.client import ExpertAiClient
client = ExpertAiClient()
讓我們舉一個(gè)例子來說明這些操作:
"Sophia is a social humanoid robot developed by Hong Kong-based company Hanson Robotics. Sophia was activated on February 14, 2016.”
a.文本細(xì)分
這個(gè)操作允許將文本從最長的形式劃分到最小的形式,在這種情況下,可以是段落、句子,短語,token。當(dāng)token是一個(gè)搭配(復(fù)合詞)時(shí),文本細(xì)分可以在分析中得到更深入的分析,直到它不能被進(jìn)一步細(xì)分的原子級。
導(dǎo)入庫并實(shí)例化客戶端后,應(yīng)設(shè)置文本語言和API參數(shù):
text = "Sophia is a social humanoid robot developed by Hong Kong-based company Hanson Robotics. Sophia was activated on February 14, 2016."
language= 'en'
output = client.specific_resource_analysis(
body={"document": {"text": text}},
params={'language': language, 'resource': 'disambiguation'
})
在API請求中,應(yīng)該在主體中提到要分析的句子,在參數(shù)中提到要分析的語言。資源參數(shù)與你需要對文本執(zhí)行的操作有關(guān),例如,消除歧義。
這種多層次的文本分析通常分為三個(gè)階段:
1.詞法分析:一個(gè)文本細(xì)分階段,允許將文本分解為基本實(shí)體(token)。
2.句法分析:包括識別構(gòu)成句法實(shí)體的詞素組合(包括詞性標(biāo)注)。
3.語義分析:消歧是在這個(gè)層次上進(jìn)行的,它根據(jù)交際語境和它們之間可能的關(guān)系來檢測這些實(shí)體的意義。
詞匯分析從第一部分開始:
# 我們使用元素output.paragraphs分成幾個(gè)段落
# start和end是分析文本中段落的位置
for paragraph in output.paragraphs:
print (f'Paragraphs:{text[paragraph.start:paragraph.end]:{20}}')
Paragraphs: Sophia is a social humanoid robot developed by Hong Kong-based company Hanson Robotics. Sophia was activated on February 14, 2016.
因?yàn)槲覀兊奈谋疽呀?jīng)是一個(gè)段落(這里是兩句話),所以細(xì)分的輸出提供了與輸入相同的文本。讓我們嘗試將段落分成句子級別,在本例中,我們只需要將元素.paragraphs修改為.sentences。最常見的分隔句子的方法是用點(diǎn)(.):
# 我們使用output.sentences把文本細(xì)分成句子
# start和end是所分析文本中句子的位置
for sentence in output.sentences:
print (f'Sentences:{text[sentence.start:sentence.end]:{20}}')
Sentences: Sophia is a social humanoid robot developed by Hong Kong-based company Hanson Robotics.
Sentences: Sophia was activated on February 14, 2016.
結(jié)果我們得到了兩句話。讓我們更深入地進(jìn)行細(xì)分,以檢索短語級別。我們使用與上面相同的方法,用.phrases,得到:
# 我們使用output.sentences把文本細(xì)分成短語
# start和end是所分析文本中短語的位置
for phrase in output.phrases:
print (f'Phrases:{text[phrase.start:phrase.end]:{20}}')
Phrases: Sophia
Phrases: is a social humanoid robot
Phrases: developed
Phrases: by Hong Kong-based company Hanson Robotics
Phrases:.
Phrases: Sophia
Phrases: was activated
Phrases: on February 14, 2016
Phrases:.
我們注意到,我們得到更多的元素。我們還可以得到文本中短語的數(shù)量:
# 數(shù)量
print("phrases array size: ", len(output.phrases))
phrases array size: 10
b.token化
此外,我們可以將短語級別分解為更小的單位,即token。這是“token化”任務(wù),在NLP中非常常見。它幫助機(jī)器理解文本。要使用Python執(zhí)行token化,我們可以使用.split函數(shù),如下所示:
例如,考慮以下句子:
text = "CNBC has commented on the robot's lifelike skin and her ability to emulate more than 60 facial expressions."
tokens = text.split()
print('These are the tokens of the sentence', tokens)
These are the tokens of the sentence ['CNBC', 'has', 'commented', 'on', 'the', "robot's", 'lifelike', 'skin', 'and', 'her', 'ability', 'to', 'emulate', 'more', 'than', '60', 'facial', 'expressions.']
如果不在split中指定分隔符,文本將按空格分隔。
通過expert.ai NL API,我們還可以執(zhí)行token化,并提供其他特性。換句話說,API提供了不同的級別token分析;API產(chǎn)生的token可以是單詞、字符(如縮寫)甚至標(biāo)點(diǎn)符號。
讓我們看看如何使用API執(zhí)行此任務(wù),我們使用與上面相同的過程,使用.tokens修改element.phrases:
text = "CNBC has commented on the robot's lifelike skin and her ability to emulate more than 60 facial expressions."
language= 'en'
output = client.specific_resource_analysis(
body={"document": {"text": text}},
params={'language': language, 'resource': 'disambiguation'
})
# 打印到句子內(nèi)的token
print (f'{"TOKEN":{20}} ')
print (f'{"----":{20}}')
# 我們使用元素output.tokens將文本細(xì)分為token
# start和end是所分析文本中token的位置
for token in output.tokens:
print (f'{text[token.start:token.end]:{20}}')
TOKEN
----
CNBC
has
commented
on
the
robot
's
lifelike
skin
and
her
ability
to
emulate
more
than
60
facial expressions
.
我們注意到,這些token要么是像skin , ability, emulate這樣的單詞,要么是像‘s、60”這樣的縮寫,甚至是像點(diǎn).這樣的標(biāo)點(diǎn)符號。
token化會導(dǎo)致搭配,這在split函數(shù)中是不可能的。該API能夠根據(jù)單詞和上下文的位置檢測句子內(nèi)的復(fù)合詞。這種搭配還可以進(jìn)一步劃分為原子級,原子級是我們可以擁有的最后一個(gè)單位:
for token in output.tokens:
print (f'{text[token.start:token.end]:{20}}')
# 我們對token數(shù)組進(jìn)行迭代,將復(fù)合詞細(xì)分為原子級
for atom in token.atoms:
print (f'\t atom:{text[atom.start:atom.end]:{20}}')
CNBC
has
commented
on
the
robot
's
lifelike
skin
and
her
ability
to
emulate
more
than
60
facial expressions
atom: facial
atom: expressions
.
c.詞性標(biāo)注
token化導(dǎo)致了自然語言處理中的第二個(gè)過程,即詞性標(biāo)注(詞性標(biāo)注)。在這一階段,我們引入句法分析,其中包括詞性標(biāo)注任務(wù)。后者包括為每個(gè)token分配一個(gè)POS或一個(gè)語法類。
POS描述了每個(gè)token的句法性質(zhì)。這些標(biāo)簽可以反映文本的一部分含義。我們可以列出英語語言中常用的幾種詞性:限定詞、名詞、副詞、動(dòng)詞、形容詞、介詞、連詞、代詞、感嘆詞……
一個(gè)詞與其他詞有相同的形式(同形異義詞)可能有不同的含義(多義詞)。這個(gè)詞可以有不同的位置,即使它有相同的形式。語法類別取決于單詞在文本中的位置及其上下文。讓我們考慮這兩句話:
The object of this exercise is to raise money for the charity.
A lot of people will object to the book.
從語言學(xué)的角度來看,在第一個(gè)句子中,object是名詞,而在第二個(gè)句子中,object是動(dòng)詞。詞性標(biāo)注是消除歧義的關(guān)鍵步驟。根據(jù)這種標(biāo)注,單詞的含義可以從上下文、單詞的形式(例如,專有名詞開頭的大寫字母)、位置(SVO詞序)等推斷出來。
讓我們嘗試使用API為前兩句生成詞性標(biāo)注:
from expertai.nlapi.cloud.client import ExpertAiClient
client = ExpertAiClient()
我們首先導(dǎo)入庫并創(chuàng)建客戶端,如下所示:
object_noun表示object是名詞的句子,object_verb表示object是動(dòng)詞的句子:
object_noun = "The object of this exercise is to raise money for the charity."
object_verb = "A lot of people will object to the book."
單詞object在兩個(gè)句子中的形式相同,但位置不同。
首先,我們指定要進(jìn)行詞性標(biāo)注的文本,對于第一個(gè)句子,它是object_noun,對于第二個(gè)句子,它是object_verb。如下所示:
# 第一句話
object_noun = "The object of this exercise is to raise money for the charity."
# 第二句
object_verb = "A lot of people will object to the book."
language = 'en'
# 請求第一句話的API
output = client.specific_resource_analysis(
body={"document": {"text": object_noun}},
params={'language': language, 'resource': 'disambiguation'
})
# 請求第二句話的API
output_2 = client.specific_resource_analysis(
body={"document": {"text": object_verb}},
params={'language': language, 'resource': 'disambiguation'
})
一旦我們設(shè)置了這些參數(shù),就需要對token進(jìn)行迭代,分別為每個(gè)示例分配一個(gè)POS;
# 第一句的POS
print (f'\t \033[1mOutput of the first sentence : \033[0m \n')
# 在輸出數(shù)組的開始部分以粗體打印TOKEN和POS:
print (f'\033[1m{"TOKEN":{20}} {"POS":{6}}\033[0m')
# 迭代token,并為第一個(gè)句子的每個(gè)token分配POS
for token in output.tokens:
print (f'{object_noun[token.start:token.end]:{20}} {token.pos:{6}}')
# 第二句的POS
print (f'\t \033[1mOutput of the second sentence : \033[0m \n')
# 在輸出數(shù)組的開始部分以粗體打印TOKEN和POS:
print (f'\033[1m{"TOKEN":{20}} {"POS":{6}}\033[0m')
# 迭代token,并為第一個(gè)句子的每個(gè)token分配POS
for token in output_2.tokens:
print (f'{object_verb[token.start:token.end]:{20}} {token.pos:{6}}')
Output of the first sentence :
TOKEN POS
The DET
object NOUN
of ADP
this DET
exercise NOUN
is VERB
to PART
raise VERB
money NOUN
for ADP
the DET
charity NOUN
. PUNCT
Output of the second sentence :
TOKEN POS
A lot of ADJ
people NOUN
will AUX
object VERB
to ADP
the DET
book NOUN
. PUNCT
一方面,賓語確實(shí)是一個(gè)名詞,前面是冠詞/限定詞(DET)。另一方面,賓語實(shí)際上是句子的動(dòng)詞,它把主語“很多人”和賓語“書”聯(lián)系起來。
NLP中使用的傳統(tǒng)詞性標(biāo)注工具通常使用相同類型的信息來標(biāo)注文本中的單詞:其上下文和詞形。expert.Ai-NL-API中詞性標(biāo)注的獨(dú)特之處不僅在于為每個(gè)token識別一個(gè)語法標(biāo)簽,還在于介紹其含義。
換言之,一個(gè)詞可以和其他詞有相同的形式,但它包含多種含義(多義詞)。每一個(gè)意義都在一個(gè)概念中表達(dá),與其他概念聯(lián)系起來,形成一個(gè)知識圖。上面看到的單詞object有不止一個(gè)含義,因此,它屬于不同的語義概念,我們在expert.ai NL API的知識圖中稱之為“Syncons”。詞性標(biāo)注可以揭示同一個(gè)詞的不同標(biāo)簽,從而產(chǎn)生不同的意義。
# object_noun的Concept_ID
print (f'\t \033[1mConcept_ID for object when NOUN \033[0m \n')
# 在輸出數(shù)組的開始部分以粗體打印TOKEN、POS和ID:
print (f'\033[1m{"TOKEN":{20}} {"POS":{15}} {"ID":{6}}\033[0m')
# Syncon代表“概念”,我們用一個(gè)ID來表示
for token in output.tokens:
print (f'{object_noun[token.start:token.end]:{20}} {token.pos:{15}} {token.syncon:{6}} ')
# object_verb的Concept_ID
print (f'\t \033[1mConcept_ID for object when VERB \033[0m \n')
# 在輸出數(shù)組的開始部分以粗體打印TOKEN、POS和ID:
print (f'\033[1m{"TOKEN":{20}} {"POS":{15}} {"ID":{6}}\033[0m')
# Syncon代表“概念”,我們用一個(gè)ID來表示
for token in output_2.tokens:
print (f'{object_verb[token.start:token.end]:{20}} {token.pos:{15}} {token.syncon:{6}} ')
Concept_ID for object when NOUN
TOKEN POS ID
The DET -1
object NOUN 26946
of ADP -1
this DET -1
exercise NOUN 32738
is VERB 64155
to PART -1
raise VERB 63426
money NOUN 54994
for ADP -1
the DET -1
charity NOUN 4217
. PUNCT -1
Concept_ID for object when VERB
TOKEN POS ID
A lot of ADJ 83474
people NOUN 35459
will AUX -1
object VERB 65789
to ADP -1
the DET -1
book NOUN 13210
. PUNCT -1
可以注意到,名詞對象屬于ID為26946的概念。這個(gè)概念包括其他具有相同含義的詞(同義詞)。相比之下,它在第二句中的同形異義詞與ID 65789有關(guān)。這些ID是知識圖中每個(gè)概念的token。
因此,不同的詞性導(dǎo)致不同的意思,即使我們有相同的詞形。
請注意,以-1作為ID的單詞,如ADP(Adposition指介詞和后置詞)、PUNCT(表示標(biāo)點(diǎn)符號)、DET(表示限定詞)等,在知識圖中不可用,因?yàn)樗鼈儾皇枪逃械恼Z義。
d.詞形還原
這是自然語言處理中的另一個(gè)核心任務(wù),稱為詞形還原。它與token化和詞性標(biāo)注一樣重要。
簡而言之,詞形還原將每個(gè)token還原為它的規(guī)范形式:
動(dòng)詞的不定式:wore, worn -> wear / ran, running, runs -> run
名詞的單數(shù)形式:mice -> mouse / die -> dice
等等。…
概念通常可以包含許多詞形。在消歧過程中,文本中的每個(gè)token都返回到其基本形式。每個(gè)詞形都與知識圖中的一個(gè)概念相關(guān)聯(lián)。因此,詞形還原可以將不同的token集簡化為不同的詞形集。這可以通過這個(gè)例子來解釋;
起初,“living”這個(gè)詞的聽者幾乎是無意識地能辨別出這個(gè)詞的意思。這對于人類來說是可能的,因?yàn)槿祟惪梢愿鶕?jù)世界的知識等做出推論。如果沒有上下文,這對于機(jī)器來說是不可能的。
為了使機(jī)器能夠預(yù)測出一個(gè)單詞在相同拼寫和相同發(fā)音的情況下產(chǎn)生的幾種意義,詞形還原是處理這種詞匯歧義的關(guān)鍵。
我們可以使用expert.ai NL API執(zhí)行此任務(wù)。讓我們考慮以下兩個(gè)例子:
She’s living her best life. What do you do for a living?
living_from_live = "She's living her best life"
living_from_living = "What do you do for a living?"
language = 'en'
# 請求API
output = client.specific_resource_analysis(
body={"document": {"text": living_from_live }},
params={'language': language, 'resource': 'disambiguation'
})
# 請求API
output_2 = client.specific_resource_analysis(
body={"document": {"text": living_from_living }},
params={'language': language, 'resource': 'disambiguation'
})
# 在輸出數(shù)組的開始部分以粗體打印TOKEN、POS和ID:
print (f'\t \033[1mOuput of the first sentence : \033[0m \n')
print (f'\033[1m{"TOKEN":{20}} {"LEMMA":{15}} {"POS":{6}} \033[0m')
#Syncon代表“概念”,我們用一個(gè)ID來表示
for token in output.tokens:
print (f'{living_from_live [token.start:token.end]:{20}} {token.lemma:{15}} {token.pos:{6}} ')
print (f'\t \033[1mOuput of the second sentence : \033[0m \n')
print (f'\033[1m{"TOKEN":{20}} {"LEMMA":{15}} {"POS":{6}} \033[0m')
for token in output_2.tokens:
print (f'{living_from_living [token.start:token.end]:{20}} {token.lemma:{15}} {token.pos:{6}} ')
Output of the first sentence :
TOKEN LEMMA POS
She she PRON
's 's AUX
living live VERB
her her PRON
best good ADJ
life life NOUN
Output of the second sentence :
TOKEN LEMMA POS
What what PRON
do do AUX
you you PRON
do do VERB
for for ADP
a a DET
living living NOUN
? ? PUNCT
如上所述,“l(fā)iving”有兩個(gè)不同的詞形,這取決于上下文及其在句子中的位置。在第一個(gè)例子中,living對應(yīng)于詞形live,live是句子的動(dòng)詞。相反,living在第二句中是一個(gè)名詞,有詞形living。意思也不同,第一個(gè)詞形描述的是“活著”的概念,而另一個(gè)是一個(gè)名詞屬于“一種收入或謀生手段”的概念。
因此,詞形還原有助于機(jī)器推斷同形詞的意義。
結(jié)論
往期精彩回顧 本站qq群851320808,加入微信群請掃碼:
