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

BUG: make resize with order=0 more robust to floating-point rounding #2648

Closed
wants to merge 3 commits into from

Conversation

grlee77
Copy link
Contributor

@grlee77 grlee77 commented May 4, 2017

Description

As reported in gh-2629, which neighbor is judged to be nearest is currently dependent on
whether numpy was built with MKL or OpenBLAS. By shifting coordinates by ~100 times machine
epsilon when order=0, this inconsistency can be avoided.

The amount of shift was determined empirically as one which gives the same result across MKL and OpenBLAS numpy builds (as tested in parallel conda environments).

I'm not sure there is a good way to properly test this fix across BLAS builds, but I did add a test verifying that for the specific example of gh-2629, the transform gives the same result for both the 2D and n-dimensional code paths.

…error

As reported in scikit-imagegh-2629, which neighbor is judged to be nearest is currently dependent on
whether numpy was built with MKL or OpenBLAS.  By shifting coordinates by ~100 times machine
epsilon when order=0, this inconsistency can be avoided.
@grlee77 grlee77 added the bug label May 4, 2017
@pep8speaks
Copy link

pep8speaks commented May 4, 2017

Hello @grlee77! Thanks for updating the PR.

Line 620:80: E501 line too long (86 > 79 characters)

Comment last updated on May 05, 2017 at 04:33 Hours UTC

@grlee77
Copy link
Contributor Author

grlee77 commented May 5, 2017

not sure what is causing the Travis failures. they don't seem related to this PR. e.g.

/home/travis/build/scikit-image/scikit-image/doc/examples/features_detection/plot_orb.py failed to execute correctly:

@soupault
Copy link
Member

Seems acceptable to me.

@mcquin Could you verify this fix?

@mcquin
Copy link

mcquin commented May 12, 2017 via email

@ahojnnes
Copy link
Member

Have you tested this for larger images as well? Something with several thousand pixels and/or larger scaling factors.

@grlee77
Copy link
Contributor Author

grlee77 commented May 12, 2017

Have you tested this for larger images as well? Something with several thousand pixels and/or larger scaling factors.

Not yet, but I will try it. Trying to account for these type of cases are why I had bumped up the offset to a much larger value than the minimum required for the specific example raised in #2629 in my second commit.

@ahojnnes
Copy link
Member

Since this is a rather critical fix that seems brittle wrt. the dimensions of the image, I suggest to do further experiments here regarding different image sizes?

@mcquin
Copy link

mcquin commented May 15, 2017

Hey @grlee77, with this change I get this result on OS X and Ubuntu 16.04.

@grlee77 grlee77 changed the title BUG: make resize with order=0 more robust to floating-point rounding WIP/BUG: make resize with order=0 more robust to floating-point rounding May 15, 2017
@grlee77
Copy link
Contributor Author

grlee77 commented May 15, 2017

please do not merge yet. Despite the apparent consistency with this toy example, in initial testing with larger sizes and scale factors I do not seem to always get identical results.

@grlee77
Copy link
Contributor Author

grlee77 commented May 15, 2017

in the toy example

Python 2.7, This patch gives consistent results across two different numpy builds. There are a total of two unique results over two numpy builds and two branches of scikit-image.
master, numpy (defaults) : result 1
master, numpy (conda-forge) : result 2
this PR, numpy (defaults) : result 2
this PR, numpy (conda-forge) : result 2
It is also the case that this result (arbitrarily labeled "result 2" here) exactly matches one of the results from the master branch.

In a larger example

randomized labels generated as:

sz = (32, 16384)
labels = np.random.rand(*sz)*4
labels = labels.astype(np.int)

results of resizing are saved out to .npy files, the numpy build or skimage branch is changed and then comparison to the previously saved results is done by loading the previously output from the other build.

master, numpy (defaults) : result 1
master, numpy (conda-forge) : result 2
this PR, numpy (defaults) : result 3
this PR, numpy (conda-forge) : result 3

So, with this PR, the result becomes consistent across numpy builds, however, unlike for the toy example the result for this branch is not identical to the result from the master branch for either numpy build. I suppose if the current behavior in master is considered a bug due to susceptibility to rounding error then this is not a problem in terms of backwards compatibliity.

consistency across numpy builds was also verified for other extreme reshape cases such as (32, 32) reshaped to (32, 100001), etc.

@grlee77 grlee77 changed the title WIP/BUG: make resize with order=0 more robust to floating-point rounding BUG: make resize with order=0 more robust to floating-point rounding May 15, 2017
@grlee77
Copy link
Contributor Author

grlee77 commented May 15, 2017

@ahojnnes
This patch seems to improve consistency even for larger test cases, but as discussed in the comment above, may result in slightly different output than current master for some inputs.

Note that the coordinate shifts are only applied when order == 0, so this will not cause in change in behaviour for the default (order=1) interpolation.

@jni
Copy link
Member

jni commented May 16, 2017

Hi @grlee77 et al!

Although I very much appreciate the effort that's gone into this PR and all the testing in #2629, I most agree with @mcquin's comment here:

I wonder if it is scikit-image's responsibility to adjust for these machine-level differences.

The proposed solution, in particular, can be qualified only as a hack, and not something I'm particularly keen to add to skimage. (I don't mean this disrespectfully btw — we all use hacks. But the standard for adding to skimage should be higher.) If we do decide that we need a solution, I would aim for something that looks at the underlying linear algebra problem being solved (is it a matrix inversion?), and what the solutions are to improve that algorithm's numerical stability.

Copy link
Member

@jni jni left a comment

Choose a reason for hiding this comment

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

See above comment #2648 (comment)

@grlee77
Copy link
Contributor Author

grlee77 commented May 16, 2017

The proposed solution, in particular, can be qualified only as a hack

Agreed. Unfortunately, I don't have the time/motivation to dig deeply into this edge case further at the moment. I understand if others do not wish to merge it as is.

@dvolgyes
Copy link
Contributor

If the decision is not to merge, then maybe it is time to close the PR, isn't it?

@stefanv
Copy link
Member

stefanv commented Aug 21, 2017

@jni I see your point, but at the same time this is a very simple modification which reduces the occurrence of a potentially nasty bug. More importantly: can we imagine any situations in which this modification would break things or propagate errors?

fbudin69500 pushed a commit to fbudin69500/debug_scikit_image_resize- that referenced this pull request Oct 5, 2018
scikit-image PR 2648 [1] reports a bug that is similar to the one
discovered in this project. Compiling scikit-image with that PR
seems to solve the discrepancy found between the two computers.

Test:
$ git clone https://github.com/scikit-image/scikit-image.git
$ cd scikit-image
$ git fetch-pr origin 2648
$ git checkout origin-pr-2648
$ mkvirtualenv scikit-debug
$ pip install -r requirements.txt
$ pip install Cython==0.23
$ pip install jupyter
$ pip install -e .

$ cd {directory containing script-resize.py}
$ ./script-resize.py
$ scp {image from computerA to computerB}
$ jupyter notebook
Load CompareImages.ipynb

[1] scikit-image/scikit-image#2648
fbudin69500 pushed a commit to fbudin69500/debug_scikit_image_resize- that referenced this pull request Oct 5, 2018
scikit-image PR 2648 [1] reports a bug that is similar to the one
discovered in this project. Compiling scikit-image with that PR
seems to solve the discrepancy found between the two computers.

Test:
$ git clone https://github.com/scikit-image/scikit-image.git
$ cd scikit-image
$ git fetch-pr origin 2648
$ git checkout origin-pr-2648
$ mkvirtualenv scikit-debug
$ pip install -r requirements.txt
$ pip install Cython==0.23
$ pip install jupyter
$ pip install -e .

$ cd {directory containing script-resize.py}
$ ./script-resize.py
$ scp {image from computerA to computerB}
$ jupyter notebook
Load CompareImages.ipynb

[1] scikit-image/scikit-image#2648
@rfezzani rfezzani added 🩹 type: Bug fix Fixes unexpected or incorrect behavior and removed type: bug labels Feb 22, 2020
Base automatically changed from master to main February 18, 2021 18:22
@grlee77
Copy link
Contributor Author

grlee77 commented Jun 20, 2021

This was not a very robust solution, so I have closed this PR

@grlee77 grlee77 closed this Jun 20, 2021
@stefanv
Copy link
Member

stefanv commented Jun 20, 2021

Thanks, Greg, I'm sorry we could not figure out a cleaner way to address this—tricky!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🩹 type: Bug fix Fixes unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants