Skip to content

Conversation

@aarmey
Copy link
Contributor

@aarmey aarmey commented Jul 12, 2022

Here is a basic test setup for complex valued tensors. I will add comments documenting the failure cases.

Addresses #422

@aarmey aarmey added the bug label Jul 12, 2022
Copy link
Contributor

@yngvem yngvem left a comment

Choose a reason for hiding this comment

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

It seems like I forgot to submit my review last week, so some of my comments may be outdated... I cannot check if that's the case now, as I'm out travelling, but hopefully they should be helpful :)

@pytest.mark.parametrize("init", ["svd", "random"])
@pytest.mark.parametrize("normalize_factors", [False, True])
@pytest.mark.parametrize("random_state", [1, 1234])
@pytest.mark.parametrize("random_state", [1, 1236])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed the random seed here because the random initialization is pathologically bad. It works fine (and I directly checked the MTTKRP error calculation) but ALS gets trapped without line search or orthogonalization.

Copy link
Member

Choose a reason for hiding this comment

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

That's awesome, thanks @aarmey!
I wonder if we could write a small tool to automatically check for such pathological cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting idea. It should be clear by looking at cp_lstsq_grad(). It'd be too expensive to run every iteration, but is certainly something you could run at the end to look for issues.

@aarmey aarmey marked this pull request as ready for review July 18, 2022 15:51
@codecov
Copy link

codecov bot commented Jul 18, 2022

Codecov Report

Merging #423 (5336518) into main (37e5bf8) will increase coverage by 0.02%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main     #423      +/-   ##
==========================================
+ Coverage   88.55%   88.58%   +0.02%     
==========================================
  Files         108      108              
  Lines        6423     6428       +5     
==========================================
+ Hits         5688     5694       +6     
+ Misses        735      734       -1     
Impacted Files Coverage Δ
...ly/decomposition/tests/test_constrained_parafac.py 100.00% <ø> (ø)
tensorly/cp_tensor.py 85.08% <100.00%> (ø)
tensorly/decomposition/_cp.py 87.27% <100.00%> (+0.36%) ⬆️
tensorly/decomposition/tests/test_cp.py 100.00% <100.00%> (ø)

📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more

@JeanKossaifi
Copy link
Member

JeanKossaifi commented Jul 18, 2022

Thanks @aarmey! I love how you also casually improved the quality of life for the whole library in the process by fixing the test and speeding up the tests for JAX and TF!

@aarmey
Copy link
Contributor Author

aarmey commented Jul 18, 2022

If someone can give this a last look, it should be ready and all the tests are passing now.

Copy link
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.

Awesome, looks good to me!

# mttkrp and factor for the last mode. This is equivalent to the
# inner product <tensor, factorization>
iprod = tl.sum(tl.sum(mttkrp * factors[-1], axis=0))
iprod = tl.sum(tl.sum(mttkrp * tl.conj(factors[-1]), axis=0))
Copy link
Member

Choose a reason for hiding this comment

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

Why does it have to be the conjugate here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@yngvem had this insight, so he might be able to explain. I confirmed that the results are indeed wrong without this.

@aarmey aarmey merged commit b672981 into tensorly:main Jul 20, 2022
@aarmey aarmey deleted the complex-test branch July 20, 2022 02:55
@yngvem
Copy link
Contributor

yngvem commented Jul 20, 2022

@aarmey @JeanKossaifi I wasn't able to find the button for submitting my comments after it was merged, so I'm answering the mttkrp-question here :)

Since iprod is supposed to be the inner product of the estimated and true tensor, it should be equal to
$\sum_{ijk} \mathcal{T}_{ijk} \hat{\mathcal{T}}_{ijk}^*$ or $\sum_{ijk} \mathcal{T}_{ijk}^* \hat{\mathcal{T}}_{ijk}$, where the $^*$ denotes conjugation. We have already computed $\sum_{jk} \mathcal{T}_{ij:} \hat{\mathcal{T}}_{ij:}^*$ in the mttkrp, so we need to conjugate the factor matrix of the last mode here to be consistent.

I think we could conjugate the mttkrp instead of the factor matrix, but I would have to check. Anyways, the point is that we need at least one conjugate on that line for there to be a complex inner product

@JeanKossaifi
Copy link
Member

Thanks for the clear answer @yngvem! Given that you went through the effort of writing it so nicely, I'd say let's add it to the docstring (in notes) or user guide, what do you think?

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants