新聞中心
進一步學(xué)習(xí)自然語言處理的基本概念
在 之前的文章 里,我介紹了自然語言處理natural language processing(NLP)和賓夕法尼亞大學(xué)研發(fā)的自然語言處理工具包Natural Language Toolkit (NLTK)。我演示了用 Python 解析文本和定義停頓詞stopword的方法,并介紹了語料庫corpus的概念。語料庫是由文本構(gòu)成的數(shù)據(jù)集,通過提供現(xiàn)成的文本數(shù)據(jù)來輔助文本處理。在這篇文章里,我將繼續(xù)用各種語料庫對文本進行對比和分析。
這篇文章主要包括以下部分:
- 詞網(wǎng)WordNet和同義詞集synset
- 相似度比較Similarity comparison
- 樹Tree和樹庫treebank
- 命名實體識別Named entity recognition
詞網(wǎng)和同義詞集
詞網(wǎng)WordNet 是 NLTK 里的一個大型詞匯數(shù)據(jù)庫語料庫。詞網(wǎng)包含各單詞的諸多認知同義詞cognitive synonyms(認知同義詞常被稱作“同義詞集synset”)。在詞網(wǎng)里,名詞、動詞、形容詞和副詞,各自被組織成一個同義詞的網(wǎng)絡(luò)。
詞網(wǎng)是一個很有用的文本分析工具。它有面向多種語言的版本(漢語、英語、日語、俄語和西班牙語等),也使用多種許可證(從開源許可證到商業(yè)許可證都有)。初代版本的詞網(wǎng)由普林斯頓大學(xué)研發(fā),面向英語,使用類 MIT 許可證MIT-like license。
因為一個詞可能有多個意義或多個詞性,所以可能與多個同義詞集相關(guān)聯(lián)。每個同義詞集通常提供下列屬性:
< 如顯示不全,請左右滑動 >
| 屬性 | 定義 | 例子 |
|---|---|---|
| 名稱Name | 此同義詞集的名稱 | 單詞 code 有 5 個同義詞集,名稱分別是 code.n.01、 code.n.02、 code.n.03、code.v.01 和 code.v.02 |
| 詞性POS | 此同義詞集的詞性 | 單詞 code 有 3 個名詞詞性的同義詞集和 2 個動詞詞性的同義詞集 |
| 定義Definition | 該詞作對應(yīng)詞性時的定義 | 動詞 code 的一個定義是:(計算機科學(xué))數(shù)據(jù)或計算機程序指令的象征性排列symbolic arrangement |
| 例子Example | 使用該詞的例子 | code 一詞的例子:We should encode the message for security reasons |
| 詞元Lemma | 與該詞相關(guān)聯(lián)的其他同義詞集(包括那些不一定嚴格地是該詞的同義詞,但可以大體看作同義詞的);詞元直接與其他詞元相關(guān)聯(lián),而不是直接與單詞word相關(guān)聯(lián) | code.v.02 的詞元是 code.v.02.encipher、code.v.02.cipher、code.v.02.cypher、code.v.02.encrypt、code.v.02.inscribe 和 code.v.02.write_in_code |
| 反義詞Antonym | 意思相反的詞 | 詞元 encode.v.01.encode 的反義詞是 decode.v.01.decode |
| 上義詞Hypernym | 該詞所屬的一個范疇更大的詞 | code.v.01 的一個上義詞是 tag.v.01 |
| 分項詞Meronym | 屬于該詞組成部分的詞 | computer 的一個分項詞是 chip |
| 總項詞Holonym | 該詞作為組成部分所屬的詞 | window 的一個總項詞是 computer screen |
同義詞集還有一些其他屬性,在 <你的 Python 安裝路徑>/Lib/site-packages 下的 nltk/corpus/reader/wordnet.py,你可以找到它們。
下面的代碼或許可以幫助理解。
這個函數(shù):
from nltk.corpus import wordnetdef synset_info(synset):print("Name", synset.name())print("POS:", synset.pos())print("Definition:", synset.definition())print("Examples:", synset.examples())print("Lemmas:", synset.lemmas())print("Antonyms:", [lemma.antonyms() for lemma in synset.lemmas() if len(lemma.antonyms()) > 0])print("Hypernyms:", synset.hypernyms())print("Instance Hypernyms:", synset.instance_hypernyms())print("Part Holonyms:", synset.part_holonyms())print("Part Meronyms:", synset.part_meronyms())print()synsets = wordnet.synsets('code')print(len(synsets), "synsets:")for synset in synsets:synset_info(synset)
將會顯示:
5 synsets:Name code.n.01POS: nDefinition: a set of rules or principles or laws (especially written ones)Examples: []Lemmas: [Lemma('code.n.01.code'), Lemma('code.n.01.codification')]Antonyms: []Hypernyms: [Synset('written_communication.n.01')]Instance Hpernyms: []Part Holonyms: []Part Meronyms: []...Name code.n.03POS: nDefinition: (computer science) the symbolic arrangement of data or instructions in a computer program or the set of such instructionsExamples: []Lemmas: [Lemma('code.n.03.code'), Lemma('code.n.03.computer_code')]Antonyms: []Hypernyms: [Synset('coding_system.n.01')]Instance Hpernyms: []Part Holonyms: []Part Meronyms: []...Name code.v.02POS: vDefinition: convert ordinary language into codeExamples: ['We should encode the message for security reasons']Lemmas: [Lemma('code.v.02.code'), Lemma('code.v.02.encipher'), Lemma('code.v.02.cipher'), Lemma('code.v.02.cypher'), Lemma('code.v.02.encrypt'), Lemma('code.v.02.inscribe'), Lemma('code.v.02.write_in_code')]Antonyms: []Hypernyms: [Synset('encode.v.01')]Instance Hpernyms: []Part Holonyms: []Part Meronyms: []
同義詞集synset和詞元lemma在詞網(wǎng)里是按照樹狀結(jié)構(gòu)組織起來的,下面的代碼會給出直觀的展現(xiàn):
def hypernyms(synset):return synset.hypernyms()synsets = wordnet.synsets('soccer')for synset in synsets:print(synset.name() + " tree:")pprint(synset.tree(rel=hypernyms))print()
code.n.01 tree:[Synset('code.n.01'),[Synset('written_communication.n.01'),...code.n.02 tree:[Synset('code.n.02'),[Synset('coding_system.n.01'),...code.n.03 tree:[Synset('code.n.03'),...code.v.01 tree:[Synset('code.v.01'),[Synset('tag.v.01'),...code.v.02 tree:[Synset('code.v.02'),[Synset('encode.v.01'),...
詞網(wǎng)并沒有涵蓋所有的單詞和其信息(現(xiàn)今英語有約 17,0000 個單詞,最新版的 詞網(wǎng) 涵蓋了約 15,5000 個),但它開了個好頭。掌握了“詞網(wǎng)”的各個概念后,如果你覺得它詞匯少,不能滿足你的需要,可以轉(zhuǎn)而使用其他工具?;蛘?,你也可以打造自己的“詞網(wǎng)”!
自主嘗試
使用 Python 庫,下載維基百科的 “open source” 頁面,并列出該頁面所有單詞的同義詞集synset和詞元lemma。
相似度比較
相似度比較的目的是識別出兩篇文本的相似度,在搜索引擎、聊天機器人等方面有很多應(yīng)用。
比如,相似度比較可以識別 football 和 soccer 是否有相似性。
syn1 = wordnet.synsets('football')syn2 = wordnet.synsets('soccer')# 一個單詞可能有多個 同義詞集,需要把 word1 的每個同義詞集和 word2 的每個同義詞集分別比較for s1 in syn1:for s2 in syn2:print("Path similarity of: ")print(s1, '(', s1.pos(), ')', '[', s1.definition(), ']')print(s2, '(', s2.pos(), ')', '[', s2.definition(), ']')print(" is", s1.path_similarity(s2))print()
Path similarity of:Synset('football.n.01') ( n ) [ any of various games played with a ball (round or oval) in which two teams try to kick or carry or propel the ball into each other's goal ]Synset('soccer.n.01') ( n ) [ a football game in which two teams of 11 players try to kick or head a ball into the opponents' goal ]is 0.5Path similarity of:Synset('football.n.02') ( n ) [ the inflated oblong ball used in playing American football ]Synset('soccer.n.01') ( n ) [ a football game in which two teams of 11 players try to kick or head a ball into the opponents' goal ]is 0.05
兩個詞各個同義詞集之間路徑相似度path similarity最大的是 0.5,表明它們關(guān)聯(lián)性很大(路徑相似度path similarity指兩個詞的意義在上下義關(guān)系的詞匯分類結(jié)構(gòu)hypernym/hypnoym taxonomy中的最短距離)。
那么 code 和 bug 呢?這兩個計算機領(lǐng)域的詞的相似度是:
Path similarity of:Synset('code.n.01') ( n ) [ a set of rules or principles or laws (especially written ones) ]Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]is 0.1111111111111111...Path similarity of:Synset('code.n.02') ( n ) [ a coding system used for transmitting messages requiring brevity or secrecy ]Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]is 0.09090909090909091...Path similarity of:Synset('code.n.03') ( n ) [ (computer science) the symbolic arrangement of data or instructions in a computer program or the set of such instructions ]Synset('bug.n.02') ( n ) [ a fault or defect in a computer program, system, or machine ]is 0.09090909090909091
這些是這兩個詞各同義詞集之間路徑相似度path similarity的最大值,這些值表明兩個詞是有關(guān)聯(lián)性的。
NLTK 提供多種相似度計分器similarity scorers,比如:
- path_similarity
- lch_similarity
- wup_similarity
- res_similarity
- jcn_similarity
- lin_similarity
要進一步了解這些相似度計分器similarity scorers,請查看 WordNet Interface 的 Similarity 部分。
自主嘗試
使用 Python 庫,從維基百科的 Category: Lists of computer terms 生成一個術(shù)語列表,然后計算各術(shù)語之間的相似度。
樹和樹庫
使用 NLTK,你可以把文本表示成樹狀結(jié)構(gòu)以便進行分析。
這里有一個例子:
這是一份簡短的文本,對其做預(yù)處理和詞性標注:
import nltktext = "I love open source"# Tokenize to wordswords = nltk.tokenize.word_tokenize(text)# POS tag the wordswords_tagged = nltk.pos_tag(words)
要把文本轉(zhuǎn)換成樹狀結(jié)構(gòu),你必須定義一個語法grammar。這個例子里用的是一個基于 Penn Treebank tags 的簡單語法。
# A simple grammar to create treegrammar = "NP: {<JJ><NN>}"
然后用這個語法grammar創(chuàng)建一顆樹tree:
# Create treeparser = nltk.RegexpParser(grammar)tree = parser.parse(words_tagged)pprint(tree)
運行上面的代碼,將得到:
Tree('S', [('I', 'PRP'), ('love', 'VBP'), Tree('NP', [('open', 'JJ'), ('source', 'NN')])])
你也可以圖形化地顯示結(jié)果。
tree.draw()
NLTK Tree
這個樹狀結(jié)構(gòu)有助于準確解讀文本的意思。比如,用它可以找到文本的 主語:
subject_tags = ["NN", "NNS", "NP", "NNP", "NNPS", "PRP", "PRP$"]def subject(sentence_tree):for tagged_word in sentence_tree:# A crude logic for this case - first word with these tags is considered subjectif tagged_word[1] in subject_tags:return tagged_word[0]print("Subject:", subject(tree))
結(jié)果顯示主語是 I:
Subject: I
這是一個比較基礎(chǔ)的文本分析步驟,可以用到更廣泛的應(yīng)用場景中。 比如,在聊天機器人方面,如果用戶告訴機器人:“給我媽媽 Jane 預(yù)訂一張機票,1 月 1 號倫敦飛紐約的”,機器人可以用這種分析方法解讀這個指令:
動作: 預(yù)訂
動作的對象: 機票
乘客: Jane
出發(fā)地: 倫敦
目的地: 紐約
日期: (明年)1 月 1 號
樹庫treebank指由許多預(yù)先標注好的樹tree構(gòu)成的語料庫?,F(xiàn)在已經(jīng)有面向多種語言的樹庫,既有開源的,也有限定條件下才能免費使用的,以及商用的。其中使用最廣泛的是面向英語的賓州樹庫。賓州樹庫取材于華爾街日報Wall Street Journal。NLTK 也包含了賓州樹庫作為一個子語料庫。下面是一些使用樹庫treebank的方法:
words = nltk.corpus.treebank.words()print(len(words), "words:")print(words)tagged_sents = nltk.corpus.treebank.tagged_sents()print(len(tagged_sents), "sentences:")print(tagged_sents)
100676 words:['Pierre', 'Vinken', ',', '61', 'years', 'old', ',', ...]3914 sentences:[[('Pierre', 'NNP'), ('Vinken', 'NNP'), (',', ','), ('61', 'CD'), ('years', 'NNS'), ('old', 'JJ'), (',', ','), ('will', 'MD'), ('join', 'VB'), ('the', 'DT'), ('board', 'NN'), ('as', 'IN'), ('a', 'DT'), ('nonexecutive', 'JJ'), ('director', 'NN'), ...]
查看一個句子里的各個標簽tags:
sent0 = tagged_sents[0]pprint(sent0)
[('Pierre', 'NNP'),('Vinken', 'NNP'),(',', ','),('61', 'CD'),('years', 'NNS'),...
定義一個語法grammar來把這個句子轉(zhuǎn)換成樹狀結(jié)構(gòu):
grammar = '''Subject: {} SubjectInfo: {} Action: {} Object: {} Stopwords: {- }
ObjectInfo: {} When: {} '''parser = nltk.RegexpParser(grammar)tree = parser.parse(sent0)print(tree)
(S(Subject Pierre/NNP Vinken/NNP),/,(SubjectInfo 61/CD years/NNS old/JJ),/,(Action will/MD join/VB)(Object the/DT board/NN)as/INa/DT(ObjectInfo nonexecutive/JJ director/NN)(Subject Nov./NNP)29/CD./.)
圖形化地顯示:
tree.draw()
NLP Treebank image
樹trees和樹庫treebanks的概念是文本分析的一個強大的組成部分。
自主嘗試
使用 Python 庫,下載維基百科的 “open source” 頁面,將得到的文本以圖形化的樹狀結(jié)構(gòu)展現(xiàn)出來。
命名實體識別
無論口語還是書面語都包含著重要數(shù)據(jù)。文本處理的主要目標之一,就是提取出關(guān)鍵數(shù)據(jù)。幾乎所有應(yīng)用場景所需要提取關(guān)鍵數(shù)據(jù),比如航空公司的訂票機器人或者問答機器人。 NLTK 為此提供了一個命名實體識別named entity recognition的功能。
這里有一個代碼示例:
sentence = 'Peterson first suggested the name "open source" at Palo Alto, California'
驗證這個句子里的人名name和地名place有沒有被識別出來。照例先預(yù)處理:
import nltkwords = nltk.word_tokenize(sentence)pos_tagged = nltk.pos_tag(words)
運行命名實體標注器named-entity tagger:
ne_tagged = nltk.ne_chunk(pos_tagged)print("NE tagged text:")print(ne_tagged)print()
NE tagged text:(S(PERSON Peterson/NNP)first/RBsuggested/VBDthe/DTname/NN``/``open/JJsource/NN''/''at/IN(FACILITY Palo/NNP Alto/NNP),/,(GPE California/NNP))
上面的結(jié)果里,命名實體被識別出來并做了標注;只提取這個樹tree里的命名實體:
print("Recognized named entities:")for ne in ne_tagged:if hasattr(ne, "label"):print(ne.label(), ne[0:])
Recognized named entities:PERSON [('Peterson', 'NNP')]FACILITY [('Palo', 'NNP'), ('Alto', 'NNP')]GPE [('California', 'NNP')]
圖形化地顯示:
ne_tagged.draw()
NLTK Treebank tree
NLTK 內(nèi)置的命名實體標注器named-entity tagger,使用的是賓州法尼亞大學(xué)的 Automatic Content Extraction(ACE)程序。該標注器能夠識別組織機構(gòu)ORGANIZATION、人名PERSON、地名LOCATION、設(shè)施FACILITY和地緣政治實體geopolitical entity等常見實體entites。
NLTK 也可以使用其他標注器tagger,比如 Stanford Named Entity Recognizer. 這個經(jīng)過訓(xùn)練的標注器用 Java 寫成,但 NLTK 提供了一個使用它的接口(詳情請查看 nltk.parse.stanford 或 nltk.tag.stanford)。
自主嘗試
使用 Python 庫,下載維基百科的 “open source” 頁面,并識別出對開源open source有影響力的人的名字,以及他們?yōu)殚_源open source做貢獻的時間和地點。
高級實踐
如果你準備好了,嘗試用這篇文章以及此前的文章介紹的知識構(gòu)建一個超級結(jié)構(gòu)superstructure。
使用 Python 庫,下載維基百科的 “Category: Computer science page”,然后:
- 找出其中頻率最高的單詞unigrams、二元搭配bigrams和三元搭配trigrams,將它們作為一個關(guān)鍵詞列表或者技術(shù)列表。相關(guān)領(lǐng)域的學(xué)生或者工程師需要了解這樣一份列表里的內(nèi)容。
- 圖形化地顯示這個領(lǐng)域里重要的人名、技術(shù)、日期和地點。這會是一份很棒的信息圖。
- 構(gòu)建一個搜索引擎。你的搜索引擎性能能夠超過維基百科嗎?
下一步?
自然語言處理是應(yīng)用構(gòu)建application building的典型支柱。NLTK 是經(jīng)典、豐富且強大的工具集,提供了為現(xiàn)實世界構(gòu)建有吸引力、目標明確的應(yīng)用的工作坊。
在這個系列的文章里,我用 NLTK 作為例子,展示了自然語言處理可以做什么。自然語言處理和 NLTK 還有太多東西值得探索,這個系列的文章只是幫助你探索它們的切入點。
如果你的需求增長到 NLTK 已經(jīng)滿足不了了,你可以訓(xùn)練新的模型或者向 NLTK 添加新的功能?;?NLTK 構(gòu)建的新的自然語言處理庫正在不斷涌現(xiàn),機器學(xué)習(xí)也正被深度用于自然語言處理。
本文名稱:進階教程:用Python和NLTK進行NLP分析
當前網(wǎng)址:http://fisionsoft.com.cn/article/copodgc.html


咨詢
建站咨詢

