【问题标题】:Shuffling multiple HDF5 datasets in-place就地改组多个 HDF5 数据集
【发布时间】:2015-09-07 18:13:47
【问题描述】:

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

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

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

【问题讨论】:

    标签: python numpy hdf5 h5py


    【解决方案1】:

    numpy 中像这样洗牌数组很简单

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

    features = features[I, ...]
    labels = labels[I]
    info = info[I, :]
    

    这不是就地操作。 labels[I]labels 的副本,而不是切片或视图。

    另一种选择

    features[I,...] = features
    

    在表面上看起来像是一个就地操作。我怀疑它在 C 代码中。它必须被缓冲,因为I 值不能保证是唯一的。事实上有一个特殊的ufunc.at方法用于无缓冲操作。

    但是看看h5py 是怎么说这种“花式索引”的:

    http://docs.h5py.org/en/latest/high/dataset.html#fancy-indexing

    labels[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 不是按递增顺序排列的。而且很大。

    我也没有看到任何关于在左侧使用这个花哨的索引,labels[I] = ...

    【讨论】:

      【解决方案2】:

      在磁盘上打乱数组会很耗时,因为这意味着您已经在 hdf5 文件中分配了新数组,然后以不同的顺序复制所有行。如果您想避免使用 PyTables 或 h5py 一次将所有数据加载到内存中,您可以遍历行(或使用行块)。

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

      x = np.random.rand(5)
      idx_map = numpy.arange(x.shape[0])
      numpy.random.shuffle(idx_map)
      

      然后您可以使用advanced numpy indexing 访问您的洗牌数据,

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

      这也适用于保存到 hdf5 的数组。当然,与在磁盘上写入混洗数组相比,会有一些开销,但根据您的用例,这可能就足够了。

      【讨论】:

      • 有人刚刚对这两个答案投了反对票。我想知道为什么?那是不是有人对我们说它不能完成感到失望?或者有人有解决方案吗?评论通常比投反对票更能提供信息。
      • 可能是因为问题指定了“没有将它们完全加载到内存中”。在这两个答案中,X 都必须加载到内存中。
      【解决方案3】:
      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-03
        • 2016-06-02
        • 2017-10-02
        • 2022-11-02
        • 2014-10-29
        • 1970-01-01
        相关资源
        最近更新 更多