Source code for hottbox.utils.generation.tensors

"""
This module contains useful functions for the iterative tensor routines
and data type conversions
"""
import numpy as np
from functools import reduce
from ...core.structures import Tensor, TensorCPD, TensorTKD, TensorTT

def _select_base_function(base):
    """ Utility for creating arrays
    Parameters
    ----------
    base : str
        Id of base function.
        If not one from ``{"arange", "randn", "rand", "ones"}`` then `np.arange` will be used.
    Returns
    -------
        Numpy function for creating arrays
    """
    return {"arange": np.arange,
            "randn": np.random.randn,
            "rand": np.random.rand,
            "ones": np.ones}.get(base, np.arange)


[docs]def quick_tensor(shape, base="arange"): """ Simplified creation of generic tensor Parameters ---------- shape : tuple Desired shape of the tensor base : str Id of base function that generates values for the tensor. If not one from ``{"arange", "randn", "rand", "ones"}`` then ``np.arange`` will be used. Returns ------- tensor : Tensor Examples -------- >>> from hottbox.utils.generation import quick_tensor >>> tensor = quick_tensor(shape=(2, 3, 4)) >>> print(tensor) This tensor is of order 3 and consists of 24 elements. Sizes and names of its modes are (2, 3, 4) and ['mode-0', 'mode-1', 'mode-2'] respectively. >>> print(tensor.data) [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]] >>> tensor = quick_tensor(shape=(2, 3, 4), base="ones") >>> print(tensor) This tensor is of order 3 and consists of 24 elements. Sizes and names of its modes are (2, 3, 4) and ['mode-0', 'mode-1', 'mode-2'] respectively. >>> print(tensor.data) [[[1. 1. 1. 1.] [1. 1. 1. 1.] [1. 1. 1. 1.]] [[1. 1. 1. 1.] [1. 1. 1. 1.] [1. 1. 1. 1.]]] """ size = reduce(lambda x, y: x * y, shape) create_ndarray = _select_base_function(base) array = np.reshape(create_ndarray(size), shape) tensor = Tensor(array=array) return tensor
[docs]def quick_tensorcpd(full_shape, rank, base="arange"): """ Simplified creation of generic tensor in kruskal form Parameters ---------- full_shape : tuple Desired shape of the tensor when it is reconstructed. Values specify the number of rows of the factor matrices. rank : tuple Desired kruskal rank of the tensor. Specifies the number of columns for all factor matrices. In order to be consistent with the rest of ``hottbox`` should be in form of ``(value,)`` base : str Id of base function that generates values for the components of kruskal tensor. If not one from ``{"arange", "randn", "rand", "ones"}`` then ``np.arange`` will be used. Returns ------- tensor_cpd : TensorCPD Examples -------- >>> from hottbox.utils.generation import quick_tensorcpd >>> tensor_cpd = quick_tensorcpd(full_shape=(3, 4, 5), rank=(2,), base="ones") >>> print(tensor_cpd) Kruskal representation of a tensor with rank=(2,). Factor matrices represent properties: ['mode-0', 'mode-1', 'mode-2'] With corresponding latent components described by (3, 4, 5) features respectively. >>> tensor = tensor_cpd.reconstruct() >>> print(tensor) This tensor is of order 3 and consists of 60 elements. Sizes and names of its modes are (3, 4, 5) and ['mode-0', 'mode-1', 'mode-2'] respectively. """ create_ndarray = _select_base_function(base) fmat_shapes = zip(full_shape, [rank[0] for _ in range(len(full_shape))]) core_values = np.ones(rank[0]) fmat = [] for fmat_shape in fmat_shapes: size = reduce(lambda x, y: x * y, fmat_shape) fmat.append(np.reshape(create_ndarray(size), fmat_shape)) tensor_cpd = TensorCPD(fmat=fmat, core_values=core_values) return tensor_cpd
[docs]def quick_tensortkd(full_shape, rank, base="arange"): """ Simplified creation of generic tensor in tucker form Parameters ---------- full_shape : tuple Desired shape of the tensor when it is reconstructed. Values specify the number of rows of the factor matrices. rank : tuple Desired multi-linear rank of the tensor. Specifies the number of columns for all factor matrices. Should be of the same length as parameter ``full_shape`` base : str Id of base function that generates values for the components of tucker tensor. If not one from ``{"arange", "randn", "rand", "ones"}`` then ``np.arange`` will be used. Returns ------- tensor_tkd : TensorTKD Examples -------- >>> from hottbox.utils.generation import quick_tensortkd >>> tensor_tkd = quick_tensortkd(full_shape=(5, 6, 7), rank=(2, 3, 4), base="ones") >>> print(tensor_tkd) Tucker representation of a tensor with multi-linear rank=(2,). Factor matrices represent properties: ['mode-0', 'mode-1', 'mode-2'] With corresponding latent components described by (5, 6, 7) features respectively. >>> tensor = tensor_tkd.reconstruct() >>> print(tensor) This tensor is of order 3 and consists of 210 elements. Sizes and names of its modes are (5, 6, 7) and ['mode-0', 'mode-1', 'mode-2'] respectively. """ create_ndarray = _select_base_function(base) fmat_shapes = zip(full_shape, rank) core_values = np.ones(rank) fmat = [] for shape in fmat_shapes: size = reduce(lambda x, y: x * y, shape) fmat.append(np.reshape(create_ndarray(size), shape)) tensor_tkd = TensorTKD(fmat=fmat, core_values=core_values) return tensor_tkd
[docs]def quick_tensortt(full_shape, rank, base="arange"): """ Simplified creation of generic tensor in tensor train form Parameters ---------- full_shape : tuple Desired shape of the tensor when it is reconstructed. rank : tuple Desired tt rank of the tensor. base : str Id of base function that generates values for the components of tensor train tensor. If not one from ``{"arange", "randn", "rand", "ones"}`` then ``np.arange`` will be used. Returns ------- tensor_tt : TensorTT Examples -------- >>> from hottbox.utils.generation import quick_tensortt >>> tensor_tt = quick_tensortt(full_shape=(3, 4, 5), rank=(2, 3), base="ones") >>> print(tensor_tt) Tensor train representation of a tensor with tt-rank=(2, 3). Shape of this representation in the full format is (3, 4, 5). Physical modes of its cores represent properties: ['mode-0', 'mode-1', 'mode-2'] >>> tensor = tensor_tt.reconstruct() >>> print(tensor) This tensor is of order 3 and consists of 60 elements. Sizes and names of its modes are (3, 4, 5) and ['mode-0', 'mode-1', 'mode-2'] respectively. """ create_ndarray = _select_base_function(base) tt_ranks_l = rank[:-1] tt_ranks_r = rank[1:] number_of_middle_cores = len(tt_ranks_l) first_core_shape = (full_shape[0], rank[0]) last_core_shape = (rank[-1], full_shape[-1]) middle_cores_shape = [(tt_ranks_l[i], full_shape[i + 1], tt_ranks_r[i]) for i in range(number_of_middle_cores)] core_shapes = [first_core_shape] + middle_cores_shape + [last_core_shape] core_values = [] for shape in core_shapes: size = reduce(lambda x, y: x * y, shape) core_values.append(np.reshape(create_ndarray(size), shape)) tensor_tt = TensorTT(core_values=core_values) return tensor_tt