am-sgmm2-test.cc
Go to the documentation of this file.
1 // sgmm2/am-sgmm2-test.cc
2 
3 // Copyright 2012 Arnab Ghoshal
4 // 2009-2011 Saarland University
5 // 2012 Johns Hopkins University (author: Daniel Povey)
6 
7 // See ../../COPYING for clarification regarding multiple authors
8 //
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 //
13 // http://www.apache.org/licenses/LICENSE-2.0
14 //
15 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
17 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
18 // MERCHANTABLITY OR NON-INFRINGEMENT.
19 // See the Apache 2 License for the specific language governing permissions and
20 // limitations under the License.
21 
22 #include "gmm/model-test-common.h"
23 #include "sgmm2/am-sgmm2.h"
24 #include "util/kaldi-io.h"
25 
26 using kaldi::AmSgmm2;
27 using kaldi::int32;
28 using kaldi::BaseFloat;
29 namespace ut = kaldi::unittest;
30 
31 // Tests the initialization routines: InitializeFromFullGmm(), CopyFromSgmm2()
32 // and CopyGlobalsInitVecs().
33 void TestSgmm2Init(const AmSgmm2 &sgmm) {
34  using namespace kaldi;
35  int32 dim = sgmm.FeatureDim();
37  config.full_gmm_nbest = std::min(config.full_gmm_nbest, sgmm.NumGauss());
38 
39  kaldi::Vector<BaseFloat> feat(dim);
40  for (int32 d = 0; d < dim; d++) {
41  feat(d) = kaldi::RandGauss();
42  }
44  frame_vars.Resize(sgmm.NumGauss(), sgmm.FeatureDim(),
45  sgmm.PhoneSpaceDim());
46 
47  std::vector<int32> gselect;
48  sgmm.GaussianSelection(config, feat, &gselect);
50  Sgmm2PerFrameDerivedVars per_frame;
51  sgmm.ComputePerFrameVars(feat, gselect, empty, &per_frame);
52  Sgmm2LikelihoodCache sgmm_cache(sgmm.NumGroups(), sgmm.NumPdfs());
53  BaseFloat loglike = sgmm.LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
54  sgmm_cache.NextFrame();
55 
56  // First, test the CopyFromSgmm2() method:
57  AmSgmm2 *sgmm1 = new AmSgmm2();
58  sgmm1->CopyFromSgmm2(sgmm, true, true);
59  sgmm1->GaussianSelection(config, feat, &gselect);
60  sgmm1->ComputePerFrameVars(feat, gselect, empty, &per_frame);
61  sgmm_cache.NextFrame();
62  BaseFloat loglike1 = sgmm1->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
63  kaldi::AssertEqual(loglike, loglike1, 1e-4);
64  delete sgmm1;
65 
66  AmSgmm2 *sgmm2 = new AmSgmm2();
67  sgmm2->CopyFromSgmm2(sgmm, false, false);
68  sgmm2->ComputeNormalizers();
69  sgmm2->ComputeWeights();
70  sgmm2->GaussianSelection(config, feat, &gselect);
71  sgmm2->ComputePerFrameVars(feat, gselect, empty, &per_frame);
72  sgmm_cache.NextFrame();
73  BaseFloat loglike2 = sgmm2->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
74  kaldi::AssertEqual(loglike, loglike2, 1e-4);
75  delete sgmm2;
76 
77  // Next, initialize using the UBM from the current model
78  AmSgmm2 *sgmm3 = new AmSgmm2();
79  {
80  std::vector<int32> pdf2group(sgmm.NumPdfs());
81  for (int32 i = 0; i < sgmm.NumPdfs(); i++) pdf2group[i] = sgmm.Pdf2Group(i);
82  sgmm3->InitializeFromFullGmm(sgmm.full_ubm(), pdf2group,
83  sgmm.PhoneSpaceDim(), sgmm.SpkSpaceDim(), true, 0.9);
84  }
85  sgmm3->ComputeNormalizers();
86  sgmm3->GaussianSelection(config, feat, &gselect);
87  sgmm3->ComputePerFrameVars(feat, gselect, empty, &per_frame);
88  sgmm_cache.NextFrame();
89  BaseFloat loglike3 = sgmm3->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
90  kaldi::AssertEqual(loglike, loglike3, 1e-4);
91  delete sgmm3;
92 }
93 
94 // Tests the Read() and Write() methods, in both binary and ASCII mode, as well
95 // as Check(), and methods in likelihood computations.
96 void TestSgmm2IO(const AmSgmm2 &sgmm) {
97  using namespace kaldi;
98  int32 dim = sgmm.FeatureDim();
100  config.full_gmm_nbest = std::min(config.full_gmm_nbest, sgmm.NumGauss());
101 
102  kaldi::Vector<BaseFloat> feat(dim);
103  for (int32 d = 0; d < dim; d++) {
104  feat(d) = kaldi::RandGauss();
105  }
107  frame_vars.Resize(sgmm.NumGauss(), sgmm.FeatureDim(),
108  sgmm.PhoneSpaceDim());
109 
110  std::vector<int32> gselect;
111  sgmm.GaussianSelection(config, feat, &gselect);
113  Sgmm2PerFrameDerivedVars per_frame;
114  sgmm.ComputePerFrameVars(feat, gselect, empty, &per_frame);
115  Sgmm2LikelihoodCache sgmm_cache(sgmm.NumGroups(), sgmm.NumPdfs());
116  BaseFloat loglike = sgmm.LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
117 
118  // First, non-binary write
119  sgmm.Write(kaldi::Output("tmpf", false).Stream(), false,
121 
122  bool binary_in;
123  AmSgmm2 *sgmm1 = new AmSgmm2();
124  // Non-binary read
125  kaldi::Input ki1("tmpf", &binary_in);
126  sgmm1->Read(ki1.Stream(), binary_in);
127  sgmm1->Check(true);
128  sgmm1->GaussianSelection(config, feat, &gselect);
129  sgmm1->ComputePerFrameVars(feat, gselect, empty, &per_frame);
130  BaseFloat loglike1 = sgmm1->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
131  kaldi::AssertEqual(loglike, loglike1, 1e-4);
132 
133  // Next, binary write
134  sgmm1->Write(kaldi::Output("tmpfb", true).Stream(), true,
136  delete sgmm1;
137 
138  AmSgmm2 *sgmm2 = new AmSgmm2();
139  // Binary read
140  kaldi::Input ki2("tmpfb", &binary_in);
141  sgmm2->Read(ki2.Stream(), binary_in);
142  sgmm2->Check(true);
143  sgmm2->GaussianSelection(config, feat, &gselect);
144  sgmm2->ComputePerFrameVars(feat, gselect, empty, &per_frame);
145  BaseFloat loglike2 = sgmm2->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
146  kaldi::AssertEqual(loglike, loglike2, 1e-4);
147  delete sgmm2;
148  unlink("tmpf");
149  unlink("tmpfb");
150 }
151 
152 void TestSgmm2Substates(const AmSgmm2 &sgmm) {
153  using namespace kaldi;
154  int32 target_substates = 2 * sgmm.NumPdfs();
155  kaldi::Vector<BaseFloat> occs(sgmm.NumPdfs());
156  for (int32 i = 0; i < occs.Dim(); i++)
157  occs(i) = std::fabs(kaldi::RandGauss()) * (kaldi::RandUniform()+1);
158  AmSgmm2 *sgmm1 = new AmSgmm2();
159  sgmm1->CopyFromSgmm2(sgmm, false, false);
161  cfg.split_substates = target_substates;
162  sgmm1->SplitSubstates(occs, cfg);
163  sgmm1->ComputeNormalizers();
164  sgmm1->ComputeWeights();
165  sgmm1->Check(true);
166  int32 dim = sgmm.FeatureDim();
168  config.full_gmm_nbest = std::min(config.full_gmm_nbest, sgmm.NumGauss());
169  kaldi::Vector<BaseFloat> feat(dim);
170  for (int32 d = 0; d < dim; d++) {
171  feat(d) = kaldi::RandGauss();
172  }
173 
174  std::vector<int32> gselect;
175  sgmm.GaussianSelection(config, feat, &gselect);
176 
178  Sgmm2PerFrameDerivedVars per_frame;
179  sgmm.ComputePerFrameVars(feat, gselect, empty, &per_frame);
180  Sgmm2LikelihoodCache sgmm_cache(sgmm.NumGroups(), sgmm.NumPdfs());
181  BaseFloat loglike = sgmm.LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
182 
183  sgmm1->GaussianSelection(config, feat, &gselect);
184  sgmm1->ComputePerFrameVars(feat, gselect, empty, &per_frame);
185  sgmm_cache.NextFrame();
186  BaseFloat loglike1 = sgmm1->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
187  kaldi::AssertEqual(loglike, loglike1, 1e-2);
188 
189  delete sgmm1;
190 }
191 
192 void TestSgmm2IncreaseDim(const AmSgmm2 &sgmm) {
193  using namespace kaldi;
194  int32 target_phn_dim = static_cast<int32>(1.5 * sgmm.PhoneSpaceDim());
195  int32 target_spk_dim = sgmm.PhoneSpaceDim() - 1;
196 
197  int32 dim = sgmm.FeatureDim();
199  config.full_gmm_nbest = std::min(config.full_gmm_nbest, sgmm.NumGauss());
200  kaldi::Vector<BaseFloat> feat(dim);
201  for (int32 d = 0; d < dim; d++) {
202  feat(d) = kaldi::RandGauss();
203  }
205 
206  std::vector<int32> gselect;
207  sgmm.GaussianSelection(config, feat, &gselect);
209  Sgmm2PerFrameDerivedVars per_frame;
210  sgmm.ComputePerFrameVars(feat, gselect, empty, &per_frame);
211  Sgmm2LikelihoodCache sgmm_cache(sgmm.NumGroups(), sgmm.NumPdfs());
212  BaseFloat loglike = sgmm.LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
213 
214  kaldi::Matrix<BaseFloat> norm_xform;
216  AmSgmm2 *sgmm1 = new AmSgmm2();
217  sgmm1->CopyFromSgmm2(sgmm, false, false);
218  sgmm1->Check(true);
219  sgmm1->IncreasePhoneSpaceDim(target_phn_dim, norm_xform);
220  sgmm1->ComputeNormalizers();
221  sgmm1->Check(true);
222 
223 
224  sgmm1->GaussianSelection(config, feat, &gselect);
225  sgmm1->ComputePerFrameVars(feat, gselect, empty, &per_frame);
226  sgmm_cache.NextFrame();
227  BaseFloat loglike1 = sgmm1->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
228  kaldi::AssertEqual(loglike, loglike1, 1e-4);
229 
230  sgmm1->IncreaseSpkSpaceDim(target_spk_dim, norm_xform, true);
231  sgmm1->Check(true);
232  sgmm1->GaussianSelection(config, feat, &gselect);
233  sgmm1->ComputePerFrameVars(feat, gselect, empty, &per_frame);
234  sgmm_cache.NextFrame();
235  BaseFloat loglike2 = sgmm1->LogLikelihood(per_frame, 0, &sgmm_cache, &empty);
236  kaldi::AssertEqual(loglike, loglike2, 1e-4);
237  delete sgmm1;
238 }
239 
240 void TestSgmm2PreXform(const AmSgmm2 &sgmm) {
241  kaldi::Matrix<BaseFloat> xform, inv_xform;
242  kaldi::Vector<BaseFloat> diag_scatter;
243  kaldi::Vector<BaseFloat> occs(sgmm.NumPdfs());
244  occs.Set(100);
245  sgmm.ComputeFmllrPreXform(occs, &xform, &inv_xform, &diag_scatter);
246  int32 dim = xform.NumRows();
247  kaldi::SubMatrix<BaseFloat> a_pre(xform, 0, dim, 0, dim),
248  a_inv(inv_xform, 0, dim, 0, dim);
249  kaldi::Vector<BaseFloat> b_pre(dim), b_inv(dim);
250  b_pre.CopyColFromMat(xform, dim);
251  b_inv.CopyColFromMat(inv_xform, dim);
252  kaldi::Matrix<BaseFloat> res_mat(dim, dim, kaldi::kSetZero);
253  res_mat.AddMatMat(1.0, a_pre, kaldi::kNoTrans, a_inv, kaldi::kNoTrans, 0.0);
254  KALDI_ASSERT(res_mat.IsUnit(1.0e-5));
256  res_vec.AddMatVec(1.0, a_inv, kaldi::kNoTrans, b_pre, 0.0);
257  res_vec.AddVec(1.0, b_inv);
258  KALDI_ASSERT(res_vec.IsZero(1.0e-5));
259 }
260 
262  size_t dim = 1 + kaldi::RandInt(0, 9); // random dimension of the gmm
263  size_t num_comp = 1 + kaldi::RandInt(0, 9); // random number of mixtures
264  kaldi::FullGmm full_gmm;
265  ut::InitRandFullGmm(dim, num_comp, &full_gmm);
266 
267  std::vector<int32> pdf2group;
268  pdf2group.push_back(0);
269  AmSgmm2 sgmm;
271  sgmm.InitializeFromFullGmm(full_gmm, pdf2group, dim+1, 0, true, 0.9);
272  sgmm.ComputeNormalizers();
273  TestSgmm2Init(sgmm);
274  TestSgmm2IO(sgmm);
275  TestSgmm2Substates(sgmm);
276  TestSgmm2IncreaseDim(sgmm);
277  TestSgmm2PreXform(sgmm);
278 }
279 
280 int main() {
281  for (int i = 0; i < 10; i++)
282  UnitTestSgmm2();
283  std::cout << "Test OK.\n";
284  return 0;
285 }
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void ComputeWeights()
Computes the weights w_jmi_, which is needed for likelihood evaluation with SSGMMs.
Definition: am-sgmm2.cc:796
void Write(std::ostream &os, bool binary, SgmmWriteFlagsType write_params) const
Definition: am-sgmm2.cc:203
Class for definition of the subspace Gmm acoustic model.
Definition: am-sgmm2.h:231
void TestSgmm2PreXform(const AmSgmm2 &sgmm)
void CopyFromSgmm2(const AmSgmm2 &other, bool copy_normalizers, bool copy_weights)
Used to copy models (useful in update)
Definition: am-sgmm2.cc:415
float RandUniform(struct RandomState *state=NULL)
Returns a random number strictly between 0 and 1.
Definition: kaldi-math.h:151
Definition for Gaussian Mixture Model with full covariances.
Definition: full-gmm.h:40
void Read(std::istream &is, bool binary)
Definition: am-sgmm2.cc:89
void InitializeFromFullGmm(const FullGmm &gmm, const std::vector< int32 > &pdf2group, int32 phn_subspace_dim, int32 spk_subspace_dim, bool speaker_dependent_weights, BaseFloat self_weight)
Initializes the SGMM parameters from a full-covariance UBM.
Definition: am-sgmm2.cc:381
float RandGauss(struct RandomState *state=NULL)
Definition: kaldi-math.h:155
kaldi::int32 int32
void UnitTestSgmm2()
void TestSgmm2IncreaseDim(const AmSgmm2 &sgmm)
const FullGmm & full_ubm() const
Accessors.
Definition: am-sgmm2.h:378
int32 PhoneSpaceDim() const
Definition: am-sgmm2.h:361
int32 FeatureDim() const
Definition: am-sgmm2.h:363
std::istream & Stream()
Definition: kaldi-io.cc:826
int32 NumGroups() const
Definition: am-sgmm2.h:351
float BaseFloat
Definition: kaldi-types.h:29
BaseFloat LogLikelihood(const Sgmm2PerFrameDerivedVars &per_frame_vars, int32 j2, Sgmm2LikelihoodCache *cache, Sgmm2PerSpkDerivedVars *spk_vars, BaseFloat log_prune=0.0) const
This does a likelihood computation for a given state using the pre-selected Gaussian components (in p...
Definition: am-sgmm2.cc:517
void SplitSubstates(const Vector< BaseFloat > &state_occupancies, const Sgmm2SplitSubstatesConfig &config)
Increases the total number of substates based on the state occupancies.
Definition: am-sgmm2.cc:657
int32 Pdf2Group(int32 j2) const
Definition: am-sgmm2.cc:196
void Check(bool show_properties=true)
Checks the various components for correct sizes.
Definition: am-sgmm2.cc:276
BaseFloat GaussianSelection(const Sgmm2GselectConfig &config, const VectorBase< BaseFloat > &data, std::vector< int32 > *gselect) const
Computes the top-scoring Gaussian indices (used for pruning of later stages of computation).
Definition: am-sgmm2.cc:1406
void TestSgmm2IO(const AmSgmm2 &sgmm)
void TestSgmm2Substates(const AmSgmm2 &sgmm)
int32 NumPdfs() const
Various model dimensions.
Definition: am-sgmm2.h:350
void AddMatMat(const Real alpha, const MatrixBase< Real > &A, MatrixTransposeType transA, const MatrixBase< Real > &B, MatrixTransposeType transB, const Real beta)
int32 full_gmm_nbest
Number of highest-scoring full-covariance Gaussians per frame.
Definition: am-sgmm2.h:120
void ComputePerFrameVars(const VectorBase< BaseFloat > &data, const std::vector< int32 > &gselect, const Sgmm2PerSpkDerivedVars &spk_vars, Sgmm2PerFrameDerivedVars *per_frame_vars) const
This needs to be called with each new frame of data, prior to accumulation or likelihood evaluation: ...
Definition: am-sgmm2.cc:442
void Resize(int32 ngauss, int32 feat_dim, int32 phn_dim)
Definition: am-sgmm2.h:151
int32 NumGauss() const
Definition: am-sgmm2.h:360
void TestSgmm2Init(const AmSgmm2 &sgmm)
void InitRandFullGmm(int32 dim, int32 num_comp, FullGmm *gmm)
void CopyColFromMat(const MatrixBase< OtherReal > &M, MatrixIndexT col)
Extracts a column of the matrix M.
A class representing a vector.
Definition: kaldi-vector.h:406
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
void Set(Real f)
Set all members of a vector to a specified value.
void ComputeNormalizers()
Computes the data-independent terms in the log-likelihood computation for each Gaussian component and...
Definition: am-sgmm2.cc:857
static void AssertEqual(float a, float b, float relative_tolerance=0.001)
assert abs(a - b) <= relative_tolerance * (abs(a)+abs(b))
Definition: kaldi-math.h:276
Sgmm2LikelihoodCache caches SGMM likelihoods at two levels: the final pdf likelihoods, and the sub-state level likelihoods, which means that with the SCTM system we can avoid redundant computation.
Definition: am-sgmm2.h:199
bool IsUnit(Real cutoff=1.0e-05) const
Returns true if the matrix is all zeros, except for ones on diagonal.
int32 SpkSpaceDim() const
Definition: am-sgmm2.h:362
void ComputeFeatureNormalizingTransform(const FullGmm &gmm, Matrix< BaseFloat > *xform)
Computes the inverse of an LDA transform (without dimensionality reduction) The computed transform is...
Definition: am-sgmm2.cc:1297
Holds the per-frame precomputed quantities x(t), x_{i}(t), z_{i}(t), and n_{i}(t) (cf...
Definition: am-sgmm2.h:142
Sub-matrix representation.
Definition: kaldi-matrix.h:988
int main()
int32 RandInt(int32 min_val, int32 max_val, struct RandomState *state)
Definition: kaldi-math.cc:95
void ComputeFmllrPreXform(const Vector< BaseFloat > &pdf_occs, Matrix< BaseFloat > *xform, Matrix< BaseFloat > *inv_xform, Vector< BaseFloat > *diag_mean_scatter) const
Computes the LDA-like pre-transform and its inverse as well as the eigenvalues of the scatter of the ...
Definition: am-sgmm2.cc:965