更多实时更新的个人学习笔记分享,请关注:
知乎:https://www.zhihu.com/people/yuquanle/columns
微信订阅号:AI小白入门
ID: StudyForAI

<center> </center>

Flair工具使用教程之如何加载自己的语料库

读取序列标记数据集

NLP中的大多数序列标记数据集使用某种列格式,其中每一行都是一个单词,每列都是一级语言标注。 比如说这句话:

George N B-PER
Washington N I-PER
went V O
to P O
Washington N B-LOC
  • 第一列是单词本身;
  • 第二列是词性(POS)标签;
  • 第三列是用BIO注释的命名实体(NER)标签,B表示实体的开始,O表示其他;

要读取此类数据集,需要将列结构定义为字典并使用辅助方法。

from flair.data import TaggedCorpus
from flair.data_fetcher import NLPTaskDataFetcher

# define columns
columns = {0: 'text', 1: 'pos', 2: 'np'}

# this is the folder in which train, test and dev files reside
data_folder = '/path/to/data/folder'

# retrieve corpus using column format, data folder and the names of the train, dev and test files
corpus: TaggedCorpus = NLPTaskDataFetcher.load_column_corpus(data_folder, columns,
                                                              train_file='train.txt',
                                                              test_file='test.txt',
                                                              dev_file='dev.txt')

这将为您提供TaggedCorpus对象,其中包含train,dev和test 集,每个对象都有一个Sentence列表。 因此,要检查训练分组中有多少句子,请执行:

len(corpus.train)

您还可以访问句子并查看注释。 让我们假设训练集中的第一个句子是上面的例句,然后使用下面代码:

print(corpus.train[0].to_tagged_string('pos'))
print(corpus.train[0].to_tagged_string('ner'))

输出具有不同注释层的句子:

George <N> Washington <N> went <V> to <P> Washington <N>

George <B-PER> Washington <I-PER> went to Washington <B-LOC> .

读取文本分类数据集

Flair使用的文本分类数据格式基于FastText格式,其中文件中的每一行代表一个文本文档。 一个文档可以有一个或多个标签,这些标签在以#_label__前缀开头的行的开头定义。 这看起来像这样:

__label__<label_1> <text>
__label__<label_1> __label__<label_2> <text>

要为文本分类任务创建TaggedCorpus,您需要以上述格式将三个文件(train,dev和test)放在一个文件夹中。 例如,对于IMDB任务,此数据文件夹结构可能如下所示:

/resources/tasks/imdb/train.txt
/resources/tasks/imdb/dev.txt
/resources/tasks/imdb/test.txt

如果您现在将NLPTaskDataFetcher指向此文件夹(/ resources / tasks / imdb),它将从三个不同的文件中创建TaggedCorpus。 因此,文件中的每一行都被转换为用标签注释的Sentence对象。代码如下:

from flair.data_fetcher import NLPTaskDataFetcher
from pathlib import Path

# use your own data path
data_folder = Path('/resources/tasks/imdb')

# load corpus containing training, test and dev data
corpus: TaggedCorpus = NLPTaskDataFetcher.load_classification_corpus(data_folder,
                                                                     test_file='test.txt',
                                                                     dev_file='dev.txt',
                                                                     train_file='train.txt')

注意:一行中的文本可以有多个句子。 因此,Sentence对象实际上可以包含多个句子。

如果您只想读取单个文件,可以使用NLPTaskDataFetcher.read_text_classification_file('path / to / file.txt),它返回Sentence对象的列表。

下载数据集

Flair还支持开箱即用的几个数据集。 例如,您可以通过调用加载这些数据集:

corpus = NLPTaskDataFetcher.load_corpus(NLPTask.UD_ENGLISH)

这行代码将下载UD_ENGLISH数据集并将其放入〜/ .flair / datasets / ud_english。 该方法返回TaggedCorpus,可直接用于训练您的模型。

目前Flair支持以下数据集:

TaggedCorpus对象

  • TaggedCorpus代表您的整个数据集。 TaggedCorpus由测试集句子列表,开发集句子列表和测试集句子列表组成。

  • TaggedCorpus包含许多有用的辅助函数。 例如,您可以通过调用downsample()并传递比率来对数据进行下采样。 所以,如果你通常得到这样的语料库:

original_corpus = NLPTaskDataFetcher.load_corpus(NLPTask.UD_ENGLISH)

然后你可以对语料库进行下采样,就像这样:

downsampled_corpus = NLPTaskDataFetcher.load_corpus(NLPTask.UD_ENGLISH).downsample(0.1)

如果您打印两个语料库,您会看到第二个语料库已被下采样到10%的数据。

print("--- 1 Original ---")
print(original_corpus)

print("--- 2 Downsampled ---")
print(downsampled_corpus)

输出:

--- 1 Original ---
TaggedCorpus: 12543 train + 2002 dev + 2077 test sentences

--- 2 Downsampled ---
TaggedCorpus: 1255 train + 201 dev + 208 test sentences

对于许多学习任务,您需要创建目标字典。 因此,TaggedCorpus使您可以创建标签或标签字典,具体取决于您要学习的任务。例如:

# create tag dictionary for a PoS task
corpus = NLPTaskDataFetcher.load_corpus(NLPTask.UD_ENGLISH)
print(corpus.make_tag_dictionary('upos'))

# create tag dictionary for an NER task
corpus = NLPTaskDataFetcher.load_corpus(NLPTask.CONLL_03_DUTCH)
print(corpus.make_tag_dictionary('ner'))

# create label dictionary for a text classification task
corpus = NLPTaskDataFetcher.load_corpus(NLPTask.IMDB, base_path='path/to/data/folder')
print(corpus.make_label_dictionary())

另一个有用的函数是obtain_statistics(),它返回一个python字典,其中包含有关数据集的有用统计信息。 例如,在像这样的IMDB数据集上使用它:

from flair.data_fetcher import NLPTaskDataFetcher, NLPTask
 
corpus = NLPTaskDataFetcher.load_corpus(NLPTask.IMDB, base_path='path/to/data/folder')
stats = corpus.obtain_statistics()
print(stats)

输出:

{
  'TRAIN': {
    'dataset': 'TRAIN', 
    'total_number_of_documents': 25000, 
    'number_of_documents_per_class': {'POSITIVE': 12500, 'NEGATIVE': 12500}, 
    'number_of_tokens': {'total': 6868314, 'min': 10, 'max': 2786, 'avg': 274.73256}
  }, 
  'TEST': {
    'dataset': 'TEST', 
    'total_number_of_documents': 12500, 
    'number_of_documents_per_class': {'NEGATIVE': 6245, 'POSITIVE': 6255}, 
    'number_of_tokens': {'total': 3379510, 'min': 8, 'max': 2768, 'avg': 270.3608}
  }, 'DEV': {
    'dataset': 'DEV', 
    'total_number_of_documents': 12500, 
    'number_of_documents_per_class': {'POSITIVE': 6245, 'NEGATIVE': 6255}, 
    'number_of_tokens': {'total': 3334898, 'min': 7, 'max': 2574, 'avg': 266.79184}
  }
}

MultiCorpus对象

如果需要一次训练多个任务,可以使用MultiCorpus对象。 要启动MultiCorpus,首先需要创建任意数量的TaggedCorpus对象。 之后,您可以将TaggedCorpus列表传递给MultiCorpus对象。

    english_corpus = NLPTaskDataFetcher.load_corpus(NLPTask.UD_ENGLISH)
    german_corpus = NLPTaskDataFetcher.load_corpus(NLPTask.UD_GERMAN)
    dutch_corpus = NLPTaskDataFetcher.load_corpus(NLPTask.UD_DUTCH)
    
    multi_corpus = MultiCorpus([english_corpus, german_corpus, dutch_corpus])

MultiCorpus对象具有与TaggedCorpus相同的接口。 您可以简单地将MultiCorpus传递给训练函数而不是TaggedCorpus,训练函数不会知道差异,训练将照常运作。