pyttb.ktensor
Classes and functions for working with Kruskal tensors.
- class pyttb.ktensor.ktensor(factor_matrices: Sequence[ndarray] | None = None, weights: ndarray | None = None, copy: bool = True)[source]
Bases:
object
KTENSOR Class for Kruskal tensors (decomposed).
Contains the following data members:
weights
:numpy.ndarray
vector containing the weights of the rank-1 tensors defined by the outer products of the column vectors of the factor_matrices.factor_matrices
:list
ofnumpy.ndarray
. The length of the list is equal to the number of dimensions of the tensor. The shape of the ith element of the list is (n_i, r), where n_i is the length dimension i and r is the rank of the tensor (as well as the length of the weights vector).Instances of
pyttb.ktensor
can be created using __init__() or one of the following methods:Examples
For all examples listed below, the following module imports are assumed:
>>> import pyttb as ttb >>> import numpy as np
Create a
pyttb.ktensor
.- Created in one of the following ways:
With no inputs (or weights and factor_matrices both None), return an empty
pyttb.ktensor
.Otherwise, return a
pyttb.ktensor
with weights and factor_matrices as provided.
- Parameters:
factor_matrices – Factors for ktensor.
weights – Tensor weights, defaults to all 1’s.
copy – Whether or not to copy the input data or just reference it.
Examples
Create an empty
pyttb.ktensor
:>>> K = ttb.ktensor() >>> print(K) ktensor of shape () with order F weights=[] factor_matrices=[]
Create a
pyttb.ktensor
from weights and a list of factor matrices:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> K = ttb.ktensor([fm0, fm1], weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
Create a
pyttb.ktensor
from alist
of factor matrices (without providing weights):>>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> factor_matrices = [fm0, fm1] >>> K = ttb.ktensor([fm0, fm1]) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 1.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
- classmethod from_function(function_handle: Callable[[Tuple[int, ...]], ndarray], shape: int | Iterable[int], num_components: int)[source]
Construct a
pyttb.ktensor
.Factor matrix entries are set using a function. The weights of the returned
pyttb.ktensor
will all be equal to 1.- Parameters:
function_handle – A function that can accept a shape (i.e.,
tuple
of dimension sizes) and return anumpy.ndarray
of that shape. Example functions include numpy.random.random_sample, numpy.zeros, numpy.ones.shape – Shape of the resulting tensor.
num_components – Number of components/weights for resulting tensor.
- Returns:
Constructed ktensor.
Examples
Create a
pyttb.ktensor
with entries of the factor matrices taken from a uniform random distribution:>>> np.random.seed(1) >>> K = ttb.ktensor.from_function(np.random.random_sample, (2, 3, 4), 2) >>> print(K) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[4.1702...e-01 7.2032...e-01] [1.1437...e-04 3.0233...e-01]] factor_matrices[1] = [[0.1467... 0.0923...] [0.1862... 0.3455...] [0.3967... 0.5388...]] factor_matrices[2] = [[0.4191... 0.6852...] [0.2044... 0.8781...] [0.0273... 0.6704...] [0.4173... 0.5586...]]
Create a
pyttb.ktensor
with entries equal to 1:>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> print(K) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[1. 1.] [1. 1.]] factor_matrices[1] = [[1. 1.] [1. 1.] [1. 1.]] factor_matrices[2] = [[1. 1.] [1. 1.] [1. 1.] [1. 1.]]
Create a
pyttb.ktensor
with entries equal to 0:>>> K = ttb.ktensor.from_function(np.zeros, (2, 3, 4), 2) >>> print(K) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[0. 0.] [0. 0.]] factor_matrices[1] = [[0. 0.] [0. 0.] [0. 0.]] factor_matrices[2] = [[0. 0.] [0. 0.] [0. 0.] [0. 0.]]
- classmethod from_vector(data: ndarray, shape: int | Iterable[int], contains_weights: bool)[source]
Construct a
pyttb.ktensor
from a vector and shape.The rank of the
pyttb.ktensor
is inferred from the shape and length of the vector.- Parameters:
data – Vector containing either elements of the factor matrices or elements of the weights and factor matrices. When both the elements of the weights and the factor_matrices are present, the weights come first and the columns of the factor matrices come next.
shape – Shape of the resulting ktensor.
contains_weights – Flag to specify if data contains weights. If False, all weights are set to 1.
- Returns:
Constructed ktensor.
Examples
Create a
pyttb.ktensor
from a vector containing only elements of the factor matrices:>>> rank = 2 >>> shape = (2, 3, 4) >>> data = np.arange(1, rank * sum(shape) + 1).astype(float) >>> K = ttb.ktensor.from_vector(data[:], shape, False) >>> print(K) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[1. 3.] [2. 4.]] factor_matrices[1] = [[ 5. 8.] [ 6. 9.] [ 7. 10.]] factor_matrices[2] = [[11. 15.] [12. 16.] [13. 17.] [14. 18.]]
Create a
pyttb.ktensor
from a vector containing elements of both the weights and the factor matrices:>>> weights = 2 * np.ones(rank).astype(float) >>> weights_and_data = np.concatenate((weights, data), axis=0) >>> K = ttb.ktensor.from_vector(weights_and_data[:], shape, True) >>> print(K) ktensor of shape (2, 3, 4) with order F weights=[2. 2.] factor_matrices[0] = [[1. 3.] [2. 4.]] factor_matrices[1] = [[ 5. 8.] [ 6. 9.] [ 7. 10.]] factor_matrices[2] = [[11. 15.] [12. 16.] [13. 17.] [14. 18.]]
- property order: Literal['F']
Return the data layout of the underlying storage.
- arrange(weight_factor: int | None = None, permutation: Tuple | List | ndarray | None = None)[source]
Arrange the rank-1 components of a
pyttb.ktensor
in place.If permutation is passed, the columns of self.factor_matrices are arranged using the provided permutation, so you must make a copy before calling this method if you want to store the original
pyttb.ktensor
. If weight_factor is passed, then the values in self.weights are absorbed into self.factor_matrices[weight_factor]. If no parameters are passed, then the columns of self.factor_matrices are normalized and then permuted such that the resulting self.weights are sorted by magnitude, greatest to least. Passing both parameters leads to an error.- Parameters:
weight_factor – Index of the factor matrix the weights will be absorbed into.
permutation – The new order of the components of the
pyttb.ktensor
into which to permute. The permutation must be of length equal to the number of components of thepyttb.ktensor
, self.ncomponents and must be a permutation of [0,…,`self.ncomponents`-1].
Examples
Create the initial
pyttb.ktensor
:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> K = ttb.ktensor([fm0, fm1], weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
Arrange the columns of the factor matrices using a permutation:
>>> p = [1, 0] >>> K.arrange(permutation=p) >>> print(K) ktensor of shape (2, 2) with order F weights=[2. 1.] factor_matrices[0] = [[2. 1.] [4. 3.]] factor_matrices[1] = [[6. 5.] [8. 7.]]
Normalize and permute columns such that weights are sorted in decreasing order:
>>> K.arrange() >>> print(K) ktensor of shape (2, 2) with order F weights=[89.4427... 27.2029...] factor_matrices[0] = [[0.4472... 0.3162...] [0.8944... 0.9486...]] factor_matrices[1] = [[0.6... 0.5812...] [0.8... 0.8137...]]
Absorb the weights into the second factor:
>>> K.arrange(weight_factor=1) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 1.] factor_matrices[0] = [[0.4472... 0.3162...] [0.8944... 0.9486...]] factor_matrices[1] = [[53.6656... 15.8113...] [71.5541... 22.1359...]]
- copy() ktensor [source]
Make a deep copy of a
pyttb.ktensor
.- Returns:
Copy of original ktensor.
Examples
Create a random
pyttb.ktensor
with weights of 1:>>> np.random.seed(1) >>> K = ttb.ktensor.from_function(np.random.random_sample, (2, 3, 4), 2) >>> print(K) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[4.1702...e-01 7.2032...e-01] [1.1437...e-04 3.0233...e-01]] factor_matrices[1] = [[0.1467... 0.0923...] [0.1862... 0.3455...] [0.3967... 0.5388...]] factor_matrices[2] = [[0.4191... 0.6852...] [0.2044... 0.8781...] [0.0273... 0.6704...] [0.4173... 0.5586...]]
Create a copy of the
pyttb.ktensor
and change the weights:>>> K2 = K.copy() >>> K2.weights = np.array([2.0, 3.0]) >>> print(K2) ktensor of shape (2, 3, 4) with order F weights=[2. 3.] factor_matrices[0] = [[4.1702...e-01 7.2032...e-01] [1.1437...e-04 3.023...e-01]] factor_matrices[1] = [[0.1467... 0.0923...] [0.1862... 0.3455...] [0.3967... 0.5388...]] factor_matrices[2] = [[0.4191... 0.6852...] [0.2044... 0.8781...] [0.0273... 0.6704...] [0.4173... 0.5586...]]
Show that the original
pyttb.ktensor
is unchanged:>>> print(K) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[4.1702...e-01 7.2032...e-01] [1.1437...e-04 3.0233...e-01]] factor_matrices[1] = [[0.1467... 0.0923...] [0.1862... 0.3455...] [0.3967... 0.5388...]] factor_matrices[2] = [[0.4191... 0.6852...] [0.2044... 0.8781...] [0.0273... 0.6704...] [0.4173... 0.5586...]]
- double() ndarray [source]
Convert
pyttb.ktensor
tonumpy.ndarray
.- Returns:
Array of re-assembled ktensor.
Examples
>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> factor_matrices = [fm0, fm1] >>> K = ttb.ktensor(factor_matrices, weights) >>> K.double() array([[29., 39.], [63., 85.]]) >>> type(K.double()) <class 'numpy.ndarray'>
- extract(idx: int | tuple | list | ndarray | None = None) ktensor [source]
Create a new
pyttb.ktensor
with only the specified components.- Parameters:
idx – Index set of components to extract. It should be the case that idx is a subset of [0,…,`self.ncomponents`]. If this parameter is None or is empty, a copy of the
pyttb.ktensor
is returned.- Returns:
Subset of original ktensor.
Examples
Create a
pyttb.ktensor
:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> K = ttb.ktensor([fm0, fm1], weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
Create a new
pyttb.ktensor
, extracting only the second component from each factor of the originalpyttb.ktensor
:>>> K.extract([1]) ktensor of shape (2, 2) with order F weights=[2.] factor_matrices[0] = [[2.] [4.]] factor_matrices[1] = [[6.] [8.]]
- fixsigns(other: ktensor | None = None) ktensor [source]
Change the elements of a
pyttb.ktensor
in place.Update so that the largest magnitude entries for each column vector in each factor matrix are positive, provided that the sign on pairs of vectors in a rank-1 component can be flipped.
- Parameters:
other – If not None, returns a version of the
pyttb.ktensor
where some of the signs of the columns of the factor matrices have been flipped to better align with other. In not None, bothpyttb.ktensor
objects are first normalized (usingnormalize()
).- Returns:
Self for chained operations.
Examples
Create a
pyttb.ktensor
with negative large magnitude entries:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> K = ttb.ktensor([fm0, fm1], weights) >>> K.factor_matrices[0][1, 1] = -K.factor_matrices[0][1, 1] >>> K.factor_matrices[1][1, 1] = -K.factor_matrices[1][1, 1] >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[ 1. 2.] [ 3. -4.]] factor_matrices[1] = [[ 5. 6.] [ 7. -8.]]
Fix the signs of the largest magnitude entries:
>>> print(K.fixsigns()) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[ 1. -2.] [ 3. 4.]] factor_matrices[1] = [[ 5. -6.] [ 7. 8.]]
Fix the signs using another
pyttb.ktensor
:>>> K = ttb.ktensor([fm0, fm1], weights) >>> K2 = K.copy() >>> K2.factor_matrices[0][1, 1] = -K2.factor_matrices[0][1, 1] >>> K2.factor_matrices[1][1, 1] = -K2.factor_matrices[1][1, 1] >>> K = K.fixsigns(K2) >>> print(K) ktensor of shape (2, 2) with order F weights=[27.2029... 89.4427...] factor_matrices[0] = [[ 0.3162... -0.4472...] [ 0.9486... -0.8944...]] factor_matrices[1] = [[ 0.5812... -0.6...] [ 0.8137... -0.8...]]
- full() tensor [source]
Convert a
pyttb.ktensor
to apyttb.tensor
.- Returns:
Re-assembled dense tensor.
Examples
>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> K = ttb.ktensor([fm0, fm1], weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]] >>> print(K.full()) tensor of shape (2, 2) with order F data[:, :] = [[29. 39.] [63. 85.]]
- to_tenmat(rdims: ndarray | None = None, cdims: ndarray | None = None, cdims_cyclic: Literal['fc'] | Literal['bc'] | Literal['t'] | None = None, copy: bool = True) tenmat [source]
Construct a
pyttb.tenmat
from apyttb.ktensor
.- Parameters:
rdims – Mapping of row indices.
cdims – Mapping of column indices.
cdims_cyclic –
- When only rdims is specified maps a single rdim to the rows and
the remaining dimensions span the columns. _fc_ (forward cyclic) in the order range(rdims,self.ndims()) followed by range(0, rdims). _bc_ (backward cyclic) range(rdims-1, -1, -1) then range(self.ndims(), rdims, -1).
copy – Whether to make a copy of provided data or just reference it.
Notes
- Forward cyclic is defined by Kiers [1] and backward cyclic is defined by
De Lathauwer, De Moor, and Vandewalle [2].
References
Examples
>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> K = ttb.ktensor([fm0, fm1], weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]] >>> K.full() tensor of shape (2, 2) with order F data[:, :] = [[29. 39.] [63. 85.]] >>> K.to_tenmat(np.array([0])) matrix corresponding to a tensor of shape (2, 2) with order F rindices = [ 0 ] (modes of tensor corresponding to rows) cindices = [ 1 ] (modes of tensor corresponding to columns) data[:, :] = [[29. 39.] [63. 85.]]
- innerprod(other: tensor | sptensor | ktensor | ttensor) float [source]
Efficient inner product with a
pyttb.ktensor
.- Efficiently computes the inner product between two tensors, self
and other. If other is a
pyttb.ktensor
, the inner product is computed using inner products of the factor matrices. Otherwise, the inner product is computed using the ttv (tensor times vector) of other with all of the columns of self.factor_matrices.
- Parameters:
other – Tensor with which to compute the inner product.
- Returns:
Innerproduct value.
Examples
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> print(K.innerprod(K)) 96.0
- isequal(other: ktensor) bool [source]
Equal comparator for
pyttb.ktensor
objects.- Parameters:
other –
pyttb.ktensor
with which to compare.
Examples
>>> K1 = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> weights = np.ones((2,)) >>> factor_matrices = [np.ones((2, 2)), np.ones((3, 2)), np.ones((4, 2))] >>> K2 = ttb.ktensor(factor_matrices, weights) >>> print(K1.isequal(K2)) True
- issymmetric(return_diffs: Literal[False]) bool [source]
- issymmetric(return_diffs: Literal[True]) Tuple[bool, ndarray]
Return True if
pyttb.ktensor
is symmetric for every permutation.- Parameters:
return_diffs – If True, returns the matrix of the norm of the differences between the factor matrices.
- Returns:
Answer and optionally matrix of the norm of the differences between the factor matrices
Examples
Create a
pyttb.ktensor
that is symmetric and test if it is symmetric:>>> K = ttb.ktensor.from_function(np.ones, (3, 3, 3), 2) >>> print(K.issymmetric()) True
Create a
pyttb.ktensor
that is not symmetric and return the differences:>>> weights = np.array([1., 2.]) >>> fm0 = np.array([[1., 2.], [3., 4.]]) >>> fm1 = np.array([[5., 6.], [7., 8.]]) >>> K2 = ttb.ktensor([fm0, fm1], weights) >>> issym, diffs = K2.issymmetric(return_diffs=True) >>> print(diffs) [[0. 8.] [0. 0.]]
- mask(W: tensor | sptensor) ndarray [source]
Extract
pyttb.ktensor
values as specified by W.W is a
pyttb.tensor
orpyttb.sptensor
containing only values of zeros (0) and ones (1). The values in thepyttb.ktensor
corresponding to the indices for the ones (1) in W will be returned as a column vector.- Parameters:
W – Mask tensor to apply to ktensor.
- Returns:
Extracted values in a column vector (array).
Examples
Create a
pyttb.ktensor
:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> K = ttb.ktensor([fm0, fm1], weights)
Create a mask
pyttb.tensor
and extract the elements of thepyttb.ktensor
using the mask:>>> W = ttb.tensor(np.array([[0, 1], [1, 0]])) >>> print(K.mask(W)) [[63.] [39.]]
- mttkrp(U: ktensor | Sequence[ndarray], n: int | integer) ndarray [source]
Matricized tensor times Khatri-Rao product for
pyttb.ktensor
.Efficiently calculates the matrix product of the n-mode matricization of the ktensor with the Khatri-Rao product of all entries in U, a
list
of factor matrices, except the nth.- Parameters:
U – Factor matrices.
n – Multiply by all modes except n.
- Returns:
Computed result.
Examples
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> U = [np.ones((2, 2)), np.ones((3, 2)), np.ones(((4, 2)))] >>> print(K.mttkrp(U, 0)) [[24. 24.] [24. 24.]]
- property ncomponents: int
Number of columns in each factor matrix for the
pyttb.ktensor
.Examples
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> print(K.ncomponents) 2
- property ndims: int
Number of dimensions of the
pyttb.ktensor
.Examples
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> print(K.ndims) 3
- norm() float [source]
Compute the norm of a
pyttb.ktensor
.Frobenius norm, or square root of the sum of squares of entries.
Examples
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> K.norm() 9.79795897...
- normalize(weight_factor: int | Literal['all'] | None = None, sort: bool | None = False, normtype: float = 2, mode: int | None = None) ktensor [source]
Normalize the columns of the factor matrices in place.
Optionally absorb the weights into desired normalized factors.
- Parameters:
weight_factor – Absorb the weights into one or more factors. If “all”, absorb weight equally across all factors. If int, absorb weight into a single dimension (value must be in range(self.ndims)).
sort – Sort the columns in descending order of the weights.
normtype – Order of the norm (see
numpy.linalg.norm()
for possible values).mode – Index of factor matrix to normalize. A value of None means normalize all factor matrices.
- Returns:
Self for chained operations.
Examples
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> print(K.normalize()) ktensor of shape (2, 3, 4) with order F weights=[4.898... 4.898...] factor_matrices[0] = [[0.7071... 0.7071...] [0.7071... 0.7071...]] factor_matrices[1] = [[0.5773... 0.5773...] [0.5773... 0.5773...] [0.5773... 0.5773...]] factor_matrices[2] = [[0.5 0.5] [0.5 0.5] [0.5 0.5] [0.5 0.5]]
- nvecs(n: int, r: int, flipsign: bool = True) ndarray [source]
Compute the leading mode-n vectors of the ktensor.
Computes the r leading eigenvectors of Xn*Xn.T (where Xn is the mode-n matricization/unfolding of self), which provides information about the mode-n fibers. In two-dimensions, the r leading mode-1 vectors are the same as the r left singular vectors and the r leading mode-2 vectors are the same as the r right singular vectors. By default, this method computes the top r eigenvectors of Xn*Xn.T.
- Parameters:
n – Mode for tensor matricization.
r – Number of eigenvectors to compute and use.
flipsign – If True, make each column’s largest element positive.
- Returns:
Computed eigenvectors.
Examples
Compute single eigenvector for dimension 0:
>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2) >>> nvecs1 = K.nvecs(0, 1) >>> print(nvecs1) [[0.70710678...] [0.70710678...]]
Compute first 2 leading eigenvectors for dimension 0:
>>> nvecs2 = K.nvecs(0, 2) >>> print(nvecs2) [[ 0.70710678... 0.70710678...] [ 0.70710678... -0.70710678...]]
- permute(order: int | float | Iterable[int] | Iterable[float] | ndarray) ktensor [source]
Permute
pyttb.ktensor
dimensions.Rearranges the dimensions of a
pyttb.ktensor
so that they are in the order specified by order. The corresponding ktensor has the same components as self but the order of the subscripts needed to access any particular element is rearranged as specified by order.- Parameters:
order – Permutation of [0,…,self.ndimensions].
- Returns:
Permuted
pyttb.ktensor
.
Examples
>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> factor_matrices = [fm0, fm1] >>> K = ttb.ktensor(factor_matrices, weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
Permute the order of the dimension so they are in reverse order:
>>> K1 = K.permute(np.array([1, 0])) >>> print(K1) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[5. 6.] [7. 8.]] factor_matrices[1] = [[1. 2.] [3. 4.]]
- redistribute(mode: int) ktensor [source]
Distribute weights of a
pyttb.ktensor
to the specified mode.The redistribution is performed in place.
- Parameters:
mode – Must be value in [0,…self.ndims].
- Returns:
Self for chained operations.
Example
Create a
pyttb.ktensor
:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> factor_matrices = [fm0, fm1] >>> K = ttb.ktensor(factor_matrices, weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
Distribute weights of that
pyttb.ktensor
to mode 0:>>> K.redistribute(0) ktensor of shape (2, 2) with order F weights=[1. 1.] factor_matrices[0] = [[1. 4.] [3. 8.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
- property shape: Tuple[int, ...]
Shape of a
pyttb.ktensor
.Returns the lengths of all dimensions of the
pyttb.ktensor
.
- score(other: ktensor, weight_penalty: bool = True, threshold: float | None = None, greedy: bool = True) Tuple[float, ktensor, bool, ndarray] [source]
Check if two
pyttb.ktensor
with the same shape match.Matching is defined as follows. If self and other are single- component
pyttb.ktensor
instances that have been normalized so that their weights are self.weights and other.weights, and their factor matrices are single column vectors containing [a1,a2,…,an] and [b1,b2,…bn], rescpetively, then the score is defined asscore = penalty * (a1.T*b1) * (a2.T*b2) * … * (an.T*bn),
where the penalty is defined by the weights such that
max_weights = max(self.weights, other.weights)
penalty = 1 - abs(self.weights - other.weights) / max_weights.
The score of multi-component
pyttb.ktensor
instances is a normalized sum of the scores across the best permutation of the components of self. self can have more components than other; any extra components are ignored in terms of the matching score.- Parameters:
other –
pyttb.ktensor
with which to match.weight_penalty – Flag indicating whether or not to consider the weights in the calculations.
threshold – Threshold specified in the formula above for determining a match. (defaults to: 0.99**self.ndims)
greedy – Flag indicating whether or not to consider all possible matchings (exponentially expensive) or just do a greedy matching.
- Returns:
Score – Between 0 and 1.
Copy of self – Which has been normalized and permuted to best match other.
Flag – Indicating a match according to a user-specified threshold.
Permutation – (i.e. array of indices of the modes of self) of the components of self that was used to best match other.
Examples
Create two
pyttb.ktensor
instances and compute the score between them:>>> factors = [np.ones((3, 3)), np.ones((4, 3)), np.ones((5, 3))] >>> weights = np.array([2.0, 1.0, 3.0]) >>> K = ttb.ktensor(factors, weights) >>> factors_2 = [np.ones((3, 2)), np.ones((4, 2)), np.ones((5, 2))] >>> weights_2 = np.array([2.0, 4.0]) >>> K2 = ttb.ktensor(factors_2, weights_2) >>> score, Kperm, flag, perm = K.score(K2) >>> print(score) 0.875 >>> print(perm) [0 2 1]
Compute score without using weights:
>>> score, Kperm, flag, perm = K.score(K2, weight_penalty=False) >>> print(score) 1.0 >>> print(perm) [0 1 2]
- symmetrize() ktensor [source]
Symmetrize a
pyttb.ktensor
in all modes.Symmetrize a
pyttb.ktensor
with respect to all modes so that the resultingpyttb.ktensor
is symmetric with respect to any permutation of indices.- Returns:
Examples
Create a
pyttb.ktensor
:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> factor_matrices = [fm0, fm1] >>> K = ttb.ktensor(factor_matrices, weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
Make the factor matrices of the
pyttb.ktensor
symmetric with respect to any permutation of the factor matrices:>>> K1 = K.symmetrize() >>> print(K1) ktensor of shape (2, 2) with order F weights=[1. 1.] factor_matrices[0] = [[2.3404... 4.9519...] [4.5960... 8.0124...]] factor_matrices[1] = [[2.3404... 4.9519...] [4.5960... 8.0124...]]
- tolist(mode: int | None = None) List[ndarray] [source]
Convert
pyttb.ktensor
to a list of factor matrices.Eevenly distributes the weights across factors. Optionally absorb the weights into a single mode.
- Parameters:
mode – Index of factor matrix to absorb all of the weights.
- Returns:
Distributed factor matrices.
Examples
Create a
pyttb.ktensor
of all ones:>>> weights = np.array([1.0, 2.0]) >>> fm0 = np.array([[1.0, 2.0], [3.0, 4.0]]) >>> fm1 = np.array([[5.0, 6.0], [7.0, 8.0]]) >>> factor_matrices = [fm0, fm1] >>> K = ttb.ktensor(factor_matrices, weights) >>> print(K) ktensor of shape (2, 2) with order F weights=[1. 2.] factor_matrices[0] = [[1. 2.] [3. 4.]] factor_matrices[1] = [[5. 6.] [7. 8.]]
Spread weights equally to all factors and return list of factor matrices:
>>> fm_list = K.tolist() >>> for fm in fm_list: ... print(fm) [[1. 2.8284...] [3. 5.6568...]] [[ 5. 8.4852...] [ 7. 11.313...]]
Shift weight to single factor matrix and return list of factor matrices:
>>> fm_list = K.tolist(0) >>> for fm in fm_list: ... print(fm) [[ 8.6023... 40. ] [25.8069... 80. ]] [[0.5812... 0.6...] [0.8137... 0.8...]]
- tovec(include_weights: bool = True) ndarray [source]
Convert
pyttb.ktensor
to column vector.Optionally include or exclude the weights. The output of this method can be consumed by
from_vector()
.- Parameters:
include_weights – Flag to specify whether or not to include weights in output.
- Returns:
The length of the column vector is (sum(self.shape)+1)*self.ncomponents. The vector contains the weights (if requested) stacked on top of each of the columns of the factor_matrices in order.
Examples
Create a
pyttb.ktensor
from a vector:>>> rank = 2 >>> shape = (2, 3, 4) >>> data = np.arange(1, rank*sum(shape)+1) >>> weights = 2 * np.ones(rank) >>> weights_and_data = np.concatenate((weights, data), axis=0) >>> K = ttb.ktensor.from_vector(weights_and_data[:], shape, True) >>> print(K) ktensor of shape (2, 3, 4) with order F weights=[2. 2.] factor_matrices[0] = [[1. 3.] [2. 4.]] factor_matrices[1] = [[ 5. 8.] [ 6. 9.] [ 7. 10.]] factor_matrices[2] = [[11. 15.] [12. 16.] [13. 17.] [14. 18.]]
Create a
pyttb.ktensor
from a vector of data extracted from anotherpyttb.ktensor
:>>> K2 = ttb.ktensor.from_vector(K.tovec(), shape, True) >>> print(K2) ktensor of shape (2, 3, 4) with order F weights=[2. 2.] factor_matrices[0] = [[1. 3.] [2. 4.]] factor_matrices[1] = [[ 5. 8.] [ 6. 9.] [ 7. 10.]] factor_matrices[2] = [[11. 15.] [12. 16.] [13. 17.] [14. 18.]]
- ttv(vector: Sequence[ndarray] | ndarray, dims: int | float | Iterable[int] | Iterable[float] | ndarray | None = None, exclude_dims: int | float | Iterable[int] | Iterable[float] | ndarray | None = None) float | ktensor [source]
Tensor times vector for a
pyttb.ktensor
.Computes the product of a
pyttb.ktensor
with a vector (i.e., np.array). If dims is an integer, it specifies the dimension in thepyttb.ktensor
along which the vector is multiplied. If the shape of the vector is = (I,), then the length of dimension dims of thepyttb.ktensor
must be I. Note that the number of dimensions of the returnedpyttb.ktensor
is 1 less than the dimension of thepyttb.ktensor
used in the multiplication because dimension dims is removed.If vector is a
list
of np.array instances, thepyttb.ktensor
is multiplied with each vector in the list. The products are computed sequentially along all dimensions (or modes) of thepyttb.ktensor
, and thus the list must contain self.ndims vectors.When dims is not None, compute the products along the dimensions specified by dims. In this case, the number of products can be less than self.ndims and the order of the sequence does not need to match the order of the dimensions in the
pyttb.ktensor
. Note that the number of vectors must match the number of dimensions provided, and the length of each vector must match the size of each dimension of thepyttb.ktensor
specified in dims.- Parameters:
vector – Vector to multiply by.
dims –
- Dimension(s) along which to multiply.
Exclusively provide dims or exclude_dims.
exclude_dims –
- Multiply by all but excluded dimension(s).
Exclusively provide dims or exclude_dims.
- Returns:
float or
pyttb.ktensor
– The number of dimensions of the returnedpyttb.ktensor
is n-k, where n = self.ndims and k = number of vectors provided as input. If k == n, a scalar is returned.
Examples
Compute the product of a
pyttb.ktensor
and a single vector (results in apyttb.ktensor
):>>> rank = 2 >>> shape = (2, 3, 4) >>> data = np.arange(1, rank * sum(shape) + 1) >>> weights = 2 * np.ones(rank) >>> weights_and_data = np.concatenate((weights, data), axis=0) >>> K = ttb.ktensor.from_vector(weights_and_data[:], shape, True) >>> K0 = K.ttv(np.array([1, 1, 1]), dims=1) # compute along a single dimension >>> print(K0) ktensor of shape (2, 4) with order F weights=[36. 54.] factor_matrices[0] = [[1. 3.] [2. 4.]] factor_matrices[1] = [[11. 15.] [12. 16.] [13. 17.] [14. 18.]]
Compute the product of a
pyttb.ktensor
and a vector for each dimension (results in a float):>>> vec2 = np.array([1, 1]) >>> vec3 = np.array([1, 1, 1]) >>> vec4 = np.array([1, 1, 1, 1]) >>> K1 = K.ttv([vec2, vec3, vec4]) >>> print(K1) 30348.0
Compute the product of a
pyttb.ktensor
and multiple vectors out of order (results in apyttb.ktensor
):>>> K2 = K.ttv([vec4, vec3], np.array([2, 1])) >>> print(K2) ktensor of shape (2,) with order F weights=[1800. 3564.] factor_matrices[0] = [[1. 3.] [2. 4.]]
- update(modes: int | float | Iterable[int] | Iterable[float] | ndarray, data: ndarray) ktensor [source]
Update a
pyttb.ktensor
in the specific dimensions.Updates with the values in data (in vector or matrix form). The value of modes must be a value in [-1,…,self.ndims]. If the Further, the number of elements in data must equal self.shape[modes] * self.ncomponents. The update is performed in place.
- Parameters:
modes – List of dimensions to update; values must be in ascending order. If the first element of the list is -1, then update the weights. All other integer values values must be sorted and in [0,…,self.ndims].
data – Data values to use in the update.
- Returns:
Self for chained operations.
Examples
Create a
pyttb.ktensor
of all ones:>>> K = ttb.ktensor.from_function(np.ones, (2, 3, 4), 2)
Create vectors for updating various factor matrices of the
pyttb.ktensor
:>>> vec0 = 2 * np.ones(K.shape[0] * K.ncomponents) >>> vec1 = 3 * np.ones(K.shape[1] * K.ncomponents) >>> vec2 = 4 * np.ones(K.shape[2] * K.ncomponents)
Update a single factor matrix:
>>> K1 = K.copy() >>> K1 = K1.update(0, vec0) >>> print(K1) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[2. 2.] [2. 2.]] factor_matrices[1] = [[1. 1.] [1. 1.] [1. 1.]] factor_matrices[2] = [[1. 1.] [1. 1.] [1. 1.] [1. 1.]]
Update all factor matrices:
>>> K2 = K.copy() >>> vec_all = np.concatenate((vec0, vec1, vec2)) >>> K2 = K2.update([0, 1, 2], vec_all) >>> print(K2) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[2. 2.] [2. 2.]] factor_matrices[1] = [[3. 3.] [3. 3.] [3. 3.]] factor_matrices[2] = [[4. 4.] [4. 4.] [4. 4.] [4. 4.]]
Update some but not all factor matrices:
>>> K3 = K.copy() >>> vec_some = np.concatenate((vec0, vec2)) >>> K3 = K3.update([0, 2], vec_some) >>> print(K3) ktensor of shape (2, 3, 4) with order F weights=[1. 1.] factor_matrices[0] = [[2. 2.] [2. 2.]] factor_matrices[1] = [[1. 1.] [1. 1.] [1. 1.]] factor_matrices[2] = [[4. 4.] [4. 4.] [4. 4.] [4. 4.]]
- viz(plots: tuple | list | None = None, show_figure: bool = True, normalize: bool = True, norm: int | float = 2, rel_weights: bool = True, rel_heights: tuple | list | None = None, rel_widths: tuple | list | None = None, horz_space: float | None = None, vert_space: float | None = None, left_space: float | None = None, right_space: float | None = None, top_space: float | None = None, bot_space: float | None = None, mode_titles: tuple | list | None = None, title=None) Tuple[Figure, Axes] [source]
Visualize factors for
pyttb.ktensor
.- Parameters:
plots – List of functions (one per mode) which visualize the respective vectors of a factor. Function for mode i must have signature f(v_i,ax) where v_i is
numpy.ndarray
vector of dimension n_i and ax is a :class:`matplotlib.axes.Axes’ on which to plot.show_figure – Boolean determining if the resulting figure should be shown.
normalize – Boolean controlling whether to normalize factors and generate a compensating weight, then sort components by weight.
norm – Norm used to normalize factors; 1 for 1-norm, 2 for 2-norm, etc.
rel_weights – Boolean determining whether weights should be made relative by dividing by largest weight.
rel_widths – List of numbers (one per mode) specifying relative widths of each plot column.
rel_heights – List of numbers (one per component) specifying relative height of each plot row.
horz/vert_space – Number determining amount of space between subplots (horizontally/vertically) as a fraction of the average axis width/height.
left/right/top/bot_space – Extent of subplots as fraction of figure width or height.
mode_titles – List of strings used as titles for each column (mode).
title – String containing overall figure title.
- Returns:
Examples
Set up a
pyttb.ktensor
to plot:>>> np.random.seed(1) >>> K = ttb.ktensor.from_function(np.random.random_sample, (2, 3, 10), 2)
Use plot K using default behavior K.viz()
>>> fig, axs = K.viz(show_figure=False) >>> plt.close(fig)
Define a more realistic plot functions with x labels, control relative widths of each plot, and set mode titles.
>>> def mode_1_plot(v, ax): ... ax.bar([1, 2], v, width=0.2) ... ax.set_xticks([1, 2], labels=["neutron", "electron"], rotation=45) >>> def mode_2_plot(v, ax): ... ax.plot(np.arange(v.shape[0]), v) ... ax.set_xlabel("$v$, [m/s]") >>> def mode_3_plot(v, ax): ... ax.semilogx(np.logspace(-2, 2, v.shape[0]), v) ... ax.set_xlabel("$E$, [kJ]") >>> plots = [mode_1_plot, mode_2_plot, mode_3_plot] >>> fig, axs = K.viz( ... show_figure=False, ... plots=plots, ... rel_widths=[1, 2, 3], ... horz_space=0.4, ... left_space=0.2, ... bot_space=0.2, ... mode_titles=["Particle", "Velocity", "Energy"], ... ) >>> plt.close(fig)
- __add__(other)[source]
Binary addition for
pyttb.ktensor
.- Parameters:
other (
pyttb.ktensor
, required) –pyttb.ktensor
to add to self.- Returns:
- __neg__()[source]
Unary minus (negative) for
pyttb.ktensor
instances.- Returns:
- __pos__()[source]
Unary plus (positive) for
pyttb.ktensor
instances.- Returns:
- __sub__(other)[source]
Binary subtraction for
pyttb.ktensor
.- Parameters:
other (
pyttb.ktensor
)- Returns:
- __mul__(other)[source]
Elementwise (including scalar) multiplication for
pyttb.ktensor
.- Parameters:
other (
pyttb.tensor
,pyttb.sptensor
, float, int)- Returns:
- __rmul__(other)[source]
Elementwise (including scalar) multiplication for
pyttb.ktensor
.- Parameters:
other (
pyttb.tensor
,pyttb.sptensor
, float, int)- Returns:
- __repr__()[source]
Return string representation of a
pyttb.ktensor
.- Returns:
str
- __str__()
Return string representation of a
pyttb.ktensor
.- Returns:
str