119 lines
5.1 KiB
C++
119 lines
5.1 KiB
C++
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#undef DLIB_LDA_ABSTRACT_Hh_
|
|
#ifdef DLIB_LDA_ABSTRACT_Hh_
|
|
|
|
#include <map>
|
|
#include "../matrix.h"
|
|
#include <vector>
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
void compute_lda_transform (
|
|
matrix<T>& X,
|
|
matrix<T,0,1>& M,
|
|
const std::vector<unsigned long>& row_labels,
|
|
unsigned long lda_dims = 500,
|
|
unsigned long extra_pca_dims = 200
|
|
);
|
|
/*!
|
|
requires
|
|
- X.size() != 0
|
|
- row_labels.size() == X.nr()
|
|
- The number of distinct values in row_labels > 1
|
|
- lda_dims != 0
|
|
ensures
|
|
- We interpret X as a collection X.nr() of input vectors, where each row of X
|
|
is one of the vectors.
|
|
- We interpret row_labels[i] as the label of the vector rowm(X,i).
|
|
- This function performs the dimensionality reducing version of linear
|
|
discriminant analysis. That is, you give it a set of labeled vectors and it
|
|
returns a linear transform that maps the input vectors into a new space that
|
|
is good for distinguishing between the different classes. In particular,
|
|
this function finds matrices Z and M such that:
|
|
- Given an input vector x, Z*x-M, is the transformed version of x. That is,
|
|
Z*x-M maps x into a space where x vectors that share the same class label
|
|
are near each other.
|
|
- Z*x-M results in the transformed vectors having zero expected mean.
|
|
- Z.nr() <= lda_dims
|
|
(it might be less than lda_dims if there are not enough distinct class
|
|
labels to support lda_dims dimensions).
|
|
- Z.nc() == X.nc()
|
|
- We overwrite the input matrix X and store Z in it. Therefore, the
|
|
outputs of this function are in X and M.
|
|
- In order to deal with very high dimensional inputs, we perform PCA internally
|
|
to map the input vectors into a space of at most lda_dims+extra_pca_dims
|
|
prior to performing LDA.
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
std::pair<double,double> equal_error_rate (
|
|
const std::vector<double>& low_vals,
|
|
const std::vector<double>& high_vals
|
|
);
|
|
/*!
|
|
ensures
|
|
- This function finds a threshold T that best separates the elements of
|
|
low_vals from high_vals by selecting the threshold with equal error rate. In
|
|
particular, we try to pick a threshold T such that:
|
|
- for all valid i:
|
|
- high_vals[i] >= T
|
|
- for all valid i:
|
|
- low_vals[i] < T
|
|
Where the best T is determined such that the fraction of low_vals >= T is the
|
|
same as the fraction of high_vals < T.
|
|
- Let ERR == the equal error rate. I.e. the fraction of times low_vals >= T
|
|
and high_vals < T. Note that 0 <= ERR <= 1.
|
|
- returns make_pair(ERR,T)
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
struct roc_point
|
|
{
|
|
double true_positive_rate;
|
|
double false_positive_rate;
|
|
double detection_threshold;
|
|
};
|
|
|
|
std::vector<roc_point> compute_roc_curve (
|
|
const std::vector<double>& true_detections,
|
|
const std::vector<double>& false_detections
|
|
);
|
|
/*!
|
|
requires
|
|
- true_detections.size() != 0
|
|
- false_detections.size() != 0
|
|
ensures
|
|
- This function computes the ROC curve (receiver operating characteristic)
|
|
curve of the given data. Therefore, we interpret true_detections as
|
|
containing detection scores for a bunch of true detections and
|
|
false_detections as detection scores from a bunch of false detections. A
|
|
perfect detector would always give higher scores to true detections than to
|
|
false detections, resulting in a true positive rate of 1 and a false positive
|
|
rate of 0, for some appropriate detection threshold.
|
|
- Returns an array, ROC, such that:
|
|
- ROC.size() == true_detections.size()+false_detections.size()
|
|
- for all valid i:
|
|
- If you were to accept all detections with a score >= ROC[i].detection_threshold
|
|
then you would obtain a true positive rate of ROC[i].true_positive_rate and a
|
|
false positive rate of ROC[i].false_positive_rate.
|
|
- ROC is ordered such that low detection rates come first. That is, the
|
|
curve is swept from a high detection threshold to a low threshold.
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_LDA_ABSTRACT_Hh_
|
|
|
|
|