从熊猫数据框在Keras中加载一批图像

时间:2018-08-14 13:52:52

标签: python pandas keras

我有一个熊猫数据框,其中有两列,一列具有图像的路径,另一列具有字符串类标签。

我还编写了以下函数,这些函数从数据帧加载图像,对其进行规范化并将类标签转换为一键矢量。

def prepare_data(df):
    data_X, data_y = df.values[:,0], df.values[:,1]

    # Load images
    data_X = np.array([np.array(imread(fname)) for fname in data_X])

    # Normalize input
    data_X = data_X / 255 - 0.5

    # Prepare labels
    data_y = np.array([label2int[label] for label in data_y])
    data_y = to_categorical(data_y)

    return data_X, data_y

我想将此数据帧提供给Keras CNN,但整个数据集太大,无法立即加载到内存中。

该站点上的其他答案告诉我,为此,我应该使用Keras ImageDataGenerator,但是老实说,我不了解如何从文档中了解该方法。

将延迟加载的批次中的数据馈送到模型的最简单方法是什么?

如果它是ImageDataGenerator,如何创建一个ImageDataGenerator来对Dataframe进行初始化,并将批处理通过我的函数传递,以创建适当的numpy数组?以及如何使用ImageDataGenerator拟合模型?

2 个答案:

答案 0 :(得分:6)

ImageDataGenerator是一个高级类,它允许从多个来源(从np arrays,从目录...)产生数据,并且包括执行图像增强等功能的实用程序功能。

更新

keras-preprocessing 1.0.4开始,ImageDataGenerator带有flow_from_dataframe method,可以解决您的情况。它需要dataframedirectory参数定义如下:

dataframe: Pandas dataframe containing the filenames of the
           images in a column and classes in another or column/s
           that can be fed as raw target data.
directory: string, path to the target directory that contains all
           the images mapped in the dataframe.

因此不再需要自己实施。


下面的原始答案

在您的情况下,使用所描述的数据框,您还可以编写自己的自定义生成器,该生成器将prepare_data函数中的逻辑用作更简单的解决方案。最好使用Keras的Sequence对象,因为它允许使用多处理(如果您使用的是gpu,这将有助于避免瓶颈)。

您可以检出Sequence对象上的docs,其中包含一个实现示例。最终,您的代码将遵循以下原则(这是样板代码,您将必须添加诸如label2int函数或图像预处理逻辑之类的细节):

from keras.utils import Sequence
class DataSequence(Sequence):
    """
    Keras Sequence object to train a model on larger-than-memory data.
    """
    def __init__(self, df, batch_size, mode='train'):
        self.df = df # your pandas dataframe
        self.bsz = batch_size # batch size
        self.mode = mode # shuffle when in train mode

        # Take labels and a list of image locations in memory
        self.labels = self.df['label'].values
        self.im_list = self.df['image_name'].tolist()

    def __len__(self):
        # compute number of batches to yield
        return int(math.ceil(len(self.df) / float(self.bsz)))

    def on_epoch_end(self):
        # Shuffles indexes after each epoch if in training mode
        self.indexes = range(len(self.im_list))
        if self.mode == 'train':
            self.indexes = random.sample(self.indexes, k=len(self.indexes))

    def get_batch_labels(self, idx):
        # Fetch a batch of labels
        return self.labels[idx * self.bsz: (idx + 1) * self.bsz]

    def get_batch_features(self, idx):
        # Fetch a batch of inputs
        return np.array([imread(im) for im in self.im_list[idx * self.bsz: (1 + idx) * self.bsz]])

    def __getitem__(self, idx):
        batch_x = self.get_batch_features(idx)
        batch_y = self.get_batch_labels(idx)
        return batch_x, batch_y

您可以像自定义生成器一样传递此对象来训练模型:

sequence = DataSequence(dataframe, batch_size)
model.fit_generator(sequence, epochs=1, use_multiprocessing=True)

如下所述,不需要实现改组逻辑。在shuffle调用中将True参数设置为fit_generator()就足够了。来自docs

  

shuffle:布尔值。是否在以下位置对订单进行混洗   每个时代的开始。仅与Sequence实例一起使用   (keras.utils.Sequence)。如果steps_per_epoch不是,则不起作用   没有。

答案 1 :(得分:2)

我是Keras的新手,所以请多加些盐。 我认为您应该使用Keras ImageDataGenerator,尤其是flow_from_dataframe选项,因为您说自己有一个Pandas数据框。 Flow_from_dataframe读取数据框的列以获取文件名和标签。

下面是一个示例片段。在线查找教程。

train_datagen = ImageDataGenerator(horizontal_flip=True,
                                   vertical_flip=False,
                                   rescale=1/255.0)

train_generator = train_datagen.flow_from_dataframe(     
    dataframe=trainDataframe,  
    directory=imageDir,
    x_col="file", # name of col in data frame that contains file names
    y_col=y_col_list, # name of col with labels
    has_ext=True, 
    batch_size=batch_size,
    shuffle=True,
    save_to_dir=saveDir,
    target_size=(img_width,img_height),
    color_mode='grayscale',
    class_mode='categorical', # for classification task
    interpolation='bilinear')