lda-estimate-test.cc File Reference
Include dependency graph for lda-estimate-test.cc:

Go to the source code of this file.

Functions

void rand_posdef_spmatrix (size_t dim, SpMatrix< BaseFloat > *matrix, TpMatrix< BaseFloat > *matrix_sqrt=NULL, BaseFloat *logdet=NULL)
 
void test_io (const LdaEstimate &lda_est, bool binary)
 
void UnitTestEstimateLda ()
 
int main ()
 

Function Documentation

◆ main()

int main ( )

Definition at line 207 of file lda-estimate-test.cc.

References rnnlm::i, and UnitTestEstimateLda().

207  {
208  // repeat the test X times
209  for (int i = 0; i < 2; i++)
211  std::cout << "Test OK.\n";
212 }
void UnitTestEstimateLda()

◆ rand_posdef_spmatrix()

void rand_posdef_spmatrix ( size_t  dim,
SpMatrix< BaseFloat > *  matrix,
TpMatrix< BaseFloat > *  matrix_sqrt = NULL,
BaseFloat *  logdet = NULL 
)

Definition at line 25 of file lda-estimate-test.cc.

References SpMatrix< Real >::AddMat2(), TpMatrix< Real >::Cholesky(), MatrixBase< Real >::Cond(), kaldi::kNoTrans, SpMatrix< Real >::LogPosDefDet(), and MatrixBase< Real >::SetRandn().

Referenced by UnitTestEstimateLda().

27  {
28  // generate random (non-singular) matrix
29  Matrix<BaseFloat> tmp(dim, dim);
30  while (1) {
31  tmp.SetRandn();
32  if (tmp.Cond() < 100) break;
33  std::cout << "Condition number of random matrix large "
34  << static_cast<float>(tmp.Cond()) << ", trying again (this is normal)"
35  << '\n';
36  }
37  // tmp * tmp^T will give positive definite matrix
38  matrix->AddMat2(1.0, tmp, kNoTrans, 0.0);
39 
40  if (matrix_sqrt != NULL) matrix_sqrt->Cholesky(*matrix);
41  if (logdet != NULL) *logdet = matrix->LogPosDefDet();
42  if ((matrix_sqrt == NULL) && (logdet == NULL)) {
43  TpMatrix<BaseFloat> sqrt(dim);
44  sqrt.Cholesky(*matrix);
45  }
46 }
void AddMat2(const Real alpha, const MatrixBase< Real > &M, MatrixTransposeType transM, const Real beta)
rank-N update: if (transM == kNoTrans) (*this) = beta*(*this) + alpha * M * M^T, or (if transM == kTr...
Definition: sp-matrix.cc:1110
void Cholesky(const SpMatrix< Real > &orig)
Definition: tp-matrix.cc:88
Real LogPosDefDet() const
Computes log determinant but only for +ve-def matrices (it uses Cholesky).
Definition: sp-matrix.cc:36
Packed symetric matrix class.
Definition: matrix-common.h:63

◆ test_io()

void test_io ( const LdaEstimate lda_est,
bool  binary 
)

Definition at line 49 of file lda-estimate-test.cc.

References MatrixBase< Real >::AddMat(), LdaEstimateOptions::dim, LdaEstimate::Dim(), LdaEstimate::Estimate(), LdaEstimate::Init(), MatrixBase< Real >::IsZero(), KALDI_ASSERT, kaldi::kNoTrans, LdaEstimate::NumClasses(), LdaEstimate::Read(), LdaEstimate::Scale(), Input::Stream(), and LdaEstimate::Write().

Referenced by UnitTestEstimateLda().

49  {
50  std::cout << "Testing I/O, binary = " << binary << '\n';
51 
52  size_t dim = lda_est.Dim();
53 
54  lda_est.Write(Output("tmp_stats", binary).Stream(), binary);
55 
56  bool binary_in;
57  LdaEstimate lda_est2;
58  lda_est2.Init(lda_est.NumClasses(), lda_est.Dim());
59  Input ki("tmp_stats", &binary_in);
60  lda_est2.Read(ki.Stream(),
61  binary_in, false); // not adding
62 
63  Input ki2("tmp_stats", &binary_in);
64  lda_est2.Read(ki2.Stream(),
65  binary_in, true); // adding
66 
67  lda_est2.Scale(0.5);
68  // 0.5 -> make it same as what it would have been if we read just once.
69 
72 
73  LdaEstimateOptions opts;
74  opts.dim = dim;
75  lda_est.Estimate(opts, &m1);
76  lda_est2.Estimate(opts, &m2);
77 
78  m1.AddMat(-1.0, m2, kNoTrans);
79  KALDI_ASSERT(m1.IsZero(1.0e-02));
80 
81  unlink("tmp_stats");
82 }
Class for computing linear discriminant analysis (LDA) transform.
Definition: lda-estimate.h:57
int32 Dim() const
Returns the dimensionality of the feature vectors.
Definition: lda-estimate.h:66
void Scale(BaseFloat f)
Scales all accumulators.
Definition: lda-estimate.cc:38
void Write(std::ostream &out_stream, bool binary) const
void AddMat(const Real alpha, const MatrixBase< Real > &M, MatrixTransposeType transA=kNoTrans)
*this += alpha * M [or M^T]
void Init(int32 num_classes, int32 dimension)
Allocates memory for accumulators.
Definition: lda-estimate.cc:26
bool IsZero(Real cutoff=1.0e-05) const
Returns true if matrix is all zeros.
void Estimate(const LdaEstimateOptions &opts, Matrix< BaseFloat > *M, Matrix< BaseFloat > *Mfull=NULL) const
Estimates the LDA transform matrix m.
Definition: lda-estimate.cc:85
void Read(std::istream &in_stream, bool binary, bool add)
int32 NumClasses() const
Returns the number of classes.
Definition: lda-estimate.h:64
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ UnitTestEstimateLda()

void UnitTestEstimateLda ( )

Definition at line 85 of file lda-estimate-test.cc.

References LdaEstimate::Accumulate(), MatrixBase< Real >::AddMatMatMat(), VectorBase< Real >::AddMatVec(), SpMatrix< Real >::AddSp(), VectorBase< Real >::AddVec(), SpMatrix< Real >::AddVec2(), VectorBase< Real >::CopyFromVec(), rnnlm::d, LdaEstimateOptions::dim, VectorBase< Real >::Dim(), LdaEstimate::Estimate(), rnnlm::i, LdaEstimate::Init(), MatrixBase< Real >::IsDiagonal(), MatrixBase< Real >::IsUnit(), KALDI_ASSERT, kaldi::kCopyData, kaldi::kNoTrans, kaldi::kTrans, rand_posdef_spmatrix(), kaldi::RandGauss(), kaldi::RandInt(), LdaEstimateOptions::remove_offset, Vector< Real >::Resize(), MatrixBase< Real >::Row(), PackedMatrix< Real >::Scale(), VectorBase< Real >::Scale(), test_io(), and LdaEstimate::ZeroAccumulators().

Referenced by main().

85  {
86  // using namespace kaldi;
87 
88  // dimension of the gmm
89  size_t dim = kaldi::RandInt(10, 20);
90 
91  // number of mixtures in the data
92  size_t num_class = dim + kaldi::RandInt(1, 10); // must be at least dim + 1
93 
94  std::cout << "Running test with " << num_class << " classes and "
95  << dim << " dimensional vectors" << '\n';
96 
97  // generate random feature vectors
98  // first, generate parameters of vectors distribution
99  // (mean and covariance matrices)
100  Matrix<BaseFloat> means_f(num_class, dim);
101  std::vector<SpMatrix<BaseFloat> > vars_f(num_class);
102  std::vector<TpMatrix<BaseFloat> > vars_f_sqrt(num_class);
103  for (size_t mix = 0; mix < num_class; mix++) {
104  vars_f[mix].Resize(dim);
105  vars_f_sqrt[mix].Resize(dim);
106  }
107 
108  for (size_t m = 0; m < num_class; m++) {
109  for (size_t d = 0; d < dim; d++) {
110  means_f(m, d) = kaldi::RandGauss();
111  }
112  rand_posdef_spmatrix(dim, &vars_f[m], &vars_f_sqrt[m], NULL);
113  }
114 
115  // second, generate X feature vectors for each of the mixture components
116  size_t counter = 0;
117  size_t vec_count = 1000;
118  Matrix<BaseFloat> feats(num_class * vec_count, dim);
119  std::vector<int32> feats_class(num_class * vec_count);
120  Vector<BaseFloat> rnd_vec(dim);
121  for (size_t m = 0; m < num_class; m++) {
122  for (size_t i = 0; i < vec_count; i++) {
123  for (size_t d = 0; d < dim; d++) {
124  rnd_vec(d) = RandGauss();
125  }
126  feats.Row(counter).CopyFromVec(means_f.Row(m));
127  feats.Row(counter).AddTpVec(1.0, vars_f_sqrt[m], kNoTrans, rnd_vec, 1.0);
128  feats_class[counter] = m;
129  ++counter;
130  }
131  }
132 
133  // Compute total covar and means for classes.
134  Vector<double> total_mean(dim);
135  Matrix<double> class_mean(num_class, dim);
136  SpMatrix<double> total_covar(dim);
137  Vector<double> tmp_vec_d(dim);
138  for (size_t i = 0; i < counter; i++) {
139  tmp_vec_d.CopyFromVec(feats.Row(i));
140  class_mean.Row(feats_class[i]).AddVec(1.0, tmp_vec_d);
141  total_mean.AddVec(1.0, tmp_vec_d);
142  total_covar.AddVec2(1.0, tmp_vec_d);
143  }
144  total_mean.Scale(1/static_cast<double>(counter));
145  total_covar.Scale(1/static_cast<double>(counter));
146  total_covar.AddVec2(-1.0, total_mean);
147  // Compute between-class covar.
148  SpMatrix<double> bc_covar(dim);
149  for (size_t c = 0; c < num_class; c++) {
150  class_mean.Row(c).Scale(1/static_cast<double>(vec_count));
151  bc_covar.AddVec2(static_cast<double>(vec_count)/counter, class_mean.Row(c));
152  }
153  bc_covar.AddVec2(-1.0, total_mean);
154  // Compute within-class covar.
155  SpMatrix<double> wc_covar(total_covar);
156  wc_covar.AddSp(-1.0, bc_covar);
157 
158  // Estimate LDA transform matrix
159  LdaEstimate lda_est;
160  lda_est.Init(num_class, dim);
161  lda_est.ZeroAccumulators();
162  for (size_t i = 0; i < counter; i++) {
163  lda_est.Accumulate(feats.Row(i), feats_class[i]);
164  }
165  LdaEstimateOptions opts;
166  opts.dim = dim;
167 
168  Matrix<BaseFloat> lda_mat_bf,
169  lda_mat_bf_mean_remove;
170  lda_est.Estimate(opts, &lda_mat_bf);
171  opts.remove_offset = true;
172  lda_est.Estimate(opts, &lda_mat_bf_mean_remove);
173 
174  {
175  Vector<BaseFloat> mean_ext(total_mean);
176  mean_ext.Resize(mean_ext.Dim() + 1, kCopyData);
177  mean_ext(mean_ext.Dim() - 1) = 1.0;
178  Vector<BaseFloat> zero(mean_ext.Dim() - 1);
179  zero.AddMatVec(1.0, lda_mat_bf_mean_remove, kNoTrans, mean_ext, 0.0);
180  KALDI_ASSERT(zero.IsZero(0.001));
181  }
182 
183  // Check lda_mat
184  Matrix<double> lda_mat(lda_mat_bf);
185  Matrix<double> tmp_mat(dim, dim);
186  Matrix<double> wc_covar_mat(wc_covar);
187  Matrix<double> bc_covar_mat(bc_covar);
188  // following product should give unit matrix
189  tmp_mat.AddMatMatMat(1.0, lda_mat, kNoTrans, wc_covar_mat, kNoTrans,
190  lda_mat, kTrans, 0.0);
191  KALDI_ASSERT(tmp_mat.IsUnit());
192  // following product should give diagonal matrix with ordered diagonal (desc)
193  tmp_mat.AddMatMatMat(1.0, lda_mat, kNoTrans, bc_covar_mat, kNoTrans,
194  lda_mat, kTrans, 0.0);
195  KALDI_ASSERT(tmp_mat.IsDiagonal());
196  for (int32 i = 1; i < static_cast<int32>(dim); i++) {
197  if (tmp_mat(i, i) < 1.0e-10) { tmp_mat(i, i) = 0.0; }
198  KALDI_ASSERT(tmp_mat(i - 1, i - 1) >= tmp_mat(i, i));
199  }
200 
201  // test I/O
202  test_io(lda_est, false);
203  test_io(lda_est, true);
204 }
void Accumulate(const VectorBase< BaseFloat > &data, int32 class_id, BaseFloat weight=1.0)
Accumulates data.
Definition: lda-estimate.cc:45
Class for computing linear discriminant analysis (LDA) transform.
Definition: lda-estimate.h:57
void rand_posdef_spmatrix(size_t dim, SpMatrix< BaseFloat > *matrix, TpMatrix< BaseFloat > *matrix_sqrt=NULL, BaseFloat *logdet=NULL)
float RandGauss(struct RandomState *state=NULL)
Definition: kaldi-math.h:155
kaldi::int32 int32
void Init(int32 num_classes, int32 dimension)
Allocates memory for accumulators.
Definition: lda-estimate.cc:26
void Estimate(const LdaEstimateOptions &opts, Matrix< BaseFloat > *M, Matrix< BaseFloat > *Mfull=NULL) const
Estimates the LDA transform matrix m.
Definition: lda-estimate.cc:85
void AddMatVec(const Real alpha, const MatrixBase< Real > &M, const MatrixTransposeType trans, const VectorBase< Real > &v, const Real beta)
Add matrix times vector : this <– beta*this + alpha*M*v.
Definition: kaldi-vector.cc:92
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void ZeroAccumulators()
Sets all accumulators to zero.
Definition: lda-estimate.cc:32
void test_io(const LdaEstimate &lda_est, bool binary)
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95