Giter Site home page Giter Site logo

Comments (5)

nlw0 avatar nlw0 commented on August 16, 2024 1

I could finally take a look at the code. Apologies I don't have a concrete answer or a working patch yet, but here's theory to what may be happening:

LOC 1

@inbounds idx[j] = tree.indices[idx[j]]

At this point in the code we have had initialized the indices array with -1, and the distances with Inf. The code is probably assuming that by now the indices have all become valid. With a distance of NaN, though, we still have a -1 indices there, and then we can assign tree.indices[-1] to idx[j], what is allowed by the @inbounds . This is how we get crazy values in the output.

LOC 2

if new_min < best_dists[1]

I believe the ultimate reason this ends up happening is because any tests with a distance of NaN will return false, including NaN < Inf. Notice it's the same for Inf in this line. Here is potentially where this may be happening.

I think the solution for that may actually involve some decisions about how the whole thing can behave. If the metric function was returning Inf when we get NaN, this might help, but I'm not sure this would guarantee the proper initialization of the indices. We might actually have to initialize them with eg 1 as well, and then in the end we would get (1, Inf) for such NaN points. Or we could even do something nifty and use "nothing" as the index, since this should be the neat way to implement an optional class for integers, that in the end is kind of what NaN is. In any case, we probably want to do something to prevent invalid array accesses based on these NaN values (and Infs?), which unfortunately are all valid Float64. Actually testing the inputs to detect NaNs would be the other path...

from nearestneighbors.jl.

nlw0 avatar nlw0 commented on August 16, 2024 1

I think initializing with 1 should be just fine, any match might be considered "good" for a NaN or Inf distances, as long as we have that distance value along with the result to judge what happened. It's a good thing if we guarantee always valid indices. The other approach is a neat handling of NaN as an optional class, either returning nothing or a guaranteed invalid index such as 0, which I'm not really a big fan of. In my opinion, returning 1 to an Inf distance, and mapping NaN distances to Inf should be fine for this code.

I don't believe there really is a Julian way to do this, because part of it is about application domain decisions. Although using nothing is indeed more or less the Julian way to implement an optional class, similar to modern C++ std::option, or the Scala option etc, or the hacky way we use "None" "null" and pointer to zero in JavaScrip, Python C etc... So returning a nothing index would probably be a neat way to do it, but I personally think ensuring valid indices would be better.

from nearestneighbors.jl.

axsk avatar axsk commented on August 16, 2024

I also experience the problem of non-existent large returned indices. Will have to investigate further.
Maybe #78 might be related?

from nearestneighbors.jl.

KristofferC avatar KristofferC commented on August 16, 2024

Clearly, something is going bananas somewhere. I think this just has to be honestly debugged with print statements and whatnot to find out where things go bad.

from nearestneighbors.jl.

axsk avatar axsk commented on August 16, 2024

Handling of nothing/null/Nan seems to be an never ending story. Initialization with 1 has the problem that in the worst case when not checking the distance, one might just reference into 1, obtaining a wrong result. I prefer the initialization with nothing, but this can lead to exceptions where if one doesn't expect nothing, though that probably is what should happen (and its more informative then some random Int). However I cannot tell how this comes down to performance...

A dirty compromise (still and Int, but throwing out of bound exceptions) might be returning 0.

Is there a Julian way to deal with NaN/nothings?

from nearestneighbors.jl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.