dense_tucker_svd#
- t3toolbox.backend.t3_svd.dense_tucker_svd(T, min_ranks=None, max_ranks=None, rtol=None, atol=None)#
def dense_tucker_svd( T: common.NDArray, # shape=(N1, N2, .., Nd) min_ranks: typ.Sequence[int] = None, # len=d max_ranks: typ.Sequence[int] = None, # len=d rtol: float = None, atol: float = None, ) -> typ.Tuple[ typ.Tuple[ typ.Tuple[common.NDArray,...], # Tucker bases, ith_elm_shape=(ni, Ni) common.NDArray, # Tucker core, shape=(n1,n2,...,nd) ], typ.Tuple[common.NDArray,...], # singular values of matricizations ]:
Compute Tucker decomposition and matricization singular values for dense tensor.
- Parameters:
T (NDArray) – The dense tensor. shape=(N1, …, Nd)
min_ranks (typ.Sequence[int]) – Minimum Tucker ranks for truncation. len=d
max_ranks (typ.Sequence[int]) – Maximum Tucker ranks for truncation. len=d
rtol (float) – Relative tolerance for truncation.
atol (float) – Absolute tolerance for truncation.
xnp – Linear algebra backend. Default: np (numpy)
- Returns:
typ.Tuple[typ.Tuple[NDArray,…],NDArray] – Tucker decomposition (tucker_bases, tucker_core). tucker_bases[ii].shape=(ni,Ni). tucker_core.shape=(n1,…,nd)
typ.Tuple[NDArray,…] – Singular values of matricizations
- Return type:
t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.typ.Tuple[t3toolbox.backend.common.typ.Tuple[NDArray, Ellipsis], NDArray], t3toolbox.backend.common.typ.Tuple[NDArray, Ellipsis]]
See also
truncated_svd,tt_svd_dense,t3_svd_dense,t3_svdExamples
No truncation – a lossless Tucker decomposition. The factors reconstruct
T, andbases[ii].shape = (ni, Ni)(the small ranknifirst), one singular-value vector per mode:>>> import numpy as np >>> import t3toolbox.backend.t3_svd as t3_svd >>> np.random.seed(0) >>> T = np.random.randn(5, 6, 7) >>> (bases, core), ss = t3_svd.dense_tucker_svd(T) >>> print(core.shape, [B.shape for B in bases]) (5, 6, 7) [(5, 5), (6, 6), (7, 7)] >>> T2 = np.einsum('abc,ai,bj,ck->ijk', core, bases[0], bases[1], bases[2]) >>> print(np.allclose(T, T2)) # exact reconstruction True
The mode-
isingular values ARE the singular values of the mode-imatricization (shown for mode 0; the other modes are analogous):>>> import numpy as np >>> import t3toolbox.backend.t3_svd as t3_svd >>> np.random.seed(0) >>> T = np.random.randn(5, 6, 7) >>> _, ss = t3_svd.dense_tucker_svd(T) >>> dense_svals = np.linalg.svd(T.reshape(5, 6 * 7), compute_uv=False) # mode-0 matricization >>> print(np.allclose(ss[0], dense_svals[:len(ss[0])])) True
Truncation – a smooth tensor has gradually decaying matricization spectra, so
rtoltruncates meaningfully (a sharp random spectrum would not):>>> import numpy as np >>> import t3toolbox.backend.t3_svd as t3_svd >>> i, j, k = np.ogrid[1:9, 1:9, 1:9] >>> T = 1.0 / (i + j + k) # graded-spectrum tensor >>> (bases_f, _), ss_full = t3_svd.dense_tucker_svd(T) # full (untruncated) spectra >>> (bases, core), _ = t3_svd.dense_tucker_svd(T, rtol=1e-3) # truncate at rtol >>> print(tuple(B.shape[0] for B in bases_f), '->', tuple(B.shape[0] for B in bases)) (8, 8, 8) -> (3, 3, 3) >>> T2 = np.einsum('abc,ai,bj,ck->ijk', core, bases[0], bases[1], bases[2]) >>> ranks = tuple(B.shape[0] for B in bases) >>> dropped_sq = sum(float(np.sum(s[r:]**2)) for s, r in zip(ss_full, ranks)) >>> print(bool(np.linalg.norm(T - T2) <= np.sqrt(dropped_sq))) # accuracy bound [Oseledets] True