【NLP學習其四】如何構建自己用於訓練的資料集?什麼是詞性標註?

dayceng發表於2021-08-08

資料集與詞性標註

資料集是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標籤作為第二、三列即可

這裡有兩個關鍵詞:POSNER

通過高強度網際網路搜尋發現NLTK正好有用於POS的模組(nltk.pos_tag)以及用於chunk的模組(ne_chunk

image-20210808103642474

檢視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

相關文章