from abc import ABC, abstractmethod from typing import Tuple, List import numpy as np from src.dto.dto import ExplanationDto class Segregator(ABC): @abstractmethod def segregate( self, explanations: ExplanationDto ) -> Tuple[List[str], List[str], List[str]]: ... class PercentileBasedSegregator(Segregator): def __init__( self, upper_bound_percentile: int = 85, middle_bound_percentile: int = 75, lower_bound_percentile: int = 10, ): self.__upper_bound_percentile = upper_bound_percentile self.__middle_bound_percentile = middle_bound_percentile self.__lower_bound_percentile = lower_bound_percentile def segregate( self, explanations: ExplanationDto, ) -> Tuple[List[str], List[str], List[str]]: scores = [explanation.score for explanation in explanations.explanations] scores = np.asarray(scores) upper_bound = np.percentile(scores, self.__upper_bound_percentile) mid_bound = np.percentile(scores, self.__middle_bound_percentile) lower_bound = np.percentile(scores, self.__lower_bound_percentile) pos_features = [ explanation.feature for explanation in explanations.explanations if explanation.score >= upper_bound and explanation.score != 0 ] mid_features = [ explanation.feature for explanation in explanations.explanations if upper_bound > explanation.score >= mid_bound > 0 ] low_features = [ explanation.feature for explanation in explanations.explanations if mid_bound > explanation.score >= lower_bound > 0 ] return pos_features, mid_features, low_features