IvectorExtractorStats Class Reference

IvectorExtractorStats is a class used to update the parameters of the ivector extractor. More...

#include <ivector-extractor.h>

Collaboration diagram for IvectorExtractorStats:

Public Member Functions

 IvectorExtractorStats ()
 
 IvectorExtractorStats (const IvectorExtractor &extractor, const IvectorExtractorStatsOptions &stats_opts)
 
void Add (const IvectorExtractorStats &other)
 
void AccStatsForUtterance (const IvectorExtractor &extractor, const MatrixBase< BaseFloat > &feats, const Posterior &post)
 
double AccStatsForUtterance (const IvectorExtractor &extractor, const MatrixBase< BaseFloat > &feats, const FullGmm &fgmm)
 
void Read (std::istream &is, bool binary, bool add=false)
 
void Write (std::ostream &os, bool binary)
 
void Write (std::ostream &os, bool binary) const
 
double Update (const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
 Returns the objf improvement per frame. More...
 
double AuxfPerFrame ()
 
void IvectorVarianceDiagnostic (const IvectorExtractor &extractor)
 Prints the proportion of the variance explained by the Ivector model versus the Gaussians. More...
 
 IvectorExtractorStats (const IvectorExtractorStats &other)
 

Protected Member Functions

void CommitStatsForUtterance (const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats)
 
void CommitStatsForM (const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats, const VectorBase< double > &ivec_mean, const SpMatrix< double > &ivec_var)
 This is called by CommitStatsForUtterance. More...
 
void FlushCache ()
 Flushes the cache for the R_ stats. More...
 
void CommitStatsForSigma (const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats)
 Commit the stats used to update the variance. More...
 
void CommitStatsForWPoint (const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats, const VectorBase< double > &ivector, double weight)
 Commit the stats used to update the weight-projection w_– this one takes a point sample, it's called from CommitStatsForW(). More...
 
void CommitStatsForW (const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats, const VectorBase< double > &ivec_mean, const SpMatrix< double > &ivec_var)
 Commit the stats used to update the weight-projection w_. More...
 
void CommitStatsForPrior (const VectorBase< double > &ivec_mean, const SpMatrix< double > &ivec_var)
 Commit the stats used to update the prior distribution. More...
 
double UpdateProjections (const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
 
double UpdateProjection (const IvectorExtractorEstimationOptions &opts, int32 gaussian, IvectorExtractor *extractor) const
 
double UpdateWeights (const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
 
double UpdateWeight (const IvectorExtractorEstimationOptions &opts, int32 gaussian, IvectorExtractor *extractor) const
 
double UpdateVariances (const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
 
double UpdatePrior (const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
 
double PriorDiagnostics (double old_prior_offset) const
 
void CheckDims (const IvectorExtractor &extractor) const
 

Protected Attributes

IvectorExtractorStatsOptions config_
 
double tot_auxf_
 Caution: if we read from disk, this. More...
 
std::mutex gamma_Y_lock_
 This mutex guards gamma_ and Y_ (for multi-threaded update) More...
 
Vector< double > gamma_
 Total occupation count for each Gaussian index (zeroth-order stats) More...
 
std::vector< Matrix< double > > Y_
 Stats Y_i for estimating projections M. More...
 
std::mutex R_lock_
 This mutex guards R_ (for multi-threaded update) More...
 
Matrix< double > R_
 R_i, quadratic term for ivector subspace (M matrix)estimation. More...
 
std::mutex R_cache_lock_
 This mutex guards R_num_cached_, R_gamma_cache_, R_ivec_cache_ (for multi-threaded update) More...
 
int32 R_num_cached_
 To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here. More...
 
Matrix< double > R_gamma_cache_
 dimension: [num-to-cache][I] More...
 
Matrix< double > R_ivec_scatter_cache_
 dimension: [num-to-cache][S*(S+1)/2] More...
 
std::mutex weight_stats_lock_
 This mutex guards Q_ and G_ (for multi-threaded update) More...
 
Matrix< double > Q_
 Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is weighted by the coefficient of the quadratic term in the expansion for w (the "safe" one, with the max expression). More...
 
Matrix< double > G_
 G_ is the linear term in the weight projection matrix w_. More...
 
std::mutex variance_stats_lock_
 This mutex guards S_ (for multi-threaded update) More...
 
std::vector< SpMatrix< double > > S_
 S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_. More...
 
std::mutex prior_stats_lock_
 This mutex guards num_ivectors_, ivector_sum_ and ivector_scatter_ (for multi-threaded update) More...
 
double num_ivectors_
 Count of the number of iVectors we trained on. More...
 
Vector< double > ivector_sum_
 Sum of all the iVector means. Needed for prior re-estimation. More...
 
SpMatrix< double > ivector_scatter_
 Second-order stats for the iVectors. Needed for prior re-estimation. More...
 

Private Member Functions

void GetOrthogonalIvectorTransform (const SubMatrix< double > &T, IvectorExtractor *extractor, Matrix< double > *A) const
 Computes an orthogonal matrix A from the iVector transform T such that T' = A*T is an alternative transform which diagonalizes the quadratic_term_ in the iVector estimation objective function. More...
 
IvectorExtractorStatsoperator= (const IvectorExtractorStats &other)
 

Friends

class IvectorExtractor
 
class IvectorExtractorUpdateProjectionClass
 
class IvectorExtractorUpdateWeightClass
 

Detailed Description

IvectorExtractorStats is a class used to update the parameters of the ivector extractor.

Definition at line 481 of file ivector-extractor.h.

Constructor & Destructor Documentation

◆ IvectorExtractorStats() [1/3]

Definition at line 485 of file ivector-extractor.h.

References kaldi::AccStatsForUtterance().

485 : tot_auxf_(0.0), R_num_cached_(0), num_ivectors_(0) { }
int32 R_num_cached_
To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here...
double tot_auxf_
Caution: if we read from disk, this.
double num_ivectors_
Count of the number of iVectors we trained on.

◆ IvectorExtractorStats() [2/3]

IvectorExtractorStats ( const IvectorExtractor extractor,
const IvectorExtractorStatsOptions stats_opts 
)

Definition at line 891 of file ivector-extractor.cc.

References IvectorExtractorStatsOptions::cache_size, IvectorExtractorStats::config_, IvectorExtractor::FeatDim(), IvectorExtractorStats::G_, IvectorExtractorStats::gamma_, rnnlm::i, IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, IvectorExtractor::IvectorDependentWeights(), IvectorExtractor::IvectorDim(), KALDI_ASSERT, IvectorExtractorStats::num_ivectors_, IvectorExtractorStatsOptions::num_samples_for_weights, IvectorExtractor::NumGauss(), IvectorExtractorStats::Q_, IvectorExtractorStats::R_, IvectorExtractorStats::R_gamma_cache_, IvectorExtractorStats::R_ivec_scatter_cache_, IvectorExtractorStats::R_num_cached_, SpMatrix< Real >::Resize(), Vector< Real >::Resize(), Matrix< Real >::Resize(), IvectorExtractorStats::S_, IvectorExtractorStats::tot_auxf_, IvectorExtractorStatsOptions::update_variances, and IvectorExtractorStats::Y_.

893  :
894  config_(stats_opts) {
895  int32 S = extractor.IvectorDim(), D = extractor.FeatDim(),
896  I = extractor.NumGauss();
897 
899  tot_auxf_ = 0.0;
900  gamma_.Resize(I);
901  Y_.resize(I);
902  for (int32 i = 0; i < I; i++)
903  Y_[i].Resize(D, S);
904  R_.Resize(I, S * (S + 1) / 2);
905  R_num_cached_ = 0;
906  KALDI_ASSERT(stats_opts.cache_size > 0 && "--cache-size=0 not allowed");
907 
908  R_gamma_cache_.Resize(stats_opts.cache_size, I);
909  R_ivec_scatter_cache_.Resize(stats_opts.cache_size, S*(S+1)/2);
910 
911  if (extractor.IvectorDependentWeights()) {
912  Q_.Resize(I, S * (S + 1) / 2);
913  G_.Resize(I, S);
914  }
915  if (stats_opts.update_variances) {
916  S_.resize(I);
917  for (int32 i = 0; i < I; i++)
918  S_[i].Resize(D);
919  }
920  num_ivectors_ = 0;
921  ivector_sum_.Resize(S);
923 }
int32 R_num_cached_
To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here...
Matrix< double > R_ivec_scatter_cache_
dimension: [num-to-cache][S*(S+1)/2]
kaldi::int32 int32
Matrix< double > R_gamma_cache_
dimension: [num-to-cache][I]
void Resize(MatrixIndexT length, MatrixResizeType resize_type=kSetZero)
Set vector to a specified size (can be zero).
double tot_auxf_
Caution: if we read from disk, this.
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
IvectorExtractorStatsOptions config_
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
void Resize(const MatrixIndexT r, const MatrixIndexT c, MatrixResizeType resize_type=kSetZero, MatrixStrideType stride_type=kDefaultStride)
Sets matrix to a specified size (zero is OK as long as both r and c are zero).
void Resize(MatrixIndexT nRows, MatrixResizeType resize_type=kSetZero)
Definition: sp-matrix.h:81
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ IvectorExtractorStats() [3/3]

IvectorExtractorStats ( const IvectorExtractorStats other)
explicit

Definition at line 1766 of file ivector-extractor.cc.

1767  :
1768  config_(other.config_), tot_auxf_(other.tot_auxf_), gamma_(other.gamma_),
1769  Y_(other.Y_), R_(other.R_), R_num_cached_(other.R_num_cached_),
1770  R_gamma_cache_(other.R_gamma_cache_),
1771  R_ivec_scatter_cache_(other.R_ivec_scatter_cache_),
1772  Q_(other.Q_), G_(other.G_), S_(other.S_), num_ivectors_(other.num_ivectors_),
1773  ivector_sum_(other.ivector_sum_), ivector_scatter_(other.ivector_scatter_) {
1774 }
int32 R_num_cached_
To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here...
Matrix< double > R_ivec_scatter_cache_
dimension: [num-to-cache][S*(S+1)/2]
Matrix< double > R_gamma_cache_
dimension: [num-to-cache][I]
double tot_auxf_
Caution: if we read from disk, this.
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
IvectorExtractorStatsOptions config_
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

Member Function Documentation

◆ AccStatsForUtterance() [1/2]

void AccStatsForUtterance ( const IvectorExtractor extractor,
const MatrixBase< BaseFloat > &  feats,
const Posterior post 
)

Definition at line 1132 of file ivector-extractor.cc.

References IvectorExtractorUtteranceStats::AccStats(), IvectorExtractorStats::CheckDims(), IvectorExtractorStats::CommitStatsForUtterance(), IvectorExtractor::FeatDim(), KALDI_ASSERT, KALDI_ERR, MatrixBase< Real >::NumCols(), IvectorExtractor::NumGauss(), MatrixBase< Real >::NumRows(), and IvectorExtractorStats::S_.

Referenced by IvectorExtractorStats::AccStatsForUtterance(), IvectorTask::operator()(), and kaldi::UnitTestIvectorExtractor().

1135  {
1136  typedef std::vector<std::pair<int32, BaseFloat> > VecType;
1137 
1138  CheckDims(extractor);
1139 
1140  int32 num_gauss = extractor.NumGauss(), feat_dim = extractor.FeatDim();
1141 
1142  if (feat_dim != feats.NumCols()) {
1143  KALDI_ERR << "Feature dimension mismatch, expected " << feat_dim
1144  << ", got " << feats.NumCols();
1145  }
1146  KALDI_ASSERT(static_cast<int32>(post.size()) == feats.NumRows());
1147 
1148  bool update_variance = (!S_.empty());
1149 
1150  // The zeroth and 1st-order stats are in "utt_stats".
1151  IvectorExtractorUtteranceStats utt_stats(num_gauss, feat_dim,
1152  update_variance);
1153 
1154  utt_stats.AccStats(feats, post);
1155 
1156  CommitStatsForUtterance(extractor, utt_stats);
1157 }
void CommitStatsForUtterance(const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats)
kaldi::int32 int32
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void CheckDims(const IvectorExtractor &extractor) const
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ AccStatsForUtterance() [2/2]

double AccStatsForUtterance ( const IvectorExtractor extractor,
const MatrixBase< BaseFloat > &  feats,
const FullGmm fgmm 
)

Definition at line 1159 of file ivector-extractor.cc.

References IvectorExtractorStats::AccStatsForUtterance(), FullGmm::ComponentPosteriors(), rnnlm::i, kaldi::kUndefined, FullGmm::NumGauss(), and MatrixBase< Real >::NumRows().

1162  {
1163  int32 num_frames = feats.NumRows();
1164  Posterior post(num_frames);
1165 
1166  double tot_log_like = 0.0;
1167  for (int32 t = 0; t < num_frames; t++) {
1168  SubVector<BaseFloat> frame(feats, t);
1169  Vector<BaseFloat> posterior(fgmm.NumGauss(), kUndefined);
1170  tot_log_like += fgmm.ComponentPosteriors(frame, &posterior);
1171  for (int32 i = 0; i < posterior.Dim(); i++)
1172  post[t].push_back(std::make_pair(i, posterior(i)));
1173  }
1174  AccStatsForUtterance(extractor, feats, post);
1175  return tot_log_like;
1176 }
kaldi::int32 int32
std::vector< std::vector< std::pair< int32, BaseFloat > > > Posterior
Posterior is a typedef for storing acoustic-state (actually, transition-id) posteriors over an uttera...
Definition: posterior.h:42
void AccStatsForUtterance(const IvectorExtractor &extractor, const MatrixBase< BaseFloat > &feats, const Posterior &post)

◆ Add()

void Add ( const IvectorExtractorStats other)

Definition at line 1178 of file ivector-extractor.cc.

References MatrixBase< Real >::AddMat(), SpMatrix< Real >::AddSp(), VectorBase< Real >::AddVec(), IvectorExtractorStats::config_, IvectorExtractorStats::G_, IvectorExtractorStats::gamma_, rnnlm::i, IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, KALDI_ASSERT, IvectorExtractorStats::num_ivectors_, IvectorExtractorStatsOptions::num_samples_for_weights, IvectorExtractorStats::Q_, IvectorExtractorStats::R_, IvectorExtractorStats::S_, IvectorExtractorStats::tot_auxf_, and IvectorExtractorStats::Y_.

Referenced by kaldi::TestIvectorExtractorStatsIO().

1178  {
1180  other.config_.num_samples_for_weights);
1181  double weight = 1.0; // will later make this configurable if needed.
1182  tot_auxf_ += weight * other.tot_auxf_;
1183  gamma_.AddVec(weight, other.gamma_);
1184  KALDI_ASSERT(Y_.size() == other.Y_.size());
1185  for (size_t i = 0; i < Y_.size(); i++)
1186  Y_[i].AddMat(weight, other.Y_[i]);
1187  R_.AddMat(weight, other.R_);
1188  Q_.AddMat(weight, other.Q_);
1189  G_.AddMat(weight, other.G_);
1190  KALDI_ASSERT(S_.size() == other.S_.size());
1191  for (size_t i = 0; i < S_.size(); i++)
1192  S_[i].AddSp(weight, other.S_[i]);
1193  num_ivectors_ += weight * other.num_ivectors_;
1194  ivector_sum_.AddVec(weight, other.ivector_sum_);
1195  ivector_scatter_.AddSp(weight, other.ivector_scatter_);
1196 }
void AddMat(const Real alpha, const MatrixBase< Real > &M, MatrixTransposeType transA=kNoTrans)
*this += alpha * M [or M^T]
double tot_auxf_
Caution: if we read from disk, this.
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
void AddSp(const Real alpha, const SpMatrix< Real > &Ma)
Definition: sp-matrix.h:211
IvectorExtractorStatsOptions config_
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
void AddVec(const Real alpha, const VectorBase< OtherReal > &v)
Add vector : *this = *this + alpha * rv (with casting between floats and doubles) ...
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ AuxfPerFrame()

double AuxfPerFrame ( )
inline

Definition at line 515 of file ivector-extractor.h.

Referenced by kaldi::UnitTestIvectorExtractor().

515 { return tot_auxf_ / gamma_.Sum(); }
double tot_auxf_
Caution: if we read from disk, this.
Real Sum() const
Returns sum of the elements.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)

◆ CheckDims()

void CheckDims ( const IvectorExtractor extractor) const
protected

Definition at line 1104 of file ivector-extractor.cc.

References IvectorExtractorStats::config_, VectorBase< Real >::Dim(), IvectorExtractor::FeatDim(), IvectorExtractorStats::G_, IvectorExtractorStats::gamma_, rnnlm::i, IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, IvectorExtractor::IvectorDependentWeights(), IvectorExtractor::IvectorDim(), KALDI_ASSERT, IvectorExtractorStats::num_ivectors_, IvectorExtractorStatsOptions::num_samples_for_weights, MatrixBase< Real >::NumCols(), IvectorExtractor::NumGauss(), MatrixBase< Real >::NumRows(), PackedMatrix< Real >::NumRows(), IvectorExtractorStats::Q_, IvectorExtractorStats::R_, IvectorExtractorStats::S_, and IvectorExtractorStats::Y_.

Referenced by IvectorExtractorStats::AccStatsForUtterance(), and IvectorExtractorStats::Update().

1104  {
1105  int32 S = extractor.IvectorDim(), D = extractor.FeatDim(),
1106  I = extractor.NumGauss();
1108  KALDI_ASSERT(gamma_.Dim() == I);
1109  KALDI_ASSERT(static_cast<int32>(Y_.size()) == I);
1110  for (int32 i = 0; i < I; i++)
1111  KALDI_ASSERT(Y_[i].NumRows() == D && Y_[i].NumCols() == S);
1112  KALDI_ASSERT(R_.NumRows() == I && R_.NumCols() == S*(S+1)/2);
1113  if (extractor.IvectorDependentWeights()) {
1114  KALDI_ASSERT(Q_.NumRows() == I && Q_.NumCols() == S*(S+1)/2);
1115  KALDI_ASSERT(G_.NumRows() == I && G_.NumCols() == S);
1116  } else {
1117  KALDI_ASSERT(Q_.NumRows() == 0);
1118  KALDI_ASSERT(G_.NumRows() == 0);
1119  }
1120  // S_ may be empty or not, depending on whether update_variances == true in
1121  // the options.
1122  if (!S_.empty()) {
1123  KALDI_ASSERT(static_cast<int32>(S_.size() == I));
1124  for (int32 i = 0; i < I; i++)
1125  KALDI_ASSERT(S_[i].NumRows() == D);
1126  }
1128  KALDI_ASSERT(ivector_sum_.Dim() == S);
1130 }
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
kaldi::int32 int32
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
MatrixIndexT NumRows() const
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
IvectorExtractorStatsOptions config_
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
#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
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ CommitStatsForM()

void CommitStatsForM ( const IvectorExtractor extractor,
const IvectorExtractorUtteranceStats utt_stats,
const VectorBase< double > &  ivec_mean,
const SpMatrix< double > &  ivec_var 
)
protected

This is called by CommitStatsForUtterance.

We commit the stats used to update the M matrix.

Definition at line 926 of file ivector-extractor.cc.

References VectorBase< Real >::AddVec(), SpMatrix< Real >::AddVec2(), PackedMatrix< Real >::Data(), VectorBase< Real >::Dim(), IvectorExtractorStats::FlushCache(), IvectorExtractorUtteranceStats::gamma_, IvectorExtractorStats::gamma_, IvectorExtractorStats::gamma_Y_lock_, rnnlm::i, IvectorExtractor::NumGauss(), MatrixBase< Real >::NumRows(), IvectorExtractorStats::R_cache_lock_, IvectorExtractorStats::R_gamma_cache_, IvectorExtractorStats::R_ivec_scatter_cache_, IvectorExtractorStats::R_num_cached_, MatrixBase< Real >::Row(), IvectorExtractorUtteranceStats::X_, and IvectorExtractorStats::Y_.

Referenced by IvectorExtractorStats::CommitStatsForUtterance().

930  {
931 
932  gamma_Y_lock_.lock();
933 
934  // We do the occupation stats here also.
935  gamma_.AddVec(1.0, utt_stats.gamma_);
936 
937  // Stats for the linear term in M:
938  for (int32 i = 0; i < extractor.NumGauss(); i++) {
939  Y_[i].AddVecVec(1.0, utt_stats.X_.Row(i),
940  Vector<double>(ivec_mean));
941  }
942  gamma_Y_lock_.unlock();
943 
944  SpMatrix<double> ivec_scatter(ivec_var);
945  ivec_scatter.AddVec2(1.0, ivec_mean);
946 
947  R_cache_lock_.lock();
948  while (R_num_cached_ == R_gamma_cache_.NumRows()) {
949  // Cache full. The "while" statement is in case of certain race conditions.
950  R_cache_lock_.unlock();
951  FlushCache();
952  R_cache_lock_.lock();
953  }
954  R_gamma_cache_.Row(R_num_cached_).CopyFromVec(utt_stats.gamma_);
955  int32 ivector_dim = ivec_mean.Dim();
956  SubVector<double> ivec_scatter_vec(ivec_scatter.Data(),
957  ivector_dim * (ivector_dim + 1) / 2);
958  R_ivec_scatter_cache_.Row(R_num_cached_).CopyFromVec(ivec_scatter_vec);
959  R_num_cached_++;
960  R_cache_lock_.unlock();
961 }
int32 R_num_cached_
To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here...
std::mutex R_cache_lock_
This mutex guards R_num_cached_, R_gamma_cache_, R_ivec_cache_ (for multi-threaded update) ...
Matrix< double > R_ivec_scatter_cache_
dimension: [num-to-cache][S*(S+1)/2]
kaldi::int32 int32
Matrix< double > R_gamma_cache_
dimension: [num-to-cache][I]
const SubVector< Real > Row(MatrixIndexT i) const
Return specific row of matrix [const].
Definition: kaldi-matrix.h:188
void FlushCache()
Flushes the cache for the R_ stats.
MatrixIndexT NumRows() const
Returns number of rows (or zero for empty matrix).
Definition: kaldi-matrix.h:64
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
void AddVec(const Real alpha, const VectorBase< OtherReal > &v)
Add vector : *this = *this + alpha * rv (with casting between floats and doubles) ...
std::mutex gamma_Y_lock_
This mutex guards gamma_ and Y_ (for multi-threaded update)

◆ CommitStatsForPrior()

void CommitStatsForPrior ( const VectorBase< double > &  ivec_mean,
const SpMatrix< double > &  ivec_var 
)
protected

Commit the stats used to update the prior distribution.

Definition at line 1067 of file ivector-extractor.cc.

References SpMatrix< Real >::AddSp(), VectorBase< Real >::AddVec(), SpMatrix< Real >::AddVec2(), IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, IvectorExtractorStats::num_ivectors_, and IvectorExtractorStats::prior_stats_lock_.

Referenced by IvectorExtractorStats::CommitStatsForUtterance().

1069  {
1070  SpMatrix<double> ivec_scatter(ivec_var);
1071  ivec_scatter.AddVec2(1.0, ivec_mean);
1072  prior_stats_lock_.lock();
1073  num_ivectors_ += 1.0;
1074  ivector_sum_.AddVec(1.0, ivec_mean);
1075  ivector_scatter_.AddSp(1.0, ivec_scatter);
1076  prior_stats_lock_.unlock();
1077 }
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
void AddSp(const Real alpha, const SpMatrix< Real > &Ma)
Definition: sp-matrix.h:211
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
std::mutex prior_stats_lock_
This mutex guards num_ivectors_, ivector_sum_ and ivector_scatter_ (for multi-threaded update) ...
void AddVec(const Real alpha, const VectorBase< OtherReal > &v)
Add vector : *this = *this + alpha * rv (with casting between floats and doubles) ...

◆ CommitStatsForSigma()

void CommitStatsForSigma ( const IvectorExtractor extractor,
const IvectorExtractorUtteranceStats utt_stats 
)
protected

Commit the stats used to update the variance.

Definition at line 988 of file ivector-extractor.cc.

References rnnlm::i, IvectorExtractor::NumGauss(), IvectorExtractorUtteranceStats::S_, IvectorExtractorStats::S_, and IvectorExtractorStats::variance_stats_lock_.

Referenced by IvectorExtractorStats::CommitStatsForUtterance().

990  {
991  variance_stats_lock_.lock();
992  // Storing the raw scatter statistics per Gaussian. In the update phase we'll
993  // take into account some other terms relating to the model means and their
994  // correlation with the data.
995  for (int32 i = 0; i < extractor.NumGauss(); i++)
996  S_[i].AddSp(1.0, utt_stats.S_[i]);
997  variance_stats_lock_.unlock();
998 }
kaldi::int32 int32
std::mutex variance_stats_lock_
This mutex guards S_ (for multi-threaded update)
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ CommitStatsForUtterance()

void CommitStatsForUtterance ( const IvectorExtractor extractor,
const IvectorExtractorUtteranceStats utt_stats 
)
protected

Definition at line 1080 of file ivector-extractor.cc.

References IvectorExtractorStats::CommitStatsForM(), IvectorExtractorStats::CommitStatsForPrior(), IvectorExtractorStats::CommitStatsForSigma(), IvectorExtractorStats::CommitStatsForW(), IvectorExtractorStatsOptions::compute_auxf, IvectorExtractorStats::config_, IvectorExtractor::GetAuxf(), IvectorExtractor::GetIvectorDistribution(), IvectorExtractor::IvectorDependentWeights(), IvectorExtractor::IvectorDim(), IvectorExtractorStats::S_, and IvectorExtractorStats::tot_auxf_.

Referenced by IvectorExtractorStats::AccStatsForUtterance().

1082  {
1083 
1084  int32 ivector_dim = extractor.IvectorDim();
1085  Vector<double> ivec_mean(ivector_dim);
1086  SpMatrix<double> ivec_var(ivector_dim);
1087 
1088  extractor.GetIvectorDistribution(utt_stats,
1089  &ivec_mean,
1090  &ivec_var);
1091 
1092  if (config_.compute_auxf)
1093  tot_auxf_ += extractor.GetAuxf(utt_stats, ivec_mean, &ivec_var);
1094 
1095  CommitStatsForM(extractor, utt_stats, ivec_mean, ivec_var);
1096  if (extractor.IvectorDependentWeights())
1097  CommitStatsForW(extractor, utt_stats, ivec_mean, ivec_var);
1098  CommitStatsForPrior(ivec_mean, ivec_var);
1099  if (!S_.empty())
1100  CommitStatsForSigma(extractor, utt_stats);
1101 }
void CommitStatsForSigma(const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats)
Commit the stats used to update the variance.
kaldi::int32 int32
double tot_auxf_
Caution: if we read from disk, this.
IvectorExtractorStatsOptions config_
void CommitStatsForW(const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats, const VectorBase< double > &ivec_mean, const SpMatrix< double > &ivec_var)
Commit the stats used to update the weight-projection w_.
void CommitStatsForPrior(const VectorBase< double > &ivec_mean, const SpMatrix< double > &ivec_var)
Commit the stats used to update the prior distribution.
void CommitStatsForM(const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats, const VectorBase< double > &ivec_mean, const SpMatrix< double > &ivec_var)
This is called by CommitStatsForUtterance.
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ CommitStatsForW()

void CommitStatsForW ( const IvectorExtractor extractor,
const IvectorExtractorUtteranceStats utt_stats,
const VectorBase< double > &  ivec_mean,
const SpMatrix< double > &  ivec_var 
)
protected

Commit the stats used to update the weight-projection w_.

Definition at line 1038 of file ivector-extractor.cc.

References MatrixBase< Real >::AddMatTp(), VectorBase< Real >::AddRowSumMat(), TpMatrix< Real >::Cholesky(), IvectorExtractorStats::CommitStatsForWPoint(), IvectorExtractorStats::config_, IvectorExtractor::IvectorDim(), KALDI_ASSERT, kaldi::kNoTrans, kaldi::kTrans, IvectorExtractorStatsOptions::num_samples_for_weights, and MatrixBase< Real >::SetRandn().

Referenced by IvectorExtractorStats::CommitStatsForUtterance().

1042  {
1044 
1045  Matrix<double> rand(config_.num_samples_for_weights, extractor.IvectorDim());
1046  rand.SetRandn();
1047  TpMatrix<double> ivec_stddev(extractor.IvectorDim());
1048  ivec_stddev.Cholesky(ivec_var);
1049  Matrix<double> ivecs(config_.num_samples_for_weights, extractor.IvectorDim());
1050  ivecs.AddMatTp(1.0, rand, kNoTrans, ivec_stddev, kTrans, 0.0);
1051  // Now make the ivecs zero-mean
1052  Vector<double> avg_ivec(extractor.IvectorDim());
1053  avg_ivec.AddRowSumMat(1.0 / config_.num_samples_for_weights, ivecs);
1054  ivecs.AddVecToRows(-1.0, avg_ivec);
1055  // Correct the variance for what we just did, so the expected
1056  // variance still has the correct value.
1057  ivecs.Scale(sqrt(config_.num_samples_for_weights / (config_.num_samples_for_weights - 1.0)));
1058  // Add the mean of the distribution to "ivecs".
1059  ivecs.AddVecToRows(1.0, ivec_mean);
1060  // "ivecs" is now a sample from the iVector distribution.
1061  for (int32 samp = 0; samp < config_.num_samples_for_weights; samp++)
1062  CommitStatsForWPoint(extractor, utt_stats,
1063  ivecs.Row(samp),
1065 }
kaldi::int32 int32
IvectorExtractorStatsOptions config_
void CommitStatsForWPoint(const IvectorExtractor &extractor, const IvectorExtractorUtteranceStats &utt_stats, const VectorBase< double > &ivector, double weight)
Commit the stats used to update the weight-projection w_– this one takes a point sample...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185

◆ CommitStatsForWPoint()

void CommitStatsForWPoint ( const IvectorExtractor extractor,
const IvectorExtractorUtteranceStats utt_stats,
const VectorBase< double > &  ivector,
double  weight 
)
protected

Commit the stats used to update the weight-projection w_– this one takes a point sample, it's called from CommitStatsForW().

Definition at line 1003 of file ivector-extractor.cc.

References VectorBase< Real >::AddMatVec(), SpMatrix< Real >::AddVec2(), MatrixBase< Real >::AddVecVec(), VectorBase< Real >::ApplySoftMax(), PackedMatrix< Real >::Data(), IvectorExtractorStats::G_, IvectorExtractorUtteranceStats::gamma_, rnnlm::i, IvectorExtractor::IvectorDim(), kaldi::kNoTrans, IvectorExtractor::NumGauss(), IvectorExtractorStats::Q_, VectorBase< Real >::Sum(), IvectorExtractor::w_, and IvectorExtractorStats::weight_stats_lock_.

Referenced by IvectorExtractorStats::CommitStatsForW().

1007  {
1008  int32 num_gauss = extractor.NumGauss();
1009  // Compare this function with GetIvectorDistWeight(), from which it
1010  // was derived.
1011  Vector<double> logw_unnorm(num_gauss);
1012  logw_unnorm.AddMatVec(1.0, extractor.w_, kNoTrans, ivector, 0.0);
1013 
1014  Vector<double> w(logw_unnorm);
1015  w.ApplySoftMax(); // now w is the weights.
1016 
1017  Vector<double> linear_coeff(num_gauss);
1018  Vector<double> quadratic_coeff(num_gauss);
1019  double gamma = utt_stats.gamma_.Sum();
1020  for (int32 i = 0; i < num_gauss; i++) {
1021  double gamma_i = utt_stats.gamma_(i);
1022  double max_term = std::max(gamma_i, gamma * w(i));
1023  linear_coeff(i) = gamma_i - gamma * w(i) + max_term * logw_unnorm(i);
1024  quadratic_coeff(i) = max_term;
1025  }
1026  weight_stats_lock_.lock();
1027  G_.AddVecVec(weight, linear_coeff, Vector<double>(ivector));
1028 
1029  int32 ivector_dim = extractor.IvectorDim();
1030  SpMatrix<double> outer_prod(ivector_dim);
1031  outer_prod.AddVec2(1.0, ivector);
1032  SubVector<double> outer_prod_vec(outer_prod.Data(),
1033  ivector_dim * (ivector_dim + 1) / 2);
1034  Q_.AddVecVec(weight, quadratic_coeff, outer_prod_vec);
1035  weight_stats_lock_.unlock();
1036 }
kaldi::int32 int32
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
std::mutex weight_stats_lock_
This mutex guards Q_ and G_ (for multi-threaded update)
void AddVecVec(const Real alpha, const VectorBase< OtherReal > &a, const VectorBase< OtherReal > &b)
*this += alpha * a * b^T

◆ FlushCache()

void FlushCache ( )
protected

Flushes the cache for the R_ stats.

Definition at line 963 of file ivector-extractor.cc.

References MatrixBase< Real >::AddMatMat(), KALDI_VLOG, kaldi::kNoTrans, kaldi::kTrans, MatrixBase< Real >::NumCols(), IvectorExtractorStats::R_, IvectorExtractorStats::R_cache_lock_, IvectorExtractorStats::R_gamma_cache_, IvectorExtractorStats::R_ivec_scatter_cache_, IvectorExtractorStats::R_lock_, IvectorExtractorStats::R_num_cached_, and MatrixBase< Real >::Range().

Referenced by IvectorExtractorStats::CommitStatsForM(), and IvectorExtractorStats::Write().

963  {
964  R_cache_lock_.lock();
965  if (R_num_cached_ > 0) {
966  KALDI_VLOG(1) << "Flushing cache for IvectorExtractorStats";
967  // Store these quantities as copies in memory so other threads can use the
968  // cache while we update R_ from the cache.
969  Matrix<double> R_gamma_cache(
971  0, R_gamma_cache_.NumCols()));
972  Matrix<double> R_ivec_scatter_cache(
975  R_num_cached_ = 0; // As far as other threads are concerned, the cache is
976  // cleared and they may write to it.
977  R_cache_lock_.unlock();
978  R_lock_.lock();
979  R_.AddMatMat(1.0, R_gamma_cache, kTrans,
980  R_ivec_scatter_cache, kNoTrans, 1.0);
981  R_lock_.unlock();
982  } else {
983  R_cache_lock_.unlock();
984  }
985 }
int32 R_num_cached_
To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here...
std::mutex R_cache_lock_
This mutex guards R_num_cached_, R_gamma_cache_, R_ivec_cache_ (for multi-threaded update) ...
MatrixIndexT NumCols() const
Returns number of columns (or zero for empty matrix).
Definition: kaldi-matrix.h:67
Matrix< double > R_ivec_scatter_cache_
dimension: [num-to-cache][S*(S+1)/2]
std::mutex R_lock_
This mutex guards R_ (for multi-threaded update)
Matrix< double > R_gamma_cache_
dimension: [num-to-cache][I]
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
void AddMatMat(const Real alpha, const MatrixBase< Real > &A, MatrixTransposeType transA, const MatrixBase< Real > &B, MatrixTransposeType transB, const Real beta)
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
SubMatrix< Real > Range(const MatrixIndexT row_offset, const MatrixIndexT num_rows, const MatrixIndexT col_offset, const MatrixIndexT num_cols) const
Return a sub-part of matrix.
Definition: kaldi-matrix.h:202

◆ GetOrthogonalIvectorTransform()

void GetOrthogonalIvectorTransform ( const SubMatrix< double > &  T,
IvectorExtractor extractor,
Matrix< double > *  A 
) const
private

Computes an orthogonal matrix A from the iVector transform T such that T' = A*T is an alternative transform which diagonalizes the quadratic_term_ in the iVector estimation objective function.

This reorders the dimensions of the iVector from most to least important, which may be more convenient to view. The transform should not affect the performance of systems which use iVectors.

Definition at line 1353 of file ivector-extractor.cc.

References MatrixBase< Real >::AddMat(), VectorBase< Real >::AddMatVec(), IvectorExtractor::ComputeDerivedVars(), rnnlm::i, MatrixBase< Real >::Invert(), IvectorExtractor::IvectorDependentWeights(), IvectorExtractor::IvectorDim(), KALDI_LOG, kaldi::kNoTrans, kaldi::kTrans, MatrixBase< Real >::NumCols(), IvectorExtractor::NumGauss(), MatrixBase< Real >::NumRows(), Matrix< Real >::Resize(), MatrixBase< Real >::SetZero(), kaldi::SortSvd(), IvectorExtractor::U_, and IvectorExtractor::w_vec_.

Referenced by IvectorExtractorStats::UpdatePrior().

1356  {
1357  extractor->ComputeDerivedVars(); // Update the extractor->U_ matrix.
1358  int32 ivector_dim = extractor->IvectorDim(),
1359  num_gauss = extractor->NumGauss();
1360  int32 quad_dim = ivector_dim*(ivector_dim + 1)/2;
1361 
1362  // Each row of extractor->U_ is an SpMatrix. We can compute the weighted
1363  // avg of these rows in a SubVector that updates the data of the SpMatrix
1364  // Uavg.
1365  SpMatrix<double> Uavg(ivector_dim), Vavg(ivector_dim - 1);
1366  SubVector<double> uavg_vec(Uavg.Data(), quad_dim);
1367  if (extractor->IvectorDependentWeights()) {
1368  Vector<double> w_uniform(num_gauss);
1369  for (int32 i = 0; i < num_gauss; i++) w_uniform(i) = 1.0;
1370  uavg_vec.AddMatVec(1.0/num_gauss, extractor->U_, kTrans, w_uniform, 0.0);
1371  } else {
1372  uavg_vec.AddMatVec(1.0, extractor->U_, kTrans, extractor->w_vec_, 0.0);
1373  }
1374 
1375  Matrix<double> Tinv(T);
1376  Tinv.Invert();
1377  Matrix<double> Vavg_temp(Vavg), Uavg_temp(Uavg);
1378 
1379  Vavg_temp.AddMatMatMat(1.0, Tinv, kTrans, SubMatrix<double>(Uavg_temp,
1380  1, ivector_dim-1, 1, ivector_dim-1),
1381  kNoTrans, Tinv, kNoTrans, 0.0);
1382  Vavg.CopyFromMat(Vavg_temp);
1383 
1384  Vector<double> s(ivector_dim-1);
1385  Matrix<double> P(ivector_dim-1, ivector_dim-1);
1386  Vavg.Eig(&s, &P);
1387  SortSvd(&s, &P);
1388  A->Resize(P.NumCols(), P.NumRows());
1389  A->SetZero();
1390  A->AddMat(1.0, P, kTrans);
1391  KALDI_LOG << "Eigenvalues of Vavg: " << s;
1392 }
kaldi::int32 int32
#define KALDI_LOG
Definition: kaldi-error.h:153
void SortSvd(VectorBase< Real > *s, MatrixBase< Real > *U, MatrixBase< Real > *Vt, bool sort_on_absolute_value)
Function to ensure that SVD is sorted.

◆ IvectorVarianceDiagnostic()

void IvectorVarianceDiagnostic ( const IvectorExtractor extractor)

Prints the proportion of the variance explained by the Ivector model versus the Gaussians.

Definition at line 1297 of file ivector-extractor.cc.

References IvectorExtractor::FeatDim(), IvectorExtractorStats::gamma_, rnnlm::i, IvectorExtractor::InvertWithFlooring(), KALDI_LOG, kaldi::kNoTrans, IvectorExtractor::M_, IvectorExtractor::NumGauss(), PackedMatrix< Real >::Scale(), IvectorExtractor::Sigma_inv_, and VectorBase< Real >::Sum().

Referenced by main().

1298  {
1299 
1300  // W is an estimate of the total residual variance explained by the
1301  // speaker-adapated model. B is an estimate of the total variance
1302  // explained by the Ivector-subspace.
1303  SpMatrix<double> W(extractor.Sigma_inv_[0].NumRows()),
1304  B(extractor.M_[0].NumRows());
1305  Vector<double> w(gamma_);
1306  w.Scale(1.0 / gamma_.Sum());
1307  for (int32 i = 0; i < extractor.NumGauss(); i++) {
1308  SpMatrix<double> Sigma_i(extractor.FeatDim());
1309  extractor.InvertWithFlooring(extractor.Sigma_inv_[i], &Sigma_i);
1310  W.AddSp(w(i), Sigma_i);
1311  B.AddMat2(w(i), extractor.M_[i], kNoTrans, 1.0);
1312  }
1313  double trace_W = W.Trace(),
1314  trace_B = B.Trace();
1315  KALDI_LOG << "The proportion of within-Gaussian variance explained by "
1316  << "the iVectors is " << trace_B / (trace_B + trace_W) << ".";
1317 }
kaldi::int32 int32
Real Sum() const
Returns sum of the elements.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ operator=()

IvectorExtractorStats& operator= ( const IvectorExtractorStats other)
private

◆ PriorDiagnostics()

double PriorDiagnostics ( double  old_prior_offset) const
protected

Definition at line 1613 of file ivector-extractor.cc.

References SpMatrix< Real >::AddVec2(), VectorBase< Real >::Dim(), IvectorExtractorStats::gamma_, IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, KALDI_LOG, SpMatrix< Real >::LogPosDefDet(), IvectorExtractorStats::num_ivectors_, PackedMatrix< Real >::Scale(), VectorBase< Real >::Scale(), VectorBase< Real >::Sum(), and SpMatrix< Real >::Trace().

Referenced by IvectorExtractorStats::UpdatePrior().

1613  {
1614  // The iVectors had a centered covariance "covar"; we want to figure out
1615  // the objective-function change from rescaling. It's as if we were
1616  // formerly modeling "covar" with the unit matrix, and we're now modeling
1617  // it with "covar" itself. This is ignoring flooring issues. Of course,
1618  // we implement it through rescaling the space, but it has the same effect.
1619  // We also need to take into account that before the rescaling etc., the
1620  // old mean might have been wrong.
1621 
1622  int32 ivector_dim = ivector_sum_.Dim();
1623  Vector<double> sum(ivector_sum_);
1624  sum.Scale(1.0 / num_ivectors_);
1625  SpMatrix<double> covar(ivector_scatter_);
1626  covar.Scale(1.0 / num_ivectors_);
1627  covar.AddVec2(-1.0, sum); // Get the centered covariance.
1628 
1629  // Now work out the offset from the old prior's mean.
1630  Vector<double> mean_offset(sum);
1631  mean_offset(0) -= old_prior_offset;
1632 
1633  SpMatrix<double> old_covar(covar); // the covariance around the old mean.
1634  old_covar.AddVec2(1.0, mean_offset);
1635  // old likelihood = -0.5 * (Trace(I old_covar) + logdet(I) + [ignored])
1636  double old_like = -0.5 * old_covar.Trace();
1637  // new likelihood is if we updated the variance to equal "covar"... this isn't
1638  // how we did it (we use rescaling of the ivectors) but it has the same
1639  // effect. -0.5 * (Trace(covar^{-1} covar) + logdet(covar))
1640  double new_like = -0.5 * (ivector_dim + covar.LogPosDefDet()),
1641  like_change = new_like - old_like,
1642  like_change_per_frame = like_change * num_ivectors_ / gamma_.Sum();
1643 
1644  KALDI_LOG << "Overall auxf improvement from prior is " << like_change_per_frame
1645  << " per frame, or " << like_change << " per iVector.";
1646  return like_change_per_frame; // we'll be adding this to other per-frame
1647  // quantities.
1648 }
kaldi::int32 int32
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
MatrixIndexT Dim() const
Returns the dimension of the vector.
Definition: kaldi-vector.h:64
Real Sum() const
Returns sum of the elements.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
#define KALDI_LOG
Definition: kaldi-error.h:153

◆ Read()

void Read ( std::istream &  is,
bool  binary,
bool  add = false 
)

Definition at line 1240 of file ivector-extractor.cc.

References kaldi::ExpectToken(), IvectorExtractorStats::G_, IvectorExtractorStats::gamma_, rnnlm::i, IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, IvectorExtractorStats::num_ivectors_, IvectorExtractorStats::Q_, IvectorExtractorStats::R_, PackedMatrix< Real >::Read(), Vector< Real >::Read(), Matrix< Real >::Read(), kaldi::ReadBasicType(), IvectorExtractorStats::S_, IvectorExtractorStats::tot_auxf_, and IvectorExtractorStats::Y_.

Referenced by main(), and kaldi::TestIvectorExtractorStatsIO().

1240  {
1241  ExpectToken(is, binary, "<IvectorExtractorStats>");
1242  ExpectToken(is, binary, "<TotAuxf>");
1243  ReadBasicType(is, binary, &tot_auxf_, add);
1244  ExpectToken(is, binary, "<gamma>");
1245  gamma_.Read(is, binary, add);
1246  ExpectToken(is, binary, "<Y>");
1247  int32 size;
1248  ReadBasicType(is, binary, &size);
1249  Y_.resize(size);
1250  for (int32 i = 0; i < size; i++)
1251  Y_[i].Read(is, binary, add);
1252  ExpectToken(is, binary, "<R>");
1253  R_.Read(is, binary, add);
1254  ExpectToken(is, binary, "<Q>");
1255  Q_.Read(is, binary, add);
1256  ExpectToken(is, binary, "<G>");
1257  G_.Read(is, binary, add);
1258  ExpectToken(is, binary, "<S>");
1259  ReadBasicType(is, binary, &size);
1260  S_.resize(size);
1261  for (int32 i = 0; i < size; i++)
1262  S_[i].Read(is, binary, add);
1263  ExpectToken(is, binary, "<NumIvectors>");
1264  ReadBasicType(is, binary, &num_ivectors_, add);
1265  ExpectToken(is, binary, "<IvectorSum>");
1266  ivector_sum_.Read(is, binary, add);
1267  ExpectToken(is, binary, "<IvectorScatter>");
1268  ivector_scatter_.Read(is, binary, add);
1269  ExpectToken(is, binary, "</IvectorExtractorStats>");
1270 }
void Read(std::istream &in, bool binary, bool add=false)
void ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
kaldi::int32 int32
void Read(std::istream &is, bool binary, bool add=false)
double tot_auxf_
Caution: if we read from disk, this.
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
void Read(std::istream &in, bool binary, bool add=false)
read from stream.
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
void ExpectToken(std::istream &is, bool binary, const char *token)
ExpectToken tries to read in the given token, and throws an exception on failure. ...
Definition: io-funcs.cc:191
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
void Read(std::istream &in, bool binary, bool add=false)
Read function using C++ streams.
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ Update()

double Update ( const IvectorExtractorEstimationOptions opts,
IvectorExtractor extractor 
) const

Returns the objf improvement per frame.

Definition at line 1272 of file ivector-extractor.cc.

References IvectorExtractorStats::CheckDims(), IvectorExtractor::ComputeDerivedVars(), IvectorExtractorStats::gamma_, IvectorExtractor::IvectorDependentWeights(), KALDI_LOG, IvectorExtractorStats::S_, VectorBase< Real >::Sum(), IvectorExtractorStats::tot_auxf_, IvectorExtractorStats::UpdatePrior(), IvectorExtractorStats::UpdateProjections(), IvectorExtractorStats::UpdateVariances(), and IvectorExtractorStats::UpdateWeights().

Referenced by main(), and kaldi::UnitTestIvectorExtractor().

1274  {
1275  CheckDims(*extractor);
1276  if (tot_auxf_ != 0.0) {
1277  KALDI_LOG << "Overall auxf/frame on training data was "
1278  << (tot_auxf_/gamma_.Sum()) << " per frame over "
1279  << gamma_.Sum() << " frames.";
1280  }
1281 
1282  double ans = 0.0;
1283  ans += UpdateProjections(opts, extractor);
1284  if (extractor->IvectorDependentWeights())
1285  ans += UpdateWeights(opts, extractor);
1286  if (!S_.empty())
1287  ans += UpdateVariances(opts, extractor);
1288  ans += UpdatePrior(opts, extractor); // This will also transform the ivector
1289  // space. Note: this must be done as the
1290  // last stage, because it will make the
1291  // stats invalid for that model.
1292  KALDI_LOG << "Overall objective-function improvement per frame was " << ans;
1293  extractor->ComputeDerivedVars();
1294  return ans;
1295 }
double UpdateVariances(const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
double UpdateWeights(const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
double tot_auxf_
Caution: if we read from disk, this.
Real Sum() const
Returns sum of the elements.
double UpdateProjections(const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
void CheckDims(const IvectorExtractor &extractor) const
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
#define KALDI_LOG
Definition: kaldi-error.h:153
double UpdatePrior(const IvectorExtractorEstimationOptions &opts, IvectorExtractor *extractor) const
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ UpdatePrior()

double UpdatePrior ( const IvectorExtractorEstimationOptions opts,
IvectorExtractor extractor 
) const
protected

Definition at line 1651 of file ivector-extractor.cc.

References SpMatrix< Real >::AddMat2Sp(), MatrixBase< Real >::AddMatMat(), SpMatrix< Real >::AddVec2(), MatrixBase< Real >::AddVecVec(), VectorBase< Real >::ApplyFloor(), VectorBase< Real >::ApplyPow(), kaldi::ApproxEqual(), IvectorExtractorEstimationOptions::diagonalize, SpMatrix< Real >::Eig(), IvectorExtractorStats::GetOrthogonalIvectorTransform(), SpMatrix< Real >::IsUnit(), IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, IvectorExtractor::IvectorDim(), KALDI_ASSERT, KALDI_LOG, KALDI_WARN, kaldi::kNoTrans, kaldi::kTrans, M_SQRT2, VectorBase< Real >::Max(), VectorBase< Real >::Min(), MatrixBase< Real >::MulRowsVec(), VectorBase< Real >::Norm(), IvectorExtractorStats::num_ivectors_, MatrixBase< Real >::NumCols(), MatrixBase< Real >::NumRows(), IvectorExtractor::prior_offset_, IvectorExtractorStats::PriorDiagnostics(), PackedMatrix< Real >::Scale(), VectorBase< Real >::Scale(), MatrixBase< Real >::SetUnit(), and IvectorExtractor::TransformIvectors().

Referenced by IvectorExtractorStats::Update().

1653  {
1654 
1655  KALDI_ASSERT(num_ivectors_ > 0.0);
1656  Vector<double> sum(ivector_sum_);
1657  sum.Scale(1.0 / num_ivectors_);
1658  SpMatrix<double> covar(ivector_scatter_);
1659  covar.Scale(1.0 / num_ivectors_);
1660  covar.AddVec2(-1.0, sum); // Get the centered covariance.
1661 
1662  int32 ivector_dim = extractor->IvectorDim();
1663  Vector<double> s(ivector_dim);
1664  Matrix<double> P(ivector_dim, ivector_dim);
1665  // decompose covar = P diag(s) P^T:
1666  covar.Eig(&s, &P);
1667  KALDI_LOG << "Eigenvalues of iVector covariance range from "
1668  << s.Min() << " to " << s.Max();
1669  int32 num_floored;
1670  s.ApplyFloor(1.0e-07, &num_floored);
1671  if (num_floored > 0)
1672  KALDI_WARN << "Floored " << num_floored << " eigenvalues of covar "
1673  << "of iVectors.";
1674 
1675  Matrix<double> T(P, kTrans);
1676  { // set T to a transformation that makes covar unit
1677  // (modulo floored eigenvalues).
1678  Vector<double> scales(s);
1679  scales.ApplyPow(-0.5);
1680  T.MulRowsVec(scales);
1681  if (num_floored == 0) { // a check..
1682  SpMatrix<double> Tproj(ivector_dim);
1683  Tproj.AddMat2Sp(1.0, T, kNoTrans, covar, 0.0);
1684  KALDI_ASSERT(Tproj.IsUnit(1.0e-06));
1685  }
1686  }
1687 
1688  Vector<double> sum_proj(ivector_dim);
1689  sum_proj.AddMatVec(1.0, T, kNoTrans, sum, 0.0);
1690 
1691  KALDI_ASSERT(sum_proj.Norm(2.0) != 0.0);
1692 
1693  // We need a projection that (like T) makes "covar" unit,
1694  // but also that sends "sum" to a multiple of the vector e0 = [ 1 0 0 0 .. ].
1695  // We'll do this by a transform that follows T, of the form
1696  // (I - 2 a a^T), where a is unit. [i.e. a Householder reflection].
1697  // Firstly, let x equal sum_proj normalized to unit length.
1698  // We'll let a = alpha x + beta e0, for suitable coefficients alpha and beta,
1699  // To project sum_proj (or equivalenty, x) to a multiple of e0, we'll need that
1700  // the x term in
1701  // (I - 2(alpha x + beta e0)(alpha x + beta e0) x
1702  // equals zero., i.e. 1 - 2 alpha (alpha x^T x + beta e0^T x) == 0,
1703  // (1 - 2 alpha^2 - 2 alpha beta x0) = 0
1704  // To ensure that a is unit, we require that
1705  // (alpha x + beta e0).(alpha x + beta e0) = 1, i.e.
1706  // alpha^2 + beta^2 + 2 alpha beta x0 = 1
1707  // at wolframalpha.com,
1708  // Solve[ {a^2 + b^2 + 2 a b x = 1}, {1 - 2 a^2 - 2 a b x = 0}, {a, b} ]
1709  // gives different solutions, but the one that keeps the offset positive
1710  // after projection seems to be:
1711  // alpha = 1/(sqrt(2)sqrt(1 - x0)), beta = -alpha
1712 
1713  Matrix<double> U(ivector_dim, ivector_dim);
1714  U.SetUnit();
1715  Vector<double> x(sum_proj);
1716  x.Scale(1.0 / x.Norm(2.0));
1717  double x0 = x(0), alpha, beta;
1718  alpha = 1.0 / (M_SQRT2 * sqrt(1.0 - x0));
1719  beta = -alpha;
1720  Vector<double> a(x);
1721  a.Scale(alpha);
1722  a(0) += beta;
1723  U.AddVecVec(-2.0, a, a);
1724 
1725  Matrix<double> V(ivector_dim, ivector_dim);
1726  V.AddMatMat(1.0, U, kNoTrans, T, kNoTrans, 0.0);
1727 
1728  // Optionally replace transform V with V' such that V' makes the
1729  // covariance unit and additionally diagonalizes the quadratic
1730  // term.
1731  if (opts.diagonalize) {
1732 
1733  SubMatrix<double> Vsub(V, 1, V.NumRows()-1, 0, V.NumCols());
1734  Matrix<double> Vtemp(SubMatrix<double>(V, 1, V.NumRows()-1,
1735  0, V.NumCols())),
1736  A;
1737  GetOrthogonalIvectorTransform(SubMatrix<double>(Vtemp, 0,
1738  Vtemp.NumRows(), 1, Vtemp.NumCols()-1),
1739  extractor, &A);
1740 
1741  // It is necessary to exclude the first row of V in this transformation
1742  // so that the sum_vproj has the form [ x 0 0 0 .. ], where x > 0.
1743  Vsub.AddMatMat(1.0, A, kNoTrans, Vtemp, kNoTrans, 0.0);
1744  }
1745 
1746  if (num_floored == 0) { // a check..
1747  SpMatrix<double> Vproj(ivector_dim);
1748  Vproj.AddMat2Sp(1.0, V, kNoTrans, covar, 0.0);
1749  KALDI_ASSERT(Vproj.IsUnit(1.0e-04));
1750  }
1751 
1752 
1753  Vector<double> sum_vproj(ivector_dim);
1754  sum_vproj.AddMatVec(1.0, V, kNoTrans, sum, 0.0);
1755  // Make sure sum_vproj is of the form [ x 0 0 0 .. ] with x > 0.
1756  // (the x > 0 part isn't really necessary, it's just nice to know.)
1757  KALDI_ASSERT(ApproxEqual(sum_vproj(0), sum_vproj.Norm(2.0)));
1758 
1759  double ans = PriorDiagnostics(extractor->prior_offset_);
1760 
1761  extractor->TransformIvectors(V, sum_vproj(0));
1762 
1763  return ans;
1764 }
kaldi::int32 int32
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
double PriorDiagnostics(double old_prior_offset) const
#define M_SQRT2
Definition: kaldi-math.h:48
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
#define KALDI_WARN
Definition: kaldi-error.h:150
void GetOrthogonalIvectorTransform(const SubMatrix< double > &T, IvectorExtractor *extractor, Matrix< double > *A) const
Computes an orthogonal matrix A from the iVector transform T such that T&#39; = A*T is an alternative tra...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_LOG
Definition: kaldi-error.h:153
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265

◆ UpdateProjection()

double UpdateProjection ( const IvectorExtractorEstimationOptions opts,
int32  gaussian,
IvectorExtractor extractor 
) const
protected

Definition at line 1319 of file ivector-extractor.cc.

References VectorBase< Real >::CopyFromVec(), SolverOptions::diagonal_precondition, IvectorExtractorStats::gamma_, IvectorExtractorEstimationOptions::gaussian_min_count, rnnlm::i, IvectorExtractor::IvectorDim(), KALDI_ASSERT, KALDI_VLOG, KALDI_WARN, kaldi::kUndefined, IvectorExtractor::M_, SolverOptions::name, IvectorExtractor::NumGauss(), IvectorExtractorStats::R_, IvectorExtractor::Sigma_inv_, kaldi::SolveQuadraticMatrixProblem(), and IvectorExtractorStats::Y_.

1322  {
1323  int32 I = extractor->NumGauss(), S = extractor->IvectorDim();
1324  KALDI_ASSERT(i >= 0 && i < I);
1325  /*
1326  For Gaussian index i, maximize the auxiliary function
1327  Q_i(x) = tr(M_i^T Sigma_i^{-1} Y_i) - 0.5 tr(Sigma_i^{-1} M_i R_i M_i^T)
1328  */
1329  if (gamma_(i) < opts.gaussian_min_count) {
1330  KALDI_WARN << "Skipping Gaussian index " << i << " because count "
1331  << gamma_(i) << " is below min-count.";
1332  return 0.0;
1333  }
1334  SpMatrix<double> R(S, kUndefined), SigmaInv(extractor->Sigma_inv_[i]);
1335  SubVector<double> R_vec(R_, i); // i'th row of R; vectorized form of SpMatrix.
1336  SubVector<double> R_sp(R.Data(), S * (S+1) / 2);
1337  R_sp.CopyFromVec(R_vec); // copy to SpMatrix's memory.
1338 
1339  Matrix<double> M(extractor->M_[i]);
1340  SolverOptions solver_opts;
1341  solver_opts.name = "M";
1342  solver_opts.diagonal_precondition = true;
1343  double impr = SolveQuadraticMatrixProblem(R, Y_[i], SigmaInv, solver_opts, &M),
1344  gamma = gamma_(i);
1345  if (i < 4) {
1346  KALDI_VLOG(1) << "Objf impr for M for Gaussian index " << i << " is "
1347  << (impr / gamma) << " per frame over " << gamma << " frames.";
1348  }
1349  extractor->M_[i].CopyFromMat(M);
1350  return impr;
1351 }
Real SolveQuadraticMatrixProblem(const SpMatrix< Real > &Q, const MatrixBase< Real > &Y, const SpMatrix< Real > &SigmaInv, const SolverOptions &opts, MatrixBase< Real > *M)
Maximizes the auxiliary function : Like a numerically stable version of .
Definition: sp-matrix.cc:729
kaldi::int32 int32
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)

◆ UpdateProjections()

double UpdateProjections ( const IvectorExtractorEstimationOptions opts,
IvectorExtractor extractor 
) const
protected

Definition at line 1416 of file ivector-extractor.cc.

References count, kaldi::g_num_threads, IvectorExtractorStats::gamma_, rnnlm::i, KALDI_LOG, TaskSequencerConfig::num_threads, IvectorExtractor::NumGauss(), TaskSequencer< C >::Run(), and VectorBase< Real >::Sum().

Referenced by IvectorExtractorStats::Update().

1418  {
1419  int32 I = extractor->NumGauss();
1420  double tot_impr = 0.0;
1421  {
1422  TaskSequencerConfig sequencer_opts;
1423  sequencer_opts.num_threads = g_num_threads;
1424  TaskSequencer<IvectorExtractorUpdateProjectionClass> sequencer(
1425  sequencer_opts);
1426  for (int32 i = 0; i < I; i++)
1427  sequencer.Run(new IvectorExtractorUpdateProjectionClass(
1428  *this, opts, i, extractor, &tot_impr));
1429  }
1430  double count = gamma_.Sum();
1431  KALDI_LOG << "Overall objective function improvement for M (mean projections) "
1432  << "was " << (tot_impr / count) << " per frame over "
1433  << count << " frames.";
1434  return tot_impr / count;
1435 }
int32 g_num_threads
Definition: kaldi-thread.cc:25
kaldi::int32 int32
const size_t count
Real Sum() const
Returns sum of the elements.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
#define KALDI_LOG
Definition: kaldi-error.h:153
friend class IvectorExtractorUpdateProjectionClass

◆ UpdateVariances()

double UpdateVariances ( const IvectorExtractorEstimationOptions opts,
IvectorExtractor extractor 
) const
protected

Definition at line 1437 of file ivector-extractor.cc.

References MatrixBase< Real >::AddMat(), SpMatrix< Real >::AddMat2Sp(), MatrixBase< Real >::AddMatMat(), SpMatrix< Real >::AddSp(), SpMatrix< Real >::ApplyFloor(), VectorBase< Real >::CopyFromVec(), PackedMatrix< Real >::Data(), IvectorExtractor::FeatDim(), IvectorExtractorStats::gamma_, IvectorExtractorEstimationOptions::gaussian_min_count, rnnlm::i, SpMatrix< Real >::Invert(), IvectorExtractor::IvectorDim(), KALDI_ASSERT, KALDI_LOG, KALDI_VLOG, KALDI_WARN, kaldi::kNoTrans, kaldi::kTakeMeanAndCheck, kaldi::kTrans, SpMatrix< Real >::LogPosDefDet(), IvectorExtractor::M_, SpMatrix< Real >::MaxAbsEig(), IvectorExtractor::NumGauss(), PackedMatrix< Real >::NumRows(), IvectorExtractorStats::R_, MatrixBase< Real >::Row(), IvectorExtractorStats::S_, PackedMatrix< Real >::Scale(), IvectorExtractor::Sigma_inv_, VectorBase< Real >::Sum(), kaldi::TraceSpSp(), IvectorExtractorEstimationOptions::variance_floor_factor, and IvectorExtractorStats::Y_.

Referenced by IvectorExtractorStats::Update().

1439  {
1440  int32 num_gauss = extractor->NumGauss(),
1441  feat_dim = extractor->FeatDim(),
1442  ivector_dim = extractor->IvectorDim();
1443  KALDI_ASSERT(!S_.empty());
1444  double tot_objf_impr = 0.0;
1445 
1446  // "raw_variances" will be the variances directly from
1447  // the stats, without any flooring.
1448  std::vector<SpMatrix<double> > raw_variances(num_gauss);
1449  SpMatrix<double> var_floor(feat_dim);
1450  double var_floor_count = 0.0;
1451 
1452  for (int32 i = 0; i < num_gauss; i++) {
1453  if (gamma_(i) < opts.gaussian_min_count) continue; // warned in UpdateProjections
1454  SpMatrix<double> &S(raw_variances[i]);
1455  S = S_[i]; // Set it to the raw scatter statistics.
1456 
1457  // The equations for estimating the variance are similar to
1458  // those used in SGMMs. We need to convert it to a centered
1459  // covariance, and for this we can use a combination of other
1460  // stats and the model parameters.
1461 
1462  Matrix<double> M(extractor->M_[i]);
1463  // Y * M^T.
1464  Matrix<double> YM(feat_dim, feat_dim);
1465  YM.AddMatMat(1.0, Y_[i], kNoTrans, M, kTrans, 0.0);
1466  Matrix<double> YMMY(YM, kTrans);
1467  YMMY.AddMat(1.0, YM);
1468  // Now, YMMY = Y * M^T + M * Y^T. This is a kind of cross-term
1469  // between the mean and the data, which we subtract.
1470  SpMatrix<double> YMMY_sp(YMMY, kTakeMeanAndCheck);
1471  S.AddSp(-1.0, YMMY_sp);
1472 
1473  // Add in a mean-squared term.
1474  SpMatrix<double> R(ivector_dim); // will be scatter of iVectors, weighted
1475  // by count for this Gaussian.
1476  SubVector<double> R_vec(R.Data(),
1477  ivector_dim * (ivector_dim + 1) / 2);
1478  R_vec.CopyFromVec(R_.Row(i)); //
1479 
1480  S.AddMat2Sp(1.0, M, kNoTrans, R, 1.0);
1481 
1482  var_floor.AddSp(1.0, S);
1483  var_floor_count += gamma_(i);
1484  S.Scale(1.0 / gamma_(i));
1485  }
1486  KALDI_ASSERT(var_floor_count > 0.0);
1487  KALDI_ASSERT(opts.variance_floor_factor > 0.0 &&
1488  opts.variance_floor_factor <= 1.0);
1489 
1490  var_floor.Scale(opts.variance_floor_factor / var_floor_count);
1491 
1492  // var_floor should not be singular in any normal case, but previously
1493  // we've had situations where cholesky on it failed (perhaps due to
1494  // people using linearly dependent features). So we floor its
1495  // singular values.
1496  int eig_floored = var_floor.ApplyFloor(var_floor.MaxAbsEig() * 1.0e-04);
1497  if (eig_floored > 0) {
1498  KALDI_WARN << "Floored " << eig_floored << " eigenvalues of the "
1499  << "variance floor matrix. This is not expected. Maybe your "
1500  << "feature data is linearly dependent.";
1501  }
1502 
1503  int32 tot_num_floored = 0;
1504  for (int32 i = 0; i < num_gauss; i++) {
1505  SpMatrix<double> &S(raw_variances[i]); // un-floored variance.
1506  if (S.NumRows() == 0) continue; // due to low count.
1507  SpMatrix<double> floored_var(S);
1508  SpMatrix<double> old_inv_var(extractor->Sigma_inv_[i]);
1509 
1510  int32 num_floored = floored_var.ApplyFloor(var_floor);
1511  tot_num_floored += num_floored;
1512  if (num_floored > 0)
1513  KALDI_LOG << "For Gaussian index " << i << ", floored "
1514  << num_floored << " eigenvalues of variance.";
1515  // this objf is per frame;
1516  double old_objf = -0.5 * (TraceSpSp(S, old_inv_var) -
1517  old_inv_var.LogPosDefDet());
1518 
1519  SpMatrix<double> new_inv_var(floored_var);
1520  new_inv_var.Invert();
1521 
1522  double new_objf = -0.5 * (TraceSpSp(S, new_inv_var) -
1523  new_inv_var.LogPosDefDet());
1524  if (i < 4) {
1525  KALDI_VLOG(1) << "Objf impr/frame for variance for Gaussian index "
1526  << i << " was " << (new_objf - old_objf);
1527  }
1528  tot_objf_impr += gamma_(i) * (new_objf - old_objf);
1529  extractor->Sigma_inv_[i].CopyFromSp(new_inv_var);
1530  }
1531  double floored_percent = tot_num_floored * 100.0 / (num_gauss * feat_dim);
1532  KALDI_LOG << "Floored " << floored_percent << "% of all Gaussian eigenvalues";
1533 
1534  KALDI_LOG << "Overall objf impr/frame for variances was "
1535  << (tot_objf_impr / gamma_.Sum()) << " over "
1536  << gamma_.Sum() << " frames.";
1537  return tot_objf_impr / gamma_.Sum();
1538 }
kaldi::int32 int32
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
const SubVector< Real > Row(MatrixIndexT i) const
Return specific row of matrix [const].
Definition: kaldi-matrix.h:188
double TraceSpSp(const SpMatrix< double > &A, const SpMatrix< double > &B)
Definition: sp-matrix.cc:326
#define KALDI_WARN
Definition: kaldi-error.h:150
Real Sum() const
Returns sum of the elements.
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
#define KALDI_LOG
Definition: kaldi-error.h:153
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

◆ UpdateWeight()

double UpdateWeight ( const IvectorExtractorEstimationOptions opts,
int32  gaussian,
IvectorExtractor extractor 
) const
protected

Definition at line 1540 of file ivector-extractor.cc.

References VectorBase< Real >::CopyFromVec(), PackedMatrix< Real >::Data(), SolverOptions::diagonal_precondition, IvectorExtractorStats::G_, IvectorExtractorStats::gamma_, IvectorExtractor::IvectorDim(), KALDI_ASSERT, KALDI_VLOG, SolverOptions::name, IvectorExtractor::NumGauss(), IvectorExtractorStats::Q_, MatrixBase< Real >::Row(), kaldi::SolveQuadraticProblem(), and IvectorExtractor::w_.

1543  {
1544 
1545  int32 num_gauss = extractor->NumGauss(),
1546  ivector_dim = extractor->IvectorDim();
1547  KALDI_ASSERT(i >= 0 && i < num_gauss);
1548 
1549  SolverOptions solver_opts;
1550  solver_opts.diagonal_precondition = true;
1551  solver_opts.name = "w";
1552 
1553  SubVector<double> w_i(extractor->w_, i);
1554  SubVector<double> g_i(G_, i);
1555  SpMatrix<double> Q(ivector_dim);
1556  SubVector<double> Q_vec(Q.Data(), ivector_dim * (ivector_dim + 1) / 2);
1557  Q_vec.CopyFromVec(Q_.Row(i));
1558  double objf_impr = SolveQuadraticProblem(Q, g_i, solver_opts, &w_i);
1559  if (i < 4 && gamma_(i) != 0.0) {
1560  KALDI_VLOG(1) << "Auxf impr/frame for Gaussian index " << i
1561  << " for weights is " << (objf_impr / gamma_(i))
1562  << " over " << gamma_(i) << " frames.";
1563  }
1564  return objf_impr;
1565 }
double SolveQuadraticProblem(const SpMatrix< double > &H, const VectorBase< double > &g, const SolverOptions &opts, VectorBase< double > *x)
Definition: sp-matrix.cc:635
kaldi::int32 int32
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
const SubVector< Real > Row(MatrixIndexT i) const
Return specific row of matrix [const].
Definition: kaldi-matrix.h:188
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)

◆ UpdateWeights()

double UpdateWeights ( const IvectorExtractorEstimationOptions opts,
IvectorExtractor extractor 
) const
protected

Definition at line 1589 of file ivector-extractor.cc.

References kaldi::g_num_threads, IvectorExtractorStats::gamma_, rnnlm::i, KALDI_LOG, TaskSequencerConfig::num_threads, IvectorExtractor::NumGauss(), TaskSequencer< C >::Run(), and VectorBase< Real >::Sum().

Referenced by IvectorExtractorStats::Update().

1591  {
1592 
1593  int32 I = extractor->NumGauss();
1594  double tot_impr = 0.0;
1595  {
1596  TaskSequencerConfig sequencer_opts;
1597  sequencer_opts.num_threads = g_num_threads;
1598  TaskSequencer<IvectorExtractorUpdateWeightClass> sequencer(
1599  sequencer_opts);
1600  for (int32 i = 0; i < I; i++)
1601  sequencer.Run(new IvectorExtractorUpdateWeightClass(
1602  *this, opts, i, extractor, &tot_impr));
1603  }
1604 
1605  double num_frames = gamma_.Sum();
1606  KALDI_LOG << "Overall auxf impr/frame from weight update is "
1607  << (tot_impr / num_frames) << " over "
1608  << num_frames << " frames.";
1609  return tot_impr / num_frames;
1610 }
int32 g_num_threads
Definition: kaldi-thread.cc:25
kaldi::int32 int32
Real Sum() const
Returns sum of the elements.
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
#define KALDI_LOG
Definition: kaldi-error.h:153
friend class IvectorExtractorUpdateWeightClass

◆ Write() [1/2]

void Write ( std::ostream &  os,
bool  binary 
)

Definition at line 1199 of file ivector-extractor.cc.

References IvectorExtractorStats::FlushCache().

Referenced by main(), kaldi::TestIvectorExtractorStatsIO(), and IvectorExtractorStats::Write().

1199  {
1200  FlushCache(); // for R stats.
1201  ((const IvectorExtractorStats&)(*this)).Write(os, binary); // call const version.
1202 }
void FlushCache()
Flushes the cache for the R_ stats.
void Write(std::ostream &os, bool binary)

◆ Write() [2/2]

void Write ( std::ostream &  os,
bool  binary 
) const

Definition at line 1205 of file ivector-extractor.cc.

References IvectorExtractorStats::G_, IvectorExtractorStats::gamma_, rnnlm::i, IvectorExtractorStats::ivector_scatter_, IvectorExtractorStats::ivector_sum_, KALDI_ASSERT, IvectorExtractorStats::num_ivectors_, IvectorExtractorStats::Q_, IvectorExtractorStats::R_, IvectorExtractorStats::R_num_cached_, IvectorExtractorStats::S_, IvectorExtractorStats::tot_auxf_, PackedMatrix< Real >::Write(), VectorBase< Real >::Write(), IvectorExtractorStats::Write(), MatrixBase< Real >::Write(), kaldi::WriteBasicType(), kaldi::WriteToken(), and IvectorExtractorStats::Y_.

1205  {
1206  KALDI_ASSERT(R_num_cached_ == 0 && "Please use the non-const Write().");
1207  WriteToken(os, binary, "<IvectorExtractorStats>");
1208  WriteToken(os, binary, "<TotAuxf>");
1209  WriteBasicType(os, binary, tot_auxf_);
1210  WriteToken(os, binary, "<gamma>");
1211  gamma_.Write(os, binary);
1212  WriteToken(os, binary, "<Y>");
1213  int32 size = Y_.size();
1214  WriteBasicType(os, binary, size);
1215  for (int32 i = 0; i < size; i++)
1216  Y_[i].Write(os, binary);
1217  WriteToken(os, binary, "<R>");
1218  Matrix<BaseFloat> R_float(R_);
1219  R_float.Write(os, binary);
1220  WriteToken(os, binary, "<Q>");
1221  Matrix<BaseFloat> Q_float(Q_);
1222  Q_float.Write(os, binary);
1223  WriteToken(os, binary, "<G>");
1224  G_.Write(os, binary);
1225  WriteToken(os, binary, "<S>");
1226  size = S_.size();
1227  WriteBasicType(os, binary, size);
1228  for (int32 i = 0; i < size; i++)
1229  S_[i].Write(os, binary);
1230  WriteToken(os, binary, "<NumIvectors>");
1231  WriteBasicType(os, binary, num_ivectors_);
1232  WriteToken(os, binary, "<IvectorSum>");
1233  ivector_sum_.Write(os, binary);
1234  WriteToken(os, binary, "<IvectorScatter>");
1235  ivector_scatter_.Write(os, binary);
1236  WriteToken(os, binary, "</IvectorExtractorStats>");
1237 }
int32 R_num_cached_
To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here...
void Write(std::ostream &out, bool binary) const
write to stream.
void Write(std::ostream &out, bool binary) const
void Write(std::ostream &Out, bool binary) const
Writes to C++ stream (option to write in binary).
kaldi::int32 int32
double tot_auxf_
Caution: if we read from disk, this.
Vector< double > ivector_sum_
Sum of all the iVector means. Needed for prior re-estimation.
Matrix< double > G_
G_ is the linear term in the weight projection matrix w_.
Matrix< double > R_
R_i, quadratic term for ivector subspace (M matrix)estimation.
Matrix< double > Q_
Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is w...
SpMatrix< double > ivector_scatter_
Second-order stats for the iVectors. Needed for prior re-estimation.
double num_ivectors_
Count of the number of iVectors we trained on.
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
Definition: io-funcs.cc:134
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
std::vector< Matrix< double > > Y_
Stats Y_i for estimating projections M.
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34
Vector< double > gamma_
Total occupation count for each Gaussian index (zeroth-order stats)
void Write(std::ostream &os, bool binary)
std::vector< SpMatrix< double > > S_
S_{i}, raw second-order stats per Gaussian which we will use to update the variances Sigma_inv_...

Friends And Related Function Documentation

◆ IvectorExtractor

friend class IvectorExtractor
friend

Definition at line 483 of file ivector-extractor.h.

◆ IvectorExtractorUpdateProjectionClass

Definition at line 525 of file ivector-extractor.h.

◆ IvectorExtractorUpdateWeightClass

friend class IvectorExtractorUpdateWeightClass
friend

Definition at line 526 of file ivector-extractor.h.

Member Data Documentation

◆ config_

◆ G_

◆ gamma_

◆ gamma_Y_lock_

std::mutex gamma_Y_lock_
protected

This mutex guards gamma_ and Y_ (for multi-threaded update)

Definition at line 613 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::CommitStatsForM().

◆ ivector_scatter_

◆ ivector_sum_

◆ num_ivectors_

double num_ivectors_
protected

Count of the number of iVectors we trained on.

Need for prior re-estimation. (make it double not int64 to more easily support weighting later.)

Definition at line 670 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::Add(), IvectorExtractorStats::CheckDims(), IvectorExtractorStats::CommitStatsForPrior(), IvectorExtractorStats::IvectorExtractorStats(), IvectorExtractorStats::PriorDiagnostics(), IvectorExtractorStats::Read(), IvectorExtractorStats::UpdatePrior(), and IvectorExtractorStats::Write().

◆ prior_stats_lock_

std::mutex prior_stats_lock_
protected

This mutex guards num_ivectors_, ivector_sum_ and ivector_scatter_ (for multi-threaded update)

Definition at line 666 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::CommitStatsForPrior().

◆ Q_

Matrix<double> Q_
protected

Q_ is like R_ (with same dimensions), except used for weight estimation; the scatter of ivectors is weighted by the coefficient of the quadratic term in the expansion for w (the "safe" one, with the max expression).

Definition at line 650 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::Add(), IvectorExtractorStats::CheckDims(), IvectorExtractorStats::CommitStatsForWPoint(), IvectorExtractorStats::IvectorExtractorStats(), IvectorExtractorStats::Read(), IvectorExtractorStats::UpdateWeight(), and IvectorExtractorStats::Write().

◆ R_

Matrix<double> R_
protected

R_i, quadratic term for ivector subspace (M matrix)estimation.

This is a kind of scatter of ivectors of training speakers, weighted by count for each Gaussian. Conceptually vector<SpMatrix<double> >, but we store each SpMatrix as a row of R_. Conceptually, the dim is [I][S][S]; the actual dim is [I][S*(S+1)/2].

Definition at line 630 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::Add(), IvectorExtractorStats::CheckDims(), IvectorExtractorStats::FlushCache(), IvectorExtractorStats::IvectorExtractorStats(), IvectorExtractorStats::Read(), IvectorExtractorStats::UpdateProjection(), IvectorExtractorStats::UpdateVariances(), and IvectorExtractorStats::Write().

◆ R_cache_lock_

std::mutex R_cache_lock_
protected

This mutex guards R_num_cached_, R_gamma_cache_, R_ivec_cache_ (for multi-threaded update)

Definition at line 634 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::CommitStatsForM(), and IvectorExtractorStats::FlushCache().

◆ R_gamma_cache_

Matrix<double> R_gamma_cache_
protected

◆ R_ivec_scatter_cache_

Matrix<double> R_ivec_scatter_cache_
protected

◆ R_lock_

std::mutex R_lock_
protected

This mutex guards R_ (for multi-threaded update)

Definition at line 623 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::FlushCache().

◆ R_num_cached_

int32 R_num_cached_
protected

To avoid too-frequent rank-1 update of R, which is slow, we cache some quantities here.

Definition at line 638 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::CommitStatsForM(), IvectorExtractorStats::FlushCache(), IvectorExtractorStats::IvectorExtractorStats(), and IvectorExtractorStats::Write().

◆ S_

◆ tot_auxf_

double tot_auxf_
protected

Caution: if we read from disk, this.

is not recovered. Options will not be used during the update phase anyway, so this should not matter. Total auxiliary function over the training data– can be used to check convergence, etc.

Definition at line 610 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::Add(), IvectorExtractorStats::CommitStatsForUtterance(), IvectorExtractorStats::IvectorExtractorStats(), IvectorExtractorStats::Read(), IvectorExtractorStats::Update(), and IvectorExtractorStats::Write().

◆ variance_stats_lock_

std::mutex variance_stats_lock_
protected

This mutex guards S_ (for multi-threaded update)

Definition at line 657 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::CommitStatsForSigma().

◆ weight_stats_lock_

std::mutex weight_stats_lock_
protected

This mutex guards Q_ and G_ (for multi-threaded update)

Definition at line 645 of file ivector-extractor.h.

Referenced by IvectorExtractorStats::CommitStatsForWPoint().

◆ Y_


The documentation for this class was generated from the following files: