source: trunk/yat/statistics/ROC.cc @ 781

Last change on this file since 781 was 781, checked in by Peter, 16 years ago

changing name to ROCScore and also added some cassert includes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.3 KB
Line 
1// $Id: ROC.cc 781 2007-03-05 19:44:03Z peter $
2
3/*
4  Copyright (C) The authors contributing to this file.
5
6  This file is part of the yat library, http://lev.thep.lu.se/trac/yat
7
8  The yat library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version.
12
13  The yat library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21  02111-1307, USA.
22*/
23
24#include "ROC.h"
25#include "yat/classifier/DataLookupWeighted1D.h"
26#include "yat/classifier/Target.h"
27#include "yat/utility/stl_utility.h"
28#include "yat/utility/vector.h"
29
30#include <gsl/gsl_cdf.h>
31
32#include <cassert>
33#include <cmath>
34#include <utility>
35#include <vector>
36
37namespace theplu {
38namespace yat {
39namespace statistics { 
40
41  ROC::ROC(void) 
42    : area_(0.5), minimum_size_(10), nof_pos_(0) 
43  {
44  }
45
46  ROC::~ROC(void)
47  {
48  }
49
50  double ROC::get_p_approx(const double area) const
51  {
52    double x = area - 0.5;
53    // Not integrating from the middle of the bin, but from the inner edge.
54    if (x>0)
55      x -= 0.5/nof_pos_/(n()-nof_pos_);
56    else if(x<0)
57      x += 0.5/nof_pos_/(n()-nof_pos_);
58
59    double sigma = (std::sqrt( (n()-nof_pos_)*nof_pos_*
60                               (n()+1.0)/12 ) /
61                    ( n() - nof_pos_ ) / nof_pos_ );
62    double p = gsl_cdf_gaussian_Q(x, sigma);
63   
64    return p;
65  }
66
67  double ROC::get_p_exact(const double block, const double nof_pos, 
68                          const double nof_neg) const
69  {
70    double p;
71    if (block <= 0.0)
72      p = 1.0;
73    else if (block > nof_neg*nof_pos)
74      p = 0.0;
75    else {
76      double p1 = get_p_exact(block-nof_neg, nof_pos-1, nof_neg);
77      double p2 = get_p_exact(block, nof_pos, nof_neg-1);
78      p = nof_pos/(nof_pos+nof_neg)*p1 + nof_neg/(nof_pos+nof_neg)*p2;
79    }
80    return p;
81  }
82
83  u_int& ROC::minimum_size(void)
84  {
85    return minimum_size_;
86  }
87
88  size_t ROC::n(void) const
89  {
90    return vec_pair_.size();
91  }
92
93  size_t ROC::n_pos(void) const
94  {
95    return nof_pos_;
96  }
97
98  double ROC::p_value(void) const
99  {
100    if (weighted_)
101      return 1.0;
102    else if (nof_pos_ < minimum_size_ & n()-nof_pos_ < minimum_size_)
103      return get_p_exact(area_*nof_pos_*(n()-nof_pos_), 
104                          nof_pos_, n()-nof_pos_);
105    else
106      return get_p_approx(area_);
107   
108  }
109
110  double ROC::score(const classifier::Target& target, 
111                    const utility::vector& value)
112  {
113    assert(target.size()==value.size());
114    weighted_=false;
115
116    vec_pair_.clear();
117    vec_pair_.reserve(target.size());
118    for (size_t i=0; i<target.size(); i++)
119      vec_pair_.push_back(std::make_pair(target.binary(i),value(i)));
120
121    std::sort(vec_pair_.begin(),vec_pair_.end(),
122              utility::pair_value_compare<bool, double>());
123    area_ = 0;
124    nof_pos_=0;
125    for (size_t i=0; i<n(); i++){
126      if (vec_pair_[i].first){
127        area_+=i;
128        nof_pos_++;
129      }
130    }
131
132    // Normalizing the area to [0,1]
133    area_ = ( (area_-nof_pos_*(nof_pos_-1)/2 ) /
134              (nof_pos_*(n()-nof_pos_)) );
135   
136    return area_;
137  }
138
139
140  // Peter, should be possible to do this in NlogN
141  double ROC::score(const classifier::Target& target, 
142                    const classifier::DataLookupWeighted1D& value)
143  {
144    weighted_=true;
145
146    vec_pair_.clear();
147    vec_pair_.reserve(target.size());
148    for (unsigned int i=0; i<target.size(); i++)
149      if (value.weight(i))
150        vec_pair_.push_back(std::make_pair(target.binary(i),value.data(i)));
151
152    std::sort(vec_pair_.begin(),vec_pair_.end(),
153              utility::pair_value_compare<int, double>());
154
155    area_=0;
156    nof_pos_=0;
157    double max_area=0;
158
159    for (size_t i=0; i<n(); i++)
160      if (target.binary(i))
161        for (size_t j=0; j<n(); j++)
162          if (!target.binary(j)){
163            if (value.data(i)>value.data(j))
164              area_+=value.weight(i)*value.weight(j);
165            max_area+=value.weight(i)*value.weight(j);
166          }
167   
168    area_/=max_area;
169   
170    return area_;
171  }
172
173
174  // Peter, should be possible to do this in NlogN
175  double ROC::score(const classifier::Target& target, 
176                    const utility::vector& value, 
177                    const utility::vector& weight)
178  {
179    weighted_=true;
180
181    vec_pair_.clear();
182    vec_pair_.reserve(target.size());
183    for (unsigned int i=0; i<target.size(); i++)
184      if (weight(i))
185        vec_pair_.push_back(std::make_pair(target.binary(i),value(i)));
186
187    std::sort(vec_pair_.begin(),vec_pair_.end(),
188              utility::pair_value_compare<int, double>());
189
190    area_=0;
191    nof_pos_=0;
192    double max_area=0;
193
194    for (size_t i=0; i<n(); i++)
195      if (target.binary(i))
196        for (size_t j=0; j<n(); j++)
197          if (!target.binary(j)){
198            if (value(i)>value(j))
199              area_+=weight(i)*weight(j);
200            max_area+=weight(i)*weight(j);
201          }
202   
203    area_/=max_area;
204   
205    return area_;
206  }
207
208  bool ROC::target(const size_t i) const
209  {
210    return vec_pair_[i].first;
211  }
212
213  std::ostream& operator<<(std::ostream& s, const ROC& r)
214  {
215    s.setf( std::ios::dec );
216    s.precision(12);
217    double sens = 1;
218    double spec = 0;
219    size_t n = r.n();
220    double nof_pos = r.n_pos();
221    for(size_t i=0; i<n-1; ++i) {
222      s << sens << "\t";
223      s << spec << "\n";
224      if (r.target(i))
225        spec -= 1/(n-nof_pos);
226      else 
227        sens -= 1/nof_pos;
228    }
229    s << sens << "\t";
230    s << spec ;
231    return s;
232  }
233
234}}} // of namespace statistics, yat, and theplu
Note: See TracBrowser for help on using the repository browser.