summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/statistics/dpca_abstract.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/statistics/dpca_abstract.h')
-rw-r--r--ml/dlib/dlib/statistics/dpca_abstract.h365
1 files changed, 365 insertions, 0 deletions
diff --git a/ml/dlib/dlib/statistics/dpca_abstract.h b/ml/dlib/dlib/statistics/dpca_abstract.h
new file mode 100644
index 00000000..d9eef635
--- /dev/null
+++ b/ml/dlib/dlib/statistics/dpca_abstract.h
@@ -0,0 +1,365 @@
+// Copyright (C) 2009 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#undef DLIB_DPCA_ABSTRaCT_
+#ifdef DLIB_DPCA_ABSTRaCT_
+
+#include <limits>
+#include <cmath>
+#include "../matrix/matrix_abstract.h"
+
+namespace dlib
+{
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename matrix_type
+ >
+ class discriminant_pca
+ {
+ /*!
+ REQUIREMENTS ON matrix_type
+ Must be some type of dlib::matrix.
+
+ INITIAL VALUE
+ - in_vector_size() == 0
+ - between_class_weight() == 1
+ - within_class_weight() == 1
+
+ WHAT THIS OBJECT REPRESENTS
+ This object implements the Discriminant PCA technique described in the paper:
+ A New Discriminant Principal Component Analysis Method with Partial Supervision (2009)
+ by Dan Sun and Daoqiang Zhang
+
+ This algorithm is basically a straightforward generalization of the classical PCA
+ technique to handle partially labeled data. It is useful if you want to learn a linear
+ dimensionality reduction rule using a bunch of data that is partially labeled.
+
+ It functions by estimating three different scatter matrices. The first is the total scatter
+ matrix St (i.e. the total data covariance matrix), the second is the between class scatter
+ matrix Sb (basically a measure of the variance between data of different classes) and the
+ third is the within class scatter matrix Sw (a measure of the variance of data within the
+ same classes).
+
+ Once these three matrices are estimated they are combined according to the following equation:
+ S = St + a*Sb - b*Sw
+ Where a and b are user supplied weights. Then the largest eigenvalues of the S matrix are
+ computed and their associated eigenvectors are returned as the output of this algorithm.
+ That is, the desired linear dimensionality reduction is given by the matrix with these
+ eigenvectors stored in its rows.
+
+ Note that if a and b are set to 0 (or no labeled data is provided) then the output transformation
+ matrix is the same as the one produced by the classical PCA algorithm.
+ !*/
+
+ public:
+
+ struct discriminant_pca_error : public error;
+ /*!
+ This exception is thrown if there is some error that prevents us from creating
+ a DPCA matrix.
+ !*/
+
+ typedef typename matrix_type::mem_manager_type mem_manager_type;
+ typedef typename matrix_type::type scalar_type;
+ typedef typename matrix_type::layout_type layout_type;
+ typedef matrix<scalar_type,0,0,mem_manager_type,layout_type> general_matrix;
+ typedef matrix<scalar_type,0,1,mem_manager_type,layout_type> column_matrix;
+
+ discriminant_pca (
+ );
+ /*!
+ ensures
+ - this object is properly initialized
+ !*/
+
+ void clear(
+ );
+ /*!
+ ensures
+ - #*this has its initial value
+ !*/
+
+ long in_vector_size (
+ ) const;
+ /*!
+ ensures
+ - if (this object has been presented with any input vectors) then
+ - returns the dimension of the column vectors used with this object
+ - else
+ - returns 0
+ !*/
+
+ void set_within_class_weight (
+ scalar_type weight
+ );
+ /*!
+ requires
+ - weight >= 0
+ ensures
+ - #within_class_weight() == weight
+ !*/
+
+ scalar_type within_class_weight (
+ ) const;
+ /*!
+ ensures
+ - returns the weight used when combining the within class scatter matrix with
+ the other scatter matrices.
+ !*/
+
+ void set_between_class_weight (
+ scalar_type weight
+ );
+ /*!
+ requires
+ - weight >= 0
+ ensures
+ - #between_class_weight() == weight
+ !*/
+
+ scalar_type between_class_weight (
+ ) const;
+ /*!
+ ensures
+ - returns the weight used when combining the between class scatter matrix with
+ the other scatter matrices.
+ !*/
+
+ void add_to_within_class_variance(
+ const matrix_exp& x,
+ const matrix_exp& y
+ );
+ /*!
+ requires
+ - is_col_vector(x) == true
+ - is_col_vector(y) == true
+ - x.size() == y.size()
+ - if (in_vector_size() != 0) then
+ - x.size() == y.size() == in_vector_size()
+ ensures
+ - #in_vector_size() == x.size()
+ - Adds (x-y)*trans(x-y) to the within class scatter matrix.
+ (i.e. the direction given by (x-y) is recorded as being a direction associated
+ with within class variance and is therefore unimportant and will be weighted
+ less in the final dimensionality reduction)
+ !*/
+
+ void add_to_between_class_variance(
+ const matrix_exp& x,
+ const matrix_exp& y
+ );
+ /*!
+ requires
+ - is_col_vector(x) == true
+ - is_col_vector(y) == true
+ - x.size() == y.size()
+ - if (in_vector_size() != 0) then
+ - x.size() == y.size() == in_vector_size()
+ ensures
+ - #in_vector_size() == x.size()
+ - Adds (x-y)*trans(x-y) to the between class scatter matrix.
+ (i.e. the direction given by (x-y) is recorded as being a direction associated
+ with between class variance and is therefore important and will be weighted
+ higher in the final dimensionality reduction)
+ !*/
+
+ void add_to_total_variance(
+ const matrix_exp& x
+ );
+ /*!
+ requires
+ - is_col_vector(x) == true
+ - if (in_vector_size() != 0) then
+ - x.size() == in_vector_size()
+ ensures
+ - #in_vector_size() == x.size()
+ - let M denote the centroid (or mean) of all the data. Then this function
+ Adds (x-M)*trans(x-M) to the total scatter matrix.
+ (i.e. the direction given by (x-M) is recorded as being a direction associated
+ with unlabeled variance and is therefore of default importance and will be weighted
+ as described in the discriminant_pca class description.)
+ !*/
+
+ const general_matrix dpca_matrix (
+ const double eps = 0.99
+ ) const;
+ /*!
+ requires
+ - 0 < eps <= 1
+ - in_vector_size() != 0
+ (i.e. you have to have given this object some data)
+ ensures
+ - computes and returns the matrix MAT given by dpca_matrix(MAT,eigen,eps).
+ That is, this function returns the dpca_matrix computed by the function
+ defined below.
+ - Note that MAT is the desired linear transformation matrix. That is,
+ multiplying a vector by MAT performs the desired linear dimensionality reduction.
+ throws
+ - discriminant_pca_error
+ This exception is thrown if we are unable to create the dpca_matrix for some
+ reason. For example, if only within class examples have been given or
+ within_class_weight() is very large then all eigenvalues will be negative and
+ that prevents this algorithm from working properly.
+ !*/
+
+ void dpca_matrix (
+ general_matrix& dpca_mat,
+ general_matrix& eigenvalues,
+ const double eps = 0.99
+ ) const;
+ /*!
+ requires
+ - 0 < eps <= 1
+ - in_vector_size() != 0
+ (i.e. you have to have given this object some data)
+ ensures
+ - is_col_vector(#eigenvalues) == true
+ - #dpca_mat.nr() == eigenvalues.size()
+ - #dpca_mat.nc() == in_vector_size()
+ - rowm(#dpca_mat,i) represents the ith eigenvector of the S matrix described
+ in the class description and its eigenvalue is given by eigenvalues(i).
+ - all values in #eigenvalues are > 0. Moreover, the eigenvalues are in
+ sorted order with the largest eigenvalue stored at eigenvalues(0).
+ - (#dpca_mat)*trans(#dpca_mat) == identity_matrix.
+ (i.e. the rows of the dpca_matrix are all unit length vectors and are mutually
+ orthogonal)
+ - Note that #dpca_mat is the desired linear transformation matrix. That is,
+ multiplying a vector by #dpca_mat performs the desired linear dimensionality
+ reduction.
+ - sum(#eigenvalues) will be equal to about eps times the total sum of all
+ positive eigenvalues in the S matrix described in this class's description.
+ This means that eps is a number that controls how "lossy" the dimensionality
+ reduction will be. Large values of eps result in more output dimensions
+ while smaller values result in fewer.
+ throws
+ - discriminant_pca_error
+ This exception is thrown if we are unable to create the dpca_matrix for some
+ reason. For example, if only within class examples have been given or
+ within_class_weight() is very large then all eigenvalues will be negative and
+ that prevents this algorithm from working properly.
+ !*/
+
+ const general_matrix dpca_matrix_of_size (
+ const long num_rows
+ );
+ /*!
+ requires
+ - 0 < num_rows <= in_vector_size()
+ ensures
+ - computes and returns the matrix MAT given by dpca_matrix_of_size(MAT,eigen,num_rows).
+ That is, this function returns the dpca_matrix computed by the function
+ defined below.
+ - Note that MAT is the desired linear transformation matrix. That is,
+ multiplying a vector by MAT performs the desired linear dimensionality
+ reduction to num_rows dimensions.
+ !*/
+
+ void dpca_matrix_of_size (
+ general_matrix& dpca_mat,
+ general_matrix& eigenvalues,
+ const long num_rows
+ );
+ /*!
+ requires
+ - 0 < num_rows <= in_vector_size()
+ ensures
+ - is_col_vector(#eigenvalues) == true
+ - #dpca_mat.nr() == eigenvalues.size()
+ - #dpca_mat.nr() == num_rows
+ - #dpca_mat.nc() == in_vector_size()
+ - rowm(#dpca_mat,i) represents the ith eigenvector of the S matrix described
+ in the class description and its eigenvalue is given by eigenvalues(i).
+ - The values in #eigenvalues might be positive or negative. Additionally, the
+ eigenvalues are in sorted order with the largest eigenvalue stored at
+ eigenvalues(0).
+ - (#dpca_mat)*trans(#dpca_mat) == identity_matrix.
+ (i.e. the rows of the dpca_matrix are all unit length vectors and are mutually
+ orthogonal)
+ - Note that #dpca_mat is the desired linear transformation matrix. That is,
+ multiplying a vector by #dpca_mat performs the desired linear dimensionality
+ reduction to num_rows dimensions.
+ !*/
+
+ discriminant_pca operator+ (
+ const discriminant_pca& item
+ ) const;
+ /*!
+ requires
+ - in_vector_size() == 0 || item.in_vector_size() == 0 || in_vector_size() == item.in_vector_size()
+ (i.e. the in_vector_size() of *this and item must match or one must be zero)
+ - between_class_weight() == item.between_class_weight()
+ - within_class_weight() == item.within_class_weight()
+ ensures
+ - returns a new discriminant_pca object that represents the combination of all
+ the measurements given to *this and item. That is, this function returns a
+ discriminant_pca object, R, that is equivalent to what you would obtain if all
+ modifying calls (e.g. the add_to_*() functions) to *this and item had instead
+ been done to R.
+ !*/
+
+ discriminant_pca& operator+= (
+ const discriminant_pca& rhs
+ );
+ /*!
+ requires
+ - in_vector_size() == 0 || rhs.in_vector_size() == 0 || in_vector_size() == rhs.in_vector_size()
+ (i.e. the in_vector_size() of *this and rhs must match or one must be zero)
+ - between_class_weight() == rhs.between_class_weight()
+ - within_class_weight() == rhs.within_class_weight()
+ ensures
+ - #*this == *item + rhs
+ - returns #*this
+ !*/
+
+ void swap (
+ discriminant_pca& item
+ );
+ /*!
+ ensures
+ - swaps *this and item
+ !*/
+
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename matrix_type
+ >
+ inline void swap (
+ discriminant_pca<matrix_type>& a,
+ discriminant_pca<matrix_type>& b
+ ) { a.swap(b); }
+ /*!
+ provides a global swap function
+ !*/
+
+ template <
+ typename matrix_type,
+ >
+ void deserialize (
+ discriminant_pca<matrix_type>& item,
+ std::istream& in
+ );
+ /*!
+ provides deserialization support
+ !*/
+
+ template <
+ typename matrix_type,
+ >
+ void serialize (
+ const discriminant_pca<matrix_type>& item,
+ std::ostream& out
+ );
+ /*!
+ provides serialization support
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+}
+
+#endif // DLIB_DPCA_ABSTRaCT_
+