torchtext入门教程必看,带你轻松玩转文本数据处理

用深度学习做nlp也有一段时间了,熟悉这块内容的同学都知道,实践算法的时候,写模型是个简单的事,最麻烦的是数据处理,数据处理不仅会浪费我们大部分时间,而且会消耗很大的计算资源,浪费人力物力。

今年开始接触pytorch,简洁的API,动态图,更加灵活的编写模式,诸多优点不用多说。

最近尝试使用torchtext工具,这里想先说明的是,torchtext并不是pytorch所独有的,使用其它深度学习框架,torchtext仍然可以使用。

但是比较麻烦的是,并没有很好很全面的torchtext教程,给同学们入门造成了一定麻烦,这也是我写这篇文章的目的。

首先整体介绍一下torchtext的组件

torchtext包含以下组件:

Field :主要包含以下数据预处理的配置信息,比如指定分词方法,是否转成小写,起始字符,结束字符,补全字符以及词典等等

Dataset :继承自pytorch的Dataset,用于加载数据,提供了TabularDataset可以指点路径,格式,Field信息就可以方便的完成数据加载。同时torchtext还提供预先构建的常用数据集的Dataset对象,可以直接加载使用,splits方法可以同时加载训练集,验证集和测试集。

Iterator : 主要是数据输出的模型的迭代器,可以支持batch定制

1. Field

Field 包含一写文本处理的通用参数的设置,同时还包含一个词典对象,可以把文本数据表示成数字类型,进而可以把文本表示成需要的tensor类型

以下是Field对象包含的参数:

sequential: 是否把数据表示成序列,如果是False, 不能使用分词 默认值: True.

use_vocab: 是否使用词典对象. 如果是False 数据的类型必须已经是数值类型. 默认值: True.

init_token: 每一条数据的起始字符 默认值: None.

eos_token: 每条数据的结尾字符 默认值: None.

fix_length: 修改每条数据的长度为该值,不够的用pad_token补全. 默认值: None.

tensor_type: 把数据转换成的tensor类型 默认值: torch.LongTensor.

preprocessing:在分词之后和数值化之前使用的管道 默认值: None.

postprocessing: 数值化之后和转化成tensor之前使用的管道默认值: None.

lower: 是否把数据转化为小写 默认值: False.

tokenize: 分词函数. 默认值: str.split.

include_lengths: 是否返回一个已经补全的最小batch的元组和和一个包含每条数据长度的列表 . 默认值: False.

batch_first: Whether to produce tensors with the batch dimension first. 默认值: False.

pad_token: 用于补全的字符. 默认值: "<pad>".

unk_token: 不存在词典里的字符. 默认值: "<unk>".

pad_first: 是否补全第一个字符. 默认值: False.

重要的几个方法:

pad(minibatch): 在一个batch对齐每条数据

build_vocab(): 建立词典

numericalize(): 把文本数据数值化,返回tensor

简单的栗子如下,建一个Field对象

TEXT = data.Field(tokenize=data.get_tokenizer('spacy'),
                  init_token='<SOS>', eos_token='<EOS>',lower=True)

2.Dataset

torchtext的Dataset是继承自pytorch的Dataset,提供了一个可以下载压缩数据并解压的方法(支持.zip, .gz, .tgz)

splits方法可以同时读取训练集,验证集,测试集

TabularDataset可以很方便的读取CSV, TSV, or JSON格式的文件,例子如下:

train, val, test = data.TabularDataset.splits(
        path='./data/', train='train.tsv',
        validation='val.tsv', test='test.tsv', format='tsv',
        fields=[('Text', TEXT), ('Label', LABEL)])

加载数据后可以建立词典,建立词典的时候可以使用与训练的word vector

TEXT.build_vocab(train, vectors="glove.6B.100d")

3. Iterator

Iterator是torchtext到模型的输出,它提供了我们对数据的一般处理方式,比如打乱,排序,等等,可以动态修改batch大小,这里也有splits方法 可以同时输出训练集,验证集,测试集

参数如下:

dataset: 加载的数据集

batch_size: Batch 大小.

batch_size_fn: 产生动态的batch大小 的函数

sort_key: 排序的key

train: 是否是一个训练集

repeat: 是否在不同epoch中重复迭代

shuffle: 是否打乱数据

sort: 是否对数据进行排序

sort_within_batch: batch内部是否排序

device: 建立batch的设备 -1:CPU ;0,1 ...:对应的GPU

使用方式如下:

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)

4.其他

torchtext提供常用文本数据集,并可以直接加载使用:

train,val,test = datasets.WikiText2.splits(text_field=TEXT)

现在包含的数据集包括:

Sentiment analysis: SST and IMDb
Question classification: TREC
Entailment: SNLI
Language modeling: WikiText-2
Machine translation: Multi30k, IWSLT, WMT14

完整例子如下,短短几行就把词典和数据batch做好了。

import spacy
import torch
from torchtext import data, datasets
spacy_en = spacy.load('en')
def tokenizer(text): # create a tokenizer function
    return [tok.text for tok in spacy_en.tokenizer(text)]
TEXT = data.Field(sequential=True, tokenize=tokenizer, lower=True, fix_length=150)
LABEL = data.Field(sequential=False, use_vocab=False)
train, val, test = data.TabularDataset.splits(
        path='./data/', train='train.tsv',
        validation='val.tsv', test='test.tsv', format='tsv',
        fields=[('Text', TEXT), ('Label', LABEL)])
TEXT.build_vocab(train, vectors="glove.6B.100d")
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)
vocab = TEXT.vocab

补充:使用TorchText处理我们自己的数据集

TorchText可以读取三种数据格式:json, tsv (tab separated values 制表分隔值)和csv(comma separated values 逗号分隔值)。

处理JSON数据

从json开始,你的数据必须是json行格式,也就是说,它必须是这样的:

{"name": "John", "location": "United Kingdom", "age": 42, "quote": ["i", "love", "the", "united kingdom"]}
{"name": "Mary", "location": "United States", "age": 36, "quote": ["i", "want", "more", "telescopes"]}

也就是说,每一行都是一个json对象。data/trian.json为例。

然后我们定义字段:

from torchtext import data
from torchtext import datasets
NAME = data.Field()
SAYING = data.Field()
PLACE = data.Field()

接下来,我们必须告诉TorchText哪个字段应用于json对象的哪个元素。

对于json数据,我们必须创建一个字典:

键与json对象的键匹配

值为元组,其中:

第一个元素成为batch对象的属性名

第二个元素是字段的名称

一些注意事项:

fields字典中键的顺序并不重要,只要它的键与json数据键匹配即可。

字段名不必与json对象中的键匹配,例如,我们使用PLACE来表示“location”字段。

当处理json数据时,并不是所有的键都必须使用,例如,我们没有使用“age”字段。

同样,如果json字段的值是一个字符串,那么将应用字段标记化(默认情况下是将字符串按空格分隔),然而,如果值是一个列表,则不应用标记化。通常情况下,将数据标记为一个列表是一个好主意,这节省了时间,因为您不必等待TorchText来做这件事。

json字段的值不必是相同的类型。有些例子的“引号”可以是字符串,有些则是列表。标记化将只应用于那些以“引号”表示字符串的字符串。

如果你正在使用一个json字段,每个例子必须有一个该字段的实例,例如在这个例子中所有的例子必须有一个name,location和quote。但是,由于我们没有使用age字段,因此示例中没有age字段也没有关系。

fields = {'name': ('n', NAME), 'location': ('p', PLACE), 'quote': ('s', SAYING)}

现在,在训练循环中,我们可以通过数据迭代器进行迭代并且通过batch.n访问name,通过batch.p访问location,通过batch.s访问quote。

然后我们使用TabularDataset.splits函数创建我们的数据集(train_data和test_data)

path参数指定两个数据集中共同的顶级文件夹,train和test参数指定每个数据集的文件名,例如,这里的train数据集位于data/train.json。

我们告诉函数我们正在使用json数据,并将前面定义的fields字典传递给它。

train_data, test_data = data.TabularDataset.splits(
                            path = 'data',
                            train = 'train.json',
                            test = 'test.json',
                            format = 'json',
                            fields = fields
)

如果已经有验证数据集,则可以将其路径作为validation 参数传递。

train_data, valid_data, test_data = data.TabularDataset.splits(
                                        path = 'data',
                                        train = 'train.json',
                                        validation = 'valid.json',
                                        test = 'test.json',
                                        format = 'json',
                                        fields = fields
)

然后,我们可以查看一个示例,以确保它已经正确地工作。

请注意字段名(n、p和s)是如何与fields字典中定义的内容匹配的。

还请注意p中的单词“United Kingdom”是如何被标记化分开的,而s中的“United Kingdom”则没有。这是由于前面提到的原因,TorchText假设任何作为列表的json字段都已经被标记化了,并且不再应用进一步的标记化。

print(vars(train_data[0]))
{'n': ['John'], 'p': ['United', 'Kingdom'], 's': ['i', 'love', 'the', 'united kingdom']}

现在我们可以使用train_data、test_data和valid_data来构建词汇表并创建迭代器。我们可以使用batch.n, batch.p and batch.s访问分别表示names、places和sayings的所有属性。

处理CSV/TSV数据

csv和tsv非常相似,只是csv的元素用逗号分隔,而tsv用制表符分隔。

用上面的例子,我们的tsv数据将会是:

name    location    age quote
John    United Kingdom  42  i love the united kingdom
Mary    United States   36  i want more telescopes

也就是说,每一行的元素都由制表符分隔,每行有一个示例。第一行通常是标题(即每个列的名称),但你的数据也可能没有标题。

tsv或csv数据中不能有列表。

字段的定义方式与json稍有不同。现在我们使用一个元组列表,其中每个元素也是一个元组。这些内部元组的第一个元素将成为batch对象的属性名,第二个元素是字段名。

与json数据不同,元组必须与tsv数据中的顺序相同。因此,当跳过一列数据时,需要使用一个none元组,如果没有,那么我们的SAYING字段将应用到tsv数据的age列,而quote列将不会被使用。

但是,如果您只想使用name和age列,您可以只使用两个元组,因为它们是前两个列。

我们更改TabularDataset以读取正确的.tsv文件,并将format参数更改为'tsv'。

如果你的数据有一个标题头,我们的数据就有,它必须通过传递skip_header = True来跳过。如果没有,TorchText会认为头部是一个例子。默认情况下,skip_header为False。

fields = [('n', NAME), ('p', PLACE), (None, None), ('s', SAYING)]
train_data, valid_data, test_data = data.TabularDataset.splits(
                                        path = 'data',
                                        train = 'train.tsv',
                                        validation = 'valid.tsv',
                                        test = 'test.tsv',
                                        format = 'tsv',
                                        fields = fields,
                                        skip_header = True
)
print(vars(train_data[0]))
{'n': ['John'], 'p': ['United', 'Kingdom'], 's': ['i', 'love', 'the', 'united', 'kingdom']}

最后,我们将讨论csv文件。

这与tsv文件几乎完全相同,只是格式参数设置为“csv”。

fields = [('n', NAME), ('p', PLACE), (None, None), ('s', SAYING)]
train_data, valid_data, test_data = data.TabularDataset.splits(
                                        path = 'data',
                                        train = 'train.csv',
                                        validation = 'valid.csv',
                                        test = 'test.csv',
                                        format = 'csv',
                                        fields = fields,
                                        skip_header = True
)
print(vars(train_data[0]))
{'n': ['John'], 'p': ['United', 'Kingdom'], 's': ['i', 'love', 'the', 'united', 'kingdom']}

为什么JSON好于CSV/TSV?

csv或tsv数据无法存储列表。这意味着数据不能被标记化,因此每次运行通过TorchText读取数据的Python脚本时,数据都必须被标记化。使用高级的标记器,如spaCy标记器,需要不可忽略的大量时间。因此,最好是对数据集进行标记并以json行格式存储它们。

如果tsv数据中出现制表符,或csv数据中出现逗号,TorchText会认为它们是列之间的分隔符。这将导致数据被错误地解析。最糟糕的是,TorchText不会提醒你这一点,因为它无法分辨字段中的制表符/逗号和作为分隔符的制表符/逗号之间的区别。由于json数据本质上是一个字典,您可以通过它的键访问字段中的数据,所以不必担心“surprise”分隔符。

迭代器

使用上面的任何数据集,我们就可以构建词汇表并创建迭代器。

NAME.build_vocab(train_data)
SAYING.build_vocab(train_data)
PLACE.build_vocab(train_data)

然后,我们可以在定义批处理大小和设备后,创建迭代器。

默认情况下,训练数据在每个epoch进行洗牌,但验证/测试数据是排序的。然而,TorchText不知道该用什么来排序我们的数据,如果我们不告诉它,它就会抛出错误。

有两种方法来处理这个问题,你可以通过传递sort = False来告诉迭代器不要对验证/测试数据进行排序,或者你可以通过传递sort_key来告诉迭代器如何对数据进行排序。sort key是一个函数,它返回一个用于对数据进行排序的键。例如,lambda x: x.s将根据它们的s属性(即它们的quote)对示例进行排序。理想情况下,您希望使用sort key,因为BucketIterator将能够对示例进行排序,然后最小化每个批处理中的填充量。

然后,我们可以遍历迭代器来获得批量数据。注意,默认情况下TorchText的批处理维度是在第二维。

import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
BATCH_SIZE = 1
train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits(
    (train_data, valid_data, test_data),
    sort = False, #don't sort test/validation data
    batch_size=BATCH_SIZE,
    device=device)
train_iterator, valid_iterator, test_iterator = data.BucketIterator.splits(
    (train_data, valid_data, test_data),
    sort_key = lambda x: x.s, #sort by s attribute (quote)
    batch_size=BATCH_SIZE,
    device=device)
print('Train:')
for batch in train_iterator:
    print(batch)

print('Valid:')
for batch in valid_iterator:
    print(batch)

print('Test:')
for batch in test_iterator:
    print(batch)
Train:
[torchtext.data.batch.Batch of size 1]
	[.n]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.p]:[torch.cuda.LongTensor of size 2x1 (GPU 0)]
	[.s]:[torch.cuda.LongTensor of size 5x1 (GPU 0)]
[torchtext.data.batch.Batch of size 1]
	[.n]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.p]:[torch.cuda.LongTensor of size 2x1 (GPU 0)]
	[.s]:[torch.cuda.LongTensor of size 4x1 (GPU 0)]
Valid:
[torchtext.data.batch.Batch of size 1]
	[.n]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.p]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.s]:[torch.cuda.LongTensor of size 2x1 (GPU 0)]
[torchtext.data.batch.Batch of size 1]
	[.n]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.p]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.s]:[torch.cuda.LongTensor of size 4x1 (GPU 0)]
Test:
[torchtext.data.batch.Batch of size 1]
	[.n]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.p]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.s]:[torch.cuda.LongTensor of size 3x1 (GPU 0)]
[torchtext.data.batch.Batch of size 1]
	[.n]:[torch.cuda.LongTensor of size 1x1 (GPU 0)]
	[.p]:[torch.cuda.LongTensor of size 2x1 (GPU 0)]
	[.s]:[torch.cuda.LongTensor of size 3x1 (GPU 0)]

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • PyTorch加载自己的数据集实例详解

    数据预处理在解决深度学习问题的过程中,往往需要花费大量的时间和精力. 数据处理的质量对训练神经网络来说十分重要,良好的数据处理不仅会加速模型训练, 更会提高模型性能.为解决这一问题,PyTorch提供了几个高效便捷的工具, 以便使用者进行数据处理或增强等操作,同时可通过并行化加速数据加载. 数据集存放大致有以下两种方式: (1)所有数据集放在一个目录下,文件名上附有标签名,数据集存放格式如下: root/cat_dog/cat.01.jpg root/cat_dog/cat.02.jpg ...

  • pytorch实现建立自己的数据集(以mnist为例)

    本文将原始的numpy array数据在pytorch下封装为Dataset类的数据集,为后续深度网络训练提供数据. 加载并保存图像信息 首先导入需要的库,定义各种路径. import os import matplotlib from keras.datasets import mnist import numpy as np from torch.utils.data.dataset import Dataset from PIL import Image import scipy.misc

  • pytorch加载自己的图像数据集实例

    之前学习深度学习算法,都是使用网上现成的数据集,而且都有相应的代码.到了自己开始写论文做实验,用到自己的图像数据集的时候,才发现无从下手 ,相信很多新手都会遇到这样的问题. 参考文章https://www.jb51.net/article/177613.htm 下面代码实现了从文件夹内读取所有图片,进行归一化和标准化操作并将图片转化为tensor.最后读取第一张图片并显示. # 数据处理 import os import torch from torch.utils import data fr

  • pytorch 数据处理:定义自己的数据集合实例

    数据处理 版本1 #数据处理 import os import torch from torch.utils import data from PIL import Image import numpy as np #定义自己的数据集合 class DogCat(data.Dataset): def __init__(self,root): #所有图片的绝对路径 imgs=os.listdir(root) self.imgs=[os.path.join(root,k) for k in imgs

  • 使用pytorch和torchtext进行文本分类的实例

    文本分类是NLP领域的较为容易的入门问题,本文记录我自己在做文本分类任务以及复现相关论文时的基本流程,绝大部分操作都使用了torch和torchtext两个库. 1. 文本数据预处理 首先数据存储在三个csv文件中,分别是train.csv,valid.csv,test.csv,第一列存储的是文本数据,例如情感分类问题经常是用户的评论review,例如imdb或者amazon数据集.第二列是情感极性polarity,N分类问题的话就有N个值,假设值得范围是0~N-1. 下面是很常见的文本预处理流

  • torchtext入门教程必看,带你轻松玩转文本数据处理

    用深度学习做nlp也有一段时间了,熟悉这块内容的同学都知道,实践算法的时候,写模型是个简单的事,最麻烦的是数据处理,数据处理不仅会浪费我们大部分时间,而且会消耗很大的计算资源,浪费人力物力. 今年开始接触pytorch,简洁的API,动态图,更加灵活的编写模式,诸多优点不用多说. 最近尝试使用torchtext工具,这里想先说明的是,torchtext并不是pytorch所独有的,使用其它深度学习框架,torchtext仍然可以使用. 但是比较麻烦的是,并没有很好很全面的torchtext教程,

  • ActiveMQ简单入门(新手必看篇)

    一.创建一个简单的Hello World案例 首先需要导入activemq-all-5.14.5.jar包,写生产端: package com.ietree.mq.helloworld; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.MessageProduc

  • SpringMvc入门指南(必看)

    Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的. Spring Web MVC也是服务到工作者模式的实现,但进行可优化.前端控制器是DispatcherServlet:应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图

  • C# Dockpanel入门基础必看篇

    一.引用: 1.建立一个WinForm工程,默认生成了一个WinForm窗体Form1(此处默认为主窗体). 2.引用->添加引用->浏览->weiFenLuo.winFormsUI.Docking.dll. 3.设置Form1窗体属性IsMdiContainer:True. 4.工具箱->右键->选择项->.net组件->浏览->weiFenLuo.winFormsUI.Docking.dll->在工具箱出现dockPanel. 5.将dockPan

  • CSS网页布局入门教程11:带当前标识的标签式横向导航图片美化版

    虽然完成了标签式导航,但是广场状的导航似乎并不能够顺应现在的设计潮流,其实导航不仅可以使用css的颜色来定义,同样可以采用精心设计的图片或其它元素来构建导航,在这里我们将开始改善导航的设计,使它成为更加出色的标签效果. 我们将考虑去掉单一的方块状背景元素,使用带色彩的圆角标签来完成我们的设计.不过从这个改进中能够体会到css设计的另一个优势,就是可以不需要修改结构代码,只需要修改样式,便可以完成改进,所以这里可以直接看看css代码的设计: <style> body { background-c

  • CSS网页布局入门教程10:带当前标识的标签式横向导航

    当前标识指用户点击该频道或栏目,该栏目的标签呈现出与其他标签不同的颜色用以提示用户所处的位置. 这种设计是网站设计中相当简单而且是相当经典的一种增进网站可用性的方式.网站让用户使用时是应该考虑到用户浏览的思考过程,糟糕的网页设计只顾及页面本身而不去考虑用户感受,优秀的设计应当是以用户为中心出发的,这样一种简单的当前频道的标识往往是许多设计师所忽略的内容,用户需要知道自已的位置,以及知道自已还能去哪里,通过对当前位置的标识,有助于让用户认清自己在网站中的方位,并引导用户访问其它频道. 从上一篇中的

  • 阿里云ECS服务器入门使用流程(新手必看教程)

    一.阿里云根据个人需要选合适的云服务器,选好cpu.内存.带宽,地域,这四个是主要的.其他可以默认选择. 二.登陆控制台 输入账号密码,进去看到服务界面,新手可能不容易看懂.点击左侧菜单,点击云服务器,显示界面如图: 点击实例,在左上角选择区域(一定要选对地域才能看到服务器),这时看到服务器信息了,如图: 大家不要看这里这么多信息,对我们有用的其实只有几个而已,别的都不用看. 更多参阅云服务器配置帮助文档. 三.连接主机 1.通过控制台连接 阿里云服务器要用到两个密码,一个是远程登录密码,一个是

  • FFmpeg视频处理入门教程(新手必看)

    目录 一.概念 1.1 容器 1.2 编码格式 1.3 编码器 二.FFmpeg 的使用格式 三.常用命令行参数 四.常见用法 4.1 查看文件信息 4.2 转换编码格式 4.3 转换容器格式 4.4 调整码率 4.5 改变分辨率(transsizing) 4.6 提取音频 4.7 添加音轨 4.8 截图 4.9 裁剪 4.10 为音频添加封面 五.参考链接 FFmpeg是视频处理最常用的开源软件. 它功能强大,用途广泛,大量用于视频网站和商业软件(比如 Youtube 和 iTunes),也是

  • 详谈Ubuntu PowerShell(小白入门必看教程)

    早在去年八月份PowerShell就开始开源跨平台了,但是一直没有去尝试,叫做PowerShell Core. 这里打算简单介绍一下如何安装和简单使用,为还不知道PowerShell Core on Ubuntu的同学们提供一点小小的入门帮助,谢谢大家支持~ PowerShell Core是由Microsoft开发的运行在.Net Core上的开源跨平台的任务自动化和配置管理系统. 1.在Ubuntu 16.04上安装PowerShell Core a)导入公共存储库GPG秘钥 curl htt

  • JavaScript基础教程——入门必看篇

    JavaScript他是一种描述性语言,其实他并不难学,只要用心学,一定会学好,我相信大家在看这篇文章的时候,一定也学过HTML吧,使用JavaScript就是为了能和网页有更好的交互,下面切入主题. 一. JavaScript 1.什么是JavaScript JavaScript是一种描述性语言,也是一种基于对象(Object)和事件驱动(Event Driven)的,并具有安全性的脚本语言. 2.JavaScript的特点 JavaScript主要用来向HTML页面添加交互行为. JavaS

随机推荐