You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理索引返回不同尺寸编码的Dataset以生成固定批量DataLoader?

解决方案:处理变长子张量数据集,生成固定批量大小

你的核心需求是:将数据集中每个样本包含的多个等维度子张量(来自HuggingFace处理器的编码结果)拆分为独立样本,让DataLoader能输出固定batch size的小批量,而非将整个变长样本作为batch元素。以下是几种高效实现方式:

方案一:扁平化数据集(推荐)

直接将所有子张量展开为独立样本,让Dataset的__getitem__返回单个子张量。这种方式适配DataLoader的原生功能(shuffle、多进程加载等),适合懒加载大文件的场景。

自定义Dataset实现

import torch
from torch.utils.data import Dataset, DataLoader

class FlattenedDataset(Dataset):
    def __init__(self):
        # 模拟原数据:实际场景可替换为文件路径列表,无需提前加载全部数据
        self.raw_samples = [
            [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
            [[0, 1, 2], [3, 4, 5]], 
            [[0, 1, 2]]
        ]
        # 构建扁平化索引映射:记录每个子张量对应的原样本索引和子元素位置
        self.flat_indices = []
        for sample_idx, sub_tensors in enumerate(self.raw_samples):
            for sub_idx in range(len(sub_tensors)):
                self.flat_indices.append((sample_idx, sub_idx))

    def __len__(self):
        return len(self.flat_indices)

    def __getitem__(self, idx):
        sample_idx, sub_idx = self.flat_indices[idx]
        # 实际场景:这里可懒加载对应文件,生成编码后提取指定子张量,再应用随机增强
        return torch.tensor(self.raw_samples[sample_idx][sub_idx])

# 测试batch_size=1
print("=== Batch size=1 输出 ===")
dataloader = DataLoader(FlattenedDataset(), batch_size=1)
for batch in dataloader:
    print(batch)

# 测试batch_size=2
print("\n=== Batch size=2 输出 ===")
dataloader = DataLoader(FlattenedDataset(), batch_size=2)
for batch in dataloader:
    print(batch)

Hugging Face Dataset 快速实现

如果使用Hugging Face的datasets.Dataset,可直接用flat_map方法扁平化:

from datasets import Dataset
from torch.utils.data import DataLoader

# 构造原数据集
raw_data = {
    "encodings": [
        [[0,1,2],[3,4,5],[6,7,8]],
        [[0,1,2],[3,4,5]],
        [[0,1,2]]
    ]
}
dataset = Dataset.from_dict(raw_data)

# 扁平化:每个子张量转为独立样本
flattened_dataset = dataset.flat_map(lambda x: {"encoding": x["encodings"]})
# 设置为PyTorch格式
flattened_dataset.set_format("torch", columns=["encoding"])

# 生成DataLoader
dataloader = DataLoader(flattened_dataset, batch_size=2)
print("=== Hugging Face 扁平化后输出 ===")
for batch in dataloader:
    print(batch["encoding"])

方案二:自定义Collate函数(保留原样本关联)

如果需要对原样本的所有子张量应用相同随机增强(比如同一样本的子张量共享增强参数),可保留原样本结构,通过自定义collate_fn在批量阶段拆分重组:

import torch
from torch.utils.data import Dataset, DataLoader

class SampleDataset(Dataset):
    def __init__(self):
        self.raw_samples = [
            [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
            [[0, 1, 2], [3, 4, 5]], 
            [[0, 1, 2]]
        ]

    def __len__(self):
        return len(self.raw_samples)

    def __getitem__(self, idx):
        # 返回原样本的所有子张量,可在此处对整个样本应用随机增强
        return [torch.tensor(sub) for sub in self.raw_samples[idx]]

def custom_collate(batch):
    # 拆分所有子张量
    all_sub_tensors = []
    for sample_subs in batch:
        all_sub_tensors.extend(sample_subs)
    # 按目标batch size重组
    target_batch_size = 2
    return [torch.stack(all_sub_tensors[i:i+target_batch_size]) 
            for i in range(0, len(all_sub_tensors), target_batch_size)]

# 注意:此处DataLoader的batch_size是原样本的批量,子张量的批量由target_batch_size控制
dataloader = DataLoader(SampleDataset(), batch_size=2, collate_fn=custom_collate)
print("=== 自定义Collate输出 ===")
for batch_group in dataloader:
    for batch in batch_group:
        print(batch)

内容的提问来源于stack exchange,提问作者Devi Prasad Khatua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:23:11