Source code for evclust.metrics

# -*- coding: utf-8 -*-
# This file as well as the whole evclust package are licenced under the MIT licence (see the LICENCE.txt)
# Armel SOUBEIGA (armelsoubeiga.github.io), France, 2023

"""
This module contains the metrics functions using to evaluate credal results
"""

#---------------------- Packges------------------------------------------------
import numpy as np
from scipy.spatial.distance import pdist, squareform




#---------------------- credalRI--------------------------------------------------

[docs] def build_matrices(F): nbFoc = F.shape[0] C = np.zeros((nbFoc, nbFoc)) # matrice pour les degrés de conflit for i in range(nbFoc): for j in range(nbFoc): C[i, j] = 1 - np.max(np.minimum(F[i, :], F[j, :])) if np.max(F[0, :]) > 0: E = np.zeros((nbFoc, nbFoc)) else: E = np.zeros((nbFoc-1, nbFoc-1)) E = np.hstack((np.ones((nbFoc-1, 1)), E)) E = np.vstack((np.ones((1, nbFoc)), E)) singleton = (np.sum(F, axis=1) == 1) # matrice pour calculer m_ij(S) S = np.diag(singleton) return {'C': C, 'E': E, 'S': S}
[docs] def pairwise_mass(clus): """ Computes relational representations for credal partition such as generated by a credal method. """ n = clus['mass'].shape[0] M = clus['mass'] mat = build_matrices(clus['F']) # Calcul des distances en utilisant les matrices E, S et C Me = pdist(M @ mat['E'] @ M.T, 'euclidean') M1 = pdist(M @ mat['S'] @ M.T, 'euclidean') M0 = pdist(M @ (mat['C'] - mat['E']) @ M.T, 'euclidean') return {'Me': squareform(Me), 'M1': squareform(M1), 'M0': squareform(M0)}
[docs] def credalRI(clus1, clus2): """ Computes generalizations of the Rand index to compare credal partitions. Parameters : ------------ clus1: Relational representation of the first credal partition such as generated by a credal method. clus2: Relational representation of the second credal partition such as generated by a credal method. Returns : --------- RI (float): Credal Rand indices. References: ----------- In Denoeux et al. (2018), two generalizations of the Rand index for comparing credal partitions are defined: one is based on distances between mass function, the other one is based on distances. """ P1 = pairwise_mass(clus1) P2 = pairwise_mass(clus2) RI = 1 - np.mean(P1['Me'] + P2['Me'] - P1['Me'] * P2['Me'] + P1['M1'] * P2['M0'] + P1['M0'] * P2['M1']) return RI
#---------------------- nonspecificity--------------------------------------------------
[docs] def nonspecificity(mass, F): """ Compute the nonspecificity of a credal partition. Parameters ----------- mass ( ndarray (n, F size)): The credal partition. F (array): The array of length of focalsets. Returns ------- NS (float): The nonspecificity of the credal partition. """ focalsets = [tuple(index + 1 for index in row.nonzero()[0]) for row in F] n_samples = mass.shape[0] len_fs = [len(fs) for fs in focalsets if fs != tuple()] len_fs = np.array(len_fs) NS = np.sum(len_fs * mass[:, 1:]) + np.sum( mass[:, 0] * np.log2(max(len_fs))) NS /= n_samples * np.log2(max(len_fs)) return NS