This是我在numpy中找到的关于标准基础向量的唯一问题,但它与我的问题没有关系。
我有一个numpy整数数组,我想确定共生矩阵,它存储指标在同一列中具有相同值的次数。 This问题更详细地描述了问题。
我有一种解决问题的方法,但它不能很好地扩展。
我的问题是:
是否可以以高效的内存方式将标准基矢量存储在numpy数组中?
我希望能够做到以下几点:
给定数组
M = e1 e2 e1
e1 e2 e2
e3 e1 e3
e2 e3 e3
其中ei
是向量空间的转置i-th
标准基矢量(在本例中为R3),使用M
的转置执行矩阵乘法,即确定np.dot(M, M.T)
}。需要说明的是,上面的矩阵M
可以写成:
M = 1 0 0 0 1 0 1 0 0
1 0 0 0 1 0 0 1 0
0 0 1 1 0 0 0 0 1
0 1 0 0 0 1 0 0 1
(为强调添加了额外的空格)。
像这样表示矩阵的问题在于它在内存中的可扩展性与行数和向量空间的维数无关。
编辑:我应该提一下,列数也会增加。内存复杂度为D * R * C
,其中D
是向量空间的维度,R
是行数,C
是列数。在一个普通的工作示例中,我大致D == 150, R == 2000 and C == 1000
,R
可以达到20,000
而C
无限制(尽管10,000
是一个合理的估算值)。
标准基矢量乘法的规则很简单(ei * ei.T == 1, ei * ej.T == 0 if i != j
)所以我想知道是否可以将这些规则存储在一个numpy数组中以节省内存。
答案 0 :(得分:2)
让我们用数字编码基矢量:e1 - > 1,e2 - > 2,...这样可以实现非常节省内存的存储。
M = np.array([[1, 2, 1], [1, 2, 2], [3, 1, 3], [2, 3, 3]], dtype=np.uint8)
# if more than 255 basis vectors, use uint16.
现在我们只需要实现一个与这些基矢量一起使用的特殊点积。基本上我们只用比较代替乘法:
def basis_dot(a, b):
return np.sum(a[:, :, np.newaxis] == b[np.newaxis, :, :], axis=1)
print(basis_dot(M, M.T))
# [[3 2 0 0]
# [2 3 0 0]
# [0 0 3 1]
# [0 0 1 3]]
让我们验证结果:
M = np.array([[1, 0, 0, 0, 1, 0, 1, 0, 0],
[1, 0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 1, 0, 0, 1]])
np.dot(M, M.T)
# array([[3, 2, 0, 0],
# [2, 3, 0, 0],
# [0, 0, 3, 1],
# [0, 0, 1, 3]])
该方法的一个潜在缺点是basis_dot
中需要大型临时数组。可以通过显式编码循环来降低内存需求,但代价是性能(除非你使用jit编译器)。
# slower but more memory friendly
def basis_dot(a, b):
out = np.empty((a.shape[0], b.shape[1]))
for i in range(a.shape[0]):
for j in range(b.shape[1]):
out[i, j] = np.sum(a[i, :] == b[:, j])
return out
答案 1 :(得分:1)
所以,基于你的例子,我的假设是你实际上使用的维度高于3。我的另一个假设是你不计算任何基础向量,而只是自动生成基础RN的载体。我将忽略您正在尝试完成的内容或为什么要存储您现在可以轻松自动生成的向量的问题。
如果上述所有假设都是准确的,那么您可以通过以稀疏数据格式存储来获得很多好处。如果你有一个优势的零,这只会改善存储,但这似乎是一个合理的假设。您可以查看大量稀疏格式here。我对你的最好猜测是coo_matrix
类。
from scipy.sparse import coo_matrix
new_matrix = coo_matrix(<your_matrix>)
然后以您选择的格式保存新矩阵。