Python 就地洗牌多个HDF5数据集

Python 就地洗牌多个HDF5数据集,python,numpy,hdf5,h5py,Python,Numpy,Hdf5,H5py,我有多个HDF5数据集保存在同一个文件中,my_file.h5。这些数据集具有不同的维度,但在第一维度中观察到的数量相同: features.shape = (1000000, 24, 7, 1) labels.shape = (1000000) info.shape = (1000000, 4) 重要的是信息/标签数据正确地连接到每一组特性,因此我想用相同的种子对这些数据集进行洗牌。此外,我希望在不将它们完全加载到内存中的情况下对它们进行洗牌。可以使用numpy和h5py吗?在磁盘上无序排列

我有多个HDF5数据集保存在同一个文件中,
my_file.h5
。这些数据集具有不同的维度,但在第一维度中观察到的数量相同:

features.shape = (1000000, 24, 7, 1)
labels.shape = (1000000)
info.shape = (1000000, 4)

重要的是信息/标签数据正确地连接到每一组特性,因此我想用相同的种子对这些数据集进行洗牌。此外,我希望在不将它们完全加载到内存中的情况下对它们进行洗牌。可以使用numpy和h5py吗?

在磁盘上无序排列阵列会很耗时,因为这意味着您必须在hdf5文件中分配新阵列,然后以不同的顺序复制所有行。如果希望避免使用PyTables或h5py将所有数据一次加载到内存中,可以对行进行迭代(或使用行块)

另一种方法是保持数据的原样,只需将新行数映射到单独数组中的旧行数(这样可以在RAM中保持完全加载,因为数组大小只有4MB)。例如,要洗牌numpy数组
x

x = np.random.rand(5)
idx_map = numpy.arange(x.shape[0])
numpy.random.shuffle(idx_map)
然后您可以使用访问您的无序数据

x[idx_map[2]] # equivalent to x_shuffled[2]
x[idx_map]    # equivament to x_shuffled[:], etc.

这也适用于保存到hdf5的阵列。当然,与在磁盘上写入洗牌数组相比,会有一些开销,但这可能足够了,具体取决于您的使用情况。

numpy
中这样洗牌数组很简单

创建大的索引(shuffle
np.arange(1000000)
)并索引数组

features = features[I, ...]
labels = labels[I]
info = info[I, :]
这不是就地操作<代码>标签[I]是标签的副本,而不是切片或视图

替代方案

features[I,...] = features
从表面上看,这是一个就地操作。我怀疑它是,在C代码中。必须对其进行缓冲,因为不能保证
I
值是唯一的。事实上,对于无缓冲操作,有一种特殊的
ufunc
.at
方法

但是看看
h5py
对这种“奇特的索引”是怎么说的:

标签[I]
选择已实现,但有限制

List selections may not be empty
Selection coordinates must be given in increasing order
Duplicate selections are ignored
Very long lists (> 1000 elements) may produce poor performance
根据定义,您的混洗
I
不是按递增顺序排列的。而且它非常大


另外,我没有看到任何关于在左手边使用这种奇特的索引,
标签[I]=…

有人刚刚否决了这两个答案。我想知道为什么?是不是有人因为我们说这件事做不到而感到失望?还是有人有解决办法?评论通常比否决票信息更丰富。可能是因为问题指定了“从未将其完全加载到内存中”。在两个答案中,X必须加载到内存中。
import numpy as np
import h5py

data = h5py.File('original.h5py', 'r')

with h5py.File('output.h5py', 'w') as out:
    indexes = np.arange(data['some_dataset_in_original'].shape[0])
    np.random.shuffle(indexes)
    for key in data.keys():
        print(key)
        feed = np.take(data[key], indexes, axis=0)
        out.create_dataset(key, data=feed)