使用Pytorch或Python将包含图像的目录拆分为子文件夹

使用Pytorch或Python将包含图像的目录拆分为子文件夹,python,pytorch,Python,Pytorch,我有一个目录,其中有两个子目录。每个子目录都有一组图像。这些子目录还指定了两类图像 我想有3个目录(训练,验证,测试),在这3个子目录中的每一个子目录,我想每个类的2个子目录分别与图像 我想通过随机抽样将图像的数量分成train、val和test目录。因此,大约60%的图像用于训练,20,val和测试中的20 初始结构: Main_folder - Good - Bad 我想要的是: Main_folder: - Train - Good - Bad - Val -

我有一个目录,其中有两个子目录。每个子目录都有一组图像。这些子目录还指定了两类图像

我想有3个目录(训练,验证,测试),在这3个子目录中的每一个子目录,我想每个类的2个子目录分别与图像

我想通过随机抽样将图像的数量分成train、val和test目录。因此,大约60%的图像用于训练,20,val和测试中的20

初始结构:

Main_folder
 - Good
 - Bad 
我想要的是:

Main_folder: 
 - Train 
  - Good
  - Bad
 - Val
  - Good 
  - Bad
 - Test 
  - Good 
  - Bad

我想通过随机分配图像将每个子目录拆分为其中的两个目录(

我不确定哪些是好的,哪些是坏的,但我非常确定您可以使用scipy train test split函数

您可以在中找到详细信息
我猜它只创建了两个图像集示例,如train test。但是,您可以再次划分测试部分以实现您的目标。此外,我记得您还可以在函数中设置train test百分比。

此问题有两个部分:

  • 给定一个文件列表,找到一个随机生成给定比例子集的算法
  • 根据生成的子集对实际文件进行无序排列
  • 第二个是
    os
    包的一个简单用例,在别处得到了回答。对于第1个,算法是(伪代码):


    在这种情况下,每个子集中的好/坏比率将与原始输入中的好/坏比率相同,这不是一个坏主意。拆分可以通过其他方式完成,但这是一个广泛的讨论,我在这里不进行讨论。然而,您可能需要至少100个图像或更多的图像才能工作-仅将40个图像拆分为6个子集实际上没有多大用处nse,它们太小了。

    您可以使用SKLearn的train\u test\u split+海底采样器,如下所示:

    from torch.utils.data.sampler import SubsetRandomSampler
    from sklearn.model_selection import train_test_split
    from torch.utils.data.sampler import SubsetRandomSampler
    valid_size_and_test = 0.4 # then I will keep 0.1 for testing 
    
    ## split the dataset into train and rest data
    targets = dataset.targets
    
    train_idx, rest_idx = train_test_split(np.arange(len(targets)), test_size= 
                        valid_size_and_test, random_state=42, shuffle=True, stratify=targets)
    test_size = int(len(rest_idx) * valid_size_and_test)
    valid_idx, test_idx = rest_idx[:test_size], rest_idx[test_size:]
    
    dataloaders = {'trainLoader' : torch.utils.data.DataLoader(dataset,batch_size=32,sampler=SubsetRandomSampler(train_idx)),
                   'validLoader' : torch.utils.data.DataLoader(dataset,batch_size=32,sampler=SubsetRandomSampler(valid_idx)),
                   'testLoader' :  torch.utils.data.DataLoader(dataset,batch_size=32,sampler=SubsetRandomSampler(test_idx)),
                  }
    

    有一种
    pytorch
    方法可以做到这一点(我建议使用单个库来完成如此简单的任务)

    创建数据集 在torchvision中有一个预先制作的,即

    只需像这样使用它:

    import torchvision
    
    dataset = torchvision.datasets.ImageFolder("./my_data")
    
    这将创建一个数据集,其中
    Good
    文件夹中的每个图像分别有
    0
    标签和
    Bad
    标签

    分为培训、验证、测试 不需要
    sklearn
    这样一个简单的工作+
    torch
    也有大部分的
    numpy
    功能,我宁愿只使用一个库而不是3个库(尽管
    train\u test\u split
    可以连续使用两次,类似于提议的那样)

    这将是:

    def get_subset(indices, start, end):
        return indices[start : start + end]
    
    
    TRAIN_PCT, VALIDATION_PCT = 0.6, 0.2  # rest will go for test
    train_count = int(len(dataset) * TRAIN_PCT)
    validation_count = int(len(dataset) * TRAIN_PCT)
    
    indices = torch.randperm(len(dataset))
    
    train_indices = get_subset(indices, 0, train_count)
    validation_indices = get_subset(indices, train_count, validation_count)
    test_indices = get_subset(indices, train_count + validation_count, len(dataset))
    
    这将为
    substrandomsampler
    torch.utils.data.DataLoader
    创建索引。 因此,再次类似于:

    dataloaders = {
        "train": torch.utils.data.DataLoader(
            dataset, sampler=SubsetRandomSampler(train_indices)
        ),
        "validation": torch.utils.data.DataLoader(
            dataset, sampler=SubsetRandomSampler(validation_indices)
        ),
        "test": torch.utils.data.DataLoader(
            dataset, sampler=SubsetRandomSampler(test_indices)
        ),
    }
    

    您可以指定
    batch\u size
    DataLoader
    的其他参数,查看是否需要更多信息。

    dataset.targets如何?它是一个torchvision.datasets.ImageFolder加载器:
    dataset=torchvision.datasets.ImageFolder(train\u dir,transform=My\u transforms)
    通过调用datasettargets,您将获得给定图像的目标,即该图像所在的文件夹名称。但是,这不会将拆分保存到文件夹中,对吗?不,为什么会这样?啊,好的。从问题的措辞来看,这就是OP想要的。谢谢
    dataloaders = {
        "train": torch.utils.data.DataLoader(
            dataset, sampler=SubsetRandomSampler(train_indices)
        ),
        "validation": torch.utils.data.DataLoader(
            dataset, sampler=SubsetRandomSampler(validation_indices)
        ),
        "test": torch.utils.data.DataLoader(
            dataset, sampler=SubsetRandomSampler(test_indices)
        ),
    }