You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PyTorch中无独立训练/测试目录时,基于ImageFolder划分训练、验证、测试集的方法是否可行?

问题解答与代码优化

首先回应你的核心疑问:只要划分过程保证了训练/验证/测试集的完全独立,且三个集合的类别分布与原数据集一致,这样的划分是符合标准验证/测试集定义的。不过你的代码目前存在两个关键问题,会影响划分的合理性,下面详细说明:

一、核心疑问的解答

标准的验证集(开发集)作用是:在训练过程中评估模型性能、调整超参数(比如学习率、batch size等);测试集则是完全独立于训练流程的,仅在模型最终训练完成后用来评估泛化能力,全程不能参与任何调参或训练环节。

你的划分思路(先拆分训练/验证,再将验证拆分为验证/测试)本身是可行的,但需要满足两个核心前提:

  • 三个数据集完全无重叠:不能出现同一个样本同时出现在两个集合里的情况
  • 分层划分:保证每个类别的样本在三个集合中的占比和原数据集一致,避免某类别在测试集中缺失或占比失衡的情况

二、你的代码存在的问题

1. 验证集与测试集数据重叠

看你代码中的这部分:

# Creating a valid and test set
valid_idx = valid_idx[int(np.floor(0.2*len(valid_idx))) : len(valid_idx)]
test_idx = valid_idx[0:int(np.floor (0.2 * len(valid_idx) ) )]

这段代码的逻辑是:先把原valid_idx的后80%重新赋值给valid_idx,然后从**新的valid_idx**中取前20%作为test_idx——这会导致test_idx的样本完全包含在新的valid_idx里,两个集合出现严重重叠!这是绝对不能出现的,因为验证集和测试集必须完全独立。

2. 未做分层随机划分

你当前只是对所有样本的索引做了随机打乱,然后直接按比例拆分,没有考虑样本的类别标签。如果原数据集的类别分布不均匀(比如某个类别的样本数量特别少),这种随机拆分可能导致某个类别在测试集中没有样本,或者占比和原数据集差异极大,最终影响模型评估的准确性。

三、优化后的代码方案

推荐使用sklearntrain_test_split来做分层划分,它可以基于类别标签保证每个集合的类别分布和原数据集一致。以下是修正后的代码:

import numpy as np
from torchvision import datasets
from torch.utils.data import SubsetRandomSampler, DataLoader
from sklearn.model_selection import train_test_split

# 加载数据集
data = datasets.ImageFolder('PATH', transform=transform)
targets = data.targets  # 获取每个样本的类别标签

# 第一步:先拆分训练集和临时集(后续拆分为验证+测试)
train_idx, temp_idx = train_test_split(
    np.arange(len(data)),
    test_size=valid_size,  # 这里的valid_size是你原来定义的验证+测试集的总比例
    stratify=targets,  # 按类别分层划分
    random_state=42  # 设置随机种子保证结果可复现
)

# 第二步:把临时集拆分为验证集和测试集
valid_idx, test_idx = train_test_split(
    temp_idx,
    test_size=0.2,  # 从临时集中取20%作为测试集,剩下80%作为验证集
    stratify=[targets[i] for i in temp_idx],  # 同样按类别分层
    random_state=42
)

# 定义采样器
train_sampler = SubsetRandomSampler(train_idx)
valid_sampler = SubsetRandomSampler(valid_idx)
test_sampler = SubsetRandomSampler(test_idx)

# 构建DataLoader
train_loader = DataLoader(data, batch_size=batch_size, sampler=train_sampler, num_workers=num_workers)
valid_loader = DataLoader(data, batch_size=batch_size, sampler=valid_sampler, num_workers=num_workers)
test_loader = DataLoader(data, batch_size=batch_size, sampler=test_sampler, num_workers=num_workers)

补充说明

  • 设置random_state可以让你的划分结果固定,方便后续复现实验结果
  • 分层划分的核心是保证三个数据集的类别分布一致,这对于小数据集或者类别不平衡的数据集尤为重要
  • 测试集一定要严格独立,训练过程中绝对不能使用测试集的任何数据(包括查看测试集的性能),否则会导致最终的模型泛化能力评估不准确

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

火山引擎 最新活动