繁体   English   中英

在 Python 中计算稀疏 Gram 矩阵的最快方法是什么?

[英]What is the fastest way to compute a sparse Gram matrix in Python?

Gram矩阵是结构X @ XT的矩阵,当然是对称的。 在处理稠密矩阵时, numpy.dot乘积实现足够智能,可以识别自乘以利用对称性,从而加快计算速度(见 )。 但是,在使用scipy.sparse矩阵时不会观察到这样的效果:

random.seed(0)
X = random.randn(5,50)
X[X < 1.5] = 0
X = scipy.sparse.csr_matrix(X)
print(f'sparsity of X: {100 * (1 - X.count_nonzero() / prod(X.shape)):5.2f} %')
# sparsity of X: 92.00 %

%timeit X @ X.T
# 248 µs ± 10.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

X2 = X.copy()
%timeit X @ X2.T
# 251 µs ± 9.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

所以我想知道:在 Python 中计算稀疏 Gram 矩阵的最快方法是什么? 值得注意的是,只计算下(或等效地,上)三角形就足够了。

我多次阅读,使用天际线格式对于对称矩阵非常有效,但是,scipy 不支持天际线格式。 Instead, people were pointing towards pysparse many times, but it seems that pysparse has been discontinued a long time ago and there is no support for Python 3. At least, my Anaconda rejects to install pysparse due to compatibility issues with Python 3.

感谢用户 CJR 的评论,我制定了一个令人满意的解决方案。 事实上,我在 GitHub 上找到了一个库,它为 Python 包装了 MKL 例程mkl_sparse_spmm 该例程用于两个稀疏矩阵的快速乘法。 所以我所要做的就是扩展库并为mkl_sparse_syrk提供一个类似的包装器。 这正是我所做的。

我仍然需要添加一些评论,之后我将向原始项目提交拉取请求。

然而,这里是性能结果,相当令人印象深刻:

random.seed(0)
X = random.randn(500, 5000)
X[X < 0.8] = 0
X = scipy.sparse.csr_matrix(X)
print(f'X sparsity: {100 * (1 - X.count_nonzero() / prod(X.shape)):5.2f} %')
# X sparsity: 78.80 %

expected_result = (X @ X.T).toarray()
expected_result_triu = expected_result.copy()
expected_result_triu[tril_indices(expected_result.shape[0], k=-1)] = 0

mkl_result1 = sparse_dot_mkl.dot_product_mkl(X, X.T)
allclose(mkl_result1.toarray(), expected_result)
# True

mkl_result2 = sparse_dot_mkl.dot_product_transpose_mkl(X)
allclose(mkl_result2.toarray(), expected_result_triu)
# True

%timeit X @ X.T
# 197 ms ± 5.21 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit sparse_dot_mkl.dot_product_mkl(X, X.T)
# 70.6 ms ± 593 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit sparse_dot_mkl.dot_product_transpose_mkl(X)
# 34.2 ms ± 421 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

使用来自 MKL 的通用点积而不是来自 scipy 的点积实现产生279% 的加速 使用 Gram 矩阵计算的专用产品可产生576% 的加速 这是巨大的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM