Tensorly部分Tucker分解的rank约束及ARPACK报错咨询
问题描述
我计划用Python的Tensorly库对4D张量做Tucker分解,仅针对第0、1维度操作,因此采用partial_tucker函数,代码如下:
F = 256 D = 96 h = 5 w = 6 ranks = [89, 48] modes = [0, 1] tensor = tl.tensor((np.arange(F*D*h*w).reshape((F, D, h, w))).astype(np.float64)) core, factors = partial_tucker(tensor, modes=modes, rank=ranks)
当ranks设为[89,48]时代码正常运行,但改为[3,4]时出现报错:
Traceback (most recent call last): File "D:\PhD_Thessaloniki\Codes\LRF_Convolutional\tucker-decomposition.py", line 49, in <module> core, factors = partial_tucker(tensor, modes=modes, rank=ranks) File "C:\Users\Milad\Anaconda3\envs\tensorly\lib\site-packages\tensorly\decomposition\_tucker.py", line 109, in partial_tucker eigenvecs, _, _ = svd_fun(unfold(core_approximation, mode), n_eigenvecs=rank[index], random_state=random_state) File "C:\Users\Milad\Anaconda3\envs\tensorly\lib\site-packages\tensorly\backend\core.py", line 913, in partial_svd S, V = scipy.sparse.linalg.eigsh( File "C:\Users\Milad\Anaconda3\envs\tensorly\lib\site-packages\scipy\sparse\linalg\_eigen\arpack\arpack.py", line 1689, in eigsh params.iterate() File "C:\Users\Milad\Anaconda3\envs\tensorly\lib\site-packages\scipy\sparse\linalg\_eigen\arpack\arpack.py", line 571, in iterate raise ArpackError(self.info, infodict=self.iterate_infodict) scipy.sparse.linalg._eigen.arpack.arpack.ArpackError: ARPACK error 3: No shifts could be applied during a cycle of the Implicitly restarted Arnoldi iteration. One possibility is to increase the size of NCV relative to NEV.
仅对单一维度分解时,如ranks=[3]、modes=[0]或ranks=[4]、modes=[1]则无报错。想了解:
- 该问题属于算法约束还是Tensorly库的问题?
- 错误原因是什么?
- 有效的rank列表需满足什么条件?
问题解答
问题归属
这属于算法底层实现的约束,而非Tensorly库本身的问题。Tensorly的partial_tucker在处理低秩分解时,依赖Scipy的ARPACK库做特征值/奇异值求解,报错直接来自ARPACK的迭代失败。
错误原因
- ARPACK迭代机制限制:ARPACK的隐式重启Arnoldi迭代需要足够多的候选向量(NCV参数)来捕捉有效特征信息。当设置的rank(对应NEV参数,即要提取的特征值数量)过小,且张量结构导致前k个奇异值区分度不足时,迭代过程中找不到合适的位移量,就会触发该错误。
- 张量结构特殊性:你用
np.arange生成的张量是高度结构化的,元素值随索引线性增长,这种张量的奇异值分布可能极为陡峭。同时对两个维度做低秩约束时,中间迭代生成的核心张量结构会让ARPACK难以稳定收敛;而单一维度分解时,展开后的矩阵结构更简单,ARPACK能正常处理。
有效rank的条件
- rank不能过小:对于多维度联合的partial Tucker分解,rank需保证ARPACK能找到足够的有效奇异值位移。一般来说,rank取值建议不低于对应维度大小的5%(比如第0维度256,rank至少13左右;第1维度96,rank至少5左右),远低于这个阈值容易触发迭代问题。
- 匹配奇异值分布:先对目标维度的展开矩阵做完整SVD,观察奇异值的衰减情况,选择在奇异值“陡降点”之后的数值作为rank。比如如果前10个奇异值占总能量的99%,那rank设为10左右是合理的,远小于这个数值易导致迭代失败。
- 调整ARPACK参数:如果一定要用很小的rank,可以手动给
partial_tucker传递svd_fun参数,指定使用完整SVD而非部分SVD(比如用tl.svd代替默认的部分SVD);或者通过partial_tucker的svd_kwargs参数,给底层partial_svd传递更大的ncv值,增加ARPACK的候选向量数量。
内容的提问来源于stack exchange,提问作者Kak Milad
相关产品推荐
相关产品推荐

