创建 Field 对象

Field这个对象包含了我们打算如何预处理文本数据的信息。 下面定义了两个 **Field 对象。

TEXT = data.Field(sequential=True, # 是否把数据表示成序列,如果是False, 不能使用分词 默认值: True.
                  tokenize=rumor_tokenize,# 分词函数
                  fix_length=max_length,#截断的长度
                  use_vocab=True)

LABEL = data.Field(sequential=False,
                   use_vocab=False)

如果LABEL是整型,不需要numericalize, 就需要将use_vocab=False.Torchtext可能也会允许使用 text 作为 label,但是现在我还没有用到。

torch text实践过程图

加载语料库

然后我们可以通过 torchtext.data.Dataset 的类方法 splits 加载所有的语料库:(假设我们有三个语料库,train.tsv, val.tsv, test.tsv)

train, dev, test = data.TabularDataset.splits(path=os.path.join(data_path,task_name),#数据集存放路径
                                              train=train_file,
                                              validation=valid_file,
                                              test=test_file,
                                              format='csv', #csv/json
                                              skip_header=True, # 跳过表头
                                              csv_reader_params={'delimiter':','}, #用/t分割
                                              fields=[("text",TEXT),('label',LABEL)])

然后构建语料库的 Vocabulary, 同时,加载预训练的 word-embedding

导入预训练词向量

# 导入预训练词向量
if load_embedding == "None":
    TEXT.build_vocab(train)
elif load_embedding == "w2v":
    cache = '.vector_cache'
    if not os.path.exists(cache):
        os.mkdir(cache)
    vectors = Vectors(name=w2v_file,cache=cache)
    TEXT.build_vocab(train, vectors=vectors)
elif load_embedding == "glove":
    cache = '.vector_cache'
    if not os.path.exists(cache):
        os.mkdir(cache)
    vectors = Vectors(name=glove_file, cache=cache)
    TEXT.build_vocab(train, vectors=vectors)
elif load_embedding == "weibo_biggram":
    cache = '.vector_cache'
    vectors = Vectors(name=weibo_file, cache=cache)
    TEXT.build_vocab(train,max_size=5000,vectors=vectors)
  
    #TEXT.bulid_vocab(train_data,max_size=10000) #将词汇表中频率前10000的单词取出来
    #TEXT.bulid_vocab(train_data,min_freq=10) #将词汇表中频率大于等于10的单词取出来
else:
    TEXT.build_vocab(train)

通过api来创建iterator

我们可以直接传一个 string,然后后端会下载 word vectors 并且加载她。我们也可以通过 vocab.Vectors 使用自定义的 vectors.

train_iter, val_iter, test_iter = data.Iterator.splits(
        (train, val, test), sort_key=lambda x: len(x.Text),
        batch_sizes=(32, 256, 256), device=-1)

batch = next(iter(train_iter))
print("batch text: ", batch.Text) # 对应 Fileld 的 name
print("batch label: ", batch.Label)
"""
BucketIterator为了使padding最少,会在batch之前先对整个dataset上的cases进行sort(按一定规则),
将相近长度的case放在一起,这样一个batch中的cases长度相当,使得padding的个数最小。
同时,为了每次能生成稍微不同的batch,在sort之前加入了noise进行长度的干扰。
"""
train_iter, val_iter, test_iter = data.BucketIterator.splits((train,dev,test),
                                                             batch_size = batch_size,
                                                             shuffle=True,
                                                             sort=False,
                                                             sort_within_batch=False,
                                                             repeat=False)
  • 如果您要运行在 CPU 上,需要设置 device=-1, 如果运行在GPU 上,需要设置device=0
  • torchtext 使用了动态 padding,意味着 batch内的所有句子会 padbatch 内最长的句子长度。
  • batch.Textbatch.Label 都是 torch.LongTensor 类型的值,保存的都是 index。

获得word vocab

我们使用 Pytorch 的 Embedding Layer 来解决 embedding lookup 问题。

Vocab = len(DataSet.getTEXT().vocab)
self.embed = nn.Embedding(Vocab, Dim)  ## 词向量,这里直接随机
# 指定嵌入矩阵的初始权重 ****
if load_embedding == "w2v":
    weight_matrix = DataSet.getTEXT().vocab.vectors
    self.embedding.weight.data.copy_(weight_matrix)
elif load_embedding == "glove":
    weight_matrix = DataSet.getTEXT().vocab.vectors
    self.embedding.weight.data.copy_(weight_matrix)
elif load_embedding == "weibo_biggram":
    weight_matrix = DataSet.getTEXT().vocab.vectors
    self.embedding.weight.data.copy_(weight_matrix)

为什么使用 Field 抽象

torchtext 认为一个样本是由多个字段(文本字段,标签字段)组成,不同的字段可能会有不同的处理方式,所以才会有 Field 抽象。

  • Field: 定义对应字段的处理操作
  • Vocab: 定义了 词汇表
  • Vectors: 用来保存预训练好的 word vectors

<span class="ne-text">TEXT.build_vocab(train, vectors="glove.6B.100d")</span>

上述代码的意思是从预训练的 vectors 中,将当前 corpus 词汇表的词向量抽取出来,构成当前 corpus 的 Vocab(词汇表)。

其它

希望迭代器返回固定长度的文本

  • 设置Fieldfix_length属性

在创建字典时, 希望仅仅保存出现频率最高的 k 个单词

  • .build_vocab时使用max_size参数指定

如何指定 Vector 缺失值的初始化方式

  • vector.unk_init = init.xavier_uniform 这种方式指定完再传入 build_vocab

参考链接

[1] https://blog.csdn.net/dendi_hust/article/details/101221922

[2] http://anie.me/On-Torchtext/

[3] https://www.yuque.com/cqustkg/lnznt6/ka69ua

最后修改:2022 年 06 月 21 日
如果觉得我的文章对你有用,请随意赞赏