1#ifndef FSTWRAPPERMETRICS_H
2#define FSTWRAPPERMETRICS_H
72template<
typename RETURNTYPE>
125template<
typename RETURNTYPE,
typename DIMTYPE>
126bool metric_from_confusion(RETURNTYPE &result,
const Wrapper_Metric metric,
const std::vector<RETURNTYPE> &confusion,
const DIMTYPE classes,
const std::vector<RETURNTYPE> &class_weights,
const DIMTYPE f1_positive=1)
128 if(classes<2 || confusion.size()<(
size_t)classes*(
size_t)classes)
return false;
129 const bool weighted=!class_weights.empty();
130 if(weighted && class_weights.size()<(
size_t)classes)
return false;
133 auto cell=[&](DIMTYPE t, DIMTYPE p)->RETURNTYPE {
134 RETURNTYPE v=confusion[(size_t)t*(
size_t)classes+(size_t)p];
135 return weighted ? v*class_weights[t] : v;
139 RETURNTYPE diag=0.0, total=0.0;
140 for(DIMTYPE t=0;t<classes;t++)
for(DIMTYPE p=0;p<classes;p++) {RETURNTYPE v=cell(t,p); total+=v;
if(t==p) diag+=v;}
141 if(!(total>0.0))
return false;
146 RETURNTYPE sum=0.0; DIMTYPE present=0;
147 for(DIMTYPE t=0;t<classes;t++) {
148 RETURNTYPE rowsum=0.0;
149 for(DIMTYPE p=0;p<classes;p++) rowsum+=cell(t,p);
150 if(rowsum>0.0) {sum+=cell(t,t)/rowsum; present++;}
152 if(present==0)
return false;
153 result=sum/(RETURNTYPE)present;
157 if(classes!=2)
return false;
158 if(f1_positive>=classes)
return false;
159 const DIMTYPE pos=f1_positive, neg=(DIMTYPE)(1-f1_positive);
160 const RETURNTYPE tp=cell(pos,pos), fp=cell(neg,pos), fn=cell(pos,neg);
161 const RETURNTYPE denom=2.0*tp+fp+fn;
162 result=(denom>0.0)?(2.0*tp/denom):(RETURNTYPE)0.0;
167 for(DIMTYPE c=0;c<classes;c++) {
168 RETURNTYPE tp=cell(c,c), fp=0.0, fn=0.0;
169 for(DIMTYPE t=0;t<classes;t++)
if(t!=c) fp+=cell(t,c);
170 for(DIMTYPE p=0;p<classes;p++)
if(p!=c) fn+=cell(c,p);
171 const RETURNTYPE denom=2.0*tp+fp+fn;
172 sum+=(denom>0.0)?(2.0*tp/denom):(RETURNTYPE)0.0;
174 result=sum/(RETURNTYPE)classes;
177 default:
return false;
189template<
typename RETURNTYPE,
typename DIMTYPE>
190bool auc_from_scores(RETURNTYPE &result, std::vector<std::pair<RETURNTYPE,DIMTYPE>> &scores)
192 const size_t n=scores.size();
193 if(n==0)
return false;
195 for(
size_t i=0;i<n;i++)
if(scores[i].second==1) n_pos++;
196 const size_t n_neg=n-n_pos;
197 if(n_pos==0 || n_neg==0)
return false;
198 std::stable_sort(scores.begin(),scores.end(),
199 [](
const std::pair<RETURNTYPE,DIMTYPE> &a,
const std::pair<RETURNTYPE,DIMTYPE> &b){return a.first<b.first;});
200 RETURNTYPE rank_sum_pos=0.0;
204 while(j<n && !(scores[i].first<scores[j].first)) j++;
205 const RETURNTYPE midrank=((RETURNTYPE)(i+1)+(RETURNTYPE)j)/2.0;
206 for(
size_t k=i;k<j;k++)
if(scores[k].second==1) rank_sum_pos+=midrank;
209 result=(rank_sum_pos-(RETURNTYPE)n_pos*((RETURNTYPE)n_pos+1.0)/2.0)/((RETURNTYPE)n_pos*(RETURNTYPE)n_neg);
221template<
typename RETURNTYPE,
typename DIMTYPE>
222bool auc_macro_from_scores(RETURNTYPE &result,
const std::vector<RETURNTYPE> &scores,
const std::vector<DIMTYPE> &labels,
const DIMTYPE classes)
224 const size_t n=labels.size();
225 if(n==0 || classes<2 || scores.size()<(
size_t)n*(
size_t)classes)
return false;
228 std::vector<std::pair<RETURNTYPE,DIMTYPE>> pairs;
229 for(DIMTYPE c=0;c<classes;c++)
231 pairs.clear(); pairs.reserve(n);
232 for(
size_t i=0;i<n;i++) pairs.push_back(std::make_pair(scores[i*(
size_t)classes+(
size_t)c],(DIMTYPE)((labels[i]==c)?1:0)));
236 if(defined==0)
return false;
237 result=sum/(RETURNTYPE)defined;
244template<
typename RETURNTYPE>
247 const size_t n=pairs.size();
248 if(n==0)
return false;
252 for(
size_t i=0;i<n;i++) mean+=pairs[i].first;
254 RETURNTYPE ss_res=0.0, ss_tot=0.0;
255 for(
size_t i=0;i<n;i++) {
256 const RETURNTYPE e=pairs[i].first-pairs[i].second, d=pairs[i].first-mean;
257 ss_res+=e*e; ss_tot+=d*d;
259 if(!(ss_tot>0.0))
return false;
260 result=1.0-ss_res/ss_tot;
265 for(
size_t i=0;i<n;i++) {
const RETURNTYPE e=pairs[i].first-pairs[i].second; ss+=e*e;}
266 result=-std::sqrt(ss/(RETURNTYPE)n);
271 for(
size_t i=0;i<n;i++) sa+=std::fabs(pairs[i].first-pairs[i].second);
272 result=-sa/(RETURNTYPE)n;
275 default:
return false;
The Feature Selection Toolbox 4 library: every library component – data access, criteria and classifi...
Definition data_accessor.hpp:80
bool metric_from_confusion(RETURNTYPE &result, const Wrapper_Metric metric, const std::vector< RETURNTYPE > &confusion, const DIMTYPE classes, const std::vector< RETURNTYPE > &class_weights, const DIMTYPE f1_positive=1)
Definition wrapper_metrics.hpp:126
bool wrapper_metric_from_name(const std::string &name, Wrapper_Metric &m)
Parses a CLI metric name (--wrapper-metric value, e.g. "f1-macro") into m.
Definition wrapper_metrics.hpp:106
const char * wrapper_metric_name(const Wrapper_Metric m)
Returns the canonical CLI name (--wrapper-metric value) for m, e.g. "balanced-accuracy"; the inverse ...
Definition wrapper_metrics.hpp:89
Wrapper_Metric
Definition wrapper_metrics.hpp:60
@ neg_rmse
regression: negated root-mean-square prediction error
Definition wrapper_metrics.hpp:67
@ accuracy
classification: fraction correct (cost-weighted if class_weights set)
Definition wrapper_metrics.hpp:61
@ auc
classification: two-class data = area under the ROC curve (exact rank statistic, midrank ties); K>2 =...
Definition wrapper_metrics.hpp:65
@ neg_mae
regression: negated mean absolute prediction error
Definition wrapper_metrics.hpp:68
@ f1
classification, two-class data: F1 of the positive class, which is Metric_Spec::f1_positive (class in...
Definition wrapper_metrics.hpp:63
@ f1_macro
classification: unweighted mean of per-class one-vs-rest F1 (0/0 contributes 0)
Definition wrapper_metrics.hpp:64
@ r2
regression: coefficient of determination (SS_tot around the test-part mean)
Definition wrapper_metrics.hpp:66
@ balanced_accuracy
classification: macro-averaged recall (classes absent from the test part are skipped)
Definition wrapper_metrics.hpp:62
bool metric_from_predictions(RETURNTYPE &result, const Wrapper_Metric metric, const std::vector< std::pair< RETURNTYPE, RETURNTYPE > > &pairs)
Definition wrapper_metrics.hpp:245
bool auc_macro_from_scores(RETURNTYPE &result, const std::vector< RETURNTYPE > &scores, const std::vector< DIMTYPE > &labels, const DIMTYPE classes)
Definition wrapper_metrics.hpp:222
bool auc_from_scores(RETURNTYPE &result, std::vector< std::pair< RETURNTYPE, DIMTYPE > > &scores)
Definition wrapper_metrics.hpp:190
configuration of the wrapper metric; immutable during search, copied by criterion clones (thread-safe...
Definition wrapper_metrics.hpp:73
std::vector< RETURNTYPE > class_weights
Definition wrapper_metrics.hpp:82
bool is_regression_metric() const
true for the three regression metrics (r2/neg_rmse/neg_mae), false for the classification metrics
Definition wrapper_metrics.hpp:85
Wrapper_Metric metric
which metric to compute; accuracy = the default path served by Classifier::test()
Definition wrapper_metrics.hpp:74
unsigned int f1_positive
class index the f1 metric scores as positive (two-class data; --f1-positive). Affects f1 ONLY - f1-ma...
Definition wrapper_metrics.hpp:83
bool is_default() const
true iff this spec is the plain unweighted accuracy path (f1_positive is irrelevant unless metric==f1...
Definition wrapper_metrics.hpp:84