Darwin  1.10(beta)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
drwnStatsUtils.h
Go to the documentation of this file.
1 /*****************************************************************************
2 ** DARWIN: A FRAMEWORK FOR MACHINE LEARNING RESEARCH AND DEVELOPMENT
3 ** Distributed under the terms of the BSD license (see the LICENSE file)
4 ** Copyright (c) 2007-2015, Stephen Gould
5 ** All rights reserved.
6 **
7 ******************************************************************************
8 ** FILENAME: drwnStatsUtils.h
9 ** AUTHOR(S): Stephen Gould <stephen.gould@anu.edu.au>
10 **
11 *****************************************************************************/
12 
19 #pragma once
20 
21 #include <cassert>
22 #include <vector>
23 #include <set>
24 #include <map>
25 #include <algorithm>
26 #include <limits>
27 #include <math.h>
28 
29 #include "Eigen/Core"
30 using namespace Eigen;
31 
32 #if defined(_WIN32)||defined(WIN32)||defined(__WIN32__)
33 #undef min
34 #undef max
35 #endif
36 
37 using namespace std;
38 
41 void drwnInitializeRand();
42 
43 namespace drwn {
44 
46  template <typename T>
47  inline T minElem(const vector<T>& v);
48 
50  template <typename T>
51  inline T maxElem(const vector<T>& v);
52 
54  template <typename T>
55  T mean(const vector<T>& v);
56 
58  template <typename T>
59  T median(const vector<T>& v);
60 
63  template <typename T>
64  T destructive_median(vector<T>& w);
65 
67  template <typename T>
68  T mode(const vector<T>& v);
69 
71  template <typename T>
72  T variance(const vector<T>& v);
73 
75  template <typename T>
76  T stdev(const vector<T>& v);
77 
79  template <typename T>
80  int argmin(const vector<T>& v);
81 
83  int argmin(const VectorXd &v);
84 
86  template <typename T>
87  vector<int> argmins(const vector<vector<T> >& v);
88 
90  template <typename T>
91  int argmax(const vector<T>& v);
92 
94  int argmax(const VectorXd &v);
95 
97  template <typename T>
98  vector<int> argmaxs(const vector<vector<T> >& v);
99 
102  int argrand(const vector<double>& v);
105  int argrand(const VectorXd &v);
106 
108  template <typename T>
109  T excessKurtosis(const vector<T> &v);
110 
111  template <typename T>
112  vector<float> percentiles(const vector<T> & v);
113 
115  template <typename T>
116  pair<T, T> range(const vector<T>& v);
117 
119  template <typename T>
120  pair<T, T> range(const vector<vector<T> >& v);
121 
123  template <typename T>
124  vector<T> extractSubVector(const vector<T>& v, const vector<int>& indx);
125 
127  template <typename T>
128  vector<T> removeOutliers(const vector<T>& v,
129  const vector<double>& scores, int keepSize);
130 
132  template <typename T>
133  set<set<T> > powerset(const set<T>& s);
134 
136  int roundUp(int n, int d);
137 
139  bool containsInvalidEntries(const vector<double> &v);
140 
142  double logistic(const vector<double>& theta, const vector<double>& data);
144  double logistic(const double *theta, const double *data, int n);
145 
147  double entropy(const std::vector<double>& p);
149  double entropy(const std::vector<int>& counts);
150 
152  double gini(const std::vector<double>& p);
154  double gini(const std::vector<int>& p);
155 
157  double expAndNormalize(std::vector<double>& v);
159  double expAndNormalize(VectorXd& v);
160 
162  inline double fastexp(double x);
163 
165  vector<int> randomPermutation(int n);
166 
168  template <typename T>
169  void shuffle(vector<T>& v);
170 
172  template <typename T>
173  vector<T> subSample(const vector<T>& v, size_t n);
174 
176  vector<double> linSpaceVector(double startValue, double endValue, unsigned n = 10);
178  vector<double> logSpaceVector(double startValue, double endValue, unsigned n = 10);
179 
183  void predecessor(std::vector<int>& array, int limit);
187  void successor(std::vector<int>& array, int limit);
191  void predecessor(std::vector<int>& array, const std::vector<int>& limits);
195  void successor(std::vector<int>& array, const std::vector<int>& limits);
196 
199  inline double huberFunction(double x, double m = 1.0);
201  inline double huberDerivative(double x, double m = 1.0);
203  inline double huberFunctionAndDerivative(double x, double *df, double m = 1.0);
204 
207  double bhattacharyyaDistance(std::vector<double>& p, std::vector<double>& q);
210  double euclideanDistanceSq(std::vector<double>& p, std::vector<double>& q);
211 
213  double sum(const vector<double> &v);
215  double sum(const double *v, size_t length);
216 
218  double dot(const double *x, const double *y, size_t length);
220  double dot(const vector<double>& x, const vector<double>& y);
221 };
222 
223 // Implementation -----------------------------------------------------------
224 
225 template <typename T>
226 T drwn::minElem(const vector<T> & v)
227 {
228  switch (v.size()) {
229  case 0: DRWN_LOG_FATAL("invalid size"); break;
230  case 1: return v.front(); break;
231  case 2: return std::min(v.front(), v.back()); break;
232  }
233 
234  T minObj(v.front());
235  for (typename vector<T>::const_iterator i = v.begin() + 1; i != v.end(); ++i) {
236  minObj = std::min(minObj, *i);
237  }
238 
239  return minObj;
240 }
241 
242 template <typename T>
243 T drwn::maxElem(const vector<T> & v)
244 {
245  switch (v.size()) {
246  case 0: DRWN_LOG_FATAL("invalid size"); break;
247  case 1: return v.front(); break;
248  case 2: return std::max(v.front(), v.back()); break;
249  }
250 
251  T maxObj(v.front());
252  for (typename vector<T>::const_iterator i = v.begin() + 1; i != v.end(); ++i) {
253  maxObj = std::max(maxObj, *i);
254  }
255 
256  return maxObj;
257 }
258 
259 template <typename T>
260 T drwn::mean(const vector<T>& v)
261 {
262  DRWN_ASSERT(v.size() > 0);
263 
264  T sum(0);
265 
266  for (typename vector<T>::const_iterator i = v.begin(); i != v.end(); ++i) {
267  sum += *i;
268  }
269 
270  return sum / T(v.size());
271 }
272 
273 template <typename T>
274 T drwn::median(const vector<T>& v)
275 {
276  DRWN_ASSERT(v.size() > 0);
277 
278  vector<T> w(v);
279  if (w.size() % 2 == 1) {
280  int ix = w.size() / 2;
281  nth_element(w.begin(), w.begin()+ix, w.end());
282  return w[ix];
283  } else {
284  // Get superior and inferior middle elements.
285  int ix_sup = w.size()/2;
286  nth_element(w.begin(), w.begin() + ix_sup, w.end());
287  nth_element(w.begin(), w.begin() + ix_sup - 1, w.begin()+ ix_sup);
288  return T(0.5 * ( w[ix_sup] + w[ix_sup-1] ));
289  }
290 }
291 
292 template <typename T>
293 T drwn::destructive_median(vector<T> &w)
294 {
295  DRWN_ASSERT(w.size() > 0);
296  if (w.size() % 2 == 1) {
297  int ix = w.size() / 2;
298  nth_element(w.begin(), w.begin()+ix, w.end());
299  return w[ix];
300  } else {
301  // Get superior and inferior middle elements.
302  int ix_sup = w.size()/2;
303  nth_element(w.begin(), w.begin() + ix_sup, w.end());
304  nth_element(w.begin(), w.begin() + ix_sup - 1, w.begin()+ ix_sup);
305  return T(0.5 * ( w[ix_sup] + w[ix_sup-1] ));
306  }
307 }
308 
309 template <typename T>
310 T drwn::mode (const vector<T>& v)
311 {
312  DRWN_ASSERT(v.size() > 0);
313  map<T, int> w;
314  int maxCount = -1;
315  typename vector<T>::const_iterator modeElement = v.begin();
316  for (typename vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
317  typename map<T, int>::iterator jt = w.find(*it);
318  if (jt == w.end()) {
319  jt = w.insert(w.end(), make_pair(*it, 0));
320  } else {
321  jt->second += 1;
322  }
323 
324  if (jt->second > maxCount) {
325  modeElement = it;
326  }
327  }
328 
329  return *modeElement;
330 }
331 
332 template <typename T>
333 T drwn::variance(const vector<T> & v)
334 {
335  DRWN_ASSERT(v.size() > 0);
336 
337  T mu = mean(v);
338  T sum(0);
339 
340  for (typename vector<T>::const_iterator i = v.begin(), last = v.end(); i != last; ++i) {
341  double dev = *i - mu;
342  sum += dev * dev;
343  }
344 
345  return sum / T(v.size());
346 }
347 
348 template <typename T>
349 T drwn::stdev(const vector<T> &v)
350 {
351  T std2 = variance(v);
352  return (std2 > 0.0 ? sqrt(std2) : 0.0);
353 }
354 
355 template <typename T>
356 int drwn::argmin(const vector<T> & v)
357 {
358  int minIndx;
359 
360  switch (v.size()) {
361  case 0: minIndx = -1; break;
362  case 1: minIndx = 0; break;
363  case 2: minIndx = (v[0] <= v[1]) ? 0 : 1; break;
364  default:
365  {
366  minIndx = 0;
367  for (int i = 1; i < (int)v.size(); i++) {
368  if (v[i] < v[minIndx]) {
369  minIndx = i;
370  }
371  }
372  }
373  }
374 
375  return minIndx;
376 }
377 
378 template <typename T>
379 vector<int> drwn::argmins(const vector<vector<T> >& v)
380 {
381  vector<int> minIndx(v.size(), -1);
382  for (int i = 0; i < (int)v.size(); i++) {
383  minIndx[i] = argmin(v[i]);
384  }
385 
386  return minIndx;
387 }
388 
389 template <typename T>
390 int drwn::argmax(const vector<T> & v)
391 {
392  int maxIndx;
393 
394  switch (v.size()) {
395  case 0: maxIndx = -1; break;
396  case 1: maxIndx = 0; break;
397  case 2: maxIndx = (v[0] >= v[1]) ? 0 : 1; break;
398  default:
399  {
400  maxIndx = 0;
401  for (int i = 1; i < (int)v.size(); i++) {
402  if (v[i] > v[maxIndx]) {
403  maxIndx = i;
404  }
405  }
406  }
407  }
408 
409  return maxIndx;
410 }
411 
412 template <typename T>
413 vector<int> drwn::argmaxs(const vector<vector<T> >& v)
414 {
415  vector<int> maxIndx(v.size(), -1);
416  for (int i = 0; i < (int)v.size(); i++) {
417  maxIndx[i] = argmax(v[i]);
418  }
419 
420  return maxIndx;
421 }
422 
423 template <typename T>
424 T drwn::excessKurtosis(const vector<T> & v)
425 {
426  DRWN_ASSERT(!v.empty());
427 
428  T mu = mean(v);
429  T sigma_squared = variance(v);
430 
431  T sum(0);
432  for (typename vector<T>::const_iterator i = v.begin(), last = v.end(); i != last; ++i) {
433  double dev = *i - mu;
434  double sqDev = dev * dev;
435  sum += sqDev * sqDev;
436  }
437 
438  return sum / ( T(v.size() * sigma_squared * sigma_squared)) - 3.0;
439 }
440 
441 template <typename T>
442 vector<float> drwn::percentiles(const vector<T> &v)
443 {
445  vector<float> rval;
446  for (int i = 0; i < v.size(); i++) {
447  int sum = 0;
448  for (int j = 0; j < v.size(); j++) {
449  if (v[j] < v[i])
450  sum++;
451  }
452  rval.push_back(float(sum)/float(v.size()));
453  }
454  return rval;
455 }
456 
457 template <typename T>
458 pair<T, T> drwn::range(const vector<T>& v)
459 {
460  DRWN_ASSERT(v.size() > 0);
461 
462  typename vector<T>::const_iterator minObj(v.begin());
463  typename vector<T>::const_iterator maxObj(v.begin());
464  for (typename vector<T>::const_iterator i = v.begin() + 1;
465  i != v.end(); ++i) {
466  if (*i < *minObj) minObj = i;
467  if (*i > *maxObj) maxObj = i;
468  }
469 
470  return make_pair(*minObj, *maxObj);
471 }
472 
473 template <typename T>
474 pair<T, T> drwn::range(const vector<vector<T> >& v)
475 {
476  DRWN_ASSERT(v.size() > 0);
477 
478  pair<T, T> r = range(*v.begin());
479  for (typename vector<vector<T> >::const_iterator i = v.begin() + 1;
480  i != v.end(); ++i) {
481  pair<T, T> ri = range(*i);
482  if (ri.first < r.first)
483  r.first = ri.first;
484  if (ri.second > r.second)
485  r.second = ri.second;
486  }
487 
488  return r;
489 }
490 
491 template <typename T>
492 vector<T> drwn::extractSubVector(const vector<T>& v, const vector<int>& indx)
493 {
494  vector<T> w;
495 
496  w.reserve(indx.size());
497  for (vector<int>::const_iterator it = indx.begin(); it != indx.end(); ++it) {
498  w.push_back(v[*it]);
499  }
500 
501  return w;
502 }
503 
504 template <typename T>
505 vector<T> drwn::removeOutliers(const vector<T>& v,
506  const vector<double>& scores, int keepSize)
507 {
508  DRWN_ASSERT(scores.size() == v.size());
509  if (keepSize >= (int)v.size()) {
510  return v;
511  }
512 
513  // sort scores
514  vector<pair<double, int> > indx(v.size());
515  for (unsigned i = 0; i < v.size(); i++) {
516  indx[i] = make_pair(scores[i], i);
517  }
518  sort(indx.begin(), indx.end());
519 
520  vector<T> w(keepSize);
521  unsigned startIndx = (v.size() - keepSize) / 2;
522  unsigned endIndx = startIndx + keepSize;
523  for (unsigned i = startIndx; i < endIndx; i++) {
524  w[i - startIndx] = v[indx[i].second];
525  }
526 
527  return w;
528 }
529 
530 template <typename T>
531 set<set<T> > drwn::powerset(const set<T>& s)
532 {
533  set<set<T> > result;
534 
535  if (s.empty()) {
536  result.insert(set<T>());
537  } else {
538  for (typename set<T>::const_iterator it = s.begin(); it != s.end(); ++it) {
539  T elem = *it;
540 
541  // copy the original set, and delete one element from it
542  set<T> smallS(s);
543  smallS.erase(elem);
544 
545  // compute the power set of this smaller set
546  set<set<T> > smallP = powerset(smallS);
547  result.insert(smallP.begin(), smallP.end());
548 
549  // add the deleted element to each member of this power set,
550  // and insert each new set
551  for (typename set<set<T> >::const_iterator jt = smallP.begin();
552  jt != smallP.end(); ++jt) {
553  set<T> next = *jt;
554  next.insert(elem);
555  result.insert(next);
556  }
557  }
558  }
559 
560  return result;
561 }
562 
563 // fastexp -------------------------------------------------------------------
564 // Nicol N. Schraudolph, "A Fast, Compact Approximation of the Exponential Function",
565 // in Neural Computation, 11,853-862 (1999).
566 
567 #define EXP_A (1048576.0 / M_LN2)
568 #define EXP_C 60801
569 
570 #ifndef M_LN2
571 #define M_LN2 0.69314718055994530942
572 #endif
573 
574 inline double drwn::fastexp(double y)
575 {
576  if (y < -700.0) return 0.0;
577 
578  union
579  {
580  double d;
581 #ifdef LITTLE_ENDIAN
582  struct { int j, i; } n;
583 #else
584  struct { int i, j; } n;
585 #endif
586  } _eco;
587  _eco.n.i = (int)(EXP_A * (y)) + (1072693248 - EXP_C);
588  _eco.n.j = 0;
589  return _eco.d;
590 }
591 
592 template <typename T>
593 void drwn::shuffle(vector<T>& v)
594 {
595  const size_t n = v.size();
596  if (n < 2) return;
597  for (size_t i = 0; i < n - 1; i++) {
598  size_t j = rand() % (n - i);
599  std::swap(v[i], v[i + j]);
600  }
601 }
602 
603 template <typename T>
604 vector<T> drwn::subSample(const vector<T>& v, size_t n)
605 {
606  if (n >= v.size()) return v;
607  if (n == 0) return vector<T>();
608 
609  // make a copy of v
610  vector<T> w(v);
611 
612  // randomly swap entries
613  for (size_t i = 0; i < n; i++) {
614  size_t j = rand() % (w.size() - i);
615  std::swap(w[i], w[i + j]);
616  }
617 
618  // resize w to only keep first n and return
619  w.resize(n);
620  return w;
621 }
622 
623 inline double drwn::huberFunction(double x, double m)
624 {
625  if (x < -m) return (m * (-2.0 * x - m));
626  if (x > m) return (m * (2.0 * x - m));
627 
628  return x * x;
629 }
630 
631 inline double drwn::huberDerivative(double x, double m)
632 {
633  if (x < -m) return -2.0 * m;
634  if (x > m) return 2.0 * m;
635 
636  return 2.0 * x;
637 }
638 
639 inline double drwn::huberFunctionAndDerivative(double x, double *df, double m)
640 {
641  if (x < -m) {
642  *df = -2.0 * m;
643  return (m * (-2.0 * x - m));
644  } else if (x > m) {
645  *df = 2.0 * m;
646  return (m * (2.0 * x - m));
647  } else {
648  *df = 2.0 * x;
649  return x * x;
650  }
651 }
652 
653 inline int drwn::roundUp(int n, int d) {
654  return (n % d == 0) ? n : n + d - (n % d);
655 }
void drwnInitializeRand()
initialize the standard C library random number generator with a time-of-day seed ...
Definition: drwnStatsUtils.cpp:33