我目前正在尝试实现Dask进行凸矩阵优化。目标是对内存不足矩阵执行矩阵优化(分解)。以一个高矩阵为输入,以两个高矩阵为输出,以及一些参数(例如收敛等),我使用dask数组对原始矩阵和中间/输出矩阵进行分块。最后,在将先前迭代的输出用作新迭代的输入的意义上,这些迭代是顺序的(请参见下面的简单示例)。
在每次迭代中,必须计算两个条件并检查其收敛性(最终if语句)。但是,如果执行如下所示的代码,我会发现Dask会计算标准(由if语句强制执行),但随后会在每次迭代中重新计算其他矩阵:例如,迭代1,标准已正确计算,迭代2不使用先前找到的A和E,而是重新计算它们,从而得到两次SVD评估,依此类推。 Dask似乎没有认识到A_hat和E_hat在上一次迭代中已经计算过的事实,然后从头开始重新计算这些值。反之亦然,它会重新计算该条件的所有步骤。
在内存中保留这些矩阵也不是一种选择,因为它们会随着时间在内存中累积。我在博客文章(https://matthewrocklin.com/blog/work/2017/03/22/dask-glm-1和http://matthewrocklin.com/blog/work/2017/04/19/dask-glm-2)中看到了类似的优化,但是似乎每次迭代都有可能将结果存储在内存中,而对于我的优化则是不可能的。我尝试了不同的设置,在其中设置了一些值,或者使用了同步和异步的持久性和计算功能。
因此,我的问题是,如何在每次迭代结束时不对矩阵(A和E,以及扩展名为Y)进行计算并将其放置在内存中,同时又如何对它们进行一些计算呢?我有一些使用期货的想法,或者明确地延迟所有单个步骤。其中一种解决方案可以解决我的问题,还是有更有效的方法?
预先感谢
罗杰
def PCP(D, lambda_i, kmax):
# Initialize norms
normD = (norm(D, 'fro')).compute()
normD2 = (norm(D, 2)).compute()
normDinf = (norm(D.ravel(), np.inf)).compute()
# Initialize Y
Y = (1/np.maximum(normD2, (1/lambda_i)*normDinf))*D
# Initialize A and A_hat
A = da.zeros_like(D)
A_hat = da.zeros_like(D)
# Initialize E and E_hat
E = da.zeros_like(D)
E_hat = da.zeros_like(D)
# Initialize mu: mu_0 > 0
mu = 1.25/normD2 # Convergence Rate
# Initialize rho: rho > 1
rho = 1.6 # Convergence Rate
runAlgorithm = True
k = 0
while runAlgorithm:
# Estimate E_hat
E_hat = da.maximum((D-A+(1/mu)*Y)-(1/mu)*lambda_i, 0)+da.minimum((D-A+(1/mu)*Y)+(1/mu)*lambda_i, 0)
# Estimate A_hat
Q = da.linalg.svd(D-E_hat+(1/mu)*Y)
svp = (Q[1] - 1/mu).clip(0)
A_hat = (Q[0]*svp)@Q[2]
# Update Y
Y = Y+mu*(D-A_hat-E_hat)
# Calculate stopping criteria
crit1 = norm(D-A_hat-E_hat, 'fro')/normD
crit2 = norm(E-E_hat, 'fro')/normD
# Update A and E
A = A_hat
E = E_hat
# Check if Converged
if k == kmax or crit1 < 0.01 or crit2 < 0.01:
runAlgorithm = False
k = k + 1
return A, E, k, crit1, crit2
我使用以下快捷分布式设置:
from dask.distributed import Client, progress
client = Client(threads_per_worker=4,
n_workers=1, memory_limit='4GB')
答案 0 :(得分:0)
我不确定我是否完全理解您的问题,但是在这里我会说一些您可能已经知道的一般性事情。
如果可以在内存中放入一些结果,则应考虑在这些部分上调用persist
以避免重复工作。如果您无法将它们容纳在内存中,那么我不确定在这里可以做什么。使高效的算法像您上面描述的那样,在很大程度上涉及确定需要将计算的哪些部分保持为小状态,以及每次都需要重新计算哪些部分。
例如,您可能想看看matrix algorithms in dask-glm,它可以有效地执行此舞蹈。