其他分享
首页 > 其他分享> > Pytorch:使用torchtext构建自己的数据集

Pytorch:使用torchtext构建自己的数据集

作者:互联网

torchtext的主要API

torchtext包含以下组件:

1. 定义Field

规定如何处理数据

  1. 主要的参数:
    • sequential: 是否把数据表示成序列,如果是False, 不能使用分词 默认值: True
    • use_vocab: 是否使用词典对象. 如果是False 数据的类型必须已经是数值类型. 默认值: True
    • init_token: 每一条数据的起始字符 默认值: None
    • eos_token: 每条数据的结尾字符 默认值: None
    • fix_length: 修改每条数据的长度为该值,不够的用pad_token补全. 默认值: None
    • tensor_type: 把数据转换成的tensor类型 默认值: torch.LongTensor
    • lower: 是否把数据转化为小写 默认值: False.
    • tokenize: 分词函数. 默认值: str.split.
    • pad_token: 用于补全的字符. 默认值: ""
    • unk_token: 不存在词典里的字符. 默认值: ""
  2. 主要的方法
    • build_vocab(): 建立词典
    • numericalize(): 把文本数据数值化,返回tensor
  3. 简单的例子
TEXT = data.Field(sequential=True, tokenize=tokenizer, fix_length=100)
LABEL = data.Field(sequential=False, use_vocab=False)

tokenizer是自定义的分词方法,也可以加载已有的分词方法,在此使用spcay。在此假设spcay已经安装完成。
三种nlp分词模型spacy en_core_web_sm/md/lg代表(small,medium,large)。
spacy en_core_web_lg(780M),spacy en_core_web_sm(10M),md介于两者之间,开发中一般使用sm即可。
使用spcay定义的tokenizer如下:

import spacy
spacy_en = spacy.load('en_core_web_sm')
def tokenizer(text):
    return [tok.text for tok in spacy_en.tokenizer(text)]

2. 读取数据集Dataset

torchtext作为一个第三方库,其Dataset也是继承自pytorch提供的Dataset。
TabularDataset 可以很方便地读取数据集,支持CSV、TSV、JSON。splits方法可以同时读取训练集、验证集、测试集。

3. 生成迭代器Iterator

在torchvision和PyTorch中,数据的处理和批处理由DataLoader处理。 torchtext相同的东西命名成了Iterator。基本功能是一样的,但Iterators具有一些NLP特有的便捷功能。

创建迭代器的例子

BucketIterator是torchtext最强大的功能之一。BucketIterator和Iterator的区别是,BucketIterator尽可能的把长度相似的句子放在一个batch里面。
而且BucketIterator会自动将输入序列进行shuffle并做bucket,不过,需要告诉BucketIterator想在哪个数据属性上做bucket。
在本文中希望根据comment_text字段的长度进行bucket处理,因此我们将其作为关键字参数传入sort_key = lambda x: len(x.content)

  1. 验证集和训练集合使用BucketIterator.splits(),目的是自动进行shuffle和padding,并且为了训练效率期间,尽量把句子长度相似的shuffle在一起。
  2. 测试集用Iterator,因为不用sort。
from torchtext.data import Iterator, BucketIterator

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
train_batch_size = 64
val_batch_size = 64
test_batch_size = 64

# 同时对训练集和验证集进行迭代器构建
train_iter, val_iter = BucketIterator.splits(
	(train_data, valid_data),
	batch_sizes=(train_batch_size, val_batch_size),
	device=device,
	sort_key=lambda x: len(x.content),
	sort_within_batch=False,
	repeat=False
)

# 对测试集进行迭代器构建
test_iter = Iterator(
	test_data,
	batch_size=test_batch_size,
	device=device, 
	sort=False,
	sort_within_batch=False,
	repeat=False
)

"""
因为sort和shuffle默认只对train=True字段进行的,train字段默认是True。所以测试集合可以令train=False的方式构建
"""
# 测试集也可以这么构建
test_iter = Iterator(
	test_data,
	batch_size=test_batch_size,
	device=device,
	train=False
)

4. 搭建TextCNN

经过上述这三步,数据集就加载好了,下面搭建一个TextCNN测试。

import torch
import torch.nn as nn
import torch.nn.functional as F


class TextCNN(nn.Module):
	def __init__(self, emb_dim, kernel_sizes, kernel_num):
		super(TextCNN, self).__init__()

		self.embedding = nn.Embedding(len(TEXT.vocab), emb_dim)
		self.embedding_dropout = nn.Dropout(0.5)
		# 使用nn.ModuleList来装三个nn.Sequential构成的卷积块
		self.convs = nn.ModuleList([
		# 使用nn.Sequential构成卷积块,每个卷积块装有一层卷积和LeakyReLU激活函数
			nn.Sequential(
				nn.Conv1d(in_channels=emb_dim,
							  out_channels=kernel_num,
							  kernel_size=size),
				nn.LeakyReLU(),
			)
			for size in kernel_sizes
		])
		in_features = kernel_num * len(kernel_sizes)
		print(in_features)
		self.linear1 = nn.Linear(in_features=in_features, out_features=in_features//2)
		self.fc_dropout = nn.Dropout(0.5)
		self.linear2 = nn.Linear(in_features=in_features//2, out_features=20)

	def forward(self,x):
		# 初始输入格式为(length, batch_size)
		out = self.embedding(x)
		out = self.embedding_dropout(out)
		# (length, batch_size, emb) -> (batch_size, emb, length)
		out = torch.transpose(out, 1, 2)
		out = torch.transpose(out, 0, 2)
		out = [conv(out) for conv in self.convs]
		# stride为步幅
		out = [F.max_pool1d(one, kernel_size=one.size(2), stride=2) for one in out]
		# 拼接维度dim=1,并去掉维度dim=2
		out = torch.cat(out, dim=1).squeeze(2)
		out = self.linear1(F.leaky_relu(out))
		out = self.fc_dropout(out)
		out = self.linear2(F.leaky_relu(out))
		return out

# 4种卷积核,每种60个,拼接后就有240种特征
model = TextCNN(50, [3, 4, 5, 6], 60).to(device)

5. 开始训练

总结

到这,一个简单的TextCNN就算是完成了。
在训练和测试中,统计混淆矩阵本来是为了计算召回率、F1、精确率等的,埋了个坑。
不过因为我有点懒,就一直没填,等什么时候有心情了再做吧。

标签:loss,torchtext,batch,Pytorch,train,构建,label,size,out
来源: https://www.cnblogs.com/tangzz/p/14598268.html