首页 > 解决方案 > 有没有办法将图像数据直接从主文件夹加载到训练和验证生成器中,而不是再次创建单独的相同文件夹?

问题描述

我正在研究一个多类分类模型,它有超过 4000 个类,这意味着每个类有 4000 个文件夹,占用大约 30GB 的空间,为了训练分类模型我将图像复制粘贴到每个类的训练和验证文件夹中处于分类文件夹结构中,这将需要另外 30GB 的空间和大量时间来读取数据。我使用来自 keras 的 ImageDataGenerator API 来加载数据并提供给模型进行训练,如下所示

train_generator = train_datagen.flow_from_directory(Training_DIR, batch_size= batch_size, class_mode='categorical',target_size=(img_height,img_width)

validation_generator = validation_datagen.flow_from_directory(VALIDATION_DIR, batch_size= batch_size, class_mode='categorical',target_size=(img_height,img_width)

然后将这些生成器传递给 model.fit_generator 函数,如下所示

model.fit_generator(train,generator,validation_data=validation_generator)

有没有更好的方法直接从包含带有类的子文件夹的主文件夹中高速加载数据,而不是创建新目录并将图像复制到其中,这将占用两倍的磁盘大小。我还没有处理这些占用我所有驱动器空间的大型数据集。

更新:我尝试了@GerryP 给出的解决方案,但我最终得到了如下错误

Epoch 1/50
2021-09-06 17:22:12.576079: I tensorflow/stream_executor/cuda/cuda_dnn.cc:369] 加载 cuDNN 版本 8101
2021-09-06 17:22:13.251294: W tensorflow/core/common_runtime/ bfc_allocator.cc:272] 分配器 (GPU_0_bfc) 内存不足,试图在 freed_by_count=0 的情况下分配 1.19GiB。调用者表示这不是失败,但可能意味着如果有更多内存可用,可能会提高性能。
2021-09-06 17:22:16.096112:E tensorflow/stream_executor/cuda/cuda_driver.cc:1010] 无法同步停止事件:CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并被终止
2021-09-06 17:22:16.096299 :E tensorflow/stream_executor/gpu/gpu_timer.cc:55]内部:销毁CUDA事件时出错:CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并被终止
2021-09-06 17:22:16.097126:E tensorflow/stream_executor/gpu/gpu_timer.cc:60] 内部:销毁 CUDA 事件时出错:CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并被终止
2021-09-06 17:22:16.097682 :我 tensorflow/stream_executor/cuda/cuda_driver.cc:732] 未能从设备分配 8B(8 个字节):CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并于
2021-09-06 17:22:16.097935 终止:E tensorflow/stream_executor/ stream.cc:4508] 内部:无法将异步 memset 操作排入队列:CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并被终止
2021-09-06 17:22:16.098312: W tensorflow/core/kernels/gpu_utils.cc:69] 无法检查 cudnn 卷积的越界读写,并显示错误消息:“无法加载内存CUBIN:CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并被终止'; 跳过此检查。这仅意味着我们不会检查 cudnn 的越界读写。此消息只会打印一次。
2021-09-06 17:22:16.098676:我 tensorflow/stream_executor/cuda/cuda_driver.cc:732] 未能从设备分配 8B(8 个字节):CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并于
2021-09-06 17终止:22:16.099006:E tensorflow/stream_executor/stream.cc:4508]内部:无法将异步memset操作排队:CUDA_ERROR_LAUNCH_TIMEOUT:启动超时并终止
2021-09-06 17:22:16.099369:F tensorflow/stream_executor/cuda/cuda_dnn.cc:216] 检查失败:状态 == CUDNN_STATUS_SUCCESS(7 对 0)未能设置 cuDNN 流。

标签: pythontensorflowmachine-learningkerasdeep-learning

解决方案


您可以将所有图像保留在一个目录 train_data_dir 中。然后您可以使用下面的代码将数据划分为训练集、验证集和测试集。该代码创建了 3 个数据帧,train_df、test_df 和 valid_df。然后它会创建 3 个生成器 train_gen、test_gen 和 valid_gen。然后您可以在 modl.fit 中使用 train_gen 和 valid_gen。在模型、评估或模型预测中使用 test_gen。

def preprocess (sdir, trsplit, vsplit, random_seed):
    filepaths=[]
    labels=[]    
    classlist=os.listdir(sdir)
    for klass in classlist:
        classpath=os.path.join(sdir,klass)
        flist=os.listdir(classpath)
        for f in flist:
            fpath=os.path.join(classpath,f)
            filepaths.append(fpath)
            labels.append(klass)
    Fseries=pd.Series(filepaths, name='filepaths')
    Lseries=pd.Series(labels, name='labels')
    df=pd.concat([Fseries, Lseries], axis=1)       
    # split df into train_df and test_df 
    dsplit=vsplit/(1-trsplit)
    strat=df['labels']    
    train_df, dummy_df=train_test_split(df, train_size=trsplit, shuffle=True, random_state=random_seed, stratify=strat)
    strat=dummy_df['labels']
    valid_df, test_df=train_test_split(dummy_df, train_size=dsplit, shuffle=True, random_state=random_seed, stratify=strat)
    print('train_df length: ', len(train_df), '  test_df length: ',len(test_df), '  valid_df length: ', len(valid_df))
    print(list(train_df['labels'].value_counts())) # shows number of samples in each class to evaluate balance
    return train_df, test_df, valid_df
sdir=train_data_dir
train_df, test_df, valid_df= preprocess(sdir, .8,.1, 123)
# now create the 3 generators
batch_size=32 # set desired batch size
img_size=(img_height, img_width)
# determine test_batch_size and test_steps so test_batch_size X test_steps= no of test samples
#this insures you evaluate all test samples exactly one time
length=len(test_df)
test_batch_size=sorted([int(length/n) for n in range(1,length+1) if length % n ==0 and length/n<=80],reverse=True)[0]  
test_steps=int(length/test_batch_size)
trgen = ImageDataGenerator(rescale=1./255, shear_range=0.2, 
                            zoom_range=0.2,horizontal_flip=True)
tvgen=ImageDataGenerator(rescale=1./255)
train_gen=trgen.flow_from_dataframe( train_df, x_col='filepaths', y_col='labels', target_size=img_size, class_mode='categorical',
                                    color_mode='rgb', shuffle=True, 
                                    batch_size=batch_size)
test_gen=tvgen.flow_from_dataframe( test_df, x_col='filepaths', y_col='labels', target_size=img_size, class_mode='categorical',
                                    color_mode='rgb', shuffle=False, 
                                     batch_size=test_batch_size)

valid_gen=tvgen.flow_from_dataframe( valid_df, x_col='filepaths', y_col='labels', target_size=img_size, class_mode='categorical',
                                    color_mode='rgb', shuffle=True, 
                                    batch_size=batch_size)
classes=list(train_gen.class_indices.keys())
class_count=len(classes)
# then train your model
history=model.fit(x=train_gen,  epochs=epochs, verbose=1,  
                validation_data=valid_gen,
                validation_steps=None,  shuffle=True,  initial_epoch=0)

推荐阅读