ebw-diag-gmm-test.cc
Go to the documentation of this file.
1 // gmm/ebw-diag-gmm-test.cc
2 
3 // Copyright 2009-2011 Petr Motlicek
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
20 #include <cmath>
21 
22 #include "gmm/diag-gmm.h"
23 #include "gmm/ebw-diag-gmm.h"
24 #include "util/kaldi-io.h"
25 
26 
27 namespace kaldi {
28 
29 
31  size_t dim = RandInt(5, 10); // dimension of the gmm
32  size_t nMix = 2; // number of mixtures in the data
33  size_t maxiterations = RandInt(2, 5); // number of iterations for estimation
34 
35  // maximum number of densities in the GMM
36  // larger than the number of mixtures in the data
37  // so that we can test the removal of unseen components
38  int32 maxcomponents = 10;
39 
40  // generate random feature vectors
41  Matrix<BaseFloat> means_f(nMix, dim), vars_f(nMix, dim);
42  // first, generate random mean and variance vectors
43  for (size_t m = 0; m < nMix; m++) {
44  for (size_t d= 0; d < dim; d++) {
45  means_f(m, d) = kaldi::RandGauss()*100.0F;
46  vars_f(m, d) = Exp(kaldi::RandGauss())*1000.0F+ 1.0F;
47  }
48  // std::cout << "Gauss " << m << ": Mean = " << means_f.Row(m) << '\n'
49  // << "Vars = " << vars_f.Row(m) << '\n';
50  }
51 
52  // Numerator stats
53  // second, generate 1000 feature vectors for each of the mixture components
54  size_t counter_num = 0, multiple = 200;
55  Matrix<BaseFloat> feats_num(nMix*multiple, dim);
56  for (size_t m = 0; m < nMix; m++) {
57  for (size_t i = 0; i < multiple; i++) {
58  for (size_t d = 0; d < dim; d++) {
59  feats_num(counter_num, d) = means_f(m, d) + kaldi::RandGauss() *
60  std::sqrt(vars_f(m, d));
61  }
62  counter_num++;
63  }
64  }
65 
66  // Denominator stats
67  // second, generate 1000 feature vectors for each of the mixture components
68  size_t counter_den = 0;
69  Matrix<BaseFloat> feats_den(nMix*multiple, dim);
70  for (size_t m = 0; m < nMix; m++) {
71  for (size_t i = 0; i < multiple; i++) {
72  for (size_t d = 0; d < dim; d++) {
73  feats_den(counter_den, d) = means_f(m, d) + kaldi::RandGauss() *
74  std::sqrt(vars_f(m, d));
75  }
76  counter_den++;
77  }
78  }
79 
80  // Compute the global mean and variance
81  Vector<BaseFloat> mean_acc(dim);
82  Vector<BaseFloat> var_acc(dim);
83  Vector<BaseFloat> featvec(dim);
84  for (size_t i = 0; i < counter_num; i++) {
85  featvec.CopyRowFromMat(feats_num, i);
86  mean_acc.AddVec(1.0, featvec);
87  featvec.ApplyPow(2.0);
88  var_acc.AddVec(1.0, featvec);
89  }
90  mean_acc.Scale(1.0F/counter_num);
91  var_acc.Scale(1.0F/counter_num);
92  var_acc.AddVec2(-1.0, mean_acc);
93  // std::cout << "Mean acc = " << mean_acc << '\n' << "Var acc = "
94  // << var_acc << '\n';
95 
96  // write the feature vectors to a file
97  std::ofstream of("tmpfeats");
98  of.precision(10);
99  of << feats_num;
100  of.close();
101 
102  // now generate randomly initial values for the GMM
103  Vector<BaseFloat> weights(1);
104  Matrix<BaseFloat> means(1, dim), vars(1, dim), invvars(1, dim);
105  for (size_t d= 0; d < dim; d++) {
106  means(0, d) = kaldi::RandGauss()*100.0F;
107  vars(0, d) = Exp(kaldi::RandGauss()) *10.0F + 1e-5F;
108  }
109  weights(0) = 1.0F;
110  invvars.CopyFromMat(vars);
111  invvars.InvertElements();
112 
113  // new GMM
114  DiagGmm *gmm = new DiagGmm();
115  gmm->Resize(1, dim);
116  gmm->SetWeights(weights);
117  gmm->SetInvVarsAndMeans(invvars, means);
118  gmm->ComputeGconsts();
119 
120 
121  EbwOptions ebw_opts;
122  EbwWeightOptions ebw_weight_opts;
123 
124  int r = Rand() % 16;
125  GmmFlagsType flags = (r%2 == 0 ? kGmmMeans : 0)
126  + ((r/2)%2 == 0 ? kGmmVariances : 0)
127  + ((r/4)%2 == 0 ? kGmmWeights : 0);
128  double tau = (r/8)%2 == 0 ? 100 : 0.0;
129 
130  if ((flags & kGmmVariances) && !(flags & kGmmMeans)) {
131  delete gmm;
132  return; // Don't do this case: not supported in the update equations.
133  }
134 
135  AccumDiagGmm num;
136  AccumDiagGmm den;
137 
138  num.Resize(gmm->NumGauss(), gmm->Dim(), flags);
139  num.SetZero(flags);
140  den.Resize(gmm->NumGauss(), gmm->Dim(), flags);
141  den.SetZero(flags);
142 
143  size_t iteration = 0;
144  double last_log_like_diff = NAN;
145  while (iteration < maxiterations) {
146  Vector<BaseFloat> featvec_num(dim);
147  Vector<BaseFloat> featvec_den(dim);
148  num.Resize(gmm->NumGauss(), gmm->Dim(), flags);
149  num.SetZero(flags);
150  den.Resize(gmm->NumGauss(), gmm->Dim(), flags);
151  den.SetZero(flags);
152 
153  double loglike_num = 0.0;
154  double loglike_den = 0.0;
155  for (size_t i = 0; i < counter_num; i++) {
156  featvec_num.CopyRowFromMat(feats_num, i);
157  loglike_num += static_cast<double>(num.AccumulateFromDiag(*gmm,
158  featvec_num, 1.0F));
159  // std::cout << "Mean accum_num: " << num.mean_accumulator() << '\n';
160  }
161  for (size_t i = 0; i < counter_den; i++) {
162  featvec_den.CopyRowFromMat(feats_den, i);
163  loglike_den += static_cast<double>(den.AccumulateFromDiag(*gmm,
164  featvec_den, 1.0F));
165  // std::cout << "Mean accum_den: " << den.mean_accumulator() << '\n';
166  }
167 
168  std::cout << "Loglikelihood Num before iteration " << iteration << " : "
169  << std::scientific << loglike_num << " number of components: "
170  << gmm->NumGauss() << '\n';
171 
172  std::cout << "Loglikelihood Den before iteration " << iteration << " : "
173  << std::scientific << loglike_den << " number of components: "
174  << gmm->NumGauss() << '\n';
175 
176  double loglike_diff = loglike_num - loglike_den;
177  if (iteration > 0) {
178  KALDI_LOG << "Objective changed " << last_log_like_diff
179  << " to " << loglike_diff;
180  if (loglike_diff < last_log_like_diff)
181  KALDI_WARN << "Objective decreased (flags = "
182  << GmmFlagsToString(flags) << ", tau = " << tau << " )";
183  }
184  last_log_like_diff = loglike_diff;
185 
186  AccumDiagGmm num_smoothed(num);
187  IsmoothStatsDiagGmm(num, tau, &num_smoothed); // Apply I-smoothing.
188 
189  BaseFloat auxf_gauss, auxf_weight, count;
190  std::cout << "MEANX: " << gmm->weights() << '\n';
191 
192  int32 num_floored;
193  UpdateEbwDiagGmm(num_smoothed, den, flags, ebw_opts,
194  gmm, &auxf_gauss, &count, &num_floored);
195 
196  if (flags & kGmmWeights) {
197  UpdateEbwWeightsDiagGmm(num, den, ebw_weight_opts, gmm, &auxf_weight,
198  &count);
199  }
200 
201  // mean_hlp.CopyFromVec(gmm->means_invvars().Row(0));
202  // std::cout << "MEANY: " << mean_hlp << '\n';
203  std::cout << "MEANY: " << gmm->weights() << '\n';
204 
205 
206  if ((iteration % 3 == 1) && (gmm->NumGauss() * 2 <= maxcomponents)) {
207  gmm->Split(gmm->NumGauss() * 2, 0.001);
208  std::cout << "Ngauss, Ndim: " << gmm->NumGauss() << " " << gmm->Dim() << '\n';
209  }
210 
211  iteration++;
212  }
213  delete gmm;
214 
215  unlink("tmpfeats");
216 }
217 
218 } // end namespace kaldi
219 
220 
221 int main() {
222  for (int i = 0; i < 5; i++) {
224  }
225  std::cout << "Test OK.\n";
226 }
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
double Exp(double x)
Definition: kaldi-math.h:83
int32 Dim() const
Returns the dimensionality of the Gaussian mean vectors.
Definition: diag-gmm.h:74
void SetInvVarsAndMeans(const MatrixBase< Real > &invvars, const MatrixBase< Real > &means)
Use SetInvVarsAndMeans if updating both means and (inverse) variances.
Definition: diag-gmm-inl.h:63
void Split(int32 target_components, float perturb_factor, std::vector< int32 > *history=NULL)
Split the components and remember the order in which the components were split.
Definition: diag-gmm.cc:154
void UpdateEbwWeightsDiagGmm(const AccumDiagGmm &num_stats, const AccumDiagGmm &den_stats, const EbwWeightOptions &opts, DiagGmm *gmm, BaseFloat *auxf_change_out, BaseFloat *count_out)
void Resize(int32 nMix, int32 dim)
Resizes arrays to this dim. Does not initialize data.
Definition: diag-gmm.cc:66
int32 ComputeGconsts()
Sets the gconsts.
Definition: diag-gmm.cc:114
float RandGauss(struct RandomState *state=NULL)
Definition: kaldi-math.h:155
kaldi::int32 int32
uint16 GmmFlagsType
Bitwise OR of the above flags.
Definition: model-common.h:35
void CopyFromMat(const MatrixBase< OtherReal > &M, MatrixTransposeType trans=kNoTrans)
Copy given matrix. (no resize is done).
void IsmoothStatsDiagGmm(const AccumDiagGmm &src_stats, double tau, AccumDiagGmm *dst_stats)
I-Smooth the stats. src_stats and dst_stats do not have to be different.
void CopyRowFromMat(const MatrixBase< Real > &M, MatrixIndexT row)
Extracts a row of the matrix M.
void UpdateEbwDiagGmm(const AccumDiagGmm &num_stats, const AccumDiagGmm &den_stats, GmmFlagsType flags, const EbwOptions &opts, DiagGmm *gmm, BaseFloat *auxf_change_out, BaseFloat *count_out, int32 *num_floored_out)
Definition: ebw-diag-gmm.cc:94
void AddVec2(const Real alpha, const VectorBase< Real > &v)
Add vector : *this = *this + alpha * rv^2 [element-wise squaring].
const size_t count
BaseFloat AccumulateFromDiag(const DiagGmm &gmm, const VectorBase< BaseFloat > &data, BaseFloat frame_posterior)
Accumulate for all components given a diagonal-covariance GMM.
#define KALDI_WARN
Definition: kaldi-error.h:150
const Vector< BaseFloat > & weights() const
Definition: diag-gmm.h:178
int32 NumGauss() const
Returns the number of mixture components in the GMM.
Definition: diag-gmm.h:72
void Scale(Real alpha)
Multiplies all elements by this constant.
void SetZero(GmmFlagsType flags)
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
int main()
void UnitTestEstimateMmieDiagGmm()
void InvertElements()
Inverts all the elements of the matrix.
A class representing a vector.
Definition: kaldi-vector.h:406
void ApplyPow(Real power)
Take all elements of vector to a power.
Definition: kaldi-vector.h:179
Definition for Gaussian Mixture Model with diagonal covariances.
Definition: diag-gmm.h:42
std::string GmmFlagsToString(GmmFlagsType flags)
Convert GMM flags to string.
Definition: model-common.cc:43
void SetWeights(const VectorBase< Real > &w)
Mutators for both float or double.
Definition: diag-gmm-inl.h:28
void Resize(int32 num_gauss, int32 dim, GmmFlagsType flags)
Allocates memory for accumulators.
#define KALDI_LOG
Definition: kaldi-error.h:153
void AddVec(const Real alpha, const VectorBase< OtherReal > &v)
Add vector : *this = *this + alpha * rv (with casting between floats and doubles) ...
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95