[英]Load data from snowflake to pandas dataframe (python) in batches
[英]Loading batches of images in Keras from pandas dataframe
我有一个包含两列的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
我想将此数据帧提供给Keras CNN,但整个数据集太大而无法立即加载到内存中。
本网站的其他答案告诉我,为此我应该使用Keras ImageDataGenerator,但说实话,我不明白如何从文档中做到这一点。
将延迟加载批次中的数据提供给模型的最简单方法是什么?
如果它是ImageDataGenerator,我如何创建一个ImageDataGenerator,它接受Dataframe的初始化并通过我的函数传递批次以创建适当的numpy数组? 我如何使用ImageDataGenerator拟合模型?
ImageDataGenerator
是一个高级类,允许从多个源(来自np arrays
,来自目录......)生成数据,并且包括用于执行图像增强等的实用程序函数。
UPDATE
从keras-preprocessing 1.0.4开始, ImageDataGenerator
附带了一个flow_from_dataframe
方法 ,可以解决您的问题。 它需要定义如下的dataframe
和directory
参数:
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
对象上的文档 ,它包含一个实现示例。 最终,你的代码将是这些代码(这是样板代码,你必须添加像label2int
函数或图像预处理逻辑的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)
如下所述,不需要实现混洗逻辑。 在fit_generator()
调用中将shuffle
参数设置为True
就足够了。 来自文档 :
shuffle:布尔值。 是否在每个时代开始时改组批次的顺序。 仅用于Sequence的实例(keras.utils.Sequence)。 当steps_per_epoch不是None时无效。
我是Keras的新手,所以请耐心等待我的建议。 我认为你应该使用flow_from_dataframe
ImageDataGenerator,特别是flow_from_dataframe
选项,因为你说你有一个Pandas数据帧。 Flow_from_dataframe
读取数据帧的cols以获取文件名和标签。
下面是一个例子的片段。 在线查看教程。
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')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.