資料集與詞性標註
資料集是NLP中的重要一環。
但是提到資料集,很多人的第一個想法可能是:“這玩意從網上下載就好了,不用管”。
真的不用管?最開始我也是這麼認為的
於是我直奔CoNLL-2003去下載資料集。地址如下:https://www.clips.uantwerpen.be/conll2003/ner/
但是經過了解,該資料集的來源是新聞報紙之類的內容,與我要應用NLP的領域嚴重不符。
所以,除非你的NLP任務與網路上已經公佈的、較多人實現的任務重合,否則資料集一般不能直接使用
也就是說,在完成你的NLP任務前,你需要自行構建一個資料集
但是怎麼做呢?我們現在可以確認的一件事情是:資料集不可能手動構建的
拿CoNLL-2003的資料集進行分析,我們需要構建一個與其形式類似的資料集應該怎麼做?
U.N. NNP I-NP I-ORG
official NN I-NP O
Ekeus NNP I-NP I-PER
heads VBZ I-VP O
for IN I-PP O
Baghdad NNP I-NP I-LOC
. . O O
這是eng.traindata資料集的一部分,簡單介紹一下構成
第一列是單詞,顯然是來自原始文字;
第二列是詞性(pos)標籤,就是名詞、動詞、專有名詞等等一些表示某個詞詞性的標註
第三列是句法塊標籤,表示某詞在該句子中的上下文成分
第四列是命名實體識別(NER)標籤,關於什麼是NER,請看
https://www.cnblogs.com/DAYceng/p/14923065.html/
由於句法分析(也就是第三列標籤)需要訓練單獨的模型來實現,這裡不做介紹
到這裡,事情就變得有點眉目了
我們只需要將第一列替換為自己需要的文字,並且獲得該文字對應的POS和NER標籤作為第二、三列即可
這裡有兩個關鍵詞:POS和NER
通過高強度網際網路搜尋發現NLTK正好有用於POS的模組(nltk.pos_tag)以及用於chunk的模組(ne_chunk)
檢視NLTK的文件得知,pos_tag()的輸入是一個進行tokenize分詞之後的句子
這裡文件使用了word_tokenize模組進行分詞,如果你覺得其分詞結果不滿意,你也可以直接用split分詞
tokenized_sentences = corup_token.split(" ")
pos_res = nltk.pos_tag(tokenized_sentences) #標註句子
這樣就得到了一個句子的POS 標籤
下面進行NER標註,依然是使用NLTK,並且需要使用到上一步中POS的結果
注:chunk的結果是一個“樹”(一種特殊的資料結構)
tree = ne_chunk(pos_res) # 使用nltk的chunk工具獲得chunk的樹結構
使用tree2conlltags對樹進行解析可以得到我們需要的結果
iob_tags_listtup = tree2conlltags(tree) # 解析樹,獲得chunktags的元組列表
至此,我們就得到了一個句子的pos和ner標籤
打包成一個函式如下:
def postags(croup_token,output):
'''
使用nltk.pos_tag對分詞之後的summary進行詞性標註
:param output:
選擇輸出形式,
輸出原始格式資料(0):[('buffer', 'NN'), ('overflow', 'NN'), ...,(...)]
輸出詞性標籤(1):['NN', 'NN',...,'...']
輸出chunking標籤(2)
:param croup_token:經過'分詞-去除特殊符號-小寫'處理的sentences資料
:return:列表返回值
'''
ne_chunked_tags = []
pos_tags = []
pos_raw = []
tokenized_sentences = croup_token_token.split(" ") #nltk.word_tokenize(data)
# print(tokenized_sentences)
pos_res = nltk.pos_tag(tokenized_sentences)
pos_res_tup = pos_res[0] # 得到元組
tree = ne_chunk(pos_res) # 使用nltk的chunk工具獲得chunk的樹結構
# print(tree)
iob_tags_listtup = tree2conlltags(tree) # 解析樹,獲得chunktags的元組列表
# print(iob_tags_listtup)
# print(iob_tags_listtup)
for i in range(len(iob_tags_listtup)):
# print(iob_tags_listtup[i])
tmp_tup = iob_tags_listtup[i]
# print(tmp_tup[2])
pos_raw.append(tmp_tup)
pos_tags.append(tmp_tup[1])
ne_chunked_tags.append(tmp_tup[2])
# print(ne_chunked_tags)
if output == 0:
return pos_raw
elif output == 1:
return pos_tags
elif output == 2:
return ne_chunked_tags