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

PyTorch DataLoader索引越界:分层拆分与加权采样报错求助

问题原因

你创建的WeightedRandomSampler是基于整个原始数据集的样本权重和索引范围,但train_dataset是原数据集的子集(长度4544),当sampler生成原数据集的大索引(比如6057)时,子集无法访问该位置,直接触发索引越界错误。

修正方案

需要为训练子集单独计算样本权重和采样器,同时测试集不需要加权采样(测试时应保持数据分布的真实性,无需重采样)。

步骤1:提取训练子集的标签

分层拆分后,从原数据集的标签中提取训练子集对应的标签:

train_targets = [dataset.targets[i] for i in train_idx]

步骤2:基于训练子集标签计算权重

用训练子集的标签计算类别权重和样本权重,而不是整个数据集的标签:

# 计算训练子集的类别权重
train_targets_array = np.array(train_targets)
class_weights = compute_class_weight('balanced', classes=np.unique(train_targets_array), y=train_targets_array)
class_weights = torch.tensor(class_weights, dtype=torch.float32, device=device)

# 生成训练子集的样本权重
sample_weights = np.zeros(len(train_targets))
for idx, label in enumerate(train_targets_array):
    sample_weights[idx] = class_weights[label]

sample_weights = torch.from_numpy(sample_weights).to(device)

步骤3:创建针对训练子集的采样器

采样器的num_samples设置为训练子集的长度:

sampler = WeightedRandomSampler(weights=sample_weights, num_samples=len(train_targets), replacement=True)

步骤4:修正DataLoader的创建

测试集不需要用加权采样器,使用默认的采样器即可:

train_loader = DataLoader(train_dataset, batch_size=32, sampler=sampler)
test_loader = DataLoader(test_dataset, batch_size=32)  # 移除sampler参数
完整修正代码
dataset = ImageFolder(root='/path/to/directory', transform=transform)

# 分层拆分
ss = StratifiedShuffleSplit(n_splits=1, test_size=0.5, train_size=0.5)
for train_idx, test_idx in ss.split(np.zeros(len(dataset.targets)), dataset.targets):
    train_dataset = Subset(dataset, train_idx)
    test_dataset = Subset(dataset, test_idx)

# 提取训练子集的标签
train_targets = [dataset.targets[i] for i in train_idx]

# 计算训练子集的权重与采样器
train_targets_array = np.array(train_targets)
class_weights = compute_class_weight('balanced', classes=np.unique(train_targets_array), y=train_targets_array)
class_weights = torch.tensor(class_weights, dtype=torch.float32, device=device)

sample_weights = np.zeros(len(train_targets))
for idx, label in enumerate(train_targets_array):
    sample_weights[idx] = class_weights[label]

sample_weights = torch.from_numpy(sample_weights).to(device)
sampler = WeightedRandomSampler(weights=sample_weights, num_samples=len(train_targets), replacement=True)

# 创建DataLoader
train_loader = DataLoader(train_dataset, batch_size=32, sampler=sampler)
test_loader = DataLoader(test_dataset, batch_size=32)
额外说明
  • 加权采样只用于训练阶段,目的是平衡类别分布;测试阶段必须保持原始数据分布,不能用加权采样,否则会影响模型评估的准确性。
  • 如果你需要对测试集做分层评估,可以在计算指标时使用类别权重,但不要修改测试集的采样方式。

内容的提问来源于stack exchange,提问作者thehumbling

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:06:10