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

shutil.copy未复制全部预期文件且无报错,Kaggle数据集拆分异常

问题排查与解决方案

核心问题1:有放回抽样导致文件重复覆盖

你的代码中使用np.random.choice(examples_path, len(examples_path))进行打乱时,默认是有放回抽样(replace=True),这会导致examples_path中出现重复的文件名。当复制这些重复文件时,后续的文件会覆盖之前的同名文件,最终训练文件夹中的实际文件数远少于打印的数量,且每次运行重复情况不同,导致数量波动。

核心问题2:数据集切片索引错误

你在划分验证集时使用了examples_path[n_train_examples:(n_train_examples+n_val_examples+1)],多了一个+1,这会导致验证集实际数量比预期的n_val_examples多1,测试集数量少1,虽然打印的数值看起来匹配,但实际比例不符合你设置的val_split和test_split。


修正步骤

  1. 改用无放回打乱方式:使用np.random.shuffle原地打乱数组(无重复),或显式设置np.random.choice的replace=False参数。
  2. 修正切片索引:移除验证集切片中的+1,确保划分比例准确。
  3. 确保模块导入完整:确认导入了shutil的copy和rmtree方法,避免隐式依赖问题。

修正后的完整代码

import os
import numpy as np
from shutil import copy, rmtree

def shuffle_split_data(source_path, dest_path, train_split, val_split, test_split, clear_existing_destination=True):
    # 清空目标目录(如果需要)
    if clear_existing_destination:
        for item in os.listdir(dest_path):
            item_path = os.path.join(dest_path, item)
            if os.path.isfile(item_path):
                os.remove(item_path)
            elif os.path.isdir(item_path):
                rmtree(item_path)

    for label in os.listdir(source_path):
        # 创建目标子目录
        train_path = os.path.join(dest_path, "training", label)
        val_path = os.path.join(dest_path, "validation", label)
        test_path = os.path.join(dest_path, "test", label)
        
        os.makedirs(train_path, exist_ok=True)
        os.makedirs(val_path, exist_ok=True)
        os.makedirs(test_path, exist_ok=True)
        
        # 获取当前类别的所有文件并打乱(无重复)
        label_source_path = os.path.join(source_path, label)
        examples_path = os.listdir(label_source_path)
        np.random.shuffle(examples_path)  # 原地打乱,无重复文件
        total_examples = len(examples_path)
        
        # 计算各集数量
        n_train_examples = int(train_split * total_examples)
        n_val_examples = int(val_split * total_examples)
        
        # 划分数据集(修正切片索引)
        train_examples = examples_path[:n_train_examples]
        val_examples = examples_path[n_train_examples : n_train_examples + n_val_examples]
        test_examples = examples_path[n_train_examples + n_val_examples : ]
        
        print(len(train_examples), len(val_examples), len(test_examples))
        
        # 复制训练集(原文件名,无重复)
        for file in train_examples:
            source = os.path.join(label_source_path, file)
            dest = os.path.join(train_path, file)
            copy(source, dest)
        
        # 复制验证集
        for file in val_examples:
            source = os.path.join(label_source_path, file)
            dest = os.path.join(val_path, file[:-4] + "_" + label + ".jpg")
            copy(source, dest)
            
        # 复制测试集
        for file in test_examples:
            source = os.path.join(label_source_path, file)
            dest = os.path.join(test_path, file[:-4] + "_" + label + ".jpg")
            copy(source, dest)

# 调用函数(确保train_split+val_split+test_split≈1)
shuffle_split_data(
    '/kaggle/input/monkeypox-skin-lesion-dataset/Original Images/Original Images',
    '/kaggle/working/',
    train_split=0.79,
    val_split=0.10,
    test_split=0.11,
    clear_existing_destination=True
)

验证效果

修正后再次运行函数,打印的训练集数量会和os.listdir统计的数量完全一致,且每次运行数值稳定,不会再出现波动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:35:03