Coverage for credoai/prism/compare.py: 94%
35 statements
« prev ^ index » next coverage.py v7.1.0, created at 2023-02-13 21:56 +0000
« prev ^ index » next coverage.py v7.1.0, created at 2023-02-13 21:56 +0000
1"""Performs comparison between 2 pipelines"""
2from typing import Literal, Optional
4from connect.evidence.containers import MetricContainer
6from credoai.evaluators.utils.validation import check_instance
7from credoai.lens import Lens
8from credoai.prism.comparators.metric_comparator import MetricComparator
9from credoai.prism.task import Task
10from credoai.utils import flatten_list
11from credoai.utils.common import ValidationError
14class Compare(Task):
15 """
16 Compare results across multiple pipelines.
18 This class coordinates prism.comparators objects in order to execute
19 comparisons across an arbitrary amount of Lens objects.
21 The code execute the following steps:
23 1. Extract results from the Lens objects
24 2. Call the suitable comparators depending on the results container type
25 3. Aggregate results from multiple comparators (currently only metrics supported)
27 Parameters
28 ----------
29 ref_type: str
30 Accepted values: model, assessment_data, training_data. Indicates which of the
31 artifacts should be used as a refence, by default model.
32 ref : Optional[str], optional
33 The model/dataset name by which to compare all others. Model/dataset names are
34 defined when instantiating Lens objects, by the usage of credo.artifacts. If None, the
35 first in the list will be used as a reference, by default None.
36 operation : Literal["diff", "ratio", "perc", "perc_diff"], optional
37 Indicates which operation is computed during the comparison. The accepted
38 options are:
40 "diff": x - ref,
41 "ratio": x / ref,
42 "perc": x * 100 / ref,
43 "perc_diff": ((x - ref) / ref) * 100,
45 abs : bool, optional
46 If true the absolute value of the operation is returned, by default False
47 """
49 SUPPORTED_CONTAINERS = [MetricContainer]
51 def __init__(
52 self,
53 ref_type: str = "model",
54 ref: Optional[str] = None,
55 operation: Literal["diff", "ratio", "perc", "perc_diff"] = "diff",
56 abs: bool = False,
57 ):
58 self.ref = ref
59 self.ref_type = ref_type
60 self.operation = operation
61 self.abs = abs
62 super().__init__()
64 def _validate(self):
65 """
66 Validate that parameters are in the correct format.
67 """
68 for evaluator in self.pipelines:
69 check_instance(evaluator, Lens)
70 if len(self.pipelines) < 2:
71 raise ValidationError("At least 2 lens objects are needed for a comparison")
73 def _setup(self):
74 pipesteps = flatten_list([x.pipeline for x in self.pipelines])
75 # Propagate step identifier to results
76 for step in pipesteps:
77 for result in step.evaluator.results:
78 # Create the id property for each of the containers taking the Step identifier
79 result.id = step.id
80 self.containers = flatten_list([x.evaluator.results for x in pipesteps])
81 # Remove unsupported containers
82 self.supported_results = [
83 x for x in self.containers if type(x) in self.SUPPORTED_CONTAINERS
84 ]
85 # Get default reference value if non is provided
86 if not self.ref:
87 self.ref = self.pipelines[0].__dict__[self.ref_type].name
88 # TODO: LOG this -> (f"Reference {self.ref_type}: {self.ref}")
90 def run(self):
91 """
92 Runs the comparisons.
93 """
94 # TODO: Add a splitter for different type of containers
95 # When we have other comparators we can use the suitable ones depending
96 # on container type. Potentially also dependent on evaluator
97 self.results = MetricComparator(
98 self.supported_results, self.ref_type, self.ref, self.operation, self.abs
99 ).compare()
100 return self
102 def get_results(self):
103 """
104 Returns the comparison results
105 """
106 return self.results.comparisons