稀疏矩阵的热力图绘制

3

我有一个包含直方图的大型稀疏矩阵,我想将其绘制成热力图。通常情况下,我会像下面这样简单地绘制完整的矩阵 (h):

import matplotlib.pyplot as plt
plt.imshow(h.T, interpolation="nearest", origin="lower")
plt.colorbar()
plt.savefig("corr.eps")

在这种情况下,我的问题是完整矩阵的维度为189,940x189,940,太大了,我无法将其保存在内存中。我已经找到了有关绘制稀疏矩阵模式(例如python matplotlib plot sparse matrix pattern)的帖子,但尚未找到如何在不将其转换为密集矩阵的情况下绘制热图的任何信息。是否可能这样做?(或者是否有其他方法可以绘制它而不会耗尽RAM?)我的稀疏矩阵目前是lilmatrix(scipy.sparse.lil_matrix)。

从来没有亲自尝试过,但你是否考虑过datashader?可能会很有用。 - undefined
你考虑过只是将这些点单独绘制成散点图或矩形集合吗? - undefined
1
我通常会这样做,但在这种情况下,每个单元格都包含一个计数,所以我不关心单元格是否被填充,而是关心它所持有的值。我不确定如何使用散点图来可视化这一点。 我还没有看过datashader,但我会去看一下。 - undefined
在热力图中,颜色被用来传达数据值的信息。通常情况下,这是通过使用一个颜色映射来实现的。因此,根据颜色映射设置散点或集合项的颜色可能是一个选择。 - undefined
我明白你的意思。你知道这个在实践中可能如何实现吗? - undefined
显示剩余2条评论
2个回答

2

一种想法是使用稀疏操作进行下采样。

 data = data.tocsc()       # sparse operations are more efficient on csc
 N, M = data.shape
 s, t = 400, 400           # decimation factors for y and x directions
 T = sparse.csc_matrix((np.ones((M,)), np.arange(M), np.r_[np.arange(0, M, t), M]), (M, (M-1) // t + 1))
 S = sparse.csr_matrix((np.ones((N,)), np.arange(N), np.r_[np.arange(0, N, s), N]), ((N-1) // s + 1, N))
 result = S @ data @ T     # downsample by binning into s x t rectangles
 result = result.todense() # ready for plotting

这段代码实现了一个简单的分箱,但可以进一步改进以包含更复杂的过滤器。分箱矩阵只是分箱id矩阵,例如S_ij = 1如果j // s = i否则为0。
更多解释。由于原始矩阵非常大,因此有可能对其进行下采样,而不会在输出中产生任何可见的差异。
问题是如何在不首先创建密集表示的情况下进行下采样。一个可能的答案是用矩阵乘法来表达分箱,然后使用稀疏矩阵乘法。
因此,如果从右侧将原始数据与分箱矩阵T相乘,则T的列对应于列箱,特别是T的列数将确定下采样数据在x方向上有多少个像素。 T的每一列确定放入相应箱子和不放入相应箱子的内容。在示例中,我设置了一些元素来编码相邻列(原始矩阵)并将其余元素设置为0。这将对这些列求和,并将总和放入结果矩阵中,换句话说,它将这些列合并到一起进行分箱。
从左边开始乘法的工作方式完全相同,只是影响行而不是列。
如果您认为分组太粗糙,可以将简单的0-1方案替换为平滑核函数,只需确保生成的矩阵仍然是稀疏的。设置这样的矩阵需要更多的努力,但并不难。您正在使用一种稀疏矩阵处理数据,因此我认为您已经熟悉如何构建稀疏矩阵。

谢谢你的建议。你能再解释一下采样是如何工作的吗?或者我如何改变被采样的内容?我担心我还没有完全理解。 - undefined
我正在使用Python2.7(抱歉,这在我的帖子中不明显),所以@运算符不存在。根据这篇帖子(https://dev59.com/iFsX5IYBdhLWcg3wLc6J),它相当于`np.matmul`而不是`np.dot`。这是你想要的吗? - undefined
@P-M 哎呀,你链接的东西真让人不爽。好消息是只要你使用2D数组np.dot(a, b)np.matmul(a, b)a @ ba.dot(b)中的任何一种,都会得到相同的结果,所以随便选吧。 - undefined
是的,我也得出了这个结论。不过我意识到,在稀疏数组上使用np.matmul是行不通的,因为我需要使用适当的scipy例程(否则会出现TypeError: Object arrays are not currently supported错误),所以我正在使用result = S.dot(data),然后再使用result = result.dot(T)。现在我正在尝试找到合适的st值,以获得一张好的图像。 - undefined

0
Paul的方法是matspy用来制作间谍情节的。在视觉上看起来像这样:

matspy triple product

Matspy只关心稀疏模式而不关心数值,但我们可以使用它内部的辅助方法来创建左右矩阵:
data  # a scipy matrix
binned_shape = tuple(int(x / 3) for x in data.shape)  # example: shrink by a third

from matspy.adapters.scipy_impl import generate_spy_triple_product_coo

left, right = generate_spy_triple_product_coo(data.shape, binned_shape)

result = left @ data @ right
result = result.todense()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接