从熊猫数据框加载Keras中的批量图像

Jse*_*mol 3 python pandas keras

我有一个包含两列的pandas数据帧,一列有图像路径,另一列有字符串类标签.

我还编写了以下函数,这些函数从数据框加载图像,重新规范化它们并将类标签转换为单热矢量.

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
Run Code Online (Sandbox Code Playgroud)

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

本网站的其他答案告诉我,为此我应该使用Keras ImageDataGenerator,但说实话,我不明白如何从文档中做到这一点.

将延迟加载批次中的数据提供给模型的最简单方法是什么?

如果它是一个ImageDataGenerator,我如何创建一个ImageDataGenerator,它接受初始化Dataframe并通过我的函数传递批次来创建适当的numpy数组?我如何使用ImageDataGenerator拟合模型?

sdc*_*cbr 8

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

UPDATE

keras-preprocessing 1.0.4开始,ImageDataGenerator附带一个解决您的案例的flow_from_dataframe方法.它要求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.
Run Code Online (Sandbox Code Playgroud)

所以不再需要自己实现它.


原答案如下

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

您可以查看对象上的文档Sequence,它包含一个实现示例.最终,您的代码将是这些行(这是样板代码,您将不得不添加像您的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
Run Code Online (Sandbox Code Playgroud)

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

sequence = DataSequence(dataframe, batch_size)
model.fit_generator(sequence, epochs=1, use_multiprocessing=True)
Run Code Online (Sandbox Code Playgroud)

如下所述,不需要实现混洗逻辑.在shuffle参数True中设置参数就足够了fit_generator().来自文档:

shuffle:布尔值.是否在每个时代开始时改组批次的顺序.仅用于Sequence的实例(keras.utils.Sequence).当steps_per_epoch不是None时无效.