python - 确保批次中的所有样本在 pytorch 数据加载器中具有相同的形状
问题描述
我的任务是使用 pyTorch 和 BERT 对自定义数据集进行多标签分类。我的数据包含大约 1500 个样本。字数可以在 1000 到 50k 字之间变化。因为 BERT 只能处理 512 的最大序列,所以我对我的数据使用滑动窗口方法。请注意,一个数据样本可以有多个句子。
作为参考,我正在使用此处和来自huggingface的示例笔记本。
这是我的脚本的最小版本:
import transformers
from torch.utils.data import Dataset, DataLoader, RandomSampler, SequentialSampler
from transformers import BertTokenizer, BertModel, BertConfig
import pandas as pd
import torch
from torch import cuda
import math
import transformers
from transformers import BertTokenizer, BertModel, BertConfig, AutoTokenizer
from torch.utils.data import Dataset, DataLoader, RandomSampler, SequentialSampler
device = 'cuda' if cuda.is_available() else 'cpu'
MAX_LEN = 400
STRIDE = 20
TRAIN_BATCH_SIZE = 8
VALID_BATCH_SIZE = 4
EPOCHS = 1
LEARNING_RATE = 1e-05
model_checkpoint = "bert-base-german-cased"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint, local_files_only=True)
assert isinstance(tokenizer, transformers.PreTrainedTokenizerFast)
class CustomDataset(Dataset):
def __init__(self, dataframe, tokenizer, max_len, stride):
self.tokenizer = tokenizer
self.data = dataframe
self.text = dataframe.text
self.targets = self.data.labels
self.max_len = max_len
self.stride = stride
def __len__(self):
return len(self.text)
def __getitem__(self, index):
text = str(self.text[index])
text = " ".join(text.split())
inputs = self.tokenizer(
text,
None,
max_length=MAX_LEN,
stride=STRIDE,
padding='max_length',
truncation='only_first',
return_overflowing_tokens=True,
)
ids = inputs['input_ids']
mask = inputs['attention_mask']
token_type_ids = inputs["token_type_ids"]
return {
'ids': torch.tensor(ids, dtype=torch.long),
'mask': torch.tensor(mask, dtype=torch.long),
'token_type_ids': torch.tensor(token_type_ids, dtype=torch.long),
'targets': torch.tensor(self.targets[index], dtype=torch.float)
}
我认为滑动窗口正在工作,因为如果我运行,[len(x) for x in inputs["input_ids"]]
我会得到我的段落/文本的 input_ids 列表。
# Creating the dataset and dataloader for the neural network
train_size = 0.8
train_dataset=training_frame.sample(frac=train_size,random_state=200)
test_dataset=training_frame.drop(train_dataset.index).reset_index(drop=True)
train_dataset = train_dataset.reset_index(drop=True)
print("FULL Dataset: {}".format(training_frame.shape))
print("TRAIN Dataset: {}".format(train_dataset.shape))
print("TEST Dataset: {}".format(test_dataset.shape))
training_set = CustomDataset(train_dataset, tokenizer, MAX_LEN, STRIDE)
testing_set = CustomDataset(test_dataset, tokenizer, MAX_LEN, STRIDE)
train_params = {'batch_size': TRAIN_BATCH_SIZE,
'shuffle': False,
'num_workers': 0
}
test_params = {'batch_size': VALID_BATCH_SIZE,
'shuffle': True,
'num_workers': 0
}
training_loader = DataLoader(training_set, **train_params)
testing_loader = DataLoader(testing_set, **test_params)
training_set
直到这里脚本运行没有任何错误,但如果我尝试像这里一样迭代:
train_iter = iter(training_loader)
print(type(train_iter))
text, labels = train_iter.next()
print(text.size())
print(labels.size())
我收到以下错误:
RuntimeError: invalid argument 0: Sizes of tensors must match except in dimension 0. Got 133 and 75 in dimension 1 at /opt/conda/conda-bld/pytorch_1556653215914/work/aten/src/TH/generic/THTensor.cpp:711
Process finished with exit code 1
在这个问题中,André 提到加载的批次具有不同的形状,这就是发生此错误的原因。他建议设置batch_size = 1
. 但是我想使用batch_size
我的脚本中定义的定义。
我认为滑动窗口会导致错误,因为input_ids
我的 batchsamples 中每个样本的列表可能会有所不同,因为文本的总长度可能不同。如何确保输入到网络的数据始终具有相同的形状?
解决方案
推荐阅读
- corda - Corda - 无法处理包含大量状态的事务
- c - C中的快速图像平滑
- reactjs - 如何就地使用 ANT Design Menu.Item 和 Upload 组件?
- c# - 如何使用 LINQ C# 中的另一个列表过滤列表
- flutter - 你将如何实现一个 BLoC 来发出所有 CRUD 调用的状态?
- javascript - 将 react.js 连接到 Google Collab
- django - Django消息未显示在重定向上,仅呈现
- javascript - 将代码片段转换为 Sphinx 中的 HTML 代码?
- javascript - Vue jest 测试当前目标父级点击时有类(通过v-for添加)
- file-upload - JMETER:多部分/表单数据请求 - 无法使用 jmeter 上传任何文件类型