【NLP学习其四】如何构建自己用于训练的数据集?什么是词性标注?

数据集与词性标注

数据集是NLP中的重要一环。

但是提到数据集,很多人的第一个想法可能是:“这玩意从网上下载就好了,不用管”。

真的不用管?最开始我也是这么认为的

于是我直奔CoNLL-2003去下载数据集。地址如下://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,请看
//www.cnblogs.com/DAYceng/p/14923065.html/

由于句法分析(也就是第三列标签)需要训练单独的模型来实现,这里不做介绍

到这里,事情就变得有点眉目了

我们得到了两个关键词: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