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

Custom metric gives error #257

Closed
alior101 opened this issue Oct 11, 2023 · 3 comments
Closed

Custom metric gives error #257

alior101 opened this issue Oct 11, 2023 · 3 comments

Comments

@alior101
Copy link

Trying a simple custom metric (which is just euclidian distan)


struct MyMetric <: SemiMetric end

function (::MyMetric)(a::AbstractVector, b::AbstractVector)
    sum(abs.(a - b))
end

R = kmeans(vecs, clusters_num; maxiter=400, display=:iter, distance=MyMetric())

I'm getting

ERROR: MethodError: no method matching (::MyMetric)(::Float64, ::Float64)
Stacktrace:
 [1] result_type(f::MyMetric, a::Type, b::Type)
   @ Distances ~/.julia/packages/Distances/yhVAl/src/generic.jl:36
 [2] result_type(dist::MyMetric, a::Matrix{Float64}, b::LinearAlgebra.Adjoint{Float64, Matrix{Float64}})
   @ Distances ~/.julia/packages/Distances/yhVAl/src/generic.jl:35
 [3] pairwise(metric::MyMetric, a::Matrix{Float64}, b::LinearAlgebra.Adjoint{Float64, Matrix{Float64}}; dims::Int64)
   @ Distances ~/.julia/packages/Distances/yhVAl/src/generic.jl:320
 [4] _kmeans!(X::LinearAlgebra.Adjoint{Float64, Matrix{Float64}}, weights::Nothing, centers::Matrix{Float64}, maxiter::Int64, tol::Float64, displevel::Int64, distance::MyMetric, rng::Random._GLOBAL_RNG)
   @ Clustering ~/.julia/packages/Clustering/8WUOQ/src/kmeans.jl:141
 [5] kmeans!(X::LinearAlgebra.Adjoint{Float64, Matrix{Float64}}, centers::Matrix{Float64}; weights::Nothing, maxiter::Int64, tol::Float64, display::Symbol, distance::MyMetric, rng::Random._GLOBAL_RNG)
   @ Clustering ~/.julia/packages/Clustering/8WUOQ/src/kmeans.jl:71
 [6] kmeans!
   @ ~/.julia/packages/Clustering/8WUOQ/src/kmeans.jl:46 [inlined]
 [7] kmeans(X::LinearAlgebra.Adjoint{Float64, Matrix{Float64}}, k::Int64; weights::Nothing, init::Symbol, maxiter::Int64, tol::Float64, display::Symbol, distance::MyMetric, rng::Random._GLOBAL_RNG)
   @ Clustering ~/.julia/packages/Clustering/8WUOQ/src/kmeans.jl:114

Any idea what am I missing ?

@alior101
Copy link
Author

Ok, I figured this out alone.. Documenting for anyone elese exepriencing this
Turns out that the distance function types must match

function (::MyMetric)(a::Float64, b::Float64)
    sum(abs.(a - b))
end

fixed it

@dkarrasch
Copy link
Member

As it says (I understand that we are not very good spelling out the requirements upfront): you need to define another method that deals with the "scalar" case:

(::MyMetric)(a::Float64, b::Float64) = abs(a - b)

This is required for the determination of the target eltype.

Note that your example is the squared Euclidean distance. Which means that integer vectors yield an integer distance. If you want the Euclidean distance (just to demonstrate the reasoning), you should take the square root in your vector-method, and perhaps define

(::MyMetric)(a::Float64, b::Float64) = float(a - b)

@KwatMDPhD
Copy link

This issue should be closed. The above answers are good! Thank you.

I did (::MyMetric)(::Real, ::Real) = NaN.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants