25 #include <MathAlgo/LDA.hh>
26 #include <MathAlgo/PCA.hh>
27 #include <MathAlgo/SVD.hh>
28 #include <Base/Math/Random.hh>
30 #include <Base/Common/BIASpragma.hh>
31 #include <Base/Common/FileHandling.hh>
37 #define REDUCTION_ZERO_THRESH 1E-8
41 for (
int i=0;i<vec.
size();i++){
42 cout << vec[i] <<
" ";
50 BIASASSERT(!vec.empty());
51 BIASASSERT(!vec[0].empty());
54 int dimensions=vec[0][0].
size();
57 cov(dimensions, dimensions, 0.0);
61 double error=0,error2=0, error3=0, maxerror=0, maxerror2=0;
63 int counter=0, counter2=0;
67 for (
int classNumber=0;classNumber<(int)vec.
size();classNumber++){
71 const std::vector<BIAS::Vector<LDAType> > & class_i = vec[classNumber];
72 for (
int classVecNumber=0; classVecNumber<(int)class_i.size();
77 for (
int dim=0; dim<dimensions; dim++){
79 const LDAType classVectordim = classVector[dim];
80 const LDAType classMean = classMeans_[classNumber][dim];
81 for (
int dim2=0;dim2<=dim;dim2++){
82 cov[dim][dim2] += (classVectordim-classMean)*(classVector[dim2]-classMeans_[classNumber][dim2]);
84 error3=fabs(classVectordim-classMean);
85 if (error3>maxerror) maxerror=error3;
91 cov/=double(class_i.size());
92 for (
int i=0; i<dimensions; i++){
93 for (
int j=0; j<=i; j++){
94 classCov[i][j] += cov[i][j];
97 error=error/(double)(128*vec[classNumber].size());
98 if (error>maxerror2) maxerror2=error;
104 for (
int i=0; i<dimensions; i++){
105 for (
int j=0; j<=i; j++){
106 classCov[j][i] = classCov[i][j];
109 classCov/=double(vec.
size());
117 svd.Compute(classCov, REDUCTION_ZERO_THRESH);
120 error2/=(double)counter;
122 cout <<
"Trailset has Trails = " << vec.
size() << endl;
123 cout <<
"Mean-Error = " << error2 << endl;
124 cout <<
"Max-Single-Error = " << maxerror << endl;
125 cout <<
"Max-Trail-Error = " << maxerror2 << endl;
127 cout <<
"Eigenvalues from S_w = ";
133 int classSizeMin,
int classSizeMax,
int vectorEntryMin,
int vectorEntryMax,
134 double stdDeviation,
double mainDirectionStdDeviation,
140 vec.resize(numberOfClasses);
141 means.resize(numberOfClasses);
143 Matrix<double> U(vectorSize,vectorSize,0.0),S(vectorSize,vectorSize,0.0),
144 UMain(vectorSize,vectorSize,0.0), SMain(vectorSize,vectorSize,0.0);
153 for (
int k=0;k<vectorSize;k++){
155 SMain[k][k]=fabs(random.
GetNormalDistributed(0,mainDirectionStdDeviation*mainDirectionStdDeviation));
162 for (
int k=0;k<vectorSize;k++){
165 if (k==vectorSize-1)
break;
167 for (
int j=k+1;j<vectorSize;j++){
182 for (
int i=0;i<numberOfClasses;i++){
184 if ((GetDebugLevel()&1)!=0)
185 cout << i <<
" " << flush;
190 for (
int k=0;k<vectorSize;k++){
235 vec[i].resize(classSize);
237 for (
int j=0;j<classSize;j++){
242 for (
int k=0;k<vectorSize;k++){
248 for (
int n=0; n<int(vectorSize); n++){
249 (*vec_ij)[n] += LDAType(l*U[k][n]);
252 for (
int n=0; n<int(vectorSize); n++){
253 (*vec_ij)[n]=min(LDAType(vectorEntryMax),max(LDAType(vectorEntryMin),(*vec_ij)[n]));
256 (*vec_ij) /= (*vec_ij).NormL2()*255.0;
262 if ((GetDebugLevel()&1)!=0)
275 if (reductionSize==-1)
276 reductionSize = reductionSize_;
277 BIASASSERT(reductionSize>0);
279 BIASASSERT(!vec.empty());
280 BIASASSERT(!vec[0].empty());
281 const int dimensions = vec[0][0].
size();
294 interclassCov(dimensions, dimensions, 0.0);
296 vector<double> classWeights;
297 classWeights.reserve(vec.
size());
301 for (
int classNumber=0;classNumber<(int)vec.
size();classNumber++){
302 Matrix<LDAType> &cov = (covs==NULL)? interclassCov : (*covs)[classNumber];
304 const std::vector<BIAS::Vector<LDAType> > & class_i = vec[classNumber];
305 if (equalClassWeights_) classWeights.push_back(1.0);
306 else classWeights.push_back(class_i.size());
308 if (class_i.size()>1) {
310 for (
int classVecNumber=0; classVecNumber<(int)class_i.size(); classVecNumber++){
313 for (
int dim=0; dim<dimensions; dim++){
315 const LDAType classVectordim = classVector[dim];
316 const LDAType classMean = classMeans_[classNumber][dim];
317 const LDAType diff = (classVectordim-classMean);
318 for (
int dim2=0;dim2<=dim;dim2++){
319 cov[dim][dim2] += diff *
320 (classVector[dim2]-classMeans_[classNumber][dim2]);
325 if (equalClassWeights_)
326 cov *= LDAType(1.0/LDAType(class_i.size()-1));
329 for (
int i=0; i<dimensions; i++){
330 for (
int j=0; j<=i; j++){
331 withinclassCov[i][j] += cov[i][j];
337 for (
int i=0; i<dimensions; i++){
338 for (
int j=0; j<i; j++){
339 withinclassCov[j][i] = withinclassCov[i][j];
343 BIASDOUT(2,
"within class cov = "<<withinclassCov);
348 for (
int classNumber=0;classNumber<(int)classMeans_.size();classNumber++){
350 const LDAType w = classWeights[classNumber];
351 for (
int i=0;i<classMean.
size();i++){
352 const LDAType weight = w * (classMean[i] - mean_[i]);
353 for (
int j=0; j<=i; j++){
355 interclassCov[i][j] += weight * (classMean[j]-mean_[j]);
360 for (
int i=0; i<dimensions; i++){
361 for (
int j=0;j<i;j++) {
362 interclassCov[j][i] = interclassCov[i][j];
371 BIASDOUT(2,
"inter class cov = "<<interclassCov);
372 ComputeReductionMatrix(withinclassCov, interclassCov, matrix, reductionSize);
384 const int dimensions = interclassCov.
num_rows();
388 for (
int i=0; i<dimensions; i++){
389 interclassCovd[i][i] = 2.0 * fabs(interclassCov[i][i]);
390 for (
int j=0;j<i;j++) {
391 interclassCovd[j][i] = interclassCovd[i][j] = double(interclassCov[i][j])
392 + double(interclassCov[j][i]) ;
395 BIASWARNONCE(
"Copying from float to double ...");
401 for (
int i=0; i<dimensions; i++){
402 withinclassCovd[i][i] = 2.0*fabs(withinclassCov[i][i]);
403 for (
int j=0;j<i;j++) {
404 withinclassCovd[i][j] = withinclassCovd[j][i] =
405 double(withinclassCov[i][j])+double(withinclassCov[j][i]);
412 if (svd.
Compute(withinclassCovd, REDUCTION_ZERO_THRESH)==0) {
415 BIASERR(
"SVD failed");
417 BIASDOUT(1,
"rank=" << svd.
Rank() <<
", dimensions=" << dimensions);
421 BIASDOUT(1,
" rank=0, make PCA");
426 if (rank<dimensions){
427 double ev = svd.
GetS()[rank-1];
428 BIASDOUT(1,
"Singularity, s="<< svd.
GetS()<<
" rank="<< svd.
Rank()
430 for (
int i=0;i<dimensions;i++){
431 withinclassCovd[i][i] += ev;
433 svd.
Compute(withinclassCovd, REDUCTION_ZERO_THRESH);
435 BIASDOUT(1,
"SECOND TRY yielded rank="
436 << svd.
Rank() <<
", added " << ev);
438 if ((
int)svd.
Rank()<dimensions) {
439 BIASERR(
"REGULARIZATION FAILED - ABORTING");
449 withinclassCovd = svd.
Invert();
455 if (rank<dimensions){
456 BIASDOUT(1,
"inter class cov is singular, regularizing and trying "
458 for (
int i=0;i<dimensions;i++){
459 interclassCovd[i][i] += svd.
GetS()[rank-1];
465 interclassCovd=svd.
SqrtT();
469 svd.
Compute(interclassCovd * withinclassCovd * interclassCovd);
477 interclassCovd = svd.
Invert(interclassCovd);
481 U = interclassCovd * U;
492 U /= svd.
GetS()[int(dimensions/2)];
494 matrix.
newsize(dimensions, reductionSize);
495 for (
int j=0;j<matrix.
num_rows();j++){
496 for (
int i=0;i<matrix.
num_cols();i++){
497 matrix[j][i] = LDAType( U[j][i] );
503 const int dimensions = vec[0][0].
size();
505 classMeans_.resize(vec.
size());
506 mean_.newsize(dimensions);
510 for (
int i=0;i<(int)vec.
size();i++){
511 classMeans_[i].newsize(dimensions);
512 classMeans_[i].SetZero();
513 allCount_+=vec[i].
size();
514 for (
int k=0;k<(int)vec[i].size();k++){
515 classMeans_[i]+=vec[i][k];
517 mean_+=classMeans_[i];
518 classMeans_[i] /= LDAType(vec[i].size());
521 mean_ /= LDAType(allCount_);
544 BIASASSERT(classmeans.size()==covs.size());
548 BIASASSERT(classmeans.size()==covs.size());
549 BIASASSERT(withinClassCov.
num_rows()==covs[0].num_rows());
554 for (
unsigned int i=0; i<classmeans.size(); i++) {
555 withinClassCov += covs[i];
557 interClassCov *= 1.0f / float(interClassCov.
NormFrobenius());
558 withinClassCov*= 1.0f / float(withinClassCov.NormFrobenius());
566 const std::vector< std::vector<BIAS::
568 BIASASSERT(!vec.empty());
569 BIASASSERT(!vec[0].empty());
570 const int dim = vec[0][0].
Size();
576 for (
unsigned int i=0; i< vec.
size(); i++) {
583 for (
unsigned int c=0; c<(*covs)[i].size(); c++) {
584 scatter += (*covs)[i][c];
588 InterClassCov += interscatter;
589 WithinClassCov += scatter;
591 ComputeReductionMatrix(WithinClassCov, InterClassCov, matrix, reductionSize);
void ComputeScatter(const std::vector< BIAS::Vector< PCAType > > &vec, const BIAS::Vector< PCAType > &mean, BIAS::Matrix< PCAType > &cov)
compute unnomalized covariance
void GenerateRandomTestData(int vectorSize, int numberOfClasses, int classSizeMin, int classSizeMax, int vectorEntryMin, int vectorEntryMax, double stdDeviation, double mainDirectionStdDeviation, std::vector< std::vector< BIAS::Vector< LDAType > > > &vec, std::vector< BIAS::Vector< LDAType > > &means, bool Normalize)
Generates random classes of vectors.
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Subscript num_cols() const
class for column vectors with arbitrary size
void ComputeAnonymousReduction(const std::vector< std::vector< BIAS::Vector< LDAType > > > &vec, BIAS::Matrix< LDAType > &matrix, int reductionSize=-1, const std::vector< std::vector< BIAS::Matrix< LDAType > > > *covs=NULL)
Computes a reduction-matrix for features of n sets (e.g.
void ComputeReductionMatrix(const std::vector< std::vector< BIAS::Vector< LDAType > > > &vec, BIAS::Matrix< LDAType > &matrix, int reductionSize=-1, std::vector< BIAS::Matrix< LDAType > > *covs=NULL)
Computes a reduction-matrix the first dimension of the matrix is taken out of the first vector...
unsigned int Rank()
returns the rank of A_
Matrix< T > & newsize(Subscript M, Subscript N)
static std::string CurrentDateTimeString()
Create a string containing date and time like 20060329_173054.
void SetReductionSize(int size)
reduction size can be set here
Matrix< double > SqrtT()
returns the square root of a symmetric positive definite matrix M A = sqrt(M) = U * sqrt(S)...
unsigned int Size() const
length of the vector
int Compute(const Matrix< double > &M, double ZeroThreshold=DEFAULT_DOUBLE_ZERO_THRESHOLD)
set a new matrix and compute its decomposition.
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
double NormL2() const
Return the L2 norm: a^2 + b^2 + c^2 + ...
int GetUniformDistributedInt(const int min, const int max)
get uniform distributed random variable including min/max
Vector< T > & newsize(Subscript N)
void SetZero()
Sets all values to zero.
void ComputeMeans(const std::vector< std::vector< BIAS::Vector< LDAType > > > &vec)
get mean of input get results with methods down under
Matrix< double > GetV() const
return V
principal component analysis on a set of vectors with PCA it is possible to find the most important d...
const Matrix< double > & GetVT() const
return VT (=transposed(V))
void GetClassMeans(std::vector< BIAS::Vector< LDAType > > &means)
get mean vector for each class ComputeReductionMatrix or ComputeMeans has to be called first ...
Vector< T > GetRow(const int &row) const
return a copy of row "row" of this matrix, zero based counting
const Vector< double > & GetS() const
return S which is a vector of the singular values of A in descending order.
void AnalyzeData(const std::vector< std::vector< BIAS::Vector< LDAType > > > &vec)
Ouput statistical-data of input-data.
void GetMean(BIAS::Vector< LDAType > &mean)
get a mean vector of all vectors ComputeReductionMatrix or ComputeMeans has to be called first ...
void Reset()
calls srand() with a seed generated from system call time, also initializes some other variables ...
const Matrix< double > & GetU() const
return U U is a m x m orthogonal matrix
void ComputeWithinAndInterClassCovs(const std::vector< BIAS::Vector< LDAType > > &classmeans, const std::vector< BIAS::Matrix< LDAType > > &covs, BIAS::Matrix< LDAType > &withinClassCov, BIAS::Matrix< LDAType > &interClassCov)
given mean and scatter of each class, compute scatter between class means and average class shape ...
Matrix< double > Invert()
returns pseudoinverse of A = U * S * V^T A^+ = V * S^+ * U^T
Subscript num_rows() const
double GetNormalDistributed(const double mean, const double sigma)
on succesive calls return normal distributed random variable with mean and standard deviation sigma ...
void ComputeMean(const std::vector< BIAS::Vector< PCAType > > &vec, BIAS::Vector< PCAType > &mean)
computes mean of a set of vectors
double NormFrobenius() const
Return Frobenius norm = sqrt(trace(A^t * A)).
class for producing random numbers from different distributions