Tensortools
-----------
[![][license-img]][license-url]
[license-img]: https://img.shields.io/github/license/mashape/apistatus.svg
[license-url]: https://github.com/ahwillia/tensortools/blob/master/LICENSE.md
TensorTools is a bare bones Python package for fitting and visualizing [canonical polyadic (CP) tensor decompositions](https://en.wikipedia.org/wiki/Tensor_rank_decomposition) of higher-order data arrays. I originally developed this library for applications in neuroscience ([Williams et al., 2018](https://doi.org/10.1016/j.neuron.2018.05.015)), but the code could be helpful in other domains.
Installation
------------
From the command line run:
```
pip install git+https://github.com/ahwillia/tensortools
```
(You will need to have `git` installed for this command to work.)
Alternatively you can download the source code and install locally by running:
```
git clone https://github.com/ahwillia/tensortools
cd tensortools
pip3 install -e .
```
Quick Start
------------
Here's how to perform a parameter sweep over 1 - 9 components, and plot the reconstruction error and similarity diagnostics as a function of the model rank (these diagnostics are described in [Williams et al., 2018](https://doi.org/10.1016/j.neuron.2018.05.015)). The snippet also uses `plot_factors(...)` to plot the factors extracted by one of the models in the ensemble.
The method `"ncp_hals"` fits a nonnegative tensor decomposition, other methods are `"ncp_bcd"` (also nonnegative) and `"cp_als"` (unconstrained decomposition). See the [`tensortools/optimize/`](/tensortools/optimize) folder for the implementation of these algorithms.
```python
import tensortools as tt
data = # ... specify a numpy array holding the tensor you wish to fit
# Fit an ensemble of models, 4 random replicates / optimization runs per model rank
ensemble = tt.Ensemble(fit_method="ncp_hals")
ensemble.fit(data, ranks=range(1, 9), replicates=4)
fig, axes = plt.subplots(1, 2)
tt.plot_objective(ensemble, ax=axes[0]) # plot reconstruction error as a function of num components.
tt.plot_similarity(ensemble, ax=axes[1]) # plot model similarity as a function of num components.
fig.tight_layout()
# Plot the low-d factors for an example model, e.g. rank-2, first optimization run / replicate.
num_components = 2
replicate = 0
tt.plot_factors(ensemble.factors(num_components)[replicate]) # plot the low-d factors
plt.show()
```
Check out the scripts in the [`examples/`](/examples) folder for other short demos.
Time-Shifted Tensor Decompositions
----------------------------------
This repo contains a module `tensortools.cpwarp` which allows for *time-shifted tensor decompositions* of 3d-arrays. The motivation behind this model and some of its implementaional details are laid out in the following set of notes.
> Alex H. Williams (2020). [Combining tensor decomposition and time warping models for multi-neuronal spike train analysis](https://doi.org/10.1101/2020.03.02.974014). *bioRxiv*. 2020.03.02.974014
A very similar model was previously proposed by [Mørup et al. (2008)](https://doi.org/10.1016/j.neuroimage.2008.05.062). Also see [Sorokin et al. (2020)](https://doi.org/10.1101/2020.03.04.976688) for an application of this model to neural data.
To fit this model, check out the script in [`examples/shift_cpd.py`](./examples/shift_cpd.py), which should reproduce Figure 4 from the [Williams (2020)](https://doi.org/10.1101/2020.03.02.974014) paper.
The important function to call is `fit_shifted_cp()`, like below:
```python
fit_shifted_cp(
data,
rank,
boundary="wrap",
n_restarts=5,
max_shift_axis0=0.1,
max_shift_axis1=None,
min_iter=10,
max_iter=100,
u_nonneg=True,
v_nonneg=True,
tol=1e-4,
patience=5,
mask=None,
)
"""
Fits a time-shifted CP decomposition to 3d-array `data`. The model parameters
are three factor matrices {u, v, w} and two sets of shift parameters {u_s, v_s}.
u.shape == (rank, data.shape[0])
v.shape == (rank, data.shape[1])
w.shape == (rank, data.shape[2])
u_s.shape == (rank, data.shape[0])
v_s.shape == (rank, data.shape[1])
The element `data[i, j, k]` is approximated by:
sum_r ( u[r, i] * v[r, j] * w[r, t + u_s[r, i] + v_s[r, i]] )
Note that if the shift parameters are zero (u_s == v_s == 0), this is the typical
CP tensor decomposition.
Parameters
----------
data : ndarray
Data tensor.
rank : int
Number of components.
init_u : ndarray or None
Initial guess for factor matrix `u`.
init_v : ndarray or None
Initial guess for factor matrix `v`.
init_w : ndarray or None
Initial guess for factor matrix `w`.
max_shift_axis0 : float or None
Maximum absolute value for u_s, expressed
as a fraction on the interval (0, 0.5].
If None, then all u_s shifts are set to zero.
max_shift_axis1 : float
Maximum absolute value for v_s, expressed
as a fraction on the interval (0, 0.5].
If None, then all v_s shifts are set to zero.
u_nonneg : bool
If True, the factor matrix u is constrained
to be nonnegative.
v_nonneg : bool
If True, the factor matrix v is constrained
to be nonnegative.
boundary : str
If equal to "wrap" the shifting along axis=2
has a periodic boundary condition. Otherwise
the behavior is similar to "edge" mode in the
numpy.pad() function.
min_iter : int
Minimum number of iterations before stopping.
max_iter : int
Maximum number of iterations before giving up.
tol : float
Convergence tolerance
patience : int
Number of iterations to wait between convergence
checks.
mask : ndarray of booleans or None
Specifies missing data, and can be used for
cross-validation.
"""
```
I hope to upload a more detailed tutorial soon; until then, please refer to the papers cited above and reach out to me by email if you are interested in further details.
Citation
--------
If you found this resource useful, please consider citing [this paper](https://doi.org/10.1016/j.neuron.2018.05.015).
```
@ARTICLE{Williams2018,
title = "Unsupervised Discovery of Demixed, {Low-Dimensional} Neural
Dynamics across Multiple Timescales through Tensor Component
Analysis",
author = "Williams, Alex H and Kim, Tony Hyun and Wang, Forea and Vyas,
Saurabh and Ryu, Stephen I and Shenoy, Krishna V and Schnitzer,
Mark and Kolda, Tamara G and Ganguli, Surya",
journal = "Neuron",
volume = 98,
number = 6,
pages = "1099--1115.e8",
month = jun,
year = 2018,
}
```
Raw data
{
"_id": null,
"home_page": "https://github.com/ahwillia/tensortools",
"name": "tensortools",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3",
"maintainer_email": "",
"keywords": "tensor decomposition,canonical decomposition,parallel factors",
"author": "Alex Williams and N. Benjamin Erichson",
"author_email": "alex.h.willia@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/73/c3/16116ca504d946e90211086f429141e75b62b48b7281dd6b9337c5fb275d/tensortools-0.4.tar.gz",
"platform": null,
"description": "Tensortools\n-----------\n[![][license-img]][license-url]\n\n[license-img]: https://img.shields.io/github/license/mashape/apistatus.svg\n[license-url]: https://github.com/ahwillia/tensortools/blob/master/LICENSE.md\n\n\nTensorTools is a bare bones Python package for fitting and visualizing [canonical polyadic (CP) tensor decompositions](https://en.wikipedia.org/wiki/Tensor_rank_decomposition) of higher-order data arrays. I originally developed this library for applications in neuroscience ([Williams et al., 2018](https://doi.org/10.1016/j.neuron.2018.05.015)), but the code could be helpful in other domains.\n\nInstallation\n------------\n\nFrom the command line run:\n\n```\npip install git+https://github.com/ahwillia/tensortools\n```\n\n(You will need to have `git` installed for this command to work.)\n\nAlternatively you can download the source code and install locally by running:\n\n```\ngit clone https://github.com/ahwillia/tensortools\ncd tensortools\npip3 install -e .\n```\n\nQuick Start\n------------\n\nHere's how to perform a parameter sweep over 1 - 9 components, and plot the reconstruction error and similarity diagnostics as a function of the model rank (these diagnostics are described in [Williams et al., 2018](https://doi.org/10.1016/j.neuron.2018.05.015)). The snippet also uses `plot_factors(...)` to plot the factors extracted by one of the models in the ensemble.\n\nThe method `\"ncp_hals\"` fits a nonnegative tensor decomposition, other methods are `\"ncp_bcd\"` (also nonnegative) and `\"cp_als\"` (unconstrained decomposition). See the [`tensortools/optimize/`](/tensortools/optimize) folder for the implementation of these algorithms.\n\n\n```python\nimport tensortools as tt\n\ndata = # ... specify a numpy array holding the tensor you wish to fit\n\n# Fit an ensemble of models, 4 random replicates / optimization runs per model rank\nensemble = tt.Ensemble(fit_method=\"ncp_hals\")\nensemble.fit(data, ranks=range(1, 9), replicates=4)\n\nfig, axes = plt.subplots(1, 2)\ntt.plot_objective(ensemble, ax=axes[0]) # plot reconstruction error as a function of num components.\ntt.plot_similarity(ensemble, ax=axes[1]) # plot model similarity as a function of num components.\nfig.tight_layout()\n\n# Plot the low-d factors for an example model, e.g. rank-2, first optimization run / replicate.\nnum_components = 2\nreplicate = 0\ntt.plot_factors(ensemble.factors(num_components)[replicate]) # plot the low-d factors\n\nplt.show()\n```\n\nCheck out the scripts in the [`examples/`](/examples) folder for other short demos.\n\nTime-Shifted Tensor Decompositions\n----------------------------------\n\nThis repo contains a module `tensortools.cpwarp` which allows for *time-shifted tensor decompositions* of 3d-arrays. The motivation behind this model and some of its implementaional details are laid out in the following set of notes.\n\n> Alex H. Williams (2020). [Combining tensor decomposition and time warping models for multi-neuronal spike train analysis](https://doi.org/10.1101/2020.03.02.974014). *bioRxiv*. 2020.03.02.974014\n\nA very similar model was previously proposed by [M\u00f8rup et al. (2008)](https://doi.org/10.1016/j.neuroimage.2008.05.062). Also see [Sorokin et al. (2020)](https://doi.org/10.1101/2020.03.04.976688) for an application of this model to neural data.\nTo fit this model, check out the script in [`examples/shift_cpd.py`](./examples/shift_cpd.py), which should reproduce Figure 4 from the [Williams (2020)](https://doi.org/10.1101/2020.03.02.974014) paper.\n\nThe important function to call is `fit_shifted_cp()`, like below:\n\n```python\nfit_shifted_cp(\n data,\n rank,\n boundary=\"wrap\",\n n_restarts=5,\n max_shift_axis0=0.1,\n max_shift_axis1=None,\n min_iter=10,\n max_iter=100,\n u_nonneg=True,\n v_nonneg=True,\n tol=1e-4,\n patience=5,\n mask=None,\n)\n\n\"\"\"\nFits a time-shifted CP decomposition to 3d-array `data`. The model parameters\nare three factor matrices {u, v, w} and two sets of shift parameters {u_s, v_s}.\n\nu.shape == (rank, data.shape[0])\nv.shape == (rank, data.shape[1])\nw.shape == (rank, data.shape[2])\nu_s.shape == (rank, data.shape[0])\nv_s.shape == (rank, data.shape[1])\n\nThe element `data[i, j, k]` is approximated by:\n\n sum_r ( u[r, i] * v[r, j] * w[r, t + u_s[r, i] + v_s[r, i]] )\n\nNote that if the shift parameters are zero (u_s == v_s == 0), this is the typical\nCP tensor decomposition.\n\nParameters\n----------\ndata : ndarray\n Data tensor.\nrank : int\n Number of components.\ninit_u : ndarray or None\n Initial guess for factor matrix `u`.\ninit_v : ndarray or None\n Initial guess for factor matrix `v`.\ninit_w : ndarray or None\n Initial guess for factor matrix `w`.\nmax_shift_axis0 : float or None\n Maximum absolute value for u_s, expressed\n as a fraction on the interval (0, 0.5].\n If None, then all u_s shifts are set to zero.\nmax_shift_axis1 : float\n Maximum absolute value for v_s, expressed\n as a fraction on the interval (0, 0.5].\n If None, then all v_s shifts are set to zero.\nu_nonneg : bool\n If True, the factor matrix u is constrained\n to be nonnegative.\nv_nonneg : bool\n If True, the factor matrix v is constrained\n to be nonnegative.\nboundary : str\n If equal to \"wrap\" the shifting along axis=2\n has a periodic boundary condition. Otherwise\n the behavior is similar to \"edge\" mode in the\n numpy.pad() function.\nmin_iter : int\n Minimum number of iterations before stopping.\nmax_iter : int\n Maximum number of iterations before giving up.\ntol : float\n Convergence tolerance\npatience : int\n Number of iterations to wait between convergence\n checks.\nmask : ndarray of booleans or None\n Specifies missing data, and can be used for\n cross-validation.\n\"\"\"\n```\n\nI hope to upload a more detailed tutorial soon; until then, please refer to the papers cited above and reach out to me by email if you are interested in further details.\n\nCitation\n--------\n\nIf you found this resource useful, please consider citing [this paper](https://doi.org/10.1016/j.neuron.2018.05.015).\n\n```\n@ARTICLE{Williams2018,\n title = \"Unsupervised Discovery of Demixed, {Low-Dimensional} Neural\n Dynamics across Multiple Timescales through Tensor Component\n Analysis\",\n author = \"Williams, Alex H and Kim, Tony Hyun and Wang, Forea and Vyas,\n Saurabh and Ryu, Stephen I and Shenoy, Krishna V and Schnitzer,\n Mark and Kolda, Tamara G and Ganguli, Surya\",\n journal = \"Neuron\",\n volume = 98,\n number = 6,\n pages = \"1099--1115.e8\",\n month = jun,\n year = 2018,\n}\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Tools for Tensor Decomposition.",
"version": "0.4",
"split_keywords": [
"tensor decomposition",
"canonical decomposition",
"parallel factors"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "73c316116ca504d946e90211086f429141e75b62b48b7281dd6b9337c5fb275d",
"md5": "a37c32e9ce011f3a4ffeabd6a2328522",
"sha256": "eb2d2b5b3d589ca1c20a4deaaf3a63447317748060310a69b643277ba8be2d08"
},
"downloads": -1,
"filename": "tensortools-0.4.tar.gz",
"has_sig": false,
"md5_digest": "a37c32e9ce011f3a4ffeabd6a2328522",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3",
"size": 37272,
"upload_time": "2023-01-11T19:42:19",
"upload_time_iso_8601": "2023-01-11T19:42:19.000553Z",
"url": "https://files.pythonhosted.org/packages/73/c3/16116ca504d946e90211086f429141e75b62b48b7281dd6b9337c5fb275d/tensortools-0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-01-11 19:42:19",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "ahwillia",
"github_project": "tensortools",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [],
"lcname": "tensortools"
}