Skip to content

Upgrade MXNet backend to MXNet.np interface - #225

Merged
JeanKossaifi merged 10 commits into
tensorly:mainfrom
aarmey:upgrade-mxnet
Feb 12, 2021
Merged

JeanKossaifi merged 10 commits into
tensorly:mainfrom
aarmey:upgrade-mxnet

Conversation

@aarmey

@aarmey aarmey commented Feb 6, 2021

Copy link
Copy Markdown
Contributor

This also removes the need for some of the MXNet-specific workarounds.

@codecov

codecov Bot commented Feb 6, 2021 •

Copy link
Copy Markdown

Codecov Report

Merging #225 (aa32605) into main (f0b701e) will increase coverage by 0.69%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #225      +/-   ##
==========================================
+ Coverage   86.35%   87.05%   +0.69%     
==========================================
  Files          82       82              
  Lines        3855     3846       -9     
==========================================
+ Hits         3329     3348      +19     
+ Misses        526      498      -28     
Impacted Files Coverage Δ
tensorly/decomposition/_cp_power.py 81.66% <ø> (ø)
tensorly/decomposition/_symmetric_cp.py 82.25% <ø> (ø)
tensorly/tenalg/proximal.py 100.00% <ø> (ø)
tensorly/contrib/decomposition/_tt_cross.py 89.37% <100.00%> (ø)
...ecomposition/tests/test_mps_decomposition_cross.py 100.00% <100.00%> (ø)
tensorly/datasets/synthetic.py 96.15% <100.00%> (ø)
tensorly/decomposition/robust_decomposition.py 100.00% <100.00%> (ø)
...rly/tenalg/tests/test_generalised_inner_product.py 100.00% <100.00%> (ø)
tensorly/tenalg/tests/test_n_mode_product.py 100.00% <100.00%> (+4.44%) ⬆️
tensorly/tests/test_cp_tensor.py 100.00% <100.00%> (ø)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f0b701e...36c5710. Read the comment docs.

@aarmey

aarmey commented Feb 11, 2021

Copy link
Copy Markdown
Contributor Author

@JeanKossaifi this should be ready to review when you have a chance.

@JeanKossaifi

Copy link
Copy Markdown
Member

Thanks @aarmey, it's great to have this!
Can you merge in the main branch? I fixed an error in the github action script that caused the tests to always be run using TensorLy.

@aarmey

aarmey commented Feb 11, 2021

Copy link
Copy Markdown
Contributor Author

Done @JeanKossaifi. MXNet seems to be extra picky about types, so I needed to adjust a few places where ints were being passed in. Everything is working aside from the robust PCA test, which I can't seem to fix. Has something changed about it recently?

skip_if_jax = pytest.mark.skipif(tl.get_backend() == "jax",
reason="Operation not supported in JAX")
skip_if_backend = pytest.mark.skipif(tl.get_backend() in ("tensorflow", "jax", "mxnet"),
reason=f"Operation not supported in {tl.get_backend()}")

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.

Why are we skipping for MXNet? I am planning to fix this for JAX and tensorflow too, should be mostly a matter of doing the index assignment with index_update.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed (mostly). See below.

@JeanKossaifi

Copy link
Copy Markdown
Member

The issue with the Robust PCA must be due to the changes in the MXNet backend: the test still passes for the other backends and the last changes where made almost a year ago (same for the test, only the random_kruskal was replaced by random_cp). Could it be due to the fact that the dtype is no longer set to float32 by default?

@aarmey

aarmey commented Feb 11, 2021

Copy link
Copy Markdown
Contributor Author

Ok, thanks. I'll try and track down the change...

Comment thread tensorly/backend/mxnet_backend.py Resolved
@JeanKossaifi

Copy link
Copy Markdown
Member

If the issue just comes from a dtype issue, then setting the default to None for the dtype as in NumPy might solve the issue. We can then let NumPy/MXNet choose the best dtype based on the input.


# Delete the selected row
mask.pop(max_row_idx)
mask.pop(tl.to_numpy(max_row_idx))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

MXNet does not automatically make scalars standard Python types, and so this is required to work with pop.

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.

Yes, I was explicitely typecasting in argmax to make up for that strange behaviour.

@skip_if_tensorflow

@skip_if_backend
@pytest.mark.skipif(tl.get_backend() in ("mxnet"), reason=f"MXNet bug in advanced indexing (Issue 18919).")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've gotten the other TT methods to work, but this one has an indexing problem where core is first created. I believe it's the same issue as this Issue on the MXNet repository.

if mask is None:
mask = 1
else:
mask = T.tensor(mask, dtype=float)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

MXNet is not properly promoting a boolean/integer-type array when multiplied by a scalar float. The threshold was being converted to 0 below.

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.

That was a tricky one, kuddos for finding/fixing it!
That's a very odd behavior from MXNet -- we could report in the main repo.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Definitely was tricky—I got lucky by seeing rec_X was always 0 with a mask.

apache/mxnet#19891

@aarmey

aarmey commented Feb 11, 2021

Copy link
Copy Markdown
Contributor Author

Everything should be resolved @JeanKossaifi

def argmin(data=None, axis=None):
res = nd.argmin(data, axis)
if res.shape == (1,):
return res.astype('int32').asscalar()

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.

I had added these asscalar and typecasting where appropriate to compensate for the issue with 0-order tensors. Do you think it's better to remove them all?

@JeanKossaifi

Copy link
Copy Markdown
Member

Looks good to me overall -- do you think it's better to not do any typecasting or asscalar() in the backend?

@aarmey

aarmey commented Feb 12, 2021

Copy link
Copy Markdown
Contributor Author

Hmm... I'm happy to go with your preference, but think the casting makes more sense this way. I think MXNet is often doing this automatically (e.g., Python's min() works in RPCA) and the only place where an issue arises is with list.pop().

In TT, the mask list could also be implemented as an array, if we made np.delete or its equivalent available as an alternative to list.pop().

It seems more surprising that operations would fundamentally change the type of a variable depending upon the shape you end up with. My mental model of Tensorly is that it provides high-level abstractions of operations that mostly remain within the backend.

@JeanKossaifi

Copy link
Copy Markdown
Member

I agree - best to let the backend decide as long as it doesn't break things for us.
Yes, the tt-cross needs some work.

Thanks for the PR, merging!

@JeanKossaifi
JeanKossaifi merged commit 4215e3d into tensorly:main Feb 12, 2021
@aarmey
aarmey deleted the upgrade-mxnet branch February 12, 2021 16:17
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.

2 participants