TensorLy 张量分解

TensorLy 笔记系列

  1. tensorly-01 安装教程
  2. tensorly-02 快速上手
  3. tensorly-03 后端系统
  4. tensorly-04 基本操作
  5. tensorly-05 张量分解
  6. tensorly-06 张量回归

5. Tensor 分解

张量的最大特征之一是可以被紧密地表示为分解形式,并且我们有强大的保证方法来得到这些分解。在本教程中,我们将学习这些分解形式以及如何进行张量分解。关于张量分解的更多信息,请参考1。

5.1. Tensor 的 Kruskal 形式

其思想是将张量表示为一阶张量的和, 也就是向量的外积的和。这种表示可以通过应用典型的Canonical Polyadic 分解(也称为CANDECOMP-PARAFAC、CP或PARAFAC分解)得到。

5.1.1. CANDECOMP-PARAFAC分解

在这里演示如何执行 Canonical Polyadic 分解。一个 rank-r Parafac将一个tensor分解成列-1张量的线性组合(详见1)。
首先,创建一个 swiss 形状是1其余是0的二阶 tensor

>>> import numpy as np
>>> import tensorly as tl
>>> tensor = tl.tensor([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
                        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
                        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
                        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
                        [ 0.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  0.],
                        [ 0.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  0.],
                        [ 0.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  0.],
                        [ 0.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  0.],
                        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
                        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
                        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
                        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])

使用 rank-2 CANDECOMP-PARAFAC(tensorly.decomposition.parafac)将tensor分解成 kruskal tensorParafac分解将tensor表示为kruskal tensor,可以表示为一列因子(矩阵)。因此,parafac函数返回一个因子列表。

>>> from tensorly.decomposition import parafac
>>> factors = parafac(tensor, rank=2)
>>> len(factors)
2
>>> [f.shape for f in factors]
[(12, 2), (12, 2)]

kruskal tensor(以矩阵列表的形式呈现),可以重构一个完整tensor:

>>> print(tl.kruskal_to_tensor(factors))
[[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
 [ 0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  0.]
 [ 0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  0.]
 [ 0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  0.]
 [ 0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]
5.2. Tensor 的 Tucker 形式

Tucker分解可以看作是CP分解的一般化:它将张量分解为一个小核心tensor和因子矩阵。CP可以看作是一个具有超对角核心的tucker分解。因此,一个分解后的Tucker形式的张量只不过是一个与原始张量具有相同阶的核张量和一列投影矩阵,每个投影矩阵对应核张量的不同模式。

5.2.1. Tucker 分解

Tucker(经典和非负)的形式在TensorLy模块tensorly.decomposition.tuckertenorly.decomposition.non_negative_tucker.
使用前文中的tensor,演示tensorrank [2, 3] 分解。

>>> from tensorly.decomposition import tucker
>>> core, factors = tucker(tensor, ranks=[2, 3])
# The core is a smaller tensor of size (2, 3):
>>> core.shape
(2, 3)
>>> len(factors)
2
>>> [f.shape for f in factors]
[(12, 2), (12, 3)]

和上述一样,也可以从Tucker分解中重建完整的tensor

>>> from tensorly import tucker_to_tensor
>>> print(tucker_to_tensor(core, factors)
[[  0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00]
 [ -7.340e-17   2.617e-16   1.914e-16   2.475e-16   1.000e+00   1.000e+00   1.000e+00   1.000e+00   2.475e-16   2.475e-16   2.475e-16   0.000e+00]
 [ -7.340e-17   2.617e-16   1.914e-16   2.475e-16   1.000e+00   1.000e+00   1.000e+00   1.000e+00   2.475e-16   2.475e-16   2.475e-16   0.000e+00]
 [ -7.340e-17   2.617e-16   1.914e-16   2.475e-16   1.000e+00   1.000e+00   1.000e+00   1.000e+00   2.475e-16   2.475e-16   2.475e-16   0.000e+00]
 [  7.746e-17   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   0.000e+00]
 [  7.746e-17   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   0.000e+00]
 [  7.746e-17   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   0.000e+00]
 [  7.746e-17   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   1.000e+00   0.000e+00]
 [ -7.340e-17   2.617e-16   1.914e-16   2.475e-16   1.000e+00   1.000e+00   1.000e+00   1.000e+00   2.475e-16   2.475e-16   2.475e-16   0.000e+00]
 [ -7.340e-17   2.617e-16   1.914e-16   2.475e-16   1.000e+00   1.000e+00   1.000e+00   1.000e+00   2.475e-16   2.475e-16   2.475e-16   0.000e+00]
 [ -7.340e-17   2.617e-16   1.914e-16   2.475e-16   1.000e+00   1.000e+00   1.000e+00   1.000e+00   2.475e-16   2.475e-16   2.475e-16   0.000e+00]
 [  0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00   0.000e+00]]

注意,有些系数几乎为零(10e-16),但由于数值近似,并不完全是零。

5.3. Matrix-Product-State/Tensor-Train分解

Tensor-Train分解,在物理学界又称矩阵积态,是一种将高阶tensor分解为三阶tensor的方法。对于一个d阶张量A[i1,…,id],它将每个维度分成一个3阶子张量,称之为因子或核。子张量的一个维数是真实物理维数,而另外两个维数是连接其前后核心的边数。
A [ i 1 , … , i d ] ≈ ∑ α 1 ⋯ ∑ α d − 1 G 1 ( i 1 , α 1 ) G 2 ( α 1 , i 2 , α 2 ) G 3 ( α 2 , i 3 , α 3 ) ⋯ G d ( α d − 1 , i d ) A[i_1, \ldots, i_d] \approx \sum_{\alpha_1}\cdots\sum_{\alpha_{d-1}}G_1(i_1, \alpha_1)G_2(\alpha_1, i_2, \alpha_2)G_3(\alpha_2, i_3, \alpha_3)\cdots G_d(\alpha_{d-1},i_d) A[i1,,id]α1αd1G1(i1,α1)G2(α1,i2,α2)G3(α2,i3,α3)Gd(αd1,id)
MPS/Tensor-Train分解的优点是存储和计算时间和维度是线性的,使得高维度问题更容易解决。

5.3.1. 实现方式

TensorLy中提供了两种tensor train分解方式:基于SVD的分解(tensorly.decomposition.mps_decomposition) 和 基于交叉逼近的方法(tensorly.contrib.mps_decomposition_cross)。使用上文中的tensor,演示尺寸(12,12) tensorrank [1,2,1]分解过程,第一个核的尺寸是(1,12,2)和第二个核的尺寸是(2,12,1):

>>> from tensorly.decomposition import matrix_product_state
>>> factors = matrix_product_state(tensor, rank=[1,2,1])
>>> len(factors)
2
>>> [f.shape for f in factors]
[(1, 12, 2), (2, 12, 1)]

也可以从 Tensor-Train分解的tensor重建为整个tensor

>>> from tensorly import mps_to_tensor
  >>> print(np.round(mps_to_tensor(factors), decimals=10))
[ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
[ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
[ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
[-0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1. -0.]
[-0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1. -0.]
[-0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1. -0.]
[-0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1. -0.]
[ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
[ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
[ 0.  0.  0.  0.  1.  1.  1.  1.  0.  0.  0.  0.]
[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

对于矩阵情况,MPS/Tensor-Train分解等价于奇异值分解。该矩阵的秩为2,因此可以通过rank-2分解完全恢复。

5.4. 参考资料
  1. T.G.Kolda and B.W.Bader, “Tensor Decompositions and Applications”, SIAM REVIEW, vol. 51, n. 3, pp. 455-500, 2009.
  2. tensorly
  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值