00001 #ifndef Impala_Core_Training_BalancedAveragePrecision_h 00002 #define Impala_Core_Training_BalancedAveragePrecision_h 00003 00004 #include "Core/Training/Evaluation.h" 00005 #include "Core/Table/Sort.h" 00006 //#include "Core/Table/Reverse.h" 00007 00008 namespace Impala 00009 { 00010 namespace Core 00011 { 00012 namespace Training 00013 { 00014 00015 00016 /* 00017 * a Balance version of AP (BAP) 00018 * see Van Gemert, Veenman, Geusebroek, "Episode-Constrained Cross-Validation in Video Concept Retrieval", Transactions of Mulimedia (submitted :) ) 00019 * It deals with the inbalance of positive shots between cross-validation folds 00020 * as will happen with episode constrained x-val since it is splitting videos not shots. 00021 * theoretically more balanced than AP, and optimising BAP optimes AP. 00022 * however... practical... it is the same as AP when 00023 * dealing with large numbers of negative samples. 00024 */ 00025 class BalancedAveragePrecision : public Evaluation 00026 { 00027 public: 00028 BalancedAveragePrecision(Table::AnnotationTable* annotation) : 00029 Evaluation(annotation) 00030 { 00031 } 00032 00033 virtual double Compute(Table::AnnotationTableBaseType* table) 00034 { 00035 Sort(table, 2, false); 00036 return ComputeSub(table); 00037 00038 } 00039 00040 virtual double ComputeReversed(Table::AnnotationTableBaseType* table) 00041 { 00042 Sort(table, 2, false); 00043 Reverse(table); 00044 return ComputeSub(table); 00045 00046 } 00047 00048 private: 00049 double ComputeSub(Table::AnnotationTableBaseType* table) 00050 { 00051 // first compute AP 00052 double ap=0; 00053 int positiveCount=0; 00054 for(int i=0 ; i<table->Size() ; i++) 00055 { 00056 Quid q = table->Get1(i); 00057 if(mAnnotation->IsPositive(q)) 00058 { 00059 positiveCount++; 00060 double precision = ((double)positiveCount)/((double)(i+1)); 00061 ap += precision; 00062 } 00063 } 00064 if(positiveCount > 0) 00065 ap /= (double)positiveCount; 00066 00067 // then compute WAP (worst case AP, ie: assume all perfectly-wrong) 00068 double wap = 0; 00069 double WminusR = table->Size() - positiveCount; 00070 for(int i=1 ; i<=positiveCount ; i++) 00071 { 00072 wap = wap + ((double)i)/(WminusR + (double)i); 00073 } 00074 wap /= (double)positiveCount; 00075 00076 // finally, compute BAP 00077 double bap = 1.0; 00078 if(wap!=1.0) 00079 bap = (ap - wap)/(1-wap); 00080 00081 return bap; 00082 } 00083 }; 00084 }//namespace Core 00085 }//namespace Training 00086 }//namespace Impala 00087 00088 #endif