如何将一定比例的文件正确复制到新目录中?

问题描述

我正在开发一个函数,该函数应该将一定比例的文件从SOURCE目录复制到两个不同的目录中,一个是训练目录,另一个是测试目录。该功能看起来像这样

def copy_file(source,training,testing,split_size):

其中:

-source是我要从中复制的源目录

-培训是要复制到的目录

-testing是要复制到的另一个目录

-split_size是我要复制到测试和培训中的源的百分比,用小数点表示(例如,如果split_size为0.9,我会将源的90%复制到培训中,将10%复制到测试中)

我的代码当前看起来像这样

def split_data(SOURCE,TRAINING,TESTING,SPLIT_SIZE):
    #get the source image names in a list
    source_images = os.listdir(SOURCE)
    splitVal_training = int(round(SPLIT_SIZE*len(source_images))) #get 1350 aka 90% of all the documents
    splitVal_testing = int(round((1 - SPLIT_SIZE)*len(source_images))) #get the remainder of the split_size,aka 10% of all images
    
    
    
    training_list = random.sample(source_images,splitVal_training) #create a new list with 1350 elements of the original list
    print(len(training_list))
    testing_list = [image for image in source_images if not image in training_list]
    print(len(testing_list))
    
    
    
    for image in training_list:
            copyfile(os.path.join(SOURCE,image),os.path.join(TRAINING,image))
        
    for image in testing_list:
            copyfile(os.path.join(SOURCE,os.path.join(TESTING,image))


CAT_SOURCE_DIR = "/tmp/Petimages/Cat/"
TRAINING_CATS_DIR = "/tmp/cats-v-dogs/training/cats/"
TESTING_CATS_DIR = "/tmp/cats-v-dogs/testing/cats/"
DOG_SOURCE_DIR = "/tmp/Petimages/Dog/"
TRAINING_DOGS_DIR = "/tmp/cats-v-dogs/training/dogs/"
TESTING_DOGS_DIR = "/tmp/cats-v-dogs/testing/dogs/"

split_size = .9
split_data(CAT_SOURCE_DIR,TRAINING_CATS_DIR,TESTING_CATS_DIR,split_size)
split_data(DOG_SOURCE_DIR,TRAINING_DOGS_DIR,TESTING_DOGS_DIR,split_size)

运行它并得到训练和测试列表的长度时,我得到的正确结果分别为1350和150。但是,当我在下一个代码单元中检查目录的长度时(我在Google Colab上工作),两个培训目录的总和都是1500,而每个测试目录的总和都是随机数。为什么是这样?我应该获得与打印培训和测试列表长度时得到的数字相同的数字吗?

print(len(os.listdir('/tmp/cats-v-dogs/training/cats/')))
print(len(os.listdir('/tmp/cats-v-dogs/training/dogs/')))
print(len(os.listdir('/tmp/cats-v-dogs/testing/cats/')))
print(len(os.listdir('/tmp/cats-v-dogs/testing/dogs/')))

# Expected output:
# 1350
# 1350
# 150
# 150

#Actual output:
#1500
#1500
#1309
#1203

更新:清除内核并今天再次运行后,我在第一次运行时得到了正确的输出。第二次及以后的运行再次给了我随机数。我第一次尝试运行的任何文件都可以保留在文件夹中并加到预期的输出中吗?

我无法解决的另一个问题是,我应该检查每个文件的大小是否大于0。为此,我尝试编辑for循环以使其看起来像这样

for image in training_list: 
     if os.path.gets_size(image) > 0 :
         copyfile(os.path.join(SOURCE,image))

但是,每次运行它时,我都会收到一条错误消息,指出该文件不存在,这是检查文件大小的错误方法吗?

解决方法

由于您不会保留在运行之间进行训练和测试时随机选择的文件名,因此最终将在训练中得到1500个文件,而在测试中得到1500个文件。

由于您将.9用作split_size,因此测试要花更长的时间。测试数据1203显然是随机大小的,是程序运行了大约8步的结果,并且与您使用的int(round(SPLIT_SIZE)有一些偏差。

您可以通过以下方式解决此问题:在序列化结构中将您的初始训练保持为培训/测试,或者在添加任何内容之前检查/ training_location /和/ test_location /的内容。

通常来说,我会避免使用os软件包来支持pathlib。 Pathlib会为您提供文件列表以及大小