TorchText-DAY1

TorchText-DAY1

TorchText是一种处理文本的工具,它是Pytorch的一个子项目。

官方文档:https://pytorch.org/text/stable/data.html

它有以下组件:

  • torchtext.data.Field:该类用来定义字段的一些处理方法(字段包含文本字段、标签字段)

  • torchtext.data.Datasets:数据集类。根据【数据文件的路径】、【Field】生成数据集。使用__ getitem __方法得到Example实例。

  • torchtext.data.Iterator:迭代器。根据【Datasets】实例获取有 batch 的Loader。

  • torchtext.data.Example:用来表示一个样本,数据+标签。

  • torchtext.vocab.Vocab:词汇表相关。(字典)
    在这里插入图片描述

我们训练使用的是迭代器类型的数据。

从上面这张图可以看出迭代器是由【Datasets】生成的;

Datasets是根据file path读取到data.csv中的数据,根据Field进行解析后的到的数据;

Field包含一个Vocab对象(就是词典对象);

而从Datasets中又可以抽离出一个个的样本Example;

Field组件

Field组件是TorchText的核心组件。用户可以根据该组件指定如何处理字段!,它包含一个Vocab词典对象 {词:词向量}

Field对象还包含 数据如何数字化的相关参数, 例如标记化方法(也就是分词方法)、应生成的Tensor的类型(例如:LongTensor、FloatTensor)

上面说了Field包含文本字段和标签字段,对于文本字段是序列化的、可以分词的,所以我们可以设置sequential=True、use_vocab=True(不过他们默认就是True的)。但是对于标签字段,我们并不需要分词,所以要设置sequential=False、use_vocab=False。

import torchtext
from torchtext.data import Field


tokenize = lambda x: x.split()

TEXT = Field(tokenize=tokenize)
LABEL = Field(sequential=False, use_vocab=False)
# TEXT.vocab_cls.load_vectors()

这样就创建了两个Fielter了,一个是处理序列化文本的TEXT;另一个是不分词的LABLE。tokenizer是用来对字段样本进行标记化,也就是分词的一个函数(在这里每个字段的数据是中文且分过词用空格隔开的)

从被注释掉的那句代码可以看到【Field】中是存在一个字段对象【vector】的(在源码的init方法中声明的)可以进行【load_vectors】进行加载字典。这里需注意的是:这个字典是TorchText自己写的字典,并不是gensim中的那个word2vec.wv对象!

  • Field构造方法所拥有的参数(Field类所拥有的属性)
属性作用
tokenize分词函数. 默认值: str.split.
sequential是否把数据表示成序列,如果是False, 不能使用分词 默认值: True.
use_vocab是否使用词典对象. 如果是False 数据的类型必须已经是数值类型. 默认值: True.
lower是否把数据转化为小写 默认值: False.
tensor_type把数据转换成的tensor类型 默认值: torch.LongTensor.
fix_length修改每条数据的长度为该值,不够的用pad_token补全. 默认值: None.
include_lengths是否返回一个已经补全的最小batch的元组和和一个包含每条数据长度的列表 . 默认值: False.
batch_first数据是否批量优先(就是批量是最外层的)默认值: False.
preprocessing在分词之后和数值化之前使用的管道 默认值: None.
postprocessing数值化之后和转化成tensor之前使用的管道默认值: None.
init_token每一条数据的起始字符 默认值: None.
eos_token每条数据的结尾字符 默认值: None.
pad_token用于补全的字符. 默认值: “<pad>”.
unk_tokenunk_token
pad_first是否补全第一个字符. 默认值: False.

需要注意的一点是训练集的Field必须构建词表后,才能使用迭代器(否则迭代器进行迭代会报Field没有vocab属性)!!!!!!!!!!!!

TEXT.build_vocab(train)
# train为训练集,可以是Dataset类型也可以是TabularDataset类型

Vocab组件

【Vocab】组件作用是字典,它可以直接放到【Field】中作为分词直接使用,通过【fieldObj.vocab = vocab】。

词典中拥有两种存储方式:一种是字典存储,另一种是列表存储

  • 列表存储:将词存入列表中,列表的索引作为词的索引。通过下标取词(可能是通过哈希表存的)

    vocab.stoi['qwe']
    # result:10
    
  • 字典存储:将词存入字典中,键为词、值为列表中的词索引。通过词取列表索引

    vocab.itos[10]
    # result:qwe
    

例子:

data:
   news author  classify
0  asdf      a         1
1   qwe      b         2
2     6      c         3
3   ert      d         4
4  tyiu      e         5
from torchtext.data import Iterator, BucketIterator

TEXT.build_vocab(train[0])
train_iter = Iterator(train[0], 
                      batch_size=1, 
                      device=-1,
                      sort=False, 
                      sort_within_batch=False, 
                      repeat=False)
for batch in train_iter:
    print(batch, type(batch))
    x = batch.news
    y = batch.classify
    print(x, y)
    print(TEXT.vocab.itos[x])
result:
[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[2]]) tensor([3])
6

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[11]]) tensor([5])
tyiu

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[9]]) tensor([4])
ert

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[4]]) tensor([1])
asdf

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[10]]) tensor([2])
qwe

这样存储的好处是:只需将词的索引存入dataset中,减小了内存使用。

Dataset组件

根据Field程序就知道怎样处理数据了,然后将Field与file path以同传入Dataset中,Field就知道处理哪里的数据了,并将处理后的数据转换成Dataset类型。

在这里注意!Field只是一个模板告诉程序怎样处理数据。我们如果传入数据对于每个字段我们都需要知道怎样处理,所以需要一个处理列表。(csv格式而言)

在这里使用【TabularDataset】,它是继承自【Dataset】的。使用它的静态方法【splits】得到数据。

方法原型:

def splits(cls, path=None, root='.data', train=None, validation=None, test=None, **kwargs)
'''
path:数据文件的前缀
root:根数据集的存储目录
train:训练数据文件名(如果不写path就必须写全路径)
validation:验证集数据文件名(如果不写path就必须写全路径)
test:测试集数据文件名(如果不写path就必须写全路径)
'''

工作原理:根据 path+[train, validation, test] 获取文件的路径,根据文件路径使用【download】读取数据,最后判断是否读取数据了,返回已读取数据的字段。

示例1:

from torchtext.data import TabularDataset
# 训练集的字段列表
trainDataFieldList = [('id', None),
                      ('news_title', TEXT),
                      ('author', LABLE),
                      ('classify', LABLE)]
# 得到训练集,验证集,测试集的 Dataset
train, validation, text = TabularDataset.splits(
    path=r'D:\poject\test\data',
    root=".data",
    train="train.csv",
    validation="validation.csv",
    format="csv",
    skip_header=True,
    fields=trainDataFieldList
)


# 测试集字段列表。因为测试集只需要数据不需要标签
testDataFieldList = [('id', None),
                     ('news_title', TEXT)]
test = TabularDataset.splits(
    path=r'D:\poject\test\data',
    root=".data",
    test="test.csv",
    format="csv",
    skip_header=True,
    fields=testDataFieldList
)

示例2:

  • 样本

       news author  classify
    0  asdf      a         1
    1   qwe      b         2
    2   wer      c         3
    3   ert      d         4
    4  tyiu      e         5
    
from torchtext.data import TabularDataset
# 训练集的字段列表
trainDataFieldList = [('id', None),
                      ('news', TEXT),
                      ('author', TEXT),
                      ('classify', LABEL)]
# 得到训练集,验证集,测试集的 Dataset
train = TabularDataset.splits(
    path=r'./data',
    root=".data",
    train="data3.csv",
    format="csv",
    skip_header=True,
    fields=trainDataFieldList
)
# 建立一个字典  拆离字典使用:TEXT.vocab
TEXT.build_vocab(train[0])


print(train[0].__dict__.keys())
print(train[0].comment_text)
结果:
(<torchtext.data.dataset.TabularDataset object at 0x000001B521021FD0>,)
dict_keys(['examples', 'fields'])
<generator object Dataset.__getattr__ at 0x000001B520DF58E0>

Example组件

【Dataset】中的每一项是一个【Example】实例。【Example】实例就是一行,拥有每个字段的一个值构成一行。

可以从中这样获取数据:

print(train[0].examples[0].news)
result:
['asdf']

这个是没有打乱的数据,【Dataset】经过【Iterator】才会打乱!

Iterator组件

现在有了【Dataset】数据了,现在需要将数据转换成一批量一批量的迭代器才能用于训练!

from torchtext.data import Iterator, BucketIterator

train_iter = Iterator(train[0], 
                      batch_size=1, 
                      device=-1,
                      sort=False, 
                      sort_within_batch=False, 
                      repeat=False)

Batch组件

Iterator组件每次迭代返回的是Batch组件!

for batch in train_iter:
    print(batch, type(batch))
result:
[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>

可以看出【batch】中的是三个字段。因为【batch_size】是1,所以每个字段中拥有一个数据;假如【batch_size】为2,那么数据的格式应该是【1*2】。

[torchtext.data.batch.Batch of size 2]
	[.news]:[torch.LongTensor of size 1x2]
	[.author]:[torch.LongTensor of size 1x2]
	[.classify]:[torch.LongTensor of size 2] <class 'torchtext.data.batch.Batch'>

可以通过字段名取出batch中的数据,通过词典转换成词:

for batch in train_iter:
    print(batch, type(batch))
    x = batch.news
    y = batch.classify
    print(x, y)
    print(TEXT.vocab.itos[x])
[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[2]]) tensor([3])
6

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[11]]) tensor([5])
tyiu

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[9]]) tensor([4])
ert

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[4]]) tensor([1])
asdf

[torchtext.data.batch.Batch of size 1]
	[.news]:[torch.LongTensor of size 1x1]
	[.author]:[torch.LongTensor of size 1x1]
	[.classify]:[torch.LongTensor of size 1] <class 'torchtext.data.batch.Batch'>
tensor([[10]]) tensor([2])
qwe

【Iterator】返回的是一个【Batch】实例,如果要进行训练需要将其中的值取出。取出的值为【tensor】类型。再进行封装即可!

class DataIterator:
    def __init__(self, iterator):
        self.iterator = iterator
        
    def __iter__(self):
        for batch in self.iterator:
            x = batch.news
            y = batch.classify
            yield x, y
    
    def __len__(self):
        return len(self.iterator)
    
dataIterator = DataIterator(train_iter)

for x, y in dataIterator:
    print(x, y)
result:
tensor([[10]]) tensor([2])
tensor([[4]]) tensor([1])
tensor([[2]]) tensor([3])
tensor([[11]]) tensor([5])
tensor([[9]]) tensor([4])

这样就可以进行训练了。说白了【torchtext】就是一个数据集构建工具,它比【torch.utils.data】中的【DataLoader, Dataset】更便捷一些,可以读取cvs等格式的数据。

这只是一个小入门,更多的操作请看官方文档!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值