Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added nanprod to ivy experimental API #21198

Merged
merged 13 commits into from
Sep 5, 2023

Conversation

BebehCodes
Copy link
Contributor

Close #21196

@ivy-leaves ivy-leaves added Array API Conform to the Array API Standard, created by The Consortium for Python Data API Standards Ivy API Experimental Run CI for testing API experimental/New feature or request PaddlePaddle Backend Developing the Paddle Paddle Backend. Ivy Functional API labels Aug 2, 2023
# Conflicts:
#	ivy/functional/backends/numpy/experimental/statistical.py
#	ivy/functional/backends/paddle/experimental/statistical.py
#	ivy/functional/backends/tensorflow/experimental/statistical.py
#	ivy/functional/backends/torch/experimental/statistical.py
Copy link
Contributor

@nassimberrada nassimberrada left a comment

Choose a reason for hiding this comment

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

Hi @BebehCodes, thank you for your contribution ! I've left a few comments could you try to address them ? Overall I think this is going in the right direction we just need to refine some corners. Let me know how this goes. Thanks !

--------
>>> a = ivy.Container(x=ivy.array([[1, 2], [3, ivy.nan]]),\
y=ivy.array([[ivy.nan, 1, 2], [1, 2, 3]])
>>> ivy.Container.static_moveaxis(a)
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume you mean static_nanprod, careful when copying examples from other functions

--------
>>> a = ivy.Container(x=ivy.array([[1, 2], [3, ivy.nan]]),\
y=ivy.array([[ivy.nan, 1, 2], [1, 2, 3]])
>>> ivy.Container.static_moveaxis(a)
Copy link
Contributor

Choose a reason for hiding this comment

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

Likewise. Also this should be a.nanprod(axis, etc...)

The product of array elements over a given axis treating
Not a Numbers (NaNs) as ones

Functional Examples
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you include more examples that have variations of the other arguments (axis, keepdims etc...) for comprehensiveness ?

):
input_dtype, x, axis, castable_dtype = dtype_x_axis_castable
x = x[0]
# Added clipping because the min_value and max_value arguments
Copy link
Contributor

Choose a reason for hiding this comment

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

This works but it would be good if the helper function could be properly used to set the necessary boundaries

x = x[0]
# Added clipping because the min_value and max_value arguments
# don't seem to clip the returned array.
# Also, for really big/small numbers some backends return something like Xe300
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't be avoiding these corner cases, instead the output should remain uniform across backends. If different backends return different outputs for the same input values then I suggest you take the majority output as your target and modify the implementation of the backends that don't provide this output such that they do.

and on_device == "cpu"
)
)
# This assumption is made because for some reason when
Copy link
Contributor

Choose a reason for hiding this comment

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

Likewise here, we don't want to just avoid testing for these cases. Again, I suggest you make all backend implementations converge to the majority output dtype

@BebehCodes
Copy link
Contributor Author

Hey @nassimberrada , sorry for the delayed response, I didn't have access to my workspace. I believe I took care of all your comments. Have a look and tell me what you think. Thank you!

@nassimberrada
Copy link
Contributor

Hey @BebehCodes, thanks for making those changes. Looks okay I think, the only issue left to address is the paddle backend which seems to fail, you can get more details by going to display_test_results -> Combined Test Results, and searching for the Falsifying Example for your function in the paddle backend.

Also, I noticed you modified the to_numpy function in the paddle general module, could you explain why you needed to ?

@BebehCodes
Copy link
Contributor Author

Hey @nassimberrada , thanks for your feedback. I think paddle is fixed now.

Regarding to_numpy, in some cases I noticed that a paddle bfloat16 tensor was converted to a uint16 array and my test cases would fail due to different returned types.

Have a look and tell me what you think!

@nassimberrada
Copy link
Contributor

nassimberrada commented Aug 21, 2023

Hey @BebehCodes, looks mostly good. Regarding the modified numpy function I'm afraid we can't pull this given numpy doesn't support bfloat16, I would suggest you try to tackle the dtype inconsistency by casting the incorrect dtype into the expected one as and when needed, if that makes sense. Could you revert your additions to the to_numpy function and try to address the failed cases differently ? Thanks!

# Conflicts:
#	ivy_tests/test_ivy/helpers/function_testing.py
@BebehCodes
Copy link
Contributor Author

Hey @nassimberrada , I've tried handling it by either doing casting when this occurs while testing, etc, but the thing is that the wrong casting that happens from to_numpy also changes the final results due to the different types, so I can handle the different dtypes but I can't seem to be able to do something about the numerical results. I noticed that something similar happens to torch's to_numpy where they also handle the bfloat16 type exclusively, similarly to how I did it for paddle. Is it possible that this could be the correct solution?
Thank you!

@nassimberrada
Copy link
Contributor

Hey, sorry for the delayed feedback. I understand, but are we sure the errors are caused by data type discrepancies ? Some of the value mismatches seem to indicate there might be another issue at play, for e.g this one

 AssertionError:  the results from backend paddle and ground truth framework tensorflow do not match
    16256.0!=1.0 
   Falsifying example: test_nanprod(
       backend_fw='paddle',
       on_device='cpu',
       dtype_x_axis_castable=('bfloat16',
        [array([1], dtype=bfloat16)],
        0,
        'bfloat16'),
       keep_dims=False,
       [rest of the error]

Does the fix you added to _to_numpy() solve these issues ? Also I see you're making changes to a function in the helper functions modules, is this for testing purposes ? Ideally we would want to contain function-specific testing within the function's test, but maybe this is serving another purpose.
One last point, I'm not sure if i'm seeing an input generation strategy for the initial argument. If not then we should probably be accounting for it as well. Thanks!

@BebehCodes
Copy link
Contributor Author

Hey @nassimberrada , sorry for the confusion, I reverted the changes of to_numpy and pushed them, so that's why you are seeing this error. This value difference seems to happen because some weird overflowing or something happens because the paddle tensor is cast to uint16 instead of keeping its bfloat16 type. With the changes in to_numpy I didn't come across something similar and seemed to fix this issue as well.

The changes I made in the function helpers were in order to handle the error since I reverted to_numpy back to its original implementation, but they didn't seem to work.

Yes you are right about initial, I will add the strategy!

Generally, I haven't figured out a way to bypass the wrong casting that happens by paddle's to_numpy other than the changes I made previously regarding the handling of bfloat16.

@nassimberrada
Copy link
Contributor

Hey, thanks for clarifying. I think the same remark applies to your additions to the helper function, ideally we want to keep these exception handling cases contained within the function. With that said, have you tried making use of the with_unsupported_dtypes decorator ? I believe this could be warranted as you're making use of functions that have a restricted set of supported data types such as paddle.nan_to_num which only takes float32 and float64, as shown in the documentation. I suggest you take a look at the corresponding section of our docs to explore this a bit. Let me know how this goes, thanks!

@BebehCodes
Copy link
Contributor Author

Hey @nassimberrada . Thanks a lot for your suggestion! I added the supported dtypes decorator and the tests are passing for all backends. Also, I added the strategy for the initial argument as well.
Have a look and tell me what you think!
Thanks!

@nassimberrada
Copy link
Contributor

Yeah, looks good to me now, great work!. I'll be merging then, thanks again for contributing!

@nassimberrada nassimberrada merged commit b507163 into ivy-llc:main Sep 5, 2023
107 of 133 checks passed
druvdub pushed a commit to druvdub/ivy that referenced this pull request Oct 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Array API Conform to the Array API Standard, created by The Consortium for Python Data API Standards Ivy API Experimental Run CI for testing API experimental/New feature or request Ivy Functional API PaddlePaddle Backend Developing the Paddle Paddle Backend.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

nanprod
3 participants