### Merge branch 'roc-for-far' into 'master'

```recompute far values in roc_for_far

Closes #27

See merge request !48```
parents d692bc9b 4f094765
Pipeline #18297 passed with stages
in 58 minutes and 40 seconds
 ... @@ -421,73 +421,21 @@ bob::measure::roc_for_far(const blitz::Array &negatives, ... @@ -421,73 +421,21 @@ bob::measure::roc_for_far(const blitz::Array &negatives, sort(negatives, neg, is_sorted); sort(negatives, neg, is_sorted); sort(positives, pos, is_sorted); sort(positives, pos, is_sorted); // do some magic to compute the FRR list blitz::Array retval(2, n_points); blitz::Array retval(2, n_points); // index into the FAR and FRR list // index into the FAR list int far_index = n_points - 1; int far_index = n_points - 1; int pos_index = 0, neg_index = 0; int n_pos = pos.extent(0), n_neg = neg.extent(0); // iterators into the result lists auto pos_it = pos.begin(), neg_it = neg.begin(); // do some fast magic to compute the FRR values ;-) do { // check whether the current positive value is less than the current // negative one if (*pos_it < *neg_it) { // increase the positive count ++pos_index; // go to the next positive value ++pos_it; } else { // increase the negative count ++neg_index; // go to the next negative value ++neg_it; } // check, if we have reached a new FAR limit, // i.e. if the relative number of negative similarities is greater than // 1-FAR (which is the CRR) if (((double)neg_index / (double)n_neg > 1. - far_list(far_index)) && !(bob::core::isClose((double)neg_index / (double)n_neg, 1. - far_list(far_index), 1e-9, 1e-9))) { // copy the far value retval(0, far_index) = far_list(far_index); // calculate the FRR for the current FAR retval(1, far_index) = (double)pos_index / (double)n_pos; // go to the next FAR value --far_index; } // do this, as long as there are elements in both lists left and not all FRR // Get the threshold for the requested far values and calculate far and frr // elements where calculated yet // values based on the threshold. } while (pos_it != pos.end() && neg_it != neg.end() && far_index >= 0); while(far_index >= 0) { // calculate the threshold for the requested far // check if all FRR values have been set auto threshold = bob::measure::farThreshold(neg, pos, far_list(far_index), true); if (far_index >= 0) { // calculate the frr and re-calculate the far // walk to the end of both lists; at least one of both lists should already auto farfrr = bob::measure::farfrr(neg, pos, threshold); // have reached its limit. retval(0, far_index) = farfrr.first; while (pos_it != pos.end() && pos_it++ != pos.end()) retval(1, far_index) = farfrr.second; ++pos_index; far_index--; while (neg_it != neg.end() && neg_it++ != neg.end()) ++neg_index; // fill in the remaining elements of the CAR list do { // copy the FAR value retval(0, far_index) = far_list(far_index); // check if the criterion is fulfilled (should be, as long as the lowest // far is not below 0) if ((double)neg_index / (double)n_neg > 1. - far_list(far_index)) { // calculate the FRR for the current FAR retval(1, far_index) = (double)pos_index / (double)n_pos; } else { // set FRR to 1 (this should never happen, but might be due to numerical // issues) retval(1, far_index) = 1.; } } while (far_index--); } } return retval; return retval; ... ...
No preview for this file type
No preview for this file type
 ... @@ -714,11 +714,7 @@ static auto far_threshold_doc = ... @@ -714,11 +714,7 @@ static auto far_threshold_doc = bob::extension::FunctionDoc( bob::extension::FunctionDoc( "far_threshold", "Computes the threshold such that the real FAR is " "far_threshold", "Computes the threshold such that the real FAR is " "**at most** the requested ``far_value`` if possible", "**at most** the requested ``far_value`` if possible", "If no such threshold can be computed, ``NaN`` is returned. It is " "\n\n.. note::\n\n" "impossible to compute the threshold, when too few non-identical " "highest scores exist, so that the desired ``far_value`` cannot be " "reached by any threshold.\n\n" ".. note::\n\n" " The scores will be sorted internally, requiring the scores to be " " The scores will be sorted internally, requiring the scores to be " "copied.\n" "copied.\n" " To avoid this copy, you can sort the ``negatives`` scores " " To avoid this copy, you can sort the ``negatives`` scores " ... @@ -774,11 +770,7 @@ static auto frr_threshold_doc = ... @@ -774,11 +770,7 @@ static auto frr_threshold_doc = bob::extension::FunctionDoc( bob::extension::FunctionDoc( "frr_threshold", "Computes the threshold such that the real FRR is " "frr_threshold", "Computes the threshold such that the real FRR is " "**at most** the requested ``frr_value`` if possible", "**at most** the requested ``frr_value`` if possible", "If no such threshold can be computed, ``NaN`` is returned. It is " "\n\n.. note::\n\n" "impossible to compute the threshold, when too few non-identical " "lowest scores exist, so that the desired ``frr_value`` cannot be " "reached by any threshold.\n\n" ".. note::\n\n" " The scores will be sorted internally, requiring the scores to be " " The scores will be sorted internally, requiring the scores to be " "copied.\n" "copied.\n" " To avoid this copy, you can sort the ``positives`` scores " " To avoid this copy, you can sort the ``positives`` scores " ... ...
 ... @@ -293,17 +293,18 @@ def test_plots(): ... @@ -293,17 +293,18 @@ def test_plots(): assert numpy.array_equal(xy, xyref) assert numpy.array_equal(xy, xyref) # This example will test the ROC for FAR plot calculation functionality. # This example will test the ROC for FAR plot calculation functionality. far = [0.01, 0.1, 1] requested_far = [0.01, 0.1, 1] ref = [0.42, 0.12, 0] expected_far = [0.0, 0.1, 1] xy = roc_for_far(negatives, positives, far) expected_frr = [0.48, 0.12, 0] xy = roc_for_far(negatives, positives, requested_far) assert numpy.array_equal(xy, far) assert numpy.array_equal(xy, expected_far), xy assert numpy.array_equal(xy, ref) assert numpy.array_equal(xy, expected_frr), xy # This example will test the Precision-Recall plot calculation functionality. # This example will test the Precision-Recall plot calculation functionality. xy = precision_recall_curve(negatives, positives, 100) xy = precision_recall_curve(negatives, positives, 100) # uncomment the next line to save a reference value # uncomment the next line to save a reference value # save('nonsep-roc.hdf5', xy) # save('nonsep-precisionrecall.hdf5', xy) xyref = bob.io.base.load(F('nonsep-precisionrecall.hdf5')) xyref = bob.io.base.load(F('nonsep-precisionrecall.hdf5')) assert numpy.array_equal(xy, xyref) assert numpy.array_equal(xy, xyref) ... ...
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!