Skip to content

Instantly share code, notes, and snippets.

@skojaku
Last active September 7, 2023 15:57
Show Gist options
  • Save skojaku/1a08a7d6145ede982eced83a2d4f50d2 to your computer and use it in GitHub Desktop.
Save skojaku/1a08a7d6145ede982eced83a2d4f50d2 to your computer and use it in GitHub Desktop.
Element-centric similarity
import numpy as np
from scipy import sparse
#
# Evaluation
#
def calc_esim(y, ypred, normalize=False):
"""
Element centric similarity.
y: numpy array of the true group memberships
ypred: numpy array of the detected group memberships
normalize: normalize = False gives the element-centric similarity. With normalize=True, the similarity is shifted to be zero for random partition on average and rescaled such that the maximum value is 1.
"""
ylab, y = np.unique(y, return_inverse=True)
ypredlab, ypred = np.unique(ypred, return_inverse=True)
Ka, Kb = len(ylab), len(ypredlab)
K = np.maximum(Ka, Kb)
N = len(y)
UA = sparse.csr_matrix((np.ones_like(y), (np.arange(y.size), y)), shape=(N, K))
UB = sparse.csr_matrix(
(np.ones_like(ypred), (np.arange(ypred.size), ypred)), shape=(N, K)
)
nA = np.array(UA.sum(axis=0)).reshape(-1)
nB = np.array(UB.sum(axis=0)).reshape(-1)
nAB = (UA.T @ UB).toarray()
nAB_rand = np.outer(nA, nB) / N
# Calc element-centric similarity
Q = np.maximum(nA[:, None] @ np.ones((1, K)), np.ones((K, 1)) @ nB[None, :])
Q = 1 / np.maximum(Q, 1)
S = np.sum(np.multiply(Q, (nAB**2))) / N
if normalize == False:
return S
# Calc the expected element-centric similarity for random partitions
Q = np.maximum(nA[:, None] @ np.ones((1, K)), np.ones((K, 1)) @ nB[None, :])
Q = 1 / np.maximum(Q, 1)
Srand = np.sum(np.multiply(Q, (nAB_rand**2))) / N
Scorrected = (S - Srand) / (1 - Srand)
return Scorrected
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment