奮戰聊天機器人(三)自動化對語料做詞性標註

1.英語詞幹提取器

import nltk
porter = nltk.PorterStemmer()
porter.stem('lying')

2.詞性標註器

import nltk
text = nltk.word_tokenize("And now for something completely different")
nltk.pos_tag(text)

其中CC是連接詞,RB是副詞,IN是介詞,NN是名次,JJ是形容詞

這是一句完整的話,實際上pos_tag是處理一個詞序列,會根據句子來動態判斷,比如:

i love you ————love識別爲名詞
love and hate —————love識別爲名詞
nltk中多數都是英文的詞性標註語料庫,如果我們想自己標註一批語料庫該怎麼辦呢?

nltk提供了比較方便的方法:

tagged_token = nltk,tag.str2truple('fly/NN')

這裏的nltk.tag.str2tuple可以把fly/NN這種字符串轉成一個二元組,事實上nltk的語料庫中都是這種字符串形式的標註,那麼我們如果把語料庫標記成:

sent = '我/NN 是/IN 一個/AT 大/JJ 傻x/NN'
[nltk.tag.str2tuple(t) for t in sent.split()]

如此一看,也是支持中文的

我們看看布朗語料庫中的標註:

nltk.corpus.brown.tagged_words()
事實上,nltk也有中文的語料庫,我們可以下載:

在nltk.download()執行的下載窗口中,選擇Corpora裏的sinica_treebank(臺灣話的中國研究院)下載

Step 1: 查看這個中文語料庫中有什麼內容

# coding:utf-8

import nltk

for word in nltk.corpus.sinica_treebank.tagged_words():
    print(word[0], word[1])

第一列是中文的詞彙,第二列是標註好的詞性

我們發現這裏面都是繁體,因爲是基於臺灣的語料生成的,想要簡體中文還得自己想辦法。不過有人已經幫我們做了這部分工作,那就是jieba分詞,強烈推薦,可以自己加載自己的語料,進行中文切詞,並且能夠自動做詞性標註

3.詞性自動標註

面對一片新的語料庫(比如我們從未處理過中文,只有中文語料),怎麼實現詞性自動標註呢?

默認標註器:

不管什麼詞,都標註爲頻率最高的一種詞性。比如經過分析,所有中文語料裏的詞是名詞的概率是13%最大,那麼我們的默認標註器就全部標註爲名詞。

這種標註器一般作爲其他標註器處理之後的最後一道門,既不知道是什麼詞?那麼他是名詞。默認標註器用DefaultTagger來實現:

# encoding:utf-8

import nltk

default_tagger = nltk.DefaultTagger('NN')
raw = '我 累 個 去'
tokens = nltk.word_tokenize(raw)
tags = default_tagger.tag(tokens)
print(tags)

正則表達式標註器:

滿足特定正則表達式的認爲是某種詞性,比如凡是帶“們”的都認爲是代詞(PRO)。正則表達式標註器通RegexpTagge實現,用法如下:

pattern = [(r'.*們$', 'PRO')]
tagger = nltk.RegexpTagger(pattern)
print(tagger.tag(nltk.word_tokenize('我們 累 個 去 你們 和 他們 啊')))

查詢標註器:

找出最頻繁的n個詞以及它的詞性,然後用這個信息去查找語料庫,匹配的就標記上,剩餘的詞使用默認標註器(回退)。這一般使用一元標註的方式,見下面。

一元標註:基於已經標註的語料庫做訓練,然後用訓練好的模型來標註新的語料,使用方法如下:

tagged_sents = [[(u'我', u'PRO'), (u'小兔', u'NN')]]
unigram_tagger = nltk.UnigramTagger(tagged_sents)
sents = brown.sents(categories='news')
sents = [[u'我', u'你', u'小兔']]
tags = unigram_tagger.tag(sents[0])
print(tags)

這裏的tagged_sents是用於訓練的語料庫,我們也可以直接用已有的標註好的語料庫,比如:

brown_tagged_sents = brown.tagged_sents(categories='news')

二元標註和多元標註:一元標註指的是隻考慮當前這個詞,不考慮上下文。二元標註器指的是考慮它前面的詞的標註,用法只需要把上面的UnigramTagger換成BigramTagger。同理三元標註換成TrigramTagger

組合標註器:

爲了提高精度和覆蓋率,我們對多種標註器組合,比如組合二元標註器、一元標註器和默認標註器,如下:

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

標註器的存儲:

訓練好的標註器爲了持久化,可以存儲到硬盤,具體方法如下:

from cPickle import dump
output = open('t2.pkl', 'wb')
dump(t2, output, -1)
output.close()

使用時加載

from cPickle import load 
input = open('t2.pkl', 'rb') 
tagger = load(input) 
input.close() 

參考資料來源:http://www.shareditor.com/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章