Project-MONAI / MONAI

AI Toolkit for Healthcare Imaging
https://monai.io/
Apache License 2.0
5.5k stars 1.01k forks source link

Numpy 2.0 Behaviour Changes #7856

Open ericspod opened 1 week ago

ericspod commented 1 week ago

Describe the bug Numpy 2.0 was just released with some behavioural changes which are showing up as bugs. One that is seen in this trace:

 Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/runner/work/MONAI/MONAI/tests/min_tests.py", line 239, in <module>
    result = test_runner.run(run_testsuit())
  File "/home/runner/work/MONAI/MONAI/tests/min_tests.py", line 226, in run_testsuit
    test_suite = unittest.TestLoader().loadTestsFromNames(cases)
  File "/opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/unittest/loader.py", line 220, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
  File "/opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/unittest/loader.py", line 220, in <listcomp>
    suites = [self.loadTestsFromName(name, module) for name in names]
  File "/opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/unittest/loader.py", line 154, in loadTestsFromName
    module = __import__(module_name)
  File "/home/runner/work/MONAI/MONAI/tests/test_inverse_collation.py", line 55, in <module>
    TESTS_3D = [
  File "/home/runner/work/MONAI/MONAI/tests/test_inverse_collation.py", line 62, in <listcomp>
    Compose([RandRotate90d(keys=KEYS, spatial_axes=(1, 2))]),
  File "/home/runner/work/MONAI/MONAI/monai/transforms/compose.py", line 251, in __init__
    self.set_random_state(seed=get_seed())
  File "/home/runner/work/MONAI/MONAI/monai/transforms/compose.py", line 263, in set_random_state
    _transform.set_random_state(seed=self.R.randint(MAX_SEED, dtype="uint32"))
  File "/home/runner/work/MONAI/MONAI/monai/transforms/transform.py", line 207, in set_random_state
    _seed = _seed % MAX_SEED
OverflowError: Python integer 4294967296 out of bounds for uint32

The underlying issue is that the MAX_SEED value is 2**32 which is an overflow value for uint32. It is stored as a Python int but when used as the right hand side of modulus in this expression where _seed is a uint32 of any value, the exception shown above is raised. In Numpy before 2.0, the expression would silently produce a int64 result.

To Reproduce Steps to reproduce the behavior:

  1. Import Numpy 2.0 as np
  2. Attempt evaluate np.uint32(1)%(np.iinfo(np.uint32).max+1)
  3. This will raise an exception rather than silently produce a np.int64 result as happens in Numpy<2.0

Expected behavior No exception should be raise for this operations if the MAX_SEED value is set correctly. The result from the expression should be a uint32.

Environment

Ensuring you use the relevant python executable, please paste the output of:

pip install numpy\>=2.0
python -c "import numpy as np;print(np.uint32(1)%(np.iinfo(np.uint32).max+1))"

Additional context This was encountered when doing a PR on the gen-ai-dev branch. @virginiafdez

ericspod commented 1 week ago

The current temporary fix is to disable Numpy 2.0 in requirements.txt and then we'll work on compatibility fixes. There are other issues beyond the raised here in terms of deterministic behaviour and accuracy and seen in tests when run with Numpy 2.0 and some fixes I tried.