Еще один эксперимент с масками Engee Function
作者
module PDIST2
mode_dict_t = Dict(1=>"euclidean",2=>"squaredeuclidean",3=>"manhattan",4=>"cosine")
function EF_pdist2(X::Matrix{Float64}, Y::Matrix{Float64}; metric::String="euclidean")
m, n = size(X)
p, n2 = size(Y)
n == n2 || throw(DimensionMismatch("Number of columns in X and Y must match"))
if metric == "euclidean"
XX = sum(X.^2, dims=2)
YY = sum(Y.^2, dims=2)
D = XX .+ YY' .- 2 .* (X * Y')
return sqrt.(max.(D, 0))
elseif metric == "squaredeuclidean"
XX = sum(X.^2, dims=2)
YY = sum(Y.^2, dims=2)
D = XX .+ YY' .- 2 .* (X * Y')
return max.(D, 0)
elseif metric == "manhattan"
D = zeros(m, p)
for j in 1:p
for i in 1:m
D[i, j] = sum(abs.(X[i, :] .- Y[j, :]))
end
end
return D
elseif metric == "cosine"
XX = sqrt.(sum(X.^2, dims=2))
YY = sqrt.(sum(Y.^2, dims=2))
norms = XX .* YY'
XY = X * Y'
# Handle division by zero: set invalid entries to 0, then correct cases where both vectors are zero
sim = zeros(size(XY))
valid = norms .> 0
sim[valid] .= XY[valid] ./ norms[valid]
# Identify pairs where both vectors are zero (cosine similarity = 1)
both_zero = (XX .== 0) .& (YY' .== 0)
sim[both_zero] .= 1
return 1 .- sim
else
throw(ArgumentError("Unknown metric: $metric. Supported metrics are 'euclidean', 'squaredeuclidean', 'manhattan', 'cosine'"))
end
end
end