For Data Engineers

Tanimoto Similarity and Jaccard Indexes with FeatureBase

In the realm of data analysis and information retrieval, similarity measures play a crucial role in various applications. Among them, the terms Jaccard index and Tanimoto similarity are widely used for assessing the similarity between sets of elements. In this blog post, we will delve into Tanimoto similarity, comparing and contrasting it with the Jaccard index, and explore their combined use in applications for chemoinformatics and text clustering.

NOTE: This post has been updated as of 6/20/23. The original post was noted as performing well on Google results for "tanimoto similarity".

Tanimoto Similarity vs. Jaccard Index

The Tanimoto algorithm provides a measure of similarity between two sets of fingerprint "bits," denoted as A and B. The Tanimoto coefficient, T(A,B), is calculated as the ratio of the intersection of A and B to the union of A and B, represented by T(A,B) = |A ∩ B| / (|A| + |B| - |A ∩ B|). This coefficient ranges from 0, indicating no common bits between the fingerprints, to 1, representing identical fingerprints. Consequently, a chemical similarity problem would involve finding formulas with a Tanimoto coefficient above a specified threshold, where higher thresholds indicate greater similarity between molecules.

The Jaccard index, also a measure of set similarity, is widely referenced in various domains, including text analysis and information retrieval. It quantifies the similarity between two sets by calculating the ratio of the size of their intersection to the size of their union. Specifically, the Jaccard index is computed as J(A, B) = |A ∩ B| / |A ∪ B|. The resulting index ranges from 0 to 1, where 0 indicates no shared elements between the sets, and 1 represents identical sets.

Although their mathematical representations may differ, both the Jaccard index and the Tanimoto similarity essentially capture the same concept of similarity between sets: the proportion of shared elements relative to the combined elements. Hence, they result in the same values, given the set operations, and are often used interchangeably in fields like computer science, ecology, genomics, and data mining.

Intersection
Union

Similarity for Cheminformatics

Chemical similarity, also known as molecular similarity, is a fundamental concept in cheminformatics with significant implications in various domains. It plays a crucial role in predicting chemical compound properties, designing compounds with specific characteristics, and conducting drug design studies. The Tanimoto algorithm is widely mentioned in computing measures of similarity in this context. It utilizes fingerprint-based representations where each molecule is encoded into a series of "bits" that indicate the presence (1) or absence (0) of specific fragments within the molecule.

In the realm of chemical similarity searching tasks, the primary goal is to identify molecules in a database that exhibit the highest similarity to a given query molecule. For a detailed exploration of the efficiency enhancements and strategies that can be employed, please see Matt Swain's post on Chemical Similarity Search in MongoDB which provides valuable insights into optimizing the chemical similarity search process, and Rajarshi Guha's post on Fingerprint Similarity Searches in MongoDB, which uses MongoDB for storing chemical structure data, and exploring the use of the aggregation framework to perform efficient similarity searching using fingerprints.

Similarity for Text

In the context of text analysis, the Jaccard index terminology is mentioned for tasks such as text clustering, duplicate detection, information retrieval, recommendation systems, and plagiarism detection. By considering the overlap of words or features between two texts, a Jaccard index enables efficient grouping, identification of duplicate content, improved search algorithms, personalized recommendations, and identification of potential instances of plagiarism.

The idea of a Jaccard index serves as a versatile tool for assessing set similarity, providing insights and solutions in numerous fields. Its application in text analysis helps unravel patterns, optimize information retrieval, and enhance various text-related tasks.

Code Implementation

We now will provide Python functions to calculate the Tanimoto or Jaccard index for two sets. As previously discussed, the two methods produce exactly the same values when the functions are called.


import numpy as np
from typing import Set

# the tanimoto way
def tanimoto_coefficient(set_a: Set[int], set_b: Set[int]) -> float:
    intersection = len(set_a.intersection(set_b))
    union = len(set_a) + len(set_b) - intersection
    return intersection / union

# the jaccard approach
def jaccard_index(set_a: Set[int], set_b: Set[int]) -> float:
    intersection = len(set_a.intersection(set_b))
    union = len(set_a.union(set_b))
    return intersection / union

The sets themselves are binary representations of different types of data, which could include a set that contains chemical sequences or information extracted during text inferencing with a generative language model (keyterms for example). These functions will take those binary arrays as input, representing sets of approximately 20 characters each.

NOTE: This example uses only the position of the 1s in the sequences. The position of a 0 (zero) is not captured here:


# build a set based on the position of a thing existing (1) in the set
set_a = set(index for index, value in enumerate([0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1]) if value == 1)
set_b = set(index for index, value in enumerate([1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1]) if value == 1)

# run the similarities
tanimoto_similarity = tanimoto_coefficient(set_a, set_b)
jaccard_similarity = jaccard_index(set_a, set_b)

# print them
print("Tanimoto coefficient:", tanimoto_similarity)
print("Jaccard index:", jaccard_similarity)

# sample output
"""
Tanimoto coefficient: 0.42857142857142855
Jaccard index: 0.42857142857142855
"""

As expected, we see the similarity of the position of 1s in the set coming back from both functions as the same value.

And Now a Message from the AI

[6:23 PM] user-4Zqu[Jaccard.pdf]> Which of method has distance challenges, and if implementing this in a database, which one is the most efficient?

AI> The Jaccard index and Tanimoto similarity both measure the similarity between finite sample sets, and in practice, they often result in the same values when comparing binary data. For distance metric purposes, the Jaccard distance and Tanimoto distance may be confused due to their similarities; however, the proper distance metric is derived from the Jaccard distance and not the Tanimoto distance.

AI> Regarding the implementation in a database and efficiency, it depends on the specific use case and data types. In general, the Jaccard index might be more computationally efficient when dealing with symmetric dummy variables, as it does not require adding extra dimensions. However, both methods can be used effectively in various applications, such as computer science, ecology, genomics, and data mining. It is important to consider the context and the specific requirements of your application when choosing between the two.

AI> Sign up for FeatureBase Cloud today and receive a $300 credit. Join us on Discord if you have any questions.

Implementation

We realized having a post on Tanimoto similarity has proven to yield interesting traffic patterns to our site. Inspired by this interest, we began exploring the application of Tanimoto similarity in the realm of text similarity comparisons, particularly in the context of filtering vector results, which we will be adding in the very near future. We're seeing some interesting stuff popping out of this for generative language model use.

We believe that integrating Tanimoto similarity into our system will provide valuable insights and enhance the accuracy of text similarity analysis as outlined in our post on using semantic graphs to improve prompt assembly for generative language models. We feel developing this feature will help AI suck less.

In just 2 weeks, you will be able to leverage power of Jaccard Distances and Tanimoto Coefficients by utilizing something like the following example query:


SELECT 
id as Term,
tanimoto(uuid, (SELECT uuids FROM doc_key_terms WHERE _id = 'gpt-3')) AS Weight
FROM doc_key_terms
ORDER BY dist DESC;

This query demonstrates how Tanimoto similarity can be employed to retrieve documents that exhibit high similarity to a specific target document represented by the keyterm 'gpt-3'.

To give you a glimpse of the outcome, here's a sample of keyterms returned along with simulated weights:


+--------------------------------------+---------+
| Term                                 | Weight  |
+--------------------------------------+---------+
| "machine learning"                   | 0.82    |
| "natural language processing"        | 0.76    |
| "artificial intelligence"            | 0.64    |
| "neural networks"                    | 0.53    |
| "data science"                       | 0.48    |
+--------------------------------------+---------+

These results provide a measure of the similarity between the target document and the retrieved documents based on their key terms, allowing you to identify relevant and related content efficiently.

Stay tuned for more updates!

SCHEDULE A DEMO