1.torchtext介绍
torchtext常用于文本处理,其结构主要是3大部分,分别是Field,Dataset和Iteration三大部分。其中Field主要是对数据字段进行预处理 ,Dataset
是定义数据源信息,至于Iteration
,和DataLoader
很类似。
Field.sequential – 输入的数据是否是序列型的,如果不是,将不使用tokenzie对数据进行处理
~Field.use_vocab – 是否使用Vocab对象,也就是使用输入的词向量,这里以后会讲到,如果不使用,那么输入Field的对象一定是数字类型的。 一
~Field.init_token – 给example数据的开头加一个token,感觉类似<CLS>标签,example之后会将
~Field.eos_token – 给example数据加一个结束token
~Field.fix_length – 设定序列的长度,不够的进行填充
~Field.dtype – 表示输入的example数据的类型
~Field.lower – 是否将输入的文本变成小写
~Field.tokenize – 设置一个tokenize分词器给Field用,这里也有内置的一些分词器可以用
~Field.tokenizer_language – 分词器tokenize的语言,这里是针对SpaCy的
~Field.include_lengths – 是否在返回文本序列的时候返回文本的长度,这里是对LSTM的变长输入设置非常好用
~Field.batch_first – 输出的数据的维度中batch的大小放到前面
~Field.pad_token – 用于填充文本的关键字,默认是<pad>
~Field.unk_token – 用于填充不在词汇表中的关键字,默认是<unk>
~Field.pad_first – 是否将填充放到文本最前面
~Field.truncate_first – 是否从文本开始的地方将文本截断
~Field.stop_words – 停止词的设置
2.Dataset
- 以TabularDataset为例:
from torchtext.data import Field
from torchtext.data import TabularDataset
# 定义Field
tokenize = lambda x: x.split()
# tokenize = lambda x: jieba.lcut(x)
# def tokenizer(text): # create a tokenizer function
# return [tok for tok in text]
TEXT = Field(sequential=True, tokenize=tokenize, lower=True, fix_length=200)
LABEL = Field(sequential=False, use_vocab=False)
# 构建Dataset
fields = [("id", None),("comment_text",TEXT),("toxic",LABEL)]
# 使用splits方法可以为多个数据集直接创建Dataset
train, valid = TabularDataset.splits(
path='data',##路径
train='xxx',
validation='xxx',
format='csv',
skip_header=True,
fields=fields)
test_datafields = [('text', None),('label', TEXT)]
# 直接创建Dataset(不使用splits)
test = TabularDataset(
path=r'xxx.csv',
format='csv',
skip_header=True,
fields=test_datafields
)
2.查看dataset实例
print(train[5])
print(train[5].__dict__.keys())
print(train[5].text,train[0].label)
3.Iteration
这里使用了BucketIterator
和Iterator
,因为BucketIterator
可以自动的选择长度类似的文本组成一个batch,所以用于训练数据,而测试数据一般而言不想进行排序或者其他的操作,就使用了Iterator
。BucketIerator:相比于标准迭代器,会将类似长度的样本当做一批来处理,因为在文本处理中经常会需要将每一批样本长度补齐为当前批中最长序列的长度,因此当样本长度差别较大时,使用BucketIerator可以带来填充效率的提高。除此之外,我们还可以在Field中通过fix_length参数来对样本进行截断补齐操作。
train_iterator = BucketIterator(train_dataset, batch_size=batch_size,
device='cuda',
sort_within_batch=True, shuffle=True)
test_iterator = Iterator(test_dataset, batch_size=batch_size,
device='cuda', train=False,
shuffle=False, sort=False, sort_within_batch=True)
4.torchtext 相关函数
构建词表
bulid_vocab()方法
TEXT.build_vocab(train)
counter – 这里用来计算输入的数据的频率的,其实没太看明白英文翻译,不过这里对应build_vocab输入的是Dataset,经过build_vocab处理之后传递给torchtext.vocab.Vocab
max_size – 词向量表的最大大小
min_freq – 参与转换成词向量的最小词频率,不满足这个词频率的直接就是<unk>了
specials – 需要添加到词向量表中的一些特殊字符,默认的包含['<unk'>,'<pad>']两种,也是因为这个参数,所以我们的txt文件中的词向量不需要包含这两个特殊字符。
vectors – 用于加载的预训练好的词向量
unk_init (callback) – 用于初始化未知词汇的词向量,默认是0
vectors_cache – 存放缓存的目录,这个不一定在这里设定,在Vectors类中设置也行
specials_first – 改变特征字符在词汇表中的位置,是放在最前面还是放在最后面
使用预训练的词向量 在使用pytorch或tensorflow等神经网络框架进行nlp任务的处理时,可以通过对应的Embedding层做词向量的处理,更多的时候,使用预训练好的词向量会带来更优的性能,下面介绍如何在torchtext中使用预训练的词向量,进而传送给神经网络模型进行训练。
不使用的话 直接就冲了。
1.#torchtext 默认的词向量
TEXT.build_vocab(train, vectors="glove.6B.200d")
"""
支持以下的词向量(直接导入)
charngram.100d
fasttext.en.300d
fasttext.simple.300d
glove.42B.300d
glove.840B.300d
glove.twitter.27B.25d
glove.twitter.27B.50d
glove.twitter.27B.100d
glove.twitter.27B.200d
glove.6B.50d
glove.6B.100d
glove.6B.200d
glove.6B.300d
"""
2.torchtext外部预训练的向量
默认情况下预训练词向量文件和缓存文件的目录位置都为当前目录下的 .vector_cache目录,虽然通过name参数指定了预训练词向量文件存在的目录,但是因为缓存文件的目录没有特殊指定,此时在当前目录下仍然需要存在 .vector_cache 目录。
if not os.path.exists(.vector_cache):
os.mkdir(.vector_cache)
vectors = Vectors(name='myvector/glove/glove.6B.200d.txt')
TEXT.build_vocab(train, vectors=vectors)
在使用预训练好的词向量时,我们需要在神经网络模型的Embedding层中明确地传递嵌入矩阵的初始权重。权重包含在词汇表的vectors属性中。以Pytorch搭建的Embedding层为例
# 通过pytorch创建的Embedding层
embedding = nn.Embedding(2000, 256)
# 指定嵌入矩阵的初始权重
weight_matrix = TEXT.vocab.vectors
embedding.weight.data.copy_(weight_matrix )
# 指定预训练权重的同时设定requires_grad=True
# embeddings.weight = nn.Parameter(embeddings, requires_grad=True)
参考来源: 知乎大v
结语
励志做一个有梦想的NLPer
坑坑 加油