将Pandas列转换为Keras神经网络的Numpy数组

Jam*_*mes 4 python numpy neural-network pandas keras

我正在学习如何创建CNN模型,并认为Kaggle举办了一场有趣的比赛来帮助我学习它.

他们提供了一个类似JSON的大型(BSON)文件,大约50GB,我正在尝试处理它.我正在尝试使用Keras模块训练卷积神经网络.在文件中,我迭代地读取具有(180,180,3)的阵列结构的图像数据.整个文件包含大约7,000,000个图像,因此最终的数组结构看起来像(7000000,180,180,3).但是,我无法将所有这些数据读入内存,所以我的目标是一次读取100,000个图像以适应神经网络,保存模型的权重,删除数组以释放内存,然后继续阅读接下来将100,000个图像放入新阵列中以重新拟合先前训练的模型.我会迭代地这样做,直到我到达最后一张图片.

我最初尝试使用'np.append()'来迭代地将每个图像阵列附加在一起,但是,这花了很多时间,因为我只通过25,000个图像,导致阵列结构(25000,180,180, 3),在10个小时内,由于尺寸的原因,它在接近结束时非常慢.

然后,我尝试使用pandas数据帧结构使用不同的方法.我将每个(1,180,180,3)阵列附加到每个单元格中.我能够使用这种方法在大约20分钟内迭代100,000张图像(大部分代码都是通过Kaggle提供的 - https://www.kaggle.com/inversion/processing-bson-files)但我在下面进行了修改:

# Simple data processing
from bson.json_util import dumps
data = bson.decode_file_iter(open('train.bson', 'rb'))

prod_to_category = dict()

i = 0
j = 1000

# Loop through dataset
for c, d in enumerate(data):
    product_id = d['_id']
    category_id = d['category_id'] # This won't be in Test data
    prod_to_category[product_id] = category_id
    i+=1

    # Create a counter to check how many records have been iterated through
    if (i == 1):
        print (i, "records loaded")
        print(picture_1.shape)
        j+=1000
    for e, pic in enumerate(d['imgs']):

    # Reshape the array and append image array data
        if (i == 0):
            picture_1 = np.reshape(imread(io.BytesIO(pic['picture'])), (1,180,180,3))
            get = pd.DataFrame({'A': [product_id], 'B': [category_id], 'C':[picture_1]})
            frames = get

            break
        else:
            picture_2 = np.reshape(imread(io.BytesIO(pic['picture'])), (1,180,180,3))
            get2 = pd.DataFrame({'A': [product_id], 'B': [category_id], 'C':[picture_2]})
            frames = frames.append(get2)

            break
Run Code Online (Sandbox Code Playgroud)

所以pandas数据框的标题'frames'看起来像这样.注意,在这个例子中假装我完全停止了100,000个记录的循环:

在此输入图像描述

我怎样才能将整个列'C'转换成每个单元看起来都有一个数组结构(1,180,180,3),进入Numpy结构数组(100000,180,180,3)然后呢我可以将它喂入我的神经网络吗?最好不要使用for循环来执行此操作.

我已经在网上看了很多东西,但却找不到如何做到这一点.一旦我搞清楚了,我应该能够用一个包含100,000个图像的新阵列重新训练我的网络,并一遍又一遍地执行此操作,直到我将所有七百万个图像都安装到我的模型中.我对这种东西真的很陌生,所以任何其他帮助或建议都会非常感激.

cha*_*id1 7

编辑:答案是矫枉过正,因为你正在寻找一个简单的熊猫功能,但我会在这里留下答案,以防它帮助其他人用Keras进行记忆内训练.

你一定要考虑使用HDF5.这是一种压缩文件格式,允许您以分层方式存储数据,并有选择地加载数据.可以把它想象成一个带有文件夹结构的zip文件.如果您正在使用Python,您可以使用h5py(链接到h5py文档,如果您拥有$$或访问Safari Bookshelf,大多数公共图书馆都可以使用本主题的非常密集且有用的O'Reilly书籍).

手动创建包含数据的HDF5文件

要使用h5py,您将创建一个HDF5文件并迭代地向其添加数据.您必须对数据进行一次传递以对其进行压缩(创建HDF5结构,并遍历每个图像以将其添加到HDF5文件中).您可能希望自己将其分成HDF5文件中的N个图像批次,但这并非绝对必要(见下文).您可以使用您选择的云提供程序在本地计算机上或高内存计算实例上执行此操作.

例如,假设你定义一个load_images()将抢特定数量的图像,从功能start_indexend_index,并会返回一个嵌套np.array()np.array()对象(我会留给你来定义,但似乎你已经有了这一点,或至少有一些非常接近的东西).然后你将数据加载到HDF5文件,如下所示:

image_set_1 = load_images(path_to_bson, start_index, end_index)
with h5py.File(output_path, mode="w") as h5file:
    h5file.create_dataset("image_set_1", data=image_set_1)
Run Code Online (Sandbox Code Playgroud)

使用燃料

我推荐使用库燃料,它用于组织/压缩/存储用于Keras,Theano和Lasagne的大型数据集.它基本上和上面做的一样,但有更多的选择.要使用它,你会:

  • 定义燃料数据集(基本上是一个存根类)
  • 定义燃料下载器(一种获取数据的方式 - 可以在本地获得,因为您已经拥有它)
  • 定义一个燃料转换器(将迭代数据并将其添加到HDF5文件,类似于上面的代码片段)

(文档给出了一个使用H5PYDataset类的玩具示例,这基本上就是你所遵循的.)

然后运行该fuel-download <name-of-dataset>实用程序以下载数据集,然后fuel-convert <name-of-datset>运行转换器.

最终结果是一个HDF5文件,它以有组织的方式包含您的数据,现在您可以通过多种方式访问​​和采样数据.例如,您可以创建一个将创建任意迭代器的DataStream,并将其传递给迭代方案,您可以在其中指定自己的自定义批量大小,随机或按顺序采样,或根据特定批次"计划"进行采样.(请参阅文档中的DataStream.)

示例:假设您的数据集有100,000张图像.燃料转换器会将所有100,000张图像填充到HDF5文件中(使用您定义的任何方案 - 也许您希望根据任务组织它们,或者您可能希望将它们全部保持平坦.由您决定.)一旦您运行转换器,您的数据是燃料数据集.然后你可能会说,我想用洗牌顺序训练我的神经网络 - 然后你会使用一个ShuffledScheme.然后明天你可能会说,我想按顺序迭代图像 - 然后你会使用SequentialScheme.然后你可能会说,我想指定每个批次使用的图像 - 然后你使用BatchScheme.这就是燃料给你的灵活性.

使用Keras HDF5Matrix

最后一个选项是使用Keras内置的utilite来处理HDF5文件:HDF5Matrix.该工作流程看起来与上面提到的HDF5工作流程类似(只需通过所有数据将其压缩为HDF5文件),但您现在可以直接从Keras中选择性地加载部分数据.这将更有利于您在HDF5文件中自己按批次分组图像的情况,您的工作流程将如下所示:

  • 加载batch1 keras.HDF5Matrix()
  • 使用batch1训练模型
  • 用于加载batch2 keras.HDF5Matrix()
  • 使用batch2训练模型
  • 等等...

这些都是自己编写的相当简单(有几个可用于各种数据集的示例,以及可用于Github上其他数据集的其他示例).

另外,您也可以加载更大的数据块(或全部)作为一个非常大的numpy的阵列,并使用startend论据,HDF5Matrix()呼叫限制你加载的数据量.不过,这也需要重塑你的numpy数据.

最终建议

我的总体建议是使用燃料.我已成功将它用于一些非常大的数据集和内存外训练方案.