diff --git a/src/chain/chain-supervision-test.cc b/src/chain/chain-supervision-test.cc index d14c80cd84f..f93fa3aef7b 100644 --- a/src/chain/chain-supervision-test.cc +++ b/src/chain/chain-supervision-test.cc @@ -157,17 +157,11 @@ void TestSupervisionAppend(const TransitionModel &trans_model, std::vector input(num_append); for (int32 i = 0; i < num_append; i++) input[i] = &supervision; - std::vector output; - bool compactify = (RandInt(0, 1) == 0); - AppendSupervision(input, compactify, &output); - if (compactify) { - KALDI_ASSERT(output.size() == 1 && - output[0].frames_per_sequence == - supervision.frames_per_sequence && - output[0].num_sequences == num_append); - } else { - KALDI_ASSERT(output.size() == input.size()); - } + Supervision output; + AppendSupervision(input, &output); + KALDI_ASSERT(output.frames_per_sequence == + supervision.frames_per_sequence && + output.num_sequences == num_append); int32 tot_sequences_in = 0, tot_sequences_out = 0, tot_frames_in = 0, tot_frames_out = 0; for (int32 i = 0; i < num_append; i++) { @@ -175,17 +169,15 @@ void TestSupervisionAppend(const TransitionModel &trans_model, tot_frames_in += input[i]->num_sequences * input[i]->frames_per_sequence; } - for (int32 i = 0; i < output.size(); i++) { - tot_sequences_out += output[i].num_sequences; - tot_frames_out += output[i].num_sequences * - output[i].frames_per_sequence; - } + tot_sequences_out += output.num_sequences; + tot_frames_out += output.num_sequences * + output.frames_per_sequence; KALDI_ASSERT(tot_sequences_out == tot_sequences_in && tot_frames_out == tot_frames_in); - TestSupervisionIo(output[0]); - TestSupervisionNumerator(output[0]); - output[0].Check(trans_model); + TestSupervisionIo(output); + TestSupervisionNumerator(output); + output.Check(trans_model); } void TestSupervisionReattached(const TransitionModel &trans_model, @@ -368,18 +360,16 @@ void TestSupervisionSplitting(const ContextDependency &ctx_dep, TestSupervisionIo(split_supervision[RandInt(0, num_ranges - 1)]); TestSupervisionFrames(split_supervision[RandInt(0, num_ranges - 1)]); - std::vector reattached_supervision; + Supervision reattached_supervision; std::vector to_append(num_ranges); for (int32 i = 0; i < num_ranges; i++) to_append[i] = &(split_supervision[i]); - bool compactify = true; - AppendSupervision(to_append, compactify, &reattached_supervision); - KALDI_ASSERT(reattached_supervision.size() == 1); - ChainTrainingTest(den_graph, reattached_supervision[0]); + AppendSupervision(to_append, &reattached_supervision); + ChainTrainingTest(den_graph, reattached_supervision); if (num_frames % frames_per_range == 0) { TestSupervisionReattached(trans_model, supervision, - reattached_supervision[0]); + reattached_supervision); } } } diff --git a/src/chain/chain-supervision.cc b/src/chain/chain-supervision.cc index 6b386638771..579e3d7b3e0 100644 --- a/src/chain/chain-supervision.cc +++ b/src/chain/chain-supervision.cc @@ -694,71 +694,57 @@ Supervision::Supervision(const Supervision &other): // This static function is called by AppendSupervision if the supervisions // are end2end. It simply puts all e2e FST's into 1 supervision. void AppendSupervisionE2e(const std::vector &input, - bool compactify, - std::vector *output_supervision) { + Supervision *output_supervision) { KALDI_ASSERT(!input.empty()); KALDI_ASSERT(input[0]->e2e); - output_supervision->clear(); - output_supervision->resize(1); KALDI_ASSERT(input[0]->e2e_fsts.size() == 1); - (*output_supervision)[0] = *(input[0]); + *output_supervision = *(input[0]); for (int32 i = 1; i < input.size(); i++) { - (*output_supervision)[0].num_sequences++; + output_supervision->num_sequences++; KALDI_ASSERT(input[i]->e2e_fsts.size() == 1); KALDI_ASSERT(input[i]->frames_per_sequence == - (*output_supervision)[0].frames_per_sequence); - (*output_supervision)[0].e2e_fsts.push_back(input[i]->e2e_fsts[0]); + output_supervision->frames_per_sequence); + output_supervision->e2e_fsts.push_back(input[i]->e2e_fsts[0]); } } void AppendSupervision(const std::vector &input, - bool compactify, - std::vector *output_supervision) { + Supervision *output_supervision) { KALDI_ASSERT(!input.empty()); int32 label_dim = input[0]->label_dim, num_inputs = input.size(); if (num_inputs == 1) { - output_supervision->resize(1); - (*output_supervision)[0] = *(input[0]); + *output_supervision = *(input[0]); return; } if (input[0]->e2e) { - AppendSupervisionE2e(input, compactify, output_supervision); + AppendSupervisionE2e(input, output_supervision); return; } - std::vector output_was_merged; for (int32 i = 1; i < num_inputs; i++) KALDI_ASSERT(input[i]->label_dim == label_dim && "Trying to append incompatible Supervision objects"); - output_supervision->clear(); - output_supervision->reserve(input.size()); - for (int32 i = 0; i < input.size(); i++) { + *output_supervision = *(input[num_inputs-1]); + for (int32 i = num_inputs - 2; i >= 0; i--) { const Supervision &src = *(input[i]); - if (compactify && !output_supervision->empty() && - output_supervision->back().weight == src.weight && - output_supervision->back().frames_per_sequence == + if (output_supervision->weight == src.weight && + output_supervision->frames_per_sequence == src.frames_per_sequence) { // Combine with current output // append src.fst to output_supervision->fst. - fst::Concat(&output_supervision->back().fst, src.fst); - output_supervision->back().num_sequences++; - output_was_merged.back() = true; + // the complexity here is O(V1 + E1) + fst::Concat(src.fst, &output_supervision->fst); + output_supervision->num_sequences++; } else { - output_supervision->resize(output_supervision->size() + 1); - output_supervision->back() = src; - output_was_merged.push_back(false); - } - } - KALDI_ASSERT(output_was_merged.size() == output_supervision->size()); - for (size_t i = 0; i < output_supervision->size(); i++) { - if (output_was_merged[i]) { - fst::StdVectorFst &out_fst = (*output_supervision)[i].fst; - // The process of concatenation will have introduced epsilons. - fst::RmEpsilon(&out_fst); - SortBreadthFirstSearch(&out_fst); + KALDI_ERR << "Mismatch weight or frames_per_sequence between inputs"; } + } + fst::StdVectorFst &out_fst = output_supervision->fst; + // The process of concatenation will have introduced epsilons. + fst::RmEpsilon(&out_fst); + SortBreadthFirstSearch(&out_fst); } // This static function is called by AddWeightToSupervisionFst if the supervision diff --git a/src/chain/chain-supervision.h b/src/chain/chain-supervision.h index 641902e6de0..13866e2aba6 100644 --- a/src/chain/chain-supervision.h +++ b/src/chain/chain-supervision.h @@ -380,15 +380,14 @@ int32 ComputeFstStateTimes(const fst::StdVectorFst &fst, /// This function appends a list of supervision objects to create what will /// usually be a single such object, but if the weights and num-frames are not /// all the same it will only append Supervision objects where successive ones -/// have the same weight and num-frames, and if 'compactify' is true. The -/// normal use-case for this is when you are combining neural-net examples for +/// have the same weight and num-frames. +/// The normal use-case for this is when you are combining neural-net examples for /// training; appending them like this helps to simplify the training process. /// This function will crash if the values of label_dim in the inputs are not /// all the same. void AppendSupervision(const std::vector &input, - bool compactify, - std::vector *output_supervision); + Supervision *output_supervision); /// This function helps you to pseudo-randomly split a sequence of length 'num_frames', diff --git a/src/nnet3/discriminative-supervision.cc b/src/nnet3/discriminative-supervision.cc index 94a165f4c50..716650f16fa 100644 --- a/src/nnet3/discriminative-supervision.cc +++ b/src/nnet3/discriminative-supervision.cc @@ -400,49 +400,36 @@ void DiscriminativeSupervisionSplitter::ComputeLatticeScores(const Lattice &lat, } void AppendSupervision(const std::vector &input, - bool compactify, - std::vector *output_supervision) { + DiscriminativeSupervision *output_supervision) { KALDI_ASSERT(!input.empty()); int32 num_inputs = input.size(); if (num_inputs == 1) { - output_supervision->resize(1); - (*output_supervision)[0] = *(input[0]); + *output_supervision = *(input[0]); return; } - std::vector output_was_merged; - output_supervision->clear(); - output_supervision->reserve(input.size()); - for (int32 i = 0; i < input.size(); i++) { + *output_supervision = *(input[num_inputs-1]); + for (int32 i = num_inputs - 2; i >= 0; i--) { const DiscriminativeSupervision &src = *(input[i]); KALDI_ASSERT(src.num_sequences == 1); - if (compactify && !output_supervision->empty() && - output_supervision->back().weight == src.weight && - output_supervision->back().frames_per_sequence == + if (output_supervision->weight == src.weight && + output_supervision->frames_per_sequence == src.frames_per_sequence) { // Combine with current output // append src.den_lat to output_supervision->den_lat. - fst::Concat(&output_supervision->back().den_lat, src.den_lat); + fst::Concat(src.den_lat, &output_supervision->den_lat); - output_supervision->back().num_ali.insert( - output_supervision->back().num_ali.end(), + output_supervision->num_ali.insert( + output_supervision->num_ali.begin(), src.num_ali.begin(), src.num_ali.end()); - output_supervision->back().num_sequences++; - output_was_merged.back() = true; + output_supervision->num_sequences++; } else { - output_supervision->resize(output_supervision->size() + 1); - output_supervision->back() = src; - output_was_merged.push_back(false); - } - } - KALDI_ASSERT(output_was_merged.size() == output_supervision->size()); - for (size_t i = 0; i < output_supervision->size(); i++) { - if (output_was_merged[i]) { - DiscriminativeSupervision &out_sup = (*output_supervision)[i]; - fst::TopSort(&(out_sup.den_lat)); - out_sup.Check(); + KALDI_ERR << "Mismatch weight or frames_per_sequence between inputs"; } } + DiscriminativeSupervision &out_sup = *output_supervision; + fst::TopSort(&(out_sup.den_lat)); + out_sup.Check(); } } // namespace discriminative diff --git a/src/nnet3/discriminative-supervision.h b/src/nnet3/discriminative-supervision.h index a9d58d120f5..6fd684093e2 100644 --- a/src/nnet3/discriminative-supervision.h +++ b/src/nnet3/discriminative-supervision.h @@ -223,8 +223,7 @@ class DiscriminativeSupervisionSplitter { /// training; appending them like this helps to simplify the training process. void AppendSupervision(const std::vector &input, - bool compactify, - std::vector *output_supervision); + DiscriminativeSupervision *output_supervision); } // namespace discriminative diff --git a/src/nnet3/nnet-chain-example.cc b/src/nnet3/nnet-chain-example.cc index 351312fb952..aad5f83bc80 100644 --- a/src/nnet3/nnet-chain-example.cc +++ b/src/nnet3/nnet-chain-example.cc @@ -204,15 +204,10 @@ static void MergeSupervision( input_supervision.reserve(inputs.size()); for (int32 n = 0; n < num_inputs; n++) input_supervision.push_back(&(inputs[n]->supervision)); - std::vector output_supervision; - bool compactify = true; + chain::Supervision output_supervision; AppendSupervision(input_supervision, - compactify, &output_supervision); - if (output_supervision.size() != 1) - KALDI_ERR << "Failed to merge 'chain' examples-- inconsistent lengths " - << "or weights?"; - output->supervision.Swap(&(output_supervision[0])); + output->supervision.Swap(&output_supervision); output->indexes.clear(); output->indexes.reserve(num_indexes); diff --git a/src/nnet3/nnet-discriminative-example.cc b/src/nnet3/nnet-discriminative-example.cc index 61a9669fb76..29eb65c30b1 100644 --- a/src/nnet3/nnet-discriminative-example.cc +++ b/src/nnet3/nnet-discriminative-example.cc @@ -196,15 +196,10 @@ void MergeSupervision( input_supervision.reserve(inputs.size()); for (int32 n = 0; n < num_inputs; n++) input_supervision.push_back(&(inputs[n]->supervision)); - std::vector output_supervision; - bool compactify = true; + discriminative::DiscriminativeSupervision output_supervision; discriminative::AppendSupervision(input_supervision, - compactify, &output_supervision); - if (output_supervision.size() != 1) - KALDI_ERR << "Failed to merge discriminative examples-- inconsistent lengths " - << "or weights?"; - output->supervision.Swap(&(output_supervision[0])); + output->supervision.Swap(&(output_supervision)); output->indexes.clear(); output->indexes.reserve(num_indexes);