You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Thanks a lot for the pull request. Can you please help elaborate on the differences between this PR and scipy's implementations (from a mathematical or computational perspective)? I am asking because scipy is already a dependency.
Thanks a lot for the pull request. Can you please help elaborate on the differences between this PR and scipy's implementations (from a mathematical or computational perspective)? I am asking because scipy is already a dependency.
Thanks for the question! Even though scipy is already a project dependency, implementing cosine and dice directly in selector.measures.similarity using NumPy is both mathematically necessary and computationally advantageous for several reasons:
1. Mathematical Differences & Input Domains
Dice is fundamentally different for continuous vectors:
scipy.spatial.distance.dice is strictly designed for boolean 1-D vectors ($u, v \in {0, 1}^p$). It computes boolean frequency counts ($c_{TF}, c_{FT}, c_{TT}$). If continuous/floating-point vectors are passed, SciPy computes $(1 - u)$ as negative values, producing invalid or even negative distance values (as noted in SciPy's own docstring example: dice([1, 0, 0], [2, 0, 0]) == -0.3333).
In contrast, this PR implements the continuous Sørensen-Dice similarity: $$S_{\text{dice}}(a, b) = \frac{2 (a \cdot b)}{|a|^2 + |b|^2}$$
For binary vectors, this formula reduces identically to $1 - \text{scipy.spatial.distance.dice}$. For continuous features, it provides a well-defined $L_2$ extension that preserves the exact monotonic relationship with Selector's continuous Tanimoto ($T$): $$S_{\text{dice}} = \frac{2T}{1 + T}$$
Return Convention (Similarity vs. Distance):
SciPy's metrics are distances/dissimilarities ($d \in [0, 2]$ for cosine, $d \in [0, 1]$ for dice).
Selector’s measures are similarities ($S \in [-1, 1]$), which directly align with Selector's selection algorithms (where subset similarity is minimized).
Zero-Vector Handling:
In SciPy, calling distance.cosine(u, v) or distance.dice(u, v) with zero vectors results in a 0/0 division, returning nan and issuing a RuntimeWarning: invalid value encountered in scalar divide.
In this PR, zero vectors are explicitly handled and return 0.0, avoiding nan contamination in pairwise similarity matrices and downstream selectors.
2. Computational & Architectural Considerations
Single-Pair Overhead:
Benchmarking 10,000 vector comparisons ($D=1024$), the NumPy implementation is ~1.5x faster than wrapping 1.0 - scipy.spatial.distance.cosine ($3.31,\mu\text{s}$ vs. $5.24,\mu\text{s}$ per call) because it avoids SciPy's internal validation wrappers (_validate_vector, _validate_weights, etc.).
Consistency:
All existing pairwise metrics in selector.measures.similarity (tanimoto, modified_tanimoto, similarity_index) are native NumPy implementations. Implementing cosine and dice natively keeps the API, error messaging, and internal design completely consistent across the module.
In summary, SciPy's dice cannot be reused because it does not support continuous vectors, and wrapping SciPy's cosine would introduce nan issues on zero vectors and unnecessary wrapper overhead.
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related to #124
This PR adds two similarity metrics to the existing similarity module:
cosine)dice)Changes:
cosine()anddice()inselector/measures/similarity.pyusing NumPy.__all__where appropriate.pairwise_similarity_bit()metric dispatch to support"cosine"and"dice".Notes for reviewers:
dicedistance.