python - Dask 数组广播似乎与稀疏矩阵不兼容
问题描述
我正在研究一种使用 Dask 来避免内存错误的算法,因为数据似乎太大而无法在我的计算机上处理。在算法的一个步骤中,我想使用一个带有 shape 的系数(和稀疏)矩阵,coefs
并对一个带有 shape(M, N)
的数组执行逐元素乘法,该数组由矩阵组成。由于是一个稀疏矩阵,我想考虑到这一点,而不是使用密集数组。T
(K, M, N)
K
MxN
coef
我正在使用以下配置:
- Python版本:3.7.3
- numpy 版本:1.16.2
- Dask 版本:1.2.0
- Scipy 版本:1.2.1
- 稀疏版本:0.7.0
我尝试了三种不同的可能性。
版本 1
系数矩阵只是一个numpy.ndarray
矩阵。
版本 2
系数矩阵是一个scipy.sparse.csr.csr_matrix
矩阵。
版本 3
系数矩阵是一个sparse.coo.core.COO
矩阵。
参考:https ://sparse.pydata.org/en/latest/
import numpy as np
import dask.array as da
import scipy.sparse as sp
import sparse
def func_test(coef):
K, M, N, tol = 10, 2000, 800, 1e-7
# Starting values
P1 = np.random.rand(K,M)
P1 /= P1.sum(1)[:, None]
P2 = np.random.rand(K, N)
P2 /= P2.sum(1)[:, None]
P3 = np.random.rand(K)
P3 /= P3.sum()
# Convert arrays to dask
P2 = da.from_array(P2, chunks=(1000))
P3 = da.from_array(P3, chunks=(1000))
# Threshold
P1[P1 < tol] = tol
P2[P2 < tol] = tol
for iter_number in range(20):
T = P3[:, None, None] * (P1[:, :, None] @ P2[:, None, :])
T *= coef # Problematic line
P1 = T.sum(2) / T.sum((1,2))[:,None] # (K, M)
P2 = T.sum(1) / T.sum((1,2))[:,None]
P3 = T.sum((1,2)) / T.sum()
# Threshold
P1[P1 < tol] = tol
P2[P2 < tol] = tol
return T, P1, P2, P3
if __name__ == "__main__":
# coef is a numpy.ndarray
M, N = 2000, 800
coef_1 = np.random.random((M, N))
# Make it sparse
coef_1[coef_1 < 0.92] = 0
# coef is a scipy.sparse matrix
coef_2 = sp.csr_matrix(coef_1)
# coef is a sparse COO matrix
coef_3 = sparse.COO.from_numpy(coef_1)
T, P1, P2, P3 = func_test(coef_1)
T = T.compute()
coef_2
如果传递给 func_test 的参数是或,代码将引发错误coef_3
。
如果参数是coef_2
Python,则会引发 ValueError:
ValueError: could not interpret dimensions
如果是coef_3
,它会引发另一个 ValueError:
ValueError: Please make sure that the broadcast shape of just the sparse arrays is the same as the broadcast shape of all the operands.
我%timeit
在 IPython 上使用过来测量执行时间:
- 与
coef_1
:869 ms ± 52.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
- 与
coef_2
:322 ms ± 3.98 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
- 与
coef_3
:249 ms ± 2.82 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我的问题是:是否可以使用具有稀疏矩阵的 Dask N 维数组执行操作?就地分配
T *= coef
似乎可以节省很多时间。
一些笔记
我试过用
T = coef.multiply(coef_2)
但它增加了执行时间:
4.65 s ± 173 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
M
和的值N
将大于代码中显示的值,因此是 dask 要求。我正在使用 Dask,但欢迎提出建议。具体来说,操作:
T = P3[:, None, None] * (P1[:, :, None] @ P2[:, None, :])
MemoryError
当矩阵太大时,会在我的计算机上导致 a 。
解决方案
推荐阅读
- javascript - Javascript 会延迟页面加载时间并破坏 google page speed insigt 中的结果
- arrays - 从json颤振中获取数组
- c - "Real" 数组指针和 malloc
- android - AirBnb Epoxy - 视图被复制而不是被替换
- hyperledger-fabric - 为什么我们不将锚节点放在第一次生成的通道配置中?
- node.js - 为什么 Electron 快速启动应用程序无法在我的 Ubuntu 实例上正确启动?
- java - android studio:java.lang.VerifyError:拒绝尝试子类型错误类java.awt.geom.Point2D的类java.awt.Point
- swiftui - Apple 建议的 .indexed() 属性如何在 ForEach 中工作?
- node.js - 如何总结一个月每天一条记录?
- terraform - Terraform azurerm_api_management_api 颠簸修订不应用所有必需的更改