1. 程式人生 > >Python自然語言處理------分類和標註詞彙

Python自然語言處理------分類和標註詞彙

寫在前面

一篇讀書筆記。

1. 使用詞性標註器

將詞彙按它們的詞性(parts-of-speech,POS)分類以及相應的標註它們的過程被稱為詞性標註(part-of-speech tagging, POS tagging)或乾脆簡稱標註。詞性也稱為詞類或詞彙範疇。用於特定任務的標記的集合被稱為一個標記集。

一個詞性標註器處理一個詞序列,為每個詞附加一個詞性標記。

import nltk
text = nltk.word_tokenize("And now for something completely different")  #分詞
nltk.pos_tag(text)   #詞性標註器

輸出為:

[('And', 'CC'),
 ('now', 'RB'),
 ('for', 'IN'),
 ('something', 'NN'),
 ('completely', 'RB'),
 ('different', 'JJ')]

其中'CC'表示並列連詞,'RB'表示副詞,'IN'表示介詞,'NN'表示名詞,'JJ'表示形容詞

similar()函式為一個詞w找出所有上下文w1ww2,然後找出所有出現在相同上下文中的詞w’即w1 w’w2

2. 標註預料庫

表示已標註的識別符號

按照NLTK 的約定,一個已標註的識別符號使用一個由識別符號和標記組成的元組來表示。我們可以使用函式str2tuple()從表示一個已標註的識別符號的標準字串建立一個這樣的特殊元組:

tagged_token = nltk.tag.str2tuple('fly/NN')  #已標註的識別符號字串轉化為元組型別
tagged_token 

此外,還可以可以直接從一個字串構造一個已標註的識別符號的連結串列。第一步是對字串分詞以便能訪問單獨的詞/標記字串,然後將每一個轉換成一個元組:

sent = '''
...The/AT grand/JJ jury/NN commented/VBD on/IN a/AT number/NN of/IN
... other/AP topics/NNS ,/, AMONG/IN them/PPO the/AT Atlanta/NP and/CC
... Fulton/NP-tl County/NN-tl purchasing/VBG departments/NNS which/WDT it/PP
... said/VBD ``/`` ARE/BER well/QL operated/VBN and/CC follow/VB generally/R
... accepted/VBN practices/NNS which/WDT inure/VB to/IN the/AT best/JJT
... interest/NN of/IN both/ABX governments/NNS ''/'' ./.
...'''

[nltk.tag.str2tuple(t) for t in sent.split()]

讀取已標註的預料庫

NLTK 中包括的若干語料庫已標註了詞性。以布朗預料庫為例:

nltk.corpus.brown.tagged_words()[:10]
如果語料庫也被分割成句子,將有一個tagged_sents()方法將已標註的詞劃分成句子,而不是將它們表示成一個大連結串列

簡化的詞性標記集

2. 自動標註

我們將看到一個詞的標記依賴於這個詞和它在句子中的上下文。出於這個原因,我們將處理(已標註)句子層次
而不是詞彙層次的資料。首先以載入要使用的資料開始
from nltk.corpus import brown
brown_tagged_sents = brown.tagged_sents(categories='news')
brown_sents = brown.sents(categories='news')

預設標註器

最簡單的標註器是為每個識別符號分配同樣的標記。顯然這個方法並不理想。

正則表示式標註器

正則表示式標註器基於匹配模式分配標記給識別符號。例如:我們可能會猜測任一以ed結尾的詞都是動詞過去分詞,任一以's 結尾的詞都是名詞所有格。例如:
patterns = [
... (r'.*ing$', 'VBG'), # gerunds
... (r'.*ed$', 'VBD'), # simple past
... (r'.*es$', 'VBZ'), # 3rd singular present
... (r'.*ould$', 'MD'), # modals
... (r'.*\'s$', 'NN$'), # possessive nouns
... (r'.*s$', 'NNS'), # plural nouns
... (r'^-?[0-9]+(.[0-9]+)?$', 'CD'), # cardinal numbers
... (r'.*', 'NN') # nouns (default)
... ]

regexp_tagger = nltk.RegexpTagger(patterns)
regexp_tagger.tag(brown_sents[3])

查詢標註器

讓我們找出100 個最頻繁的詞,儲存它們最有可能的標記。然後我們可以使用這個資訊作為“查詢標註器”的模型:
fd = nltk.FreqDist(brown.words(categories='news'))
cfd = nltk.ConditionalFreqDist(brown.tagged_words(categories='news'))
most_freq_words = fd.keys()[:100]
likely_tags = dict((word, cfd[word].max()) for word in most_freq_words)
baseline_tagger = nltk.UnigramTagger(model=likely_tags)
baseline_tagger.evaluate(brown_tagged_sents)
但是該模型在未標註的輸入文字上,很多不在這100個最頻繁的詞中的詞會被分配為“None”標註,在這些情況下,考慮到在所有情況中名詞“NN”是最多的,所以直接預設分配為NN。只需對上述baseline_tagger新增一個backoff引數指向預設標註器即可。
baseline_tagger = nltk.UnigramTagger(model=likely_tags,
... backoff=nltk.DefaultTagger('NN'))

3.N-gram標註

一元標註(Unigram Tagging)

一元標註器基於一個簡單的統計演算法:對每個識別符號分配這個獨特的識別符號最有可能的標記。

一般的N-gram標註

一個n-gram標註器是一個 unigram 標註器的一般化,它的上下文是當前詞和它前面n-1 個識別符號的詞性標記。

當n=1時即為一元標註器(unigram tagger),n=2時稱為二元標註器(bigram taggers),n=3時稱為三元標註器(trigram taggers)。

NgramTagger 類使用一個已標註的訓練語料庫來確定對每個上下文哪個詞性標記最有可能。

組合標註器

解決精度和覆蓋範圍之間的權衡的一個辦法是儘可能的使用更精確的演算法,但卻在很多時候落後於具有更廣覆蓋範圍的演算法。例如:我們可以按如下方式組合bigram 標註器、unigram 標註器和一個預設標註器:

1. 嘗試使用bigram 標註器標註識別符號。
2. 如果bigram 標註器無法找到一個標記,嘗試unigram 標註器。
3. 如果unigram 標註器也無法找到一個標記,使用預設標註器。

t0 = nltk.DefaultTagger('NN')
t1 = nltk.UnigramTagger(train_sents, backoff=t0)
t2 = nltk.BigramTagger(train_sents, backoff=t1)
t2.evaluate(test_sents)

跨句子邊界標註

當使用Ngram標註器,如果遇到句子的第一個詞時,trigram標註器將使用前面兩個識別符號的詞性標記,這通常會是前面句子的最後一個詞和句子結尾的標點符號。然而,在前一句結尾的詞的類別與下一句的開頭通常沒有關係。

為了應對這種情況,我們可以使用已標註句子的連結串列來訓練、執行和評估標註器。

brown_tagged_sents = brown.tagged_sents(categories='news')
brown_sents = brown.sents(categories='news')
size = int(len(brown_tagged_sents) * 0.9)
train_sents = brown_tagged_sents[:size]
test_sents = brown_tagged_sents[size:]
t0 = nltk.DefaultTagger('NN')
t1 = nltk.UnigramTagger(train_sents, backoff=t0)
t2 = nltk.BigramTagger(train_sents, backoff=t1)

t2.evaluate(test_sents)

4. 如何確定一個詞的分類

形態學線索

一個詞的內部結構可能為這個詞分類提供有用的線索。舉例來說:-ness 是一個字尾,與形容詞結合產生一個名詞,如happy→happiness,ill→illness。因此如果我們遇到的一個以-ness 結尾的詞,很可能是一個名詞。同樣的,-ment 是與一些動詞結合產生一個名詞的字尾,如govern→government和 establish→establishment。

句法線索

另一個資訊來源是一個詞可能出現的典型的上下文語境。。例如:假設我們已經確定了名詞類。那麼我們可以說,英語形容詞的句法標準是它可以立即出現在一個名詞前,或緊跟在詞be 或very 後。

語義線索

一個詞的意思對其詞彙範疇是一個有用的線索。。例如:名詞的眾所周知的一個定義是根據語義的:“一個人、地方或事物的名稱。”

以上~

2018.06.15