Commit c86d4ba7 authored by Korbinian Riedhammer's avatar Korbinian Riedhammer
Browse files

unified the nomencature to codebook* and tied*; introduced more cache-like...

unified the nomencature to codebook* and tied*; introduced more cache-like tied codebook evaluation, integrated dan's proposal for smoothing as MleTiedGmm::Interpolate2

git-svn-id: https://svn.code.sf.net/p/kaldi/code/sandbox/discrim@471 5e6a8d80-dfce-4ca6-a32a-6e07a63d50c8
parent 7248f460
......@@ -22,12 +22,13 @@ using std::vector;
namespace kaldi {
BaseFloat DecodableAmTiedDiagGmm::LogLikelihoodZeroBased(int32 frame, int32 pdf_index) {
BaseFloat DecodableAmTiedDiagGmm::LogLikelihoodZeroBased(int32 frame,
int32 pdf_index) {
KALDI_ASSERT(frame >= 0 && frame < NumFrames());
KALDI_ASSERT(pdf_index >= 0 && pdf_index < NumIndices());
if (log_like_cache_[pdf_index].hit_time == frame) {
return log_like_cache_[pdf_index].log_like; // return cached value, if found
return log_like_cache_[pdf_index].log_like;
}
const VectorBase<BaseFloat> &data = feature_matrix_.Row(frame);
......@@ -38,12 +39,13 @@ BaseFloat DecodableAmTiedDiagGmm::LogLikelihoodZeroBased(int32 frame, int32 pdf_
}
if (frame != previous_frame_) {
// different frame, evaluate all codebooks
// different frame, prepare the per-frame-vars
acoustic_model_.ComputePerFrameVars(data, &per_frame_vars_);
previous_frame_ = frame;
}
BaseFloat loglike = acoustic_model_.LogLikelihood(per_frame_vars_, pdf_index);
BaseFloat loglike = acoustic_model_.LogLikelihood(pdf_index,
&per_frame_vars_);
if (KALDI_ISNAN(loglike) || KALDI_ISINF(loglike))
KALDI_ERR << "Invalid answer (overflow or invalid variances/features?)";
......
......@@ -22,12 +22,13 @@ using std::vector;
namespace kaldi {
BaseFloat DecodableAmTiedFullGmm::LogLikelihoodZeroBased(int32 frame, int32 pdf_index) {
BaseFloat DecodableAmTiedFullGmm::LogLikelihoodZeroBased(int32 frame,
int32 pdf_index) {
KALDI_ASSERT(frame >= 0 && frame < NumFrames());
KALDI_ASSERT(pdf_index >= 0 && pdf_index < NumIndices());
if (log_like_cache_[pdf_index].hit_time == frame) {
return log_like_cache_[pdf_index].log_like; // return cached value, if found
return log_like_cache_[pdf_index].log_like;
}
const VectorBase<BaseFloat> &data = feature_matrix_.Row(frame);
......@@ -38,12 +39,13 @@ BaseFloat DecodableAmTiedFullGmm::LogLikelihoodZeroBased(int32 frame, int32 pdf_
}
if (frame != previous_frame_) {
// different frame, evaluate all codebooks
// different frame, prepare per-frame-vars
acoustic_model_.ComputePerFrameVars(data, &per_frame_vars_);
previous_frame_ = frame;
}
BaseFloat loglike = acoustic_model_.LogLikelihood(per_frame_vars_, pdf_index);
BaseFloat loglike = acoustic_model_.LogLikelihood(pdf_index,
&per_frame_vars_);
if (KALDI_ISNAN(loglike) || KALDI_ISINF(loglike))
KALDI_ERR << "Invalid answer (overflow or invalid variances/features?)";
......
......@@ -47,8 +47,8 @@ void TestAmTiedDiagGmmIO(const AmTiedDiagGmm &am_gmm) {
am_gmm.SetupPerFrameVars(&pfv);
am_gmm.ComputePerFrameVars(feat, &pfv);
for (int32 i = 0; i < am_gmm.NumPdfs(); ++i)
loglike += am_gmm.LogLikelihood(pfv, i);
for (int32 i = 0; i < am_gmm.NumCodebooks(); ++i)
loglike += am_gmm.LogLikelihood(i, &pfv);
// First, non-binary write
am_gmm.Write(kaldi::Output("tmpf", false).Stream(), false);
......@@ -64,8 +64,8 @@ void TestAmTiedDiagGmmIO(const AmTiedDiagGmm &am_gmm) {
am_gmm1->SetupPerFrameVars(&pfv);
am_gmm1->ComputePerFrameVars(feat, &pfv);
for (int32 i = 0; i < am_gmm1->NumPdfs(); ++i)
loglike1 += am_gmm1->LogLikelihood(pfv, i);
for (int32 i = 0; i < am_gmm1->NumCodebooks(); ++i)
loglike1 += am_gmm1->LogLikelihood(i, &pfv);
kaldi::AssertEqual(loglike, loglike1, 1e-4);
......@@ -83,8 +83,8 @@ void TestAmTiedDiagGmmIO(const AmTiedDiagGmm &am_gmm) {
am_gmm2->SetupPerFrameVars(&pfv);
am_gmm2->ComputePerFrameVars(feat, &pfv);
for (int32 i = 0; i < am_gmm2->NumPdfs(); ++i)
loglike2 += am_gmm2->LogLikelihood(pfv, i);
for (int32 i = 0; i < am_gmm2->NumCodebooks(); ++i)
loglike2 += am_gmm2->LogLikelihood(i, &pfv);
kaldi::AssertEqual(loglike, loglike2, 1e-4);
delete am_gmm2;
......@@ -106,17 +106,17 @@ void UnitTestAmTiedDiagGmm() {
for (int32 i = 1; i < num_pdfs; ++i) {
num_comp = 4 + kaldi::RandInt(0, 12); // random number of mixtures
ut::InitRandDiagGmm(dim, num_comp, &diag);
am_gmm.AddPdf(diag);
am_gmm.AddCodebook(diag);
}
// add tied mixtures, round robin with codebooks
for (int32 i = 0; i < num_tied_pdfs; ++i) {
TiedGmm tied;
int32 pdf_index = i % num_pdfs;
tied.Setup(pdf_index, am_gmm.GetPdf(pdf_index).NumGauss());
tied.Setup(pdf_index, am_gmm.GetCodebook(pdf_index).NumGauss());
// generate random weights
Vector<BaseFloat> wts(am_gmm.GetPdf(pdf_index).NumGauss());
Vector<BaseFloat> wts(am_gmm.GetCodebook(pdf_index).NumGauss());
for (int32 j = 0; j < wts.Dim(); ++j)
wts(j) = kaldi::RandInt(1, 1024);
......
......@@ -51,7 +51,7 @@ void AmTiedDiagGmm::Init(const DiagGmm& proto) {
dim_ = proto.Dim();
}
void AmTiedDiagGmm::AddPdf(const DiagGmm &gmm) {
void AmTiedDiagGmm::AddCodebook(const DiagGmm &gmm) {
if (densities_.size() != 0) // not the first gmm
assert(static_cast<int32>(gmm.Dim()) == dim_);
else
......@@ -74,36 +74,23 @@ void AmTiedDiagGmm::AddTiedPdf(const TiedGmm &tied) {
tied_densities_.push_back(tgmm_ptr);
}
/// Remove designated codebook
/// caveat: does not take care of the tied dependents!
void AmTiedDiagGmm::RemovePdf(const int32 pdf_index) {
KALDI_ASSERT(static_cast<size_t>(pdf_index) < densities_.size());
delete densities_[pdf_index];
densities_.erase(densities_.begin() + pdf_index);
}
/// Remove designated tied pdf
void AmTiedDiagGmm::RemoveTiedPdf(int32 tied_pdf_index) {
KALDI_ASSERT(static_cast<size_t>(tied_pdf_index) < tied_densities_.size());
delete tied_densities_[tied_pdf_index];
tied_densities_.erase(tied_densities_.begin() + tied_pdf_index);
}
/// Replace the codebook of the designated tied pdf by the new index
void AmTiedDiagGmm::ReplacePdf(int32 tied_pdf_index, int32 new_pdf_index) {
KALDI_ASSERT(static_cast<size_t>(new_pdf_index) < densities_.size());
/// Set the codebook of the designated tied pdf
void AmTiedDiagGmm::ReplaceCodebook(int32 tied_pdf_index,
int32 new_codebook_index) {
KALDI_ASSERT(static_cast<size_t>(new_codebook_index) < densities_.size());
KALDI_ASSERT(static_cast<size_t>(tied_pdf_index) < tied_densities_.size());
tied_densities_[tied_pdf_index]->SetPdfIndex(new_pdf_index);
tied_densities_[tied_pdf_index]->SetCodebookIndex(new_codebook_index);
}
/// Replace the designated codebook
void AmTiedDiagGmm::ReplacePdf(int32 pdf_index, const DiagGmm &gmm) {
void AmTiedDiagGmm::ReplaceCodebook(int32 codebook_index, const DiagGmm &gmm) {
if (densities_.size() != 0) // not the first gmm
assert(static_cast<int32>(gmm.Dim()) == dim_);
KALDI_ASSERT(static_cast<size_t>(pdf_index) < densities_.size());
densities_[pdf_index]->CopyFromDiagGmm(gmm);
KALDI_ASSERT(static_cast<size_t>(codebook_index) < densities_.size());
densities_[codebook_index]->CopyFromDiagGmm(gmm);
}
void AmTiedDiagGmm::CopyFromAmTiedDiagGmm(const AmTiedDiagGmm &other) {
......@@ -115,7 +102,7 @@ void AmTiedDiagGmm::CopyFromAmTiedDiagGmm(const AmTiedDiagGmm &other) {
DeletePointers(&tied_densities_);
}
densities_.resize(other.NumPdfs(), NULL);
densities_.resize(other.NumCodebooks(), NULL);
tied_densities_.resize(other.NumTiedPdfs(), NULL);
dim_ = other.dim_;
......@@ -148,29 +135,34 @@ int32 AmTiedDiagGmm::ComputeGconsts() {
void AmTiedDiagGmm::SetupPerFrameVars(
TiedGmmPerFrameVars *per_frame_vars) const {
// init containers
per_frame_vars->Setup(dim_, NumPdfs());
per_frame_vars->Setup(dim_, NumCodebooks());
// allocate the svqs
for (int32 i = 0; i < NumPdfs(); ++i)
per_frame_vars->ResizeSvq(i, GetPdf(i).NumGauss());
for (int32 i = 0; i < NumCodebooks(); ++i) {
per_frame_vars->ResizeSvq(i, GetCodebook(i).NumGauss());
per_frame_vars->current[i] = false;
}
}
void AmTiedDiagGmm::ComputePerFrameVars(
const VectorBase<BaseFloat> &data,
TiedGmmPerFrameVars *per_frame_vars) const {
// copy the current data vector
per_frame_vars->x.CopyFromVec(data);
for (int32 i = 0; i < NumPdfs(); ++i)
per_frame_vars->c(i) = ComputePerFrameVars(data, per_frame_vars->svq[i], i);
// set the currency indicators to false
for (int32 i = 0; i < NumCodebooks(); ++i)
per_frame_vars->current[i] = false;
}
BaseFloat AmTiedDiagGmm::ComputePerFrameVars(const VectorBase<BaseFloat> &data,
Vector<BaseFloat> *svq,
int32 pdfid) const {
int32 codebook_index,
Vector<BaseFloat> *svq) const {
// get loglikes
densities_[pdfid]->LogLikelihoods(data, svq);
densities_[codebook_index]->LogLikelihoods(data, svq);
// subtract log(weight) = log(1/NumGauss) = -log(NumGauss)
svq->Add(log(densities_[pdfid]->NumGauss()));
svq->Add(log(densities_[codebook_index]->NumGauss()));
// normalize; speed-up by using svq->Max() instead?
BaseFloat c = svq->LogSumExp();
......
......@@ -40,23 +40,16 @@ class AmTiedDiagGmm {
void Init(const DiagGmm &proto);
/// Adds a DiagGmm as codebook to the model
void AddPdf(const DiagGmm &gmm);
void AddCodebook(const DiagGmm &gmm);
/// Adds a tied PDF to the model
void AddTiedPdf(const TiedGmm &tied);
/// Remove designated codebook
/// caveat: does not take care of the tied dependents!
void RemovePdf(int32 pdf_index);
/// Remove designated tied pdf
void RemoveTiedPdf(int32 tied_pdf_index);
/// Replace the codebook of the designated tied pdf by the new index
void ReplacePdf(int32 tied_pdf_index, int32 new_pdf_index);
/// Set the codebook of the designated tied pdf
void ReplaceCodebook(int32 tied_pdf_index, int32 new_codebook_index);
/// Replace the designated codebook
void ReplacePdf(int32 pdf_index, const DiagGmm &gmm);
void ReplaceCodebook(int32 codebook_index, const DiagGmm &gmm);
/// Copies the parameters from another model. Allocates necessary memory.
void CopyFromAmTiedDiagGmm(const AmTiedDiagGmm &other);
......@@ -71,30 +64,29 @@ class AmTiedDiagGmm {
void ComputePerFrameVars(const VectorBase<BaseFloat> &data,
TiedGmmPerFrameVars *per_frame_vars) const;
/// Computes the individual codebook per frame variables
/// Evaluate the target codebook and save the scores to svq
BaseFloat ComputePerFrameVars(const VectorBase<BaseFloat> &data,
Vector<BaseFloat> *svq,
int32 pdfid) const;
int32 codebook_index,
Vector<BaseFloat> *svq) const;
BaseFloat LogLikelihood(const TiedGmmPerFrameVars &per_frame_vars,
const int32 pdf_index) const;
BaseFloat LogLikelihood(int32 tied_pdf_index,
TiedGmmPerFrameVars *per_frame_vars) const;
void Read(std::istream &in_stream, bool binary);
void Write(std::ostream &out_stream, bool binary) const;
int32 Dim() const { return dim_; }
int32 NumPdfs() const { return densities_.size(); }
int32 NumCodebooks() const { return densities_.size(); }
int32 NumTiedPdfs() const { return tied_densities_.size(); }
int32 NumGaussInPdf(int32 pdf_index) const;
/// Accessors
DiagGmm& GetPdf(int32 pdf_index);
const DiagGmm& GetPdf(int32 pdf_index) const;
DiagGmm& GetCodebook(int32 codebook_index);
const DiagGmm& GetCodebook(int32 codebook_index) const;
TiedGmm& GetTiedPdf(int32 pdf_index);
const TiedGmm& GetTiedPdf(int32 pdf_index) const;
TiedGmm& GetTiedPdf(int32 tied_pdf_index);
const TiedGmm& GetTiedPdf(int32 tied_pdf_index) const;
int32 GetPdfIdOfTiedPdf(int32 pdf_index) const;
int32 GetCodebookIndexOfTiedPdf(int32 tied_pdf_index) const;
private:
std::vector<DiagGmm*> densities_;
......@@ -105,26 +97,34 @@ class AmTiedDiagGmm {
};
inline BaseFloat AmTiedDiagGmm::LogLikelihood(
const TiedGmmPerFrameVars &per_frame_vars,
const int32 pdf_index) const {
TiedGmm *tied = tied_densities_[pdf_index];
int32 pdfid = tied->pdf_index();
Vector<BaseFloat> *svq = per_frame_vars.svq[pdfid];
return tied->LogLikelihood(per_frame_vars.c(pdfid), *svq);
int32 tied_pdf_index,
TiedGmmPerFrameVars *per_frame_vars) const {
TiedGmm *tied = tied_densities_[tied_pdf_index];
int32 i = tied->codebook_index();
// get the svq vector
Vector<BaseFloat> *svq = per_frame_vars->svq[i];
// refresh the svq values
if (!per_frame_vars->current[i]) {
per_frame_vars->c(i) = ComputePerFrameVars(per_frame_vars->x, i, svq);
per_frame_vars->current[i] = true;
}
return tied->LogLikelihood(per_frame_vars->c(i), *svq);
}
inline DiagGmm& AmTiedDiagGmm::GetPdf(int32 pdf_index) {
KALDI_ASSERT((static_cast<size_t>(pdf_index) < densities_.size())
&& (densities_[pdf_index] != NULL));
return *(densities_[pdf_index]);
inline DiagGmm& AmTiedDiagGmm::GetCodebook(int32 codebook_index) {
KALDI_ASSERT((static_cast<size_t>(codebook_index) < densities_.size())
&& (densities_[codebook_index] != NULL));
return *(densities_[codebook_index]);
}
inline const DiagGmm& AmTiedDiagGmm::GetPdf(int32 pdf_index) const {
KALDI_ASSERT((static_cast<size_t>(pdf_index) < densities_.size())
&& (densities_[pdf_index] != NULL));
return *(densities_[pdf_index]);
inline const DiagGmm& AmTiedDiagGmm::GetCodebook(int32 codebook_index) const {
KALDI_ASSERT((static_cast<size_t>(codebook_index) < densities_.size())
&& (densities_[codebook_index] != NULL));
return *(densities_[codebook_index]);
}
inline TiedGmm& AmTiedDiagGmm::GetTiedPdf(int32 tied_pdf_index) {
......@@ -139,10 +139,11 @@ inline const TiedGmm& AmTiedDiagGmm::GetTiedPdf(int32 tied_pdf_index) const {
return *(tied_densities_[tied_pdf_index]);
}
inline int32 AmTiedDiagGmm::GetPdfIdOfTiedPdf(int32 pdf_index) const {
KALDI_ASSERT((static_cast<size_t>(pdf_index) < tied_densities_.size())
&& (tied_densities_[pdf_index] != NULL));
return tied_densities_[pdf_index]->pdf_index();
inline int32 AmTiedDiagGmm::GetCodebookIndexOfTiedPdf(int32 tied_pdf_index)
const {
KALDI_ASSERT((static_cast<size_t>(tied_pdf_index) < tied_densities_.size())
&& (tied_densities_[tied_pdf_index] != NULL));
return tied_densities_[tied_pdf_index]->codebook_index();
}
} // namespace kaldi
......
......@@ -47,8 +47,8 @@ void TestAmTiedDiagGmmIO(const AmTiedDiagGmm &am_gmm) {
am_gmm.SetupPerFrameVars(&pfv);
am_gmm.ComputePerFrameVars(feat, &pfv);
for (int32 i = 0; i < am_gmm.NumPdfs(); ++i)
loglike += am_gmm.LogLikelihood(pfv, i);
for (int32 i = 0; i < am_gmm.NumCodebooks(); ++i)
loglike += am_gmm.LogLikelihood(i, &pfv);
// First, non-binary write
am_gmm.Write(kaldi::Output("tmpf", false).Stream(), false);
......@@ -64,8 +64,8 @@ void TestAmTiedDiagGmmIO(const AmTiedDiagGmm &am_gmm) {
am_gmm1->SetupPerFrameVars(&pfv);
am_gmm1->ComputePerFrameVars(feat, &pfv);
for (int32 i = 0; i < am_gmm1->NumPdfs(); ++i)
loglike1 += am_gmm1->LogLikelihood(pfv, i);
for (int32 i = 0; i < am_gmm1->NumCodebooks(); ++i)
loglike1 += am_gmm1->LogLikelihood(i, &pfv);
kaldi::AssertEqual(loglike, loglike1, 1e-4);
......@@ -83,8 +83,8 @@ void TestAmTiedDiagGmmIO(const AmTiedDiagGmm &am_gmm) {
am_gmm2->SetupPerFrameVars(&pfv);
am_gmm2->ComputePerFrameVars(feat, &pfv);
for (int32 i = 0; i < am_gmm2->NumPdfs(); ++i)
loglike2 += am_gmm2->LogLikelihood(pfv, i);
for (int32 i = 0; i < am_gmm2->NumCodebooks(); ++i)
loglike2 += am_gmm2->LogLikelihood(i, &pfv);
kaldi::AssertEqual(loglike, loglike2, 1e-4);
delete am_gmm2;
......@@ -106,17 +106,17 @@ void UnitTestAmTiedDiagGmm() {
for (int32 i = 1; i < num_pdfs; ++i) {
num_comp = 4 + kaldi::RandInt(0, 12); // random number of mixtures
ut::InitRandDiagGmm(dim, num_comp, &diag);
am_gmm.AddPdf(diag);
am_gmm.AddCodebook(diag);
}
// add tied mixtures, round robin with codebooks
for (int32 i = 0; i < num_tied_pdfs; ++i) {
TiedGmm tied;
int32 pdf_index = i % num_pdfs;
tied.Setup(pdf_index, am_gmm.GetPdf(pdf_index).NumGauss());
tied.Setup(pdf_index, am_gmm.GetCodebook(pdf_index).NumGauss());
// generate random weights
Vector<BaseFloat> wts(am_gmm.GetPdf(pdf_index).NumGauss());
Vector<BaseFloat> wts(am_gmm.GetCodebook(pdf_index).NumGauss());
for (int32 j = 0; j < wts.Dim(); ++j)
wts(j) = kaldi::RandInt(1, 1024);
......
......@@ -51,7 +51,7 @@ void AmTiedFullGmm::Init(const FullGmm& proto) {
dim_ = proto.Dim();
}
void AmTiedFullGmm::AddPdf(const FullGmm &gmm) {
void AmTiedFullGmm::AddCodebook(const FullGmm &gmm) {
if (densities_.size() != 0) // not the first gmm
assert(static_cast<int32>(gmm.Dim()) == dim_);
else
......@@ -74,36 +74,21 @@ void AmTiedFullGmm::AddTiedPdf(const TiedGmm &tied) {
tied_densities_.push_back(tgmm_ptr);
}
/// Remove designated codebook
/// caveat: does not take care of the tied dependents!
void AmTiedFullGmm::RemovePdf(int32 pdf_index) {
KALDI_ASSERT(static_cast<size_t>(pdf_index) < densities_.size());
delete densities_[pdf_index];
densities_.erase(densities_.begin() + pdf_index);
}
/// Remove designated tied pdf
void AmTiedFullGmm::RemoveTiedPdf(int32 tied_pdf_index) {
/// Set the codebook index of the designated tied pdf
void AmTiedFullGmm::ReplaceCodebook(int32 tied_pdf_index, int32 new_codebook_index) {
KALDI_ASSERT(static_cast<size_t>(new_codebook_index) < densities_.size());
KALDI_ASSERT(static_cast<size_t>(tied_pdf_index) < tied_densities_.size());
delete tied_densities_[tied_pdf_index];
tied_densities_.erase(tied_densities_.begin() + tied_pdf_index);
}
/// Replace the codebook of the designated tied pdf by the new index
void AmTiedFullGmm::ReplacePdf(int32 tied_pdf_index, int32 new_pdf_index) {
KALDI_ASSERT(static_cast<size_t>(new_pdf_index) < densities_.size());
KALDI_ASSERT(static_cast<size_t>(tied_pdf_index) < tied_densities_.size());
tied_densities_[tied_pdf_index]->SetPdfIndex(new_pdf_index);
tied_densities_[tied_pdf_index]->SetCodebookIndex(new_codebook_index);
}
/// Replace the designated codebook
void AmTiedFullGmm::ReplacePdf(int32 pdf_index, const FullGmm &gmm) {
void AmTiedFullGmm::ReplaceCodebook(int32 codebook_index, const FullGmm &gmm) {
if (densities_.size() != 0) // not the first gmm
assert(static_cast<int32>(gmm.Dim()) == dim_);
KALDI_ASSERT(static_cast<size_t>(pdf_index) < densities_.size());
KALDI_ASSERT(static_cast<size_t>(codebook_index) < densities_.size());
densities_[pdf_index]->CopyFromFullGmm(gmm);
densities_[codebook_index]->CopyFromFullGmm(gmm);
}
void AmTiedFullGmm::CopyFromAmTiedFullGmm(const AmTiedFullGmm &other) {
......@@ -115,7 +100,7 @@ void AmTiedFullGmm::CopyFromAmTiedFullGmm(const AmTiedFullGmm &other) {
DeletePointers(&tied_densities_);
}
densities_.resize(other.NumPdfs(), NULL);
densities_.resize(other.NumCodebooks(), NULL);
tied_densities_.resize(other.NumTiedPdfs(), NULL);
dim_ = other.dim_;
......@@ -148,29 +133,34 @@ int32 AmTiedFullGmm::ComputeGconsts() {
void AmTiedFullGmm::SetupPerFrameVars(
TiedGmmPerFrameVars *per_frame_vars) const {
// init containers
per_frame_vars->Setup(dim_, NumPdfs());
per_frame_vars->Setup(dim_, NumCodebooks());
// allocate the svqs
for (int32 i = 0; i < NumPdfs(); ++i)
per_frame_vars->ResizeSvq(i, GetPdf(i).NumGauss());
for (int32 i = 0; i < NumCodebooks(); ++i) {
per_frame_vars->ResizeSvq(i, GetCodebook(i).NumGauss());
per_frame_vars->current[i] = false;
}
}
void AmTiedFullGmm::ComputePerFrameVars(
const VectorBase<BaseFloat> &data,
TiedGmmPerFrameVars *per_frame_vars) const {
// copy the current data vector
per_frame_vars->x.CopyFromVec(data);
for (int32 i = 0; i < NumPdfs(); ++i)
per_frame_vars->c(i) = ComputePerFrameVars(data, per_frame_vars->svq[i], i);
// set the currency indicators to false
for (int32 i = 0; i < NumCodebooks(); ++i)
per_frame_vars->current[i] = false;
}
BaseFloat AmTiedFullGmm::ComputePerFrameVars(const VectorBase<BaseFloat> &data,
Vector<BaseFloat> *svq,
int32 pdfid) const {
int32 codebook_index,
Vector<BaseFloat> *svq) const {
// get loglikes
densities_[pdfid]->LogLikelihoods(data, svq);
densities_[codebook_index]->LogLikelihoods(data, svq);
// subtract log(weight) = log(1/NumGauss) = -log(NumGauss)
svq->Add(log(densities_[pdfid]->NumGauss()));
svq->Add(log(densities_[codebook_index]->NumGauss()));
// normalize; speed-up using svq->Max()?
BaseFloat c = svq->LogSumExp();
......
......@@ -40,23 +40,16 @@ class AmTiedFullGmm {
void Init(const FullGmm &proto);
/// Adds a DiagGmm as codebook to the model
void AddPdf(const FullGmm &gmm);
void AddCodebook(const FullGmm &gmm);
/// Adds a tied PDF to the model
void AddTiedPdf(const TiedGmm &tied);
/// Remove designated codebook
/// caveat: does not take care of the tied dependents!
void RemovePdf(int32 pdf_index);
/// Remove designated tied pdf
void RemoveTiedPdf(int32 tied_pdf_index);
/// Replace the codebook of the designated tied pdf by the new index
void ReplacePdf(int32 tied_pdf_index, int32 new_pdf_index);
/// Set the codebook index of the designated tied pdf
void ReplaceCodebook(int32 tied_pdf_index, int32 new_codebook_index);
/// Replace the designated codebook
void ReplacePdf(int32 pdf_index, const FullGmm &gmm);
void ReplaceCodebook(int32 codebook_index, const FullGmm &gmm);
/// Copies the parameters from another model. Allocates necessary memory.
void CopyFromAmTiedFullGmm(const AmTiedFullGmm &other);
......@@ -73,28 +66,27 @@ class AmTiedFullGmm {
/// Computes the individual codebook per frame variables
BaseFloat ComputePerFrameVars(const VectorBase<BaseFloat> &data,
Vector<BaseFloat> *svq,
int32 pdfid) const;
int32 codebook_index,
Vector<BaseFloat> *svq) const;
BaseFloat LogLikelihood(const TiedGmmPerFrameVars &per_frame_vars,
const int32 pdf_index) const;
BaseFloat LogLikelihood(int32 tied_pdf_index,
TiedGmmPerFrameVars *per_frame_vars) const;
void Read(std::istream &in_stream, bool binary);
void Write(std::ostream &out_stream, bool binary) const;
int32 Dim() const { return dim_; }
int32 NumPdfs() const { return densities_.size(); }
int32 NumCodebooks() const { return densities_.size(); }
int32 NumTiedPdfs() const { return tied_densities_.size(); }
int32 NumGaussInPdf(int32 pdf_index) const;
/// Accessors
FullGmm& GetPdf(int32 pdf_index);
const FullGmm& GetPdf(int32 pdf_index) const;
FullGmm& GetCodebook(int32 codebook_index);
const FullGmm& GetCodebook(int32 codebook_index) const;
TiedGmm& GetTiedPdf(int32 pdf_index);
const TiedGmm& GetTiedPdf(int32 pdf_index) const;
TiedGmm& GetTiedPdf(int32 tied_pdf_index);
const TiedGmm& GetTiedPdf(int32 tied_pdf_index) const;
int32 GetPdfIdOfTiedPdf(int32 pdf_index) const;
int32 GetCodebookIndexOfTiedPdf(int32 tied_pdf_index) const;
private:
std::vector<FullGmm*> densities_;
......@@ -105,26 +97,34 @@ class AmTiedFullGmm {
};