【问题标题】:Histograms with a lot of dimensions in PythonPython中具有很多维度的直方图
【发布时间】:2020-07-14 15:35:20
【问题描述】:

我正在模拟一个随机多体系统,目前我需要从生成的数据中获取多维概率分布。为此,我尝试使用np.histogramdd

bins = np.linspace(start = -x_max, stop = x_max, num = n_bins)
hists = np.histogramdd(Data, bins = [bins] * dimensions, density = True)

但是,此代码已经为 n_bins = 20dimensions = 5np.shape(Data) = (1000, 5) 产生了 MemoryError(或引发有关某些数组太大的异常),这远低于目标值。桶的数量随着维度的数量呈指数增长,因此很容易看出为什么会出现这些问题。所以,问题是:如何在 Python 中生成、存储和使用大尺寸的直方图?有没有这方面的现有框架?换别的东西会更好吗?

编辑:MCEV 和错误代码示例。

x_max = 10 
n_bins = 20 
Data = np.random.uniform(-x_max, x_max, size=(1000, dimensions))

bins = np.linspace(start = -x_max, stop = x_max, num = n_bins)
hists = np.histogramdd(Data, bins = [bins] * dimensions, density = True)

输入dimensions = 7,我明白了:

lib\site-packages\numpy\lib\histograms.py in histogramdd(sample, bins, range, normed, weights, density)
1066 # Compute the number of repetitions in xy and assign it to the
1067 # flattened histmat.
-> 1068  hist = np.bincount(xy, weights, minlength=nbin.prod())
MemoryError:

dimensions = 15:

   1062     # Compute the sample indices in the flattened histogram matrix.
   1063     # This raises an error if the array is too large.
-> 1064     xy = np.ravel_multi_index(Ncount, nbin)
   1065 
   1066     # Compute the number of repetitions in xy and assign it to the

ValueError: invalid dims: array size defined by dims is larger than the maximum possible size. 

dimensions = 10

   1066     # Compute the number of repetitions in xy and assign it to the
   1067     # flattened histmat.
-> 1068     hist = np.bincount(xy, weights, minlength=nbin.prod())
   1069 
   1070     # Shape into a proper matrix

ValueError: 'minlength' must not be negative

【问题讨论】:

  • 能否将错误代码添加到问题中?
  • @amzon-ex 完成。
  • 你能提供一个MCVE吗?如果我在您的代码前面加上 x_max = 10; bins = 20; dimensions = 5; Data = np.random.uniform(-x_max, x_max, size=(1000, dimensions)),则不会出错。
  • @Han-KwangNienhuys 保持所有其他变量相同,对于尺寸 = 7,我得到错误号。 1,对于尺寸 = 10,错误编号。 3,对于尺寸 = 15,错误编号。 2. 我将编辑帖子以反映这一点
  • 您实际拥有多少样本?如果不够,您的直方图可能没有价值。除此之外,您可能需要使用稀疏直方图。所以创建一个n维的稀疏矩阵并自己填充。

标签: python numpy bigdata histogram


【解决方案1】:

如果直方图在每个轴上都有固定的 bin 宽度,您可以自己记账并使用低内存数据类型进行计数(例如每个 bin 1 字节)。在以下示例中,每个轴的 bin 都相同,但您可以针对沿轴不同的 bin 范围进行调整,只要 bin 边缘等距即可。

此代码不会进行范围检查;您需要确保直方图箱足够宽以适合数据,否则您会收到错误。

import numpy as np

x_max = 10 
n_dim = 7
n_data = 100000
data = np.random.uniform(-x_max, x_max-0.01, size=(n_data, n_dim))

# assume bins are the same for all dimensions. Bin edges at x0+i*xstep.
n_bins = 5
x0 = -x_max
xstep = 2*x_max/n_bins

# high-dimensional histogram
hist = np.zeros((n_bins,)*n_dim, dtype=np.int8)

# build the histogram indices corresponding to the data samples.
ii = ((data - x0)*(1/xstep)).astype(np.int16) # shape (n_data, n_dim)

# increment the histogram bins. The np.add.at will correctly handle 
# bins that occur multiple times in the input.
np.add.at(hist, tuple(ii.T), 1)

但是使用n_dim=89 无论如何,大多数系统上的内存都会用完。

问题是您将如何处理具有10**10 箱的直方图;你有 10**11 或更多的样本吗?

保留ii 数组并在需要时生成低维直方图更实用。例如,如果您想将坐标轴上的 7D 直方图缩减为 4D 直方图0, 1, 5, 6

hist_4d = np.zeros((n_bins,)*4, dtype=np.int16)
np.add.at(hist_4d, tuple(ii[:, [0, 1, 5, 6]].T), 1)

注意:我建议您对 bin 计数使用有符号整数。整数溢出将保持沉默,但至少 bin 中的负数将表明您发生了溢出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    相关资源
    最近更新 更多