Library / SDK
tensorly/tensorly avatar
tensorly/tensorly

TensorLy's backend switch is one function call, and its license is recorded two different ways

TensorLy: Tensor Learning in Python.

1,693 stars303 forksPythonNOASSERTION

At a glance

What is it?
TensorLy is a tensor decomposition library whose NumPy, PyTorch, JAX, TensorFlow, CuPy and Paddle support runs through one set_backend call. Its release tags stopped in November 2024 while the branch kept moving, and its license is recorded as NOASSERTION outside a tree that ships LICENSE.txt under a modified BSD line.
Who is it for?
TensorLy suits a researcher who wants to try the same decomposition across two frameworks without rewriting the call, because the backend switch is a single set_backend call rather than a separate API per framework, and the test targets exist to keep the backends behaving alike. Two things are worth checking before depending on it.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 9, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The backend is a function call, not a fork

The design decision everything else follows from is that one API sits on top of several array libraries. A decomposition is written once and executed by whichever framework is active, so switching is a single call:

python
tl.set_backend('pytorch') # Or 'numpy', 'tensorflow', 'cupy' or 'jax'
tensor = tl.tensor(np.arange(24).reshape((3, 4, 2)), device='cuda:0')
type(tensor) # torch.Tensor

After that line the returned object is a torch.Tensor and the computation runs on PyTorch, including placing tensors on a CUDA device. The listed backends are NumPy, PyTorch, JAX, TensorFlow, CuPy and Paddle, with NumPy as the default, and the library advertises that it runs methods at scale on CPU or GPU.

The cost of that portability is stated plainly in the install note: TensorLy depends on NumPy by default, and anyone using another backend has to install those packages separately. So the dependency footprint is one package for the default path and two ecosystems for any other.

The same shape holds for the algebra primitives. Tensors are built through tl.tensor from a NumPy array with an explicit dtype, tl.unfold turns a tensor into a matricized form along a mode, and tl.fold reverses it given the original shape. Random tensors come from a separate random module with a rank argument, including the string form that returns a factorized CP tensor directly rather than a dense one.

Releases stopped in November 2024 while the branch kept moving

The tag list and the branch tell different stories. The most recent release is 0.9.0, published 2024-11-12, before that 0.8.2 on 2024-06-09 and 0.8.0 on 2023-01-15. The default branch, main, was pushed on 2026-10-02.

So a pip install of tensorly gives you the 0.9.0 line, roughly two years behind whatever is at the branch tip, and there is no newer tag to move to. The repository is not archived, so the gap is one of releases rather than of work.

The install paths reflect the same split. The documented commands are pip install -U tensorly for the released package, conda install -c tensorly tensorly for the conda channel, and a from-git sequence that clones the repository, changes into the directory and runs pip install -e . with an equivalent long form of the same flag. Anyone who needs the unreleased code has to take the editable path and accept that it moves.

One detail in that third option is worth noting for anyone packaging around it: the version is not written in setup.py. It is read out of the package's own __init__.py with a regular expression looking for the version assignment, and setup.py raises a RuntimeError if that line is absent. The single-source pattern means a checkout and a wheel report the same number, but it also means the number comes from a file you would otherwise not think to edit.

Three records of the license and no single answer

The license is recorded in three places and they do not line up.

The repository's own metadata reports NOASSERTION, which means no license was detected rather than that one was found and found to be permissive. The tree carries a LICENSE.txt at the root, and setup.py declares a license field reading Modified BSD. So there is a license file, there is a declared identifier, and the metadata layer that other tools read says it cannot tell.

This is not a problem to resolve by inference. Modified BSD and the file at the root are separate artefacts, and nothing in the packaging configuration points at one as the text of the other. Anyone whose compliance process needs a single authoritative answer has to read LICENSE.txt and decide for themselves which terms apply, rather than trusting a field that says nothing.

The package is otherwise plainly declared. The name is tensorly, the author is recorded as Jean Kossaifi, the summary line reads Tensor learning in Python, the long description is the README rendered as reStructuredText, and the project URL is the GitHub repository. install_requires is a short list of numpy and scipy, which matches the note about NumPy being the default dependency.

The Makefile drives five backends and skips one

The test surface is organised by backend, which is how a library with one API over six frameworks stays consistent between them. The Makefile takes a BACKEND variable defaulting to numpy, and the targets are small enough to read in one pass.

The debug target runs pytest with -v and --pdb against the tensorly directory under a TENSORLY_BACKEND environment variable. The plain test target runs the same pytest invocation without the debugger. Coverage adds --cov tensorly. A default target chains install and test, so make alone gives you an editable install followed by the numpy suite.

The cross-backend target is the interesting one, and it is where the list and the documentation disagree. test-all sets TENSORLY_BACKEND five times in a row, to numpy, cupy, pytorch, jax and tensorflow. Paddle is absent, even though Paddle is named in the project's own description of supported backends alongside the other five. So the repository's own consistency check covers every advertised backend except one.

The tooling around the suite is also worth naming, since requirements.txt lists pytest-randomly beside pytest, pytest-cov, numpy and scipy. Randomised ordering is a deliberate choice for a numerical library, where test order can hide state leaking between cases. requirements.txt and setup.py's install_requires are not the same list: the test runners appear only in the former, so a plain install does not bring them.

Black formats the code, and the badge points at a branch that is not main

The contribution instructions are short and name a single tool. Style is enforced with black, installed and run over the tree with pip install black followed by black . , and the readme asks contributors to run it before submitting. Everything else about the workflow is delegated to an issue or a pull request on GitHub, and the text invites reports of a typo in documentation with the same seriousness as a method bug.

Testing is described as essential because every function is expected to come with unit tests and documentation. That claim is what makes the Makefile's per-backend targets meaningful rather than ceremonial.

One inconsistency sits in the badge block at the top. The coverage badge points at a graph for branch master while the project's default branch is main, and the test workflow badge points at branch main explicitly by way of a query parameter. One of the two badges is therefore tracking a branch that is not the one being developed.

The rest of the header is conventional: a package version badge, a conda channel badge, a CI status badge and a Slack invite link. The repository itself carries a CHANGELOG.md, a CITATION.cff for citation metadata, an AUTHORS.rst and a CONTRIBUTING.rst, plus a Makefile, a setup.cfg, a requirements.txt and a .travis.yml at the root, so the historical CI configuration is still sitting next to the GitHub Actions workflow the badges point at.

The quickstart builds a 3 by 4 by 2 tensor and stops there

The worked example in the readme is deliberately minimal. It creates a third-order tensor of size 3 x 4 x 2 from a NumPy array, unfolds it along mode 0, and folds it back using the original shape, which is a demonstration that the matricization round-trips rather than a decomposition tutorial.

Decomposition arrives in the next block, with Tucker applied at rank [2, 2, 2] and the full tensor reconstructed from the decomposed form with tl.tucker_to_tensor. The CP path is shown only through the random module's rank string, which returns a factorized tensor without ever materialising a dense one.

What the example set does not include is a benchmark or a timing claim. The repository carries an examples directory with subdirectories for applications, decomposition and regression, a plot_tensor.py script, and a sparse_parafac notebook, and the readme points at a separate notebooks repository maintained under a different account for Jupyter material. There is no performance table anywhere in the readme, so the only scale statement available is the general claim that methods run at scale on CPU or GPU.

For a reader deciding whether the library fits, that is the honest boundary. The API surface is small enough to read in one sitting and the backend abstraction is the part that carries real weight; everything about how fast any particular decomposition runs on any particular backend has to come from your own measurement.

Editorial conclusion

TensorLy suits a researcher who wants to try the same decomposition across two frameworks without rewriting the call, because the backend switch is a single set_backend call rather than a separate API per framework, and the test targets exist to keep the backends behaving alike. Two things are worth checking before depending on it. The newest tag is 0.9.0 from 2024-11-12 while the default branch was pushed on 2026-10-02, so a pip install and a checkout are not the same code and there is no tag to point a production dependency at. And the license needs a decision from you: NOASSERTION is the value recorded for this repository while the tree ships LICENSE.txt and setup.py declares a modified BSD line, and only one of those three is authoritative for your compliance process. Anyone who needs a release cadence they can pin against should track the branch deliberately rather than assume the tag list is current.

Frequently asked questions

How do I install TensorLy?

Python 3 is the only stated prerequisite. The documented commands are pip install -U tensorly, conda install -c tensorly tensorly, or a from-git sequence that clones the repository, changes into it and runs pip install -e . . NumPy and scipy are pulled in by the install.

Which backends does TensorLy support?

NumPy, PyTorch, JAX, TensorFlow, CuPy and Paddle, with NumPy as the default. You switch with tl.set_backend, and any backend other than NumPy has to be installed separately. The Makefile's test-all target exercises numpy, cupy, pytorch, jax and tensorflow, leaving paddle out.

What license is TensorLy under?

The three records disagree and the metadata layer reports NOASSERTION. A LICENSE.txt sits at the repository root and setup.py declares a license field reading Modified BSD. Reading the file is the only way to settle which terms apply.

What is the newest TensorLy release?

0.9.0, published 2024-11-12, preceded by 0.8.2 on 2024-06-09 and 0.8.0 on 2023-01-15. The default branch was last pushed on 2026-10-02, so a pip install and a current checkout are not the same code.

How does TensorLy run its tests across backends?

Through the Makefile, with a BACKEND variable defaulting to numpy. The debug target runs pytest -v --pdb under a TENSORLY_BACKEND variable, coverage adds --cov tensorly, and test-all sets TENSORLY_BACKEND for numpy, cupy, pytorch, jax and tensorflow in turn.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. tensorly/tensorly on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tensorly-tensorly.svg)](https://hysenlabs.com/projects/tensorly-tensorly)