20 #include "ConfusionMatrix.h"
24 bool compareClass(
const std::string& string1,
const std::string& string2){
25 int int1=string2type<int>(string1);
26 int int2=string2type<int>(string2);
30 ConfusionMatrix::ConfusionMatrix()
31 : m_classes(),m_results()
35 ConfusionMatrix::~ConfusionMatrix()
40 ConfusionMatrix::ConfusionMatrix(
short nclass){
44 ConfusionMatrix::ConfusionMatrix(
const std::vector<std::string>& classNames){
45 setClassNames(classNames);
50 setClassNames(cm.m_classes);
51 setResults(cm.m_results);
60 setClassNames(cm.m_classes);
61 setResults(cm.m_results);
68 if(cm.m_classes.size()!=this->m_classes.size()){
69 std::cerr <<
"error0: "<< cm.m_classes.size() <<
"!=" << this->m_classes.size() << std::endl;
72 if(cm.m_results.size()!=this->m_results.size()){
73 std::cerr <<
"error1: "<< cm.m_results.size() <<
"!=" << this->m_results.size() << std::endl;
76 for(
int irow=0;irow<m_results.size();++irow){
77 if(cm.m_results[irow].size()!=this->m_results[irow].size()){
78 std::cerr <<
"error2: " << cm.m_results[irow].size() <<
"!=" << this->m_results[irow].size() << std::endl;
81 for(
int icol=0;icol<m_results[irow].size();++icol)
82 this->m_results[irow][icol]+=cm.m_results[irow][icol];
89 for(
int irow=0;irow<m_results.size();++irow){
90 for(
int icol=0;icol<m_results[irow].size();++icol)
91 m_results[irow][icol]*=weight;
96 void ConfusionMatrix::sortClassNames(){
97 sort(m_classes.begin(),m_classes.end(),compareClass);
107 void ConfusionMatrix::resize(
short nclass){
108 m_classes.resize(nclass);
109 for(
short iclass=0;iclass<nclass;++iclass){
110 std::ostringstream osclass;
112 m_classes[iclass]=osclass.str();
114 m_results.resize(nclass,nclass);
117 void ConfusionMatrix::setClassNames(
const std::vector<std::string>& classNames,
bool doSort){
118 m_classes=classNames;
121 if(m_results.size()!=m_classes.size())
122 m_results.resize(m_classes.size(),m_classes.size());
125 void ConfusionMatrix::pushBackClassName(
const std::string& className,
bool doSort){
126 m_classes.push_back(className);
129 if(m_results.size()!=m_classes.size())
130 m_results.resize(m_classes.size(),m_classes.size());
135 m_results=theResults;
138 void ConfusionMatrix::clearResults(){
140 m_results.resize(m_classes.size(),m_classes.size());
143 void ConfusionMatrix::setResult(
const std::string& theRef,
const std::string& theClass,
double theResult){
150 int ir=getClassIndex(theRef);
151 int ic=getClassIndex(theClass);
152 m_results[ir][ic]=theResult;
155 void ConfusionMatrix::incrementResult(
const std::string& theRef,
const std::string& theClass,
double theIncrement){
158 int ir=getClassIndex(theRef);
159 int ic=getClassIndex(theClass);
161 if(ir>=m_results.size())
162 std::cerr <<
"Error: " << theRef <<
" not found in class ConfusionMatrix when incrementing for class " << theClass << std::endl;
163 assert(ir<m_results.size());
165 assert(ic<m_results[ir].size());
166 m_results[ir][ic]+=theIncrement;
169 double ConfusionMatrix::nReference(
const std::string& theRef)
const{
171 int ir=getClassIndex(theRef);
172 return accumulate(m_results[ir].begin(),m_results[ir].end(),0);
175 double ConfusionMatrix::nReference()
const{
177 for(
int ir=0;ir<m_classes.size();++ir)
178 nref+=accumulate(m_results[ir].begin(),m_results[ir].end(),0);
182 double ConfusionMatrix::nClassified(
const std::string& theClass)
const{
184 int ic=getClassIndex(theClass);
185 double nclassified=0;
186 for(
int iref=0;iref<m_results.size();++iref){
187 assert(ic<m_results[iref].size());
188 nclassified+=m_results[iref][ic];
193 double ConfusionMatrix::pa(
const std::string& theClass,
double* se95)
const{
194 assert(m_results.size());
195 assert(m_results.size()==m_classes.size());
198 int ir=getClassIndex(theClass);
200 assert(ir<m_results.size());
201 assert(!theClass.compare(m_classes[ir]));
202 for(
int iclass=0;iclass<m_results.size();++iclass){
203 assert(iclass<m_results[ir].size());
204 producer+=m_results[ir][iclass];
206 double dpa=(producer>0)? static_cast<double>(m_results[ir][ir])/producer : 0;
209 *se95=(dpa<1&&dpa>0)? sqrt(dpa*dqa/(producer-1)) : 0;
213 int ConfusionMatrix::pa_pct(
const std::string& theClass,
double* se95)
const{
214 double dpa=pa(theClass,se95);
216 *se95=
static_cast<double>(
static_cast<int>(0.5+1000*(*se95)))/10.0;
217 return static_cast<int>(0.5+100.0*dpa);
221 double ConfusionMatrix::ua(
const std::string& theClass,
double* se95)
const{
222 assert(m_results.size());
223 assert(m_results.size()==m_classes.size());
226 int ic=getClassIndex(theClass);
228 assert(ic<m_results.size());
229 assert(!theClass.compare(m_classes[ic]));
230 for(
int iref=0;iref<m_results.size();++iref){
231 assert(ic<m_results[iref].size());
232 user+=m_results[iref][ic];
234 double dua=(user>0)? static_cast<double>(m_results[ic][ic])/user : 0;
237 *se95=(dua<1&&dua>0)? sqrt(dua*dva/(user-1)) : 0;
241 int ConfusionMatrix::ua_pct(
const std::string& theClass,
double* se95)
const{
242 double dua=ua(theClass,se95);
244 *se95=
static_cast<double>(
static_cast<int>(0.5+1000*(*se95)))/10.0;
245 return static_cast<int>(0.5+100.0*dua);
248 double ConfusionMatrix::oa(
double* se95)
const{
249 double ntotal=m_results.sum();
252 for(
int iclass=0;iclass<m_classes.size();++iclass)
253 pCorrect+=static_cast<double>(m_results[iclass][iclass])/ntotal;
254 double qCorrect=1-pCorrect;
256 *se95=(pCorrect<1&&pCorrect>0)? sqrt(pCorrect*qCorrect/(ntotal-1)) : 0;
263 int ConfusionMatrix::oa_pct(
double* se95)
const{
266 *se95=
static_cast<double>(
static_cast<int>(0.5+1000*(*se95)))/10.0;
267 return static_cast<int>(0.5+100.0*doa);
270 double ConfusionMatrix::kappa()
const{
271 double ntotal=m_results.sum();
274 for(
int iclass=0;iclass<m_classes.size();++iclass){
275 pChance+=nClassified(m_classes[iclass])*nReference(m_classes[iclass])/ntotal/ntotal;
276 pCorrect+=
static_cast<double>(m_results[iclass][iclass])/ntotal;
279 return((pCorrect-pChance)/(1-pChance));