Main Tensor Formats¶
Three of the most popular tensor decompositions are supported in tntorch:
Those formats are all represented using \(N\) tensor cores (one per tensor dimension, used for CP/TT) and, optionally, up to \(N\) factor matrices (needed for Tucker).
In an \(N\)-D tensor of shape \(I_1 \times \dots \times I_N\), each \(n\)-th core can come in four flavors:
- \(R^{\mathrm{TT}}_n \times I_n \times R^{\mathrm{TT}}_{n+1}\): a TT core.
- \(R^{\mathrm{TT}}_n \times S_n^{\mathrm{Tucker}} \times R^{\mathrm{TT}}_{n+1}\): a TT-Tucker core, accompanied by an \(I_n \times S_n^{\mathrm{Tucker}}\) factor matrix.
- \(I_n \times R^{\mathrm{CP}}_n\): a CP core. Conceptually, it works as if it were a 3D TT core of shape \(R^{\mathrm{CP}}_n \times I_n \times R^{\mathrm{CP}}_n\) whose slices along the 2nd mode are all diagonal matrices.
- \(S_n^{\mathrm{Tucker}} \times R^{\mathrm{CP}}_n\): a CP-Tucker core, accompanied by an \(I_n \times S_n^{\mathrm{Tucker}}\) factor matrix. Conceptually, it works as a 3D TT-Tucker core.
One tensor network can combine cores of different kinds. So all in all one may have TT, TT-Tucker, Tucker, CP, TT-CP, CP-Tucker, and TT-CP-Tucker tensors. We will show examples of all.
(see `this notebook <decompositions.ipynb>`__ to decompose full tensors into those main formats)
(see `this notebook <other_formats.ipynb>`__ for other structured and custom decompositions)
TT¶
Tensor train cores are represented in parentheses ( )
:
[1]:
import tntorch as tn
tn.rand([32]*5, ranks_tt=5)
[1]:
5D TT tensor:
32 32 32 32 32
| | | | |
(0) (1) (2) (3) (4)
/ \ / \ / \ / \ / \
1 5 5 5 5 1
TT-Tucker¶
In this format, TT cores are compressed along their spatial dimension (2nd mode) using an accompanying Tucker factor. This was considered e.g. in the original TT paper.
[2]:
tn.rand([32]*5, ranks_tt=5, ranks_tucker=6)
[2]:
5D TT-Tucker tensor:
32 32 32 32 32
| | | | |
6 6 6 6 6
(0) (1) (2) (3) (4)
/ \ / \ / \ / \ / \
1 5 5 5 5 1
Here is an example where only some cores have Tucker factors:
[3]:
tn.rand([32]*5, ranks_tt=5, ranks_tucker=[None, 6, None, None, 7])
[3]:
5D TT-Tucker tensor:
32 32
32 | 32 32 |
| 6 | | 7
(0) (1) (2) (3) (4)
/ \ / \ / \ / \ / \
1 5 5 5 5 1
Note: if you want to leave some factors fixed during gradient descent, simply set them to some PyTorch tensor that has requires_grad=False.
Tucker¶
“Pure” Tucker is technically speaking not supported, but is equivalent to a TT-Tucker tensor with full TT-ranks. The minimal necessary ranks are automatically computed and set up for you:
[4]:
tn.rand([32]*5, ranks_tucker=3) # Actually a TT-Tucker network, but just as expressive as a pure Tucker decomposition
[4]:
5D TT-Tucker tensor:
32 32 32 32 32
| | | | |
3 3 3 3 3
(0) (1) (2) (3) (4)
/ \ / \ / \ / \ / \
1 3 9 9 3 1
In other words, all \(32^5\) tensors of Tucker rank \(3\) can be represented by a tensor that has the shape shown above, and vice versa.
CP¶
CP factors are shown as cores in brackets < >
:
[5]:
tn.rand([32]*5, ranks_cp=4)
[5]:
5D CP tensor:
32 32 32 32 32
| | | | |
<0> <1> <2> <3> <4>
/ \ / \ / \ / \ / \
4 4 4 4 4 4
Even though those factors work conceptually as 3D cores in a tensor train (every CP tensor is a particular case of the TT format), they are stored in 2D as in a standard CP decomposition. In this case all cores have shape \(32 \times 4\).
TT-CP¶
TT and CP cores can be combined by specifying lists of ranks for each format. You should provide \(N-1\) TT ranks and \(N\) CP ranks and use None
so that they do not collide anywhere. Also note that consecutive CP ranks must coincide. Here is a tensor with 3 TT cores and 2 CP cores:
[6]:
tn.rand([32]*5, ranks_tt=[2, 3, None, None], ranks_cp=[None, None, None, 4, 4])
[6]:
5D TT-CP tensor:
32 32 32 32 32
| | | | |
(0) (1) (2) <3> <4>
/ \ / \ / \ / \ / \
1 2 3 4 4 4
Here is another example with 2 TT cores and 3 CP cores:
[7]:
tn.rand([32]*5, ranks_tt=[None, 2, None, None], ranks_cp=[4, None, None, 5, 5])
[7]:
5D TT-CP tensor:
32 32 32 32 32
| | | | |
<0> (1) (2) <3> <4>
/ \ / \ / \ / \ / \
4 4 2 5 5 5
CP-Tucker¶
Similarly to TT-Tucker, this model restricts the columns along CP factors to live in a low-dimensional subspace. It is also known as a canonical decomposition with linear constraints (*CANDELINC*). Compressing a Tucker core via CP leads to an equivalent format.
[8]:
tn.rand([32]*5, ranks_cp=2, ranks_tucker=4)
[8]:
5D CP-Tucker tensor:
32 32 32 32 32
| | | | |
4 4 4 4 4
<0> <1> <2> <3> <4>
/ \ / \ / \ / \ / \
2 2 2 2 2 2
TT-CP-Tucker¶
Finally, we can combine all sorts of cores to get a hybrid of all 3 models:
[9]:
tn.rand([32]*5, ranks_tt=[2, 3, None, None], ranks_cp=[None, None, None, 10, 10], ranks_tucker=[5, None, 5, 5, None])
[9]:
5D TT-CP-Tucker tensor:
32 32 32
| 32 | | 32
5 | 5 5 |
(0) (1) (2) <3> <4>
/ \ / \ / \ / \ / \
1 2 3 10 10 10