Source code for plismbench.metrics.cosine_similarity
"""Module for cosine similarity metric."""
from plismbench.metrics.base import BasePlismMetric
[docs]
class CosineSimilarity(BasePlismMetric):
"""Cosine similarity metric."""
def __init__(self, device: str, use_mixed_precision: bool = True):
super().__init__(device, use_mixed_precision)
[docs]
def compute_metric(self, matrix_a, matrix_b):
"""Compute cosine similarity metric."""
# Compute cosine simlilarity for each pair of tiles between features
# matrix a and b.
if matrix_a.shape[0] != matrix_b.shape[0]:
raise ValueError(
f"Number of tiles must match. Got {matrix_a.shape[0]} and {matrix_b.shape[0]}."
)
# Put matrix_a and matrix_b on the gpu if needed
matrix_a = self.ncp.asarray(matrix_a) # shape (n_tiles, n_features)
matrix_b = self.ncp.asarray(matrix_b) # shape (n_tiles, n_features)
if self.use_mixed_precision:
matrix_a = matrix_a.astype(self.ncp.float16)
matrix_b = matrix_b.astype(self.ncp.float16)
# Compute cosine similarity
dot_product_ab = self.ncp.matmul(
matrix_a, matrix_b.T
) # shape (n_tiles, n_tiles)
norm_a = self.ncp.linalg.norm(
matrix_a, axis=1, keepdims=True
) # shape (n_tiles, )
norm_b = self.ncp.linalg.norm(
matrix_b, axis=1, keepdims=True
) # shape (n_tiles, )
cosine_ab = dot_product_ab / (norm_a * norm_b.T) # shape (n_tiles, n_tiles)
_mean_cosine_ab = self.ncp.diag(cosine_ab).mean()
mean_cosine_ab = (
float(_mean_cosine_ab.get())
if self.device == "gpu"
else float(_mean_cosine_ab)
)
return mean_cosine_ab