如何将 'collate_fn' 与数据加载器一起使用?

How to use 'collate_fn' with dataloaders?

我正在尝试使用 3 输入、3 input_masks 和标签作为张量来训练预训练的 roberta 模型我的训练数据集。

我使用以下代码执行此操作:

from torch.utils.data import TensorDataset, DataLoader, RandomSampler, SequentialSampler
batch_size = 32
# Create the DataLoader for our training set.
train_data = TensorDataset(train_AT, train_BT, train_CT, train_maskAT, train_maskBT, train_maskCT, labels_trainT)
train_dataloader = DataLoader(train_data, batch_size=batch_size)

# Create the Dataloader for our validation set.
validation_data = TensorDataset(val_AT, val_BT, val_CT, val_maskAT, val_maskBT, val_maskCT, labels_valT)
val_dataloader = DataLoader(validation_data, batch_size=batch_size)

# Pytorch Training
training_args = TrainingArguments(
    output_dir='C:/Users/samvd/Documents/Master/AppliedMachineLearning/FinalProject/results',          # output directory
    num_train_epochs=1,              # total # of training epochs
    per_device_train_batch_size=32,  # batch size per device during training
    per_device_eval_batch_size=32,   # batch size for evaluation
    warmup_steps=500,                # number of warmup steps for learning rate scheduler
    weight_decay=0.01,               # strength of weight decay
    logging_dir='C:/Users/samvd/Documents/Master/AppliedMachineLearning/FinalProject/logs',            # directory for storing logs
)

trainer = Trainer(
    model=model,                          # the instantiated  Transformers model to be trained
    args=training_args,                   # training arguments, defined above
    train_dataset = train_data,           # training dataset
    eval_dataset = validation_data,       # evaluation dataset
)

trainer.train()

但是这给了我以下错误:

TypeError: vars() argument must have dict attribute

现在我发现这可能是因为我在使用 DataLoader 时没有使用 collate_fn,但是我真的找不到可以帮助我正确定义它的来源,所以培训师了解我输入的不同张量。

谁能指出我正确的方向?

基本上,如果您的 __getitem__ 函数来自 Dataset 子类 returns 一个元组,collate_fn 会收到一个元组列表,或者如果您的 Dataset 子类 [=32] 只是一个普通列表=] 只有一个元素。它的主要 objective 是创建您的批次,而无需花费太多时间手动实施它。尝试将其视为您指定示例在批次中粘合在一起的方式的粘合剂。如果你不使用它,PyTorch 只会像使用 torch.stack 一样将 batch_size 个示例放在一起(不完全是,但它很简单)。

例如,假设您要创建不同维度张量列表的批次。下面的代码用 0 填充序列,直到批处理的最大序列大小,这就是我们需要 collate_fn 的原因,因为标准批处理算法(仅使用 torch.stack)在这种情况下不起作用,在创建批处理之前,我们需要手动将可变长度的不同序列填充到相同的大小。

def collate_fn(data):
    """
       data: is a list of tuples with (example, label, length)
             where 'example' is a tensor of arbitrary shape
             and label/length are scalars
    """
    _, labels, lengths = zip(*data)
    max_len = max(lengths)
    n_ftrs = data[0][0].size(1)
    features = torch.zeros((len(data), max_len, n_ftrs))
    labels = torch.tensor(labels)
    lengths = torch.tensor(lengths)

    for i in range(len(data)):
        j, k = data[i][0].size(0), data[i][0].size(1)
        features[i] = torch.cat([data[i][0], torch.zeros((max_len - j, k))])

    return features.float(), labels.long(), lengths.long()

上面的函数被馈送到 DataLoader 中的 collate_fn 参数,例如:

DataLoader(toy_dataset, collate_fn=collate_fn, batch_size=5)

使用此 collate_fn 函数,您将始终拥有一个张量,其中所有示例都具有相同的大小。因此,当您将此数据提供给 forward() 函数时,您需要使用长度来取回原始数据,而不是在计算中使用那些无意义的零。

来源:Pytorch Forum