创建 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,但是现在我还没有用到。
加载语料库
然后我们可以通过 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内的所有句子会 pad 成 batch 内最长的句子长度。
- batch.Text 和 batch.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(词汇表)。
其它
希望迭代器返回固定长度的文本
- 设置Field的fix_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