Skip to content

Added support for factors-only initialization in tucker decomposition#596

Open
sebulo wants to merge 1 commit intotensorly:mainfrom
sebulo:main
Open

Added support for factors-only initialization in tucker decomposition#596
sebulo wants to merge 1 commit intotensorly:mainfrom
sebulo:main

Conversation

@sebulo
Copy link
Copy Markdown

@sebulo sebulo commented Feb 26, 2025

Motivation

The initialize_tucker function currently requires init to be "svd", "random", or a (core, factors) tuple. For warm-starting Tucker decomposition, users may only have factors without a core. This PR lets init accept a list of factors and recomputes the core internally.

Changes

  • In initialize_tucker:

    • Added support for init as a list of factors under elif isinstance(init, (tuple, list)):
    • Validates factor count and shapes, then recomputes core with multi_mode_dot
    • Updated error message to include the new option
  • In mode_dot:

    • Added handling of Complex32 floats to support low-precision complex tensors.

Copy link
Copy Markdown
Member

@JeanKossaifi JeanKossaifi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, thanks @sebulo, I left some comments in the code. Generally, it's good to group each big change in its own PR.

Comment thread tensorly/decomposition/_tucker.py Outdated
factors : list of factors
"""
# Validate rank against tensor shape
rank = validate_tucker_rank(tensor.shape, rank)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to add this? We already validate inside the main decomposition function, which would be called less frequently than this one. I think we can assume it is already validated here - and document that in the docstring.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. It is already validated earlier.

Comment thread tensorly/decomposition/_tucker.py Outdated
]

elif isinstance(init, (tuple, list)): # either a tuple (core, factors) or a list of factors
if isinstance(init, tuple) and len(init) == 2:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to use Iterable here instead of tuple to keep it consistent and more robust, same below instead of list.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think we may want to verify that init[1] is also Iterable.. It's verbose but init may be a weird 2-tuple from a partial-tucker

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comments! I addressed these concerns in the newest commit: use Iterable, validate factors in tuple init.

Comment thread tensorly/decomposition/_tucker.py Outdated
"""
if fixed_factors:
try:
if isinstance(init, list): # Handle factors-only init
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, let's use Iterable here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in latest commit.

Comment thread tensorly/decomposition/_tucker.py Outdated
if fixed_factors:
try:
if isinstance(init, list): # Handle factors-only init
init = initialize_tucker(tensor, rank, list(range(tensor.ndim)), random_state, init=init)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to create intermediate init variable, we can directly unpack into (core, factors)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in latest commit.


res = T.dot(matrix_or_vector, unfold(tensor, mode))
unfolded = unfold(tensor, mode)
if tensor.dtype == torch.complex32 and not handle_complex_half_by_upcasting:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave this for a separate PR, we need to think better on how to incorporate it cleanly. Also we should be using tl.dtype not directly torch.dtype since the latter will break on other backends.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @JeanKossaifi, the support of complex operations in Tensorly, while interesting, should be handled separately.

Also, I believe some backends like Pytorch have built-in support for matrix multiplication with complex numbers, that may be faster than doing the splitting of real and imaginary parts manually, e.g. see here

@cohenjer
Copy link
Copy Markdown
Contributor

Thanks for the useful addition @sebulo! Can I also ask if you can add a small unit test for the initialization with only factor matrices? something like checking that the core computed is indeed the optimal one, and that Tucker runs when called after with this initialization (on very small examples).

@JeanKossaifi
Copy link
Copy Markdown
Member

@sebulo would be great if you could give this another pass whenever you have time!

@sebulo
Copy link
Copy Markdown
Author

sebulo commented Mar 24, 2026

Sorry for the long delay. I gave this another pass and pushed a cleaned update focused only on factors-only Tucker initialization.

The change allows init in Tucker decomposition to be provided as only the factor matrices, without an explicit core. In that case, the core is recomputed from the input tensor and the provided factors.

I also removed the unrelated mode_dot complex change from this PR and added tests for:

  • checking that the core recomputed from the provided factors is the expected one
  • checking that tucker(...) runs correctly when initialized with factors only

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants