MCPcopy Create free account
hub / github.com/ciphermodelabs/ciphercore / instantiate

Method instantiate

ciphercore-base/src/ops/auc.rs:56–111  ·  view source on GitHub ↗
(&self, context: Context, arguments_types: Vec<Type>)

Source from the content-addressed store, hash-verified

54#[typetag::serde]
55impl CustomOperationBody for AucScore {
56 fn instantiate(&self, context: Context, arguments_types: Vec<Type>) -> Result<Graph> {
57 if arguments_types.len() != 2 {
58 return Err(runtime_error!("Invalid number of arguments for AucMetric"));
59 }
60 let t = arguments_types[0].clone();
61 if !t.is_array() {
62 return Err(runtime_error!(
63 "`y_true` in AucMetric must be an array, got {t:?}"
64 ));
65 }
66 if t.get_dimensions().len() != 1 {
67 return Err(runtime_error!(
68 "`y_true` in AucMetric must be 1-dimensional, got {t:?}"
69 ));
70 }
71 let n = t.get_dimensions()[0];
72 if n >= (1 << MAX_LOG_ARRAY_SIZE) {
73 return Err(runtime_error!(
74 "`y_true` in AucMetric must have less than 2^{} elements, got {n:?}",
75 MAX_LOG_ARRAY_SIZE
76 ));
77 }
78 let sc = t.get_scalar_type();
79 if sc != INT64 {
80 return Err(runtime_error!(
81 "`y_true` in AucMetric must consist of INT64's, got {sc:?}"
82 ));
83 }
84 if arguments_types[1] != t {
85 return Err(runtime_error!(
86 "`y_pred` in AucMetric must be of the same type as `y_true`, got {:?} vs {:?}",
87 t,
88 arguments_types[1]
89 ));
90 }
91
92 let g = context.create_graph()?;
93 let y_true = g.input(t.clone())?;
94 let y_pred = g.input(t)?;
95 // Intuitively, AUC is the probability that a randomly chosen positive example is ranked higher than a randomly chosen negative example.
96 // SKLearn definition expands it with the following: if two examples have the same prediction, this pair is accounted as 0.5 rather than 1.
97 // E.g., if we have y_true = [0, 0, 1, 1], and y_pred = [10, 10, 10, 10], SKLearn will return 0.5.
98 // This complicates implementation in CipherCore. Luckily, we can utilize the following trick.
99 // Let's assume that we compute the AUC by sorting the data over predictions, and ignoring the fact that some of the predictions are equal.
100 // Our sorting is stable, so if we repeat the process on the reversed data, pairs of equal predictions will be counted as 1 in one case, and
101 // 0 in the other one, while pairs of predictions which are not equal will be counted the same way in both cases.
102 // This means that we can compute AUC in a naive way on the data and reversed data, and just average the results.
103 let auc1 = compute_naive_auc(y_true.clone(), y_pred.clone(), &self.fp)?;
104 let y_true = y_true.get_slice(vec![SliceElement::SubArray(None, None, Some(-1))])?;
105 let y_pred = y_pred.get_slice(vec![SliceElement::SubArray(None, None, Some(-1))])?;
106 let auc2 = compute_naive_auc(y_true, y_pred, &self.fp)?;
107 let auc = auc1.add(auc2)?.truncate(2)?;
108 auc.set_as_output()?;
109 g.finalize()?;
110 Ok(g)
111 }
112
113 fn get_name(&self) -> String {

Callers

nothing calls this directly

Calls 12

compute_naive_aucFunction · 0.85
cloneMethod · 0.80
is_arrayMethod · 0.80
get_dimensionsMethod · 0.80
get_scalar_typeMethod · 0.45
create_graphMethod · 0.45
inputMethod · 0.45
get_sliceMethod · 0.45
truncateMethod · 0.45
addMethod · 0.45
set_as_outputMethod · 0.45
finalizeMethod · 0.45

Tested by

no test coverage detected