从hdf5获取随机数组元素

时间:2017-11-19 20:48:16

标签: python hdf5 h5py

我正在训练神经网络,我所拥有的训练集存储在1.5Tb hdf5文件中,该文件被分成125组(grp0 ... grp124)。每组包含2个数据集'x'和'y',它们是保存为hdf5格式的numpy数组。每个数据集x和y由大约10,000个训练样例组成,或者采用几百个(这些组的大小不均匀,总共约120万个训练样例)。我想要做的是从这个hdf5文件中动态生成随机训练小批量。现在,我生成这样一个批处理的代码如下所示:

    #grps is a dictionary of group sizes (they are not exactly uniform)
    def data_gen(PATH,grps,batch_size=32):
        while(True): 
            pick_grp = random.randint(0,len(grps)-1)
            size = grps['grp_'+str(pick_grp)]
            indices = random.sample(range(size),batch_size)
            with h5py.File(PATH,'r') as f:
                X = f['grp'+str(pick_grp)]['x'][indices]
                Y = f['grp'+str(pick_grp)]['y'][indices]
                yield (X,Y)

正如你所看到的,我正在尝试做的是选择一个随机的grp,然后从那个grp选择一个随机的batch_sized数量的训练样例。使用numpy数组,这个切片可以工作,但显然h5py不支持这种数据集的切片,我得到错误

    TypeError: Indexing elements must be in increasing order

当我尝试运行此代码时。或者,我可以使用for循环一次手动构建一个批处理训练示例,但我认为这会完全减慢我的代码。我使用GeForce 1080Ti进行小批量运行,因此对单个小批量的培训非常快。我不想被构建迷你批次的CPU过程所困扰。有没有一种聪明的方法可以做我想做的事情?我还考虑过简单地选择随机起始索引,然后从grps中抓取一个小批量:

    i = random.randint(0,size-batch_size-1)
    X=f['grp'+str(pick_grp)]['x'][i:i+batch_size]
我抓住之后可以将小批量洗牌。但这意味着相邻的培训示例可能总是出现在同一个小批量中。我不知道这会对神经网络训练产生什么样的影响(如果有的话),但对于我现在的随机索引切片方法来说,这似乎是次优的。理想情况下,我希望能够从一个迷你批次中的125个组中的任何一个中获取示例(由于在生成此hdf5文件期间的内存限制,该文件被分段为125个组),但我还没想到一种方法。

1 个答案:

答案 0 :(得分:0)

我的解决方案是简单地使用sorted()索引列表,然后重新随机处理该批次:

def data_gen(PATH,grps,batch_size=32):
        while(True): 
            pick_grp = random.randint(0,len(grps)-1)
            size = grps['grp_'+str(pick_grp)]
            indices = random.sample(range(size),batch_size)
            with h5py.File(PATH,'r') as f:
                X = f['grp'+str(pick_grp)]['x'][sorted(indices)]
                Y = f['grp'+str(pick_grp)]['y'][sorted(indices)]
                another_idx = np.random.permutation(X.shape[0]) #shuffle after reading data but not necessary
                yield (X[another_idx],Y[another_idx])