Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 计算从hdf5文件映射的大numpy数组的平均值_Python_Numpy_H5py - Fatal编程技术网

Python 计算从hdf5文件映射的大numpy数组的平均值

Python 计算从hdf5文件映射的大numpy数组的平均值,python,numpy,h5py,Python,Numpy,H5py,我在用numpy计算数组的平均值时遇到了一个问题,该数组对于RAM来说太大了(~100G) 我已经研究过如何使用np.memmap,但不幸的是,我的数组作为数据集存储在hdf5文件中。根据我的尝试,np.memmap不接受hdf5数据集作为输入。 TypeError:强制使用Unicode:需要字符串或缓冲区,找到数据集 那么,如何才能有效地从磁盘对内存映射数组调用np.mean?当然,我可以循环数据集的各个部分,每个部分都可以放入内存中。 然而,这感觉太像是一种变通方法,我也不确定它是否能

我在用numpy计算数组的平均值时遇到了一个问题,该数组对于RAM来说太大了(~100G)


我已经研究过如何使用
np.memmap
,但不幸的是,我的数组作为数据集存储在hdf5文件中。根据我的尝试,np.memmap不接受hdf5数据集作为输入。
TypeError:强制使用Unicode:需要字符串或缓冲区,找到数据集

那么,如何才能有效地从磁盘对内存映射数组调用
np.mean
?当然,我可以循环数据集的各个部分,每个部分都可以放入内存中。
然而,这感觉太像是一种变通方法,我也不确定它是否能达到最佳性能


下面是一些示例代码:

data = np.randint(0, 255, 100000*10*10*10, dtype=np.uint8)
data.reshape((100000,10,10,10)) # typically lot larger, ~100G

hdf5_file = h5py.File('data.h5', 'w')
hdf5_file.create_dataset('x', data=data, dtype='uint8')

def get_mean_image(filepath):
    """
    Returns the mean_array of a dataset.
    """
    f = h5py.File(filepath, "r")
    xs_mean = np.mean(f['x'], axis=0) # memory error with large enough array

    return xs_mean

xs_mean = get_mean_image('./data.h5')

正如hpaulj在评论中所建议的,我只是将平均值计算分为多个步骤。
以下是我的(简化)代码,如果它对某人有用的话:

def get_mean_image(filepath):
    """
    Returns the mean_image of a xs dataset.
    :param str filepath: Filepath of the data upon which the mean_image should be calculated.
    :return: ndarray xs_mean: mean_image of the x dataset. 
    """
    f = h5py.File(filepath, "r")

    # check available memory and divide the mean calculation in steps
    total_memory = 0.5 * psutil.virtual_memory() # In bytes. Take 1/2 of what is available, just to make sure.
    filesize = os.path.getsize(filepath)
    steps = int(np.ceil(filesize/total_memory))
    n_rows = f['x'].shape[0]
    stepsize = int(n_rows / float(steps))

    xs_mean_arr = None
    for i in xrange(steps):
        if xs_mean_arr is None: # create xs_mean_arr that stores intermediate mean_temp results
            xs_mean_arr = np.zeros((steps, ) + f['x'].shape[1:], dtype=np.float64)

        if i == steps-1: # for the last step, calculate mean till the end of the file
            xs_mean_temp = np.mean(f['x'][i * stepsize: n_rows], axis=0, dtype=np.float64)
        else:
            xs_mean_temp = np.mean(f['x'][i*stepsize : (i+1) * stepsize], axis=0, dtype=np.float64)
        xs_mean_arr[i] = xs_mean_temp

    xs_mean = np.mean(xs_mean_arr, axis=0, dtype=np.float64).astype(np.float32)

    return xs_mean

我将继续对
h5py
数据集进行分块读取。让它工作起来。然后您可以测试迭代是否真的花费了您的时间。对于大型阵列,内存管理的成本可能会超过迭代的成本。你是对的,实际上成本并不高。唯一让人感到困惑的是你必须编码的循环,所以它不是那么优雅。非常感谢。如果所有铲斗的尺寸相同,则平均值的平均值仅等于真实平均值。你的最后一个桶不是,所以它稍微扭曲了你的结果。