[英]Histograms with a lot of dimensions in Python
我正在模擬一個隨機多體系統,目前我需要從生成的數據中獲取多維概率分布。 為此,我嘗試使用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 = 20
、 dimensions = 5
和np.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
如果直方圖在每個軸上都有固定的 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=8
或9
的情況下,無論如何你都會在大多數系統上用完 memory。
問題是你要如何處理一個有10**10
bin 的直方圖; 你有 10**11 或更多的樣品嗎?
保留ii
數組並在需要時生成低維直方圖更實用。 例如,如果要將 7D 直方圖簡化為軸0, 1, 5, 6
上的 4D 直方圖:
hist_4d = np.zeros((n_bins,)*4, dtype=np.int16)
np.add.at(hist_4d, tuple(ii[:, [0, 1, 5, 6]].T), 1)
注意:我建議您對 bin 計數使用有符號整數。 Integer 溢出將保持沉默,但至少垃圾箱中的負數將表明您有溢出。
在第三種情況下,dims=10,由於溢出,您會收到錯誤。 此處添加了一個相關線程: 為什么 numpy.prod() 對於我的長自然數列表錯誤地返回負結果或 0? 這與 numpy.ndarray.prod() 特別相關。 您可以將產品計算切換回默認的 python 方式,而不是使用 numpy.ndarray.prod()。 但是,為此您必須編輯直方圖 dd 的源代碼
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.