Skip to content
This repository was archived by the owner on Nov 17, 2025. It is now read-only.

Remove MaxAndArgmax Op#874

Closed
aerubanov wants to merge 3 commits intoaesara-devs:mainfrom
aerubanov:maxandargmax_refactoring
Closed

Remove MaxAndArgmax Op#874
aerubanov wants to merge 3 commits intoaesara-devs:mainfrom
aerubanov:maxandargmax_refactoring

Conversation

@aerubanov
Copy link
Copy Markdown
Contributor

@aerubanov aerubanov commented Mar 23, 2022

Closes #765

@aerubanov aerubanov marked this pull request as draft March 23, 2022 13:32
@brandonwillard brandonwillard added the refactor This issue involves refactoring label Apr 14, 2022
@brandonwillard brandonwillard changed the title Remove MaxAndArgmax Op Remove MaxAndArgmax Op Apr 28, 2022
Copy link
Copy Markdown
Member

@brandonwillard brandonwillard left a comment

Choose a reason for hiding this comment

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

Looks like this is making good progress; much appreciated!

Comment thread aesara/tensor/math.py Outdated
Comment thread aesara/tensor/math.py Outdated
Comment thread aesara/tensor/math.py Outdated
Comment thread aesara/tensor/math.py Outdated
Comment thread aesara/tensor/opt_uncanonicalize.py Outdated
Comment thread tests/link/test_numba.py
Comment on lines -2140 to -2136
def test_MaxAndArgmax(x, axes, exc):
g = aem.MaxAndArgmax(axes)(x)

if isinstance(g, list):
g_fg = FunctionGraph(outputs=g)
else:
g_fg = FunctionGraph(outputs=[g])

cm = contextlib.suppress() if exc is None else pytest.warns(exc)
with cm:
compare_numba_and_py(
g_fg,
[
i.tag.test_value
for i in g_fg.inputs
if not isinstance(i, (SharedVariable, Constant))
],
)
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 can add a new pytest.mark.parametrize and parameter that cycles through the two now independent Ops and runs the same tests.

assert softmax_grad_legacy not in ops


def test_argmax_pushdown():
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.

It should be possible to refactor these so that they work with each Op separately.

Comment thread tests/tensor/test_math.py
f([[0, 1, 2]])


class TestMaxAndArgmax:
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.

These tests need to be converted to work with the two Ops , as well.

from tests.link.test_link import make_function


class TestMaxAndArgmax:
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 here.

Comment thread tests/tensor/test_math_opt.py Outdated
@aerubanov
Copy link
Copy Markdown
Contributor Author

@brandonwillard, thanks for the review! I will work on the requested changes.

@aerubanov
Copy link
Copy Markdown
Contributor Author

Hi @brandonwillard! I have the test that fails because max() here https://github.com/aerubanov/aesara/blob/b310d4dc10c959e5b7917159dea8397aceaba56f/aesara/tensor/math.py#L561 does not work correctly when the input tensor has a value that is the maximum of the uint64 type. I don't understand why this happens and what needs to be changed to fix it. Could you take a look when you have a chance?

Copy link
Copy Markdown
Member

@brandonwillard brandonwillard left a comment

Choose a reason for hiding this comment

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

I just made some small fixes and rebased onto main. The errors I'm seeing now are due to the unfinished Numba implementations. Is that older, more cryptic error still present? (Nevermind, I see it in tests.tensor.test_math.TestMinMax.test_uint. I'll look into it.)

Since these commits need to be restructured/squashed anyway, it would be good to reorganize them so that the Max and ArgMax updates and their corresponding tests are added first (e.g. in a single commit or one for each Op along with their JAX and Numba implementations), then the removal/replacement of MaxAndArgmax in another commit.

@aerubanov
Copy link
Copy Markdown
Contributor Author

@brandonwillard Thanks for the review! I'll be working on those changes.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 10, 2022

Codecov Report

Merging #874 (af1f40b) into main (be222f0) will decrease coverage by 0.04%.
The diff coverage is 90.62%.

❗ Current head af1f40b differs from pull request most recent head 114bf01. Consider uploading reports for the commit 114bf01 to get more accurate results

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #874      +/-   ##
==========================================
- Coverage   79.25%   79.20%   -0.05%     
==========================================
  Files         152      152              
  Lines       47882    47882              
  Branches    10909    10906       -3     
==========================================
- Hits        37949    37926      -23     
- Misses       7436     7454      +18     
- Partials     2497     2502       +5     
Impacted Files Coverage Δ
aesara/ifelse.py 49.85% <ø> (+0.14%) ⬆️
aesara/tensor/math.py 90.06% <88.23%> (+0.26%) ⬆️
aesara/link/jax/dispatch.py 81.34% <100.00%> (-0.43%) ⬇️
aesara/link/numba/dispatch/elemwise.py 93.00% <100.00%> (-4.13%) ⬇️
aesara/tensor/nnet/basic.py 80.34% <100.00%> (+0.06%) ⬆️
aesara/tensor/opt_uncanonicalize.py 96.42% <100.00%> (+0.39%) ⬆️
aesara/link/numba/dispatch/basic.py 87.25% <0.00%> (-4.81%) ⬇️
aesara/sparse/type.py 72.11% <0.00%> (-2.66%) ⬇️
aesara/link/numba/dispatch/tensor_basic.py 97.95% <0.00%> (-2.05%) ⬇️
... and 37 more

@aerubanov
Copy link
Copy Markdown
Contributor Author

Hi @brandonwillard ! I seem to be able to fix the errors that occurred after removing MaxAndArgmax. Now I'm going to edit the commit history. But I would also like to ask you to review my changes and pay attention to the following points:

  • I implemented Max as COp using MaxAndArgmax code, because it allows me to fix tests.tensor.test_math.TestMinMax.test_uint (see previous comments). But may be it is not the best option;
  • I keep max_and_argmax() because it is part of API - now it create Max and Argmax nodes. Do we want to keep this function or I should make it deprecated?

@aerubanov aerubanov marked this pull request as ready for review July 15, 2022 16:37
@aerubanov aerubanov requested a review from brandonwillard July 15, 2022 16:37
Copy link
Copy Markdown
Member

@brandonwillard brandonwillard left a comment

Choose a reason for hiding this comment

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

Looks like an extra file got added: aesara/tensor/\.

Comment on lines +3599 to +3600
# at_max,
# at_min,
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 have the max and min functions been removed from TestLocalReduce?

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.

@brandonwillard I moved the MaxAndArgmax functionality to Max and now Max is implemented as a COp, so the tests for CAReduce will not work with Max.

Comment thread aesara/tensor/math.py Outdated
Comment on lines +470 to +257
def R_op(self, inputs, eval_points):
raise ValueError("Argmax is not a differentiable operation")

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.

Suggested change
def R_op(self, inputs, eval_points):
raise ValueError("Argmax is not a differentiable operation")

There's already a grad implementation—albeit effectively non-functional—so I don't know if it helps to have an R_op like this. Also, I don't think a ValueError would be the best here.

If a gradient is undefined, I believe we should return an aesara.gradient.grad_undefined-generated NullType. Same with unimplemented gradients: we should use aesara.gradient.grad_not_implemented.

aerubanov and others added 3 commits July 18, 2022 18:38
…ly.github.com>

modify Max

Co-authored-by: Brandon T. Willard <971601+brandonwillard@users.noreply.github.com>
Co-authored-by: Brandon T. Willard <971601+brandonwillard@users.noreply.github.com>
Co-authored-by: Brandon T. Willard <971601+brandonwillard@users.noreply.github.com>
@aerubanov
Copy link
Copy Markdown
Contributor Author

@brandonwillard I removed Argmax`s R_op and replace Value Error on aesara.gradient.grad_undefined.

@aerubanov aerubanov requested a review from brandonwillard July 19, 2022 09:10
@aerubanov
Copy link
Copy Markdown
Contributor Author

@brandonwillard, just soft reminder)

Copy link
Copy Markdown
Member

@brandonwillard brandonwillard left a comment

Choose a reason for hiding this comment

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

Looks like one of the commit messages got scrambled.

Comment thread aesara/tensor/math.py
Comment on lines -625 to +404
class Max(NonZeroCAReduce):
nfunc_spec = ("max", 1, 1)
class Max(COp):
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 aren't we using the NonZeroCAReduce base class for this?

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.

@brandonwillard Thank you for review. To fix this #874 (comment) problem with Max I coped the code from MaxAndArgmax and made it COp. Do you think that it can add some problems?

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.

It could interfere with existing code that assumes Max is a subclass of NonZeroCAReduce (e.g. rewrites, our JAX and/or Numba implementations, etc.)

Also, we generally want to make use of existing code. In this case, subclassing NonZeroCAReduce could make adding a C implementation much easier that it otherwise would be.

Comment thread tests/tensor/test_math.py
Comment on lines -750 to +751
MaxAndArgmax.debug = 0
Argmax.debug = 0
Max.debug = 0
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.

What do these do?

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.

Hm, it looks like a piece of old code. I think I should to remove it.

@aerubanov aerubanov closed this by deleting the head repository Jul 29, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

refactor This issue involves refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove MaxAndArgmax

2 participants