Initial commit: FunASR Speech Recognition Toolkit
Update API Documentation / build-api-docs (push) Has been cancelled
Update API Documentation / build-api-docs (push) Has been cancelled
Add complete FunASR codebase including models, runtime, and documentation.
This commit is contained in:
@@ -0,0 +1,401 @@
|
||||
// fstext/trivial-factor-weight.h
|
||||
|
||||
// Copyright 2009-2011 Microsoft Corporation
|
||||
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
// This is a modified file from the OpenFST Library v1.2.7 available at
|
||||
// http://www.openfst.org and released under the Apache License Version 2.0.
|
||||
//
|
||||
//
|
||||
// See ../../COPYING for clarification regarding multiple authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright 2005-2010 Google, Inc.
|
||||
// Author: allauzen@google.com (Cyril Allauzen)
|
||||
|
||||
|
||||
#ifndef KALDI_FSTEXT_TRIVIAL_FACTOR_WEIGHT_H_
|
||||
#define KALDI_FSTEXT_TRIVIAL_FACTOR_WEIGHT_H_
|
||||
|
||||
|
||||
// TrivialFactorWeight.h This is an extension to factor-weight.h in the OpenFst
|
||||
// code. It is a version of FactorWeight that creates separate states (with
|
||||
// input epsilons) rather than pushing the factors forward. This is for
|
||||
// converting from Gallic FSTs, where you want the result to be a bit more
|
||||
// trivial with input epsilons inserted where there are multiple output symbols.
|
||||
// This has the advantage that it always works, for any input (also I just
|
||||
// prefer this approach).
|
||||
|
||||
#include <unordered_map>
|
||||
using std::unordered_map;
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fst/cache.h>
|
||||
#include <fst/test-properties.h>
|
||||
|
||||
namespace fst {
|
||||
|
||||
|
||||
template <class Arc>
|
||||
struct TrivialFactorWeightOptions : CacheOptions {
|
||||
typedef typename Arc::Label Label;
|
||||
float delta;
|
||||
Label extra_ilabel; // input label of extra arcs
|
||||
Label extra_olabel; // output label of extra arcs
|
||||
|
||||
TrivialFactorWeightOptions(const CacheOptions &opts, float d,
|
||||
Label il = 0, Label ol = 0)
|
||||
: CacheOptions(opts), delta(d), extra_ilabel(il), extra_olabel(ol) {}
|
||||
|
||||
explicit TrivialFactorWeightOptions(
|
||||
float d, Label il = 0, Label ol = 0)
|
||||
: delta(d), extra_ilabel(il), extra_olabel(ol) {}
|
||||
|
||||
TrivialFactorWeightOptions(): delta(kDelta), extra_ilabel(0), extra_olabel(0) {}
|
||||
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Implementation class for TrivialFactorWeight
|
||||
template <class A, class F>
|
||||
class TrivialFactorWeightFstImpl
|
||||
: public CacheImpl<A> {
|
||||
public:
|
||||
using CacheImpl<A>::PushArc;
|
||||
using FstImpl<A>::SetType;
|
||||
using FstImpl<A>::SetProperties;
|
||||
using FstImpl<A>::Properties;
|
||||
using FstImpl<A>::SetInputSymbols;
|
||||
using FstImpl<A>::SetOutputSymbols;
|
||||
|
||||
using CacheBaseImpl< CacheState<A> >::HasStart;
|
||||
using CacheBaseImpl< CacheState<A> >::HasFinal;
|
||||
using CacheBaseImpl< CacheState<A> >::HasArcs;
|
||||
|
||||
typedef A Arc;
|
||||
typedef typename A::Label Label;
|
||||
typedef typename A::Weight Weight;
|
||||
typedef typename A::StateId StateId;
|
||||
typedef F FactorIterator;
|
||||
|
||||
typedef DefaultCacheStore<A> Store;
|
||||
typedef typename Store::State State;
|
||||
|
||||
struct Element {
|
||||
Element() {}
|
||||
|
||||
Element(StateId s, Weight w) : state(s), weight(w) {}
|
||||
|
||||
StateId state; // Input state Id
|
||||
Weight weight; // Residual weight
|
||||
};
|
||||
|
||||
TrivialFactorWeightFstImpl(const Fst<A> &fst, const TrivialFactorWeightOptions<A> &opts)
|
||||
: CacheImpl<A>(opts),
|
||||
fst_(fst.Copy()),
|
||||
delta_(opts.delta),
|
||||
extra_ilabel_(opts.extra_ilabel),
|
||||
extra_olabel_(opts.extra_olabel) {
|
||||
SetType("factor-weight");
|
||||
uint64 props = fst.Properties(kFstProperties, false);
|
||||
SetProperties(FactorWeightProperties(props), kCopyProperties);
|
||||
|
||||
SetInputSymbols(fst.InputSymbols());
|
||||
SetOutputSymbols(fst.OutputSymbols());
|
||||
}
|
||||
|
||||
TrivialFactorWeightFstImpl(const TrivialFactorWeightFstImpl<A, F> &impl)
|
||||
: CacheImpl<A>(impl),
|
||||
fst_(impl.fst_->Copy(true)),
|
||||
delta_(impl.delta_),
|
||||
extra_ilabel_(impl.extra_ilabel_),
|
||||
extra_olabel_(impl.extra_olabel_) {
|
||||
SetType("factor-weight");
|
||||
SetProperties(impl.Properties(), kCopyProperties);
|
||||
SetInputSymbols(impl.InputSymbols());
|
||||
SetOutputSymbols(impl.OutputSymbols());
|
||||
}
|
||||
|
||||
StateId Start() {
|
||||
if (!HasStart()) {
|
||||
StateId s = fst_->Start();
|
||||
if (s == kNoStateId)
|
||||
return kNoStateId;
|
||||
StateId start = this->FindState(Element(fst_->Start(), Weight::One()));
|
||||
this->SetStart(start);
|
||||
}
|
||||
return CacheImpl<A>::Start();
|
||||
}
|
||||
|
||||
Weight Final(StateId s) {
|
||||
if (!HasFinal(s)) {
|
||||
const Element &e = elements_[s];
|
||||
Weight w;
|
||||
if (e.state == kNoStateId) { // extra state inserted to represent final weights.
|
||||
FactorIterator fit(e.weight);
|
||||
if (fit.Done()) { // cannot be factored.
|
||||
w = e.weight; // so it's final
|
||||
} else {
|
||||
w = Weight::Zero(); // need another transition.
|
||||
}
|
||||
} else {
|
||||
if (e.weight != Weight::One()) { // Not a real state.
|
||||
w = Weight::Zero();
|
||||
} else { // corresponds to a "real" state.
|
||||
w = fst_->Final(e.state);
|
||||
FactorIterator fit(w);
|
||||
if (!fit.Done()) // we would have intermediate states representing this final state.
|
||||
w = Weight::Zero();
|
||||
}
|
||||
}
|
||||
this->SetFinal(s, w);
|
||||
return w;
|
||||
} else {
|
||||
return CacheImpl<A>::Final(s);
|
||||
}
|
||||
}
|
||||
|
||||
size_t NumArcs(StateId s) {
|
||||
if (!HasArcs(s))
|
||||
Expand(s);
|
||||
return CacheImpl<A>::NumArcs(s);
|
||||
}
|
||||
|
||||
size_t NumInputEpsilons(StateId s) {
|
||||
if (!HasArcs(s))
|
||||
Expand(s);
|
||||
return CacheImpl<A>::NumInputEpsilons(s);
|
||||
}
|
||||
|
||||
size_t NumOutputEpsilons(StateId s) {
|
||||
if (!HasArcs(s))
|
||||
Expand(s);
|
||||
return CacheImpl<A>::NumOutputEpsilons(s);
|
||||
}
|
||||
|
||||
void InitArcIterator(StateId s, ArcIteratorData<A> *data) {
|
||||
if (!HasArcs(s))
|
||||
Expand(s);
|
||||
CacheImpl<A>::InitArcIterator(s, data);
|
||||
}
|
||||
|
||||
|
||||
// Find state corresponding to an element. Create new state
|
||||
// if element not found.
|
||||
StateId FindState(const Element &e) {
|
||||
typename ElementMap::iterator eit = element_map_.find(e);
|
||||
if (eit != element_map_.end()) {
|
||||
return (*eit).second;
|
||||
} else {
|
||||
StateId s = elements_.size();
|
||||
elements_.push_back(e);
|
||||
element_map_.insert(std::pair<const Element, StateId>(e, s));
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
// Computes the outgoing transitions from a state, creating new destination
|
||||
// states as needed.
|
||||
void Expand(StateId s) {
|
||||
CHECK(static_cast<size_t>(s) < elements_.size());
|
||||
Element e = elements_[s];
|
||||
if (e.weight != Weight::One()) {
|
||||
FactorIterator fit(e.weight);
|
||||
if (fit.Done()) { // Cannot be factored-> create a link to dest state directly
|
||||
if (e.state != kNoStateId) {
|
||||
StateId dest = FindState(Element(e.state, Weight::One()));
|
||||
PushArc(s, Arc(extra_ilabel_, extra_olabel_, e.weight, dest));
|
||||
} // else we're done. This is a final state.
|
||||
} else { // Can be factored.
|
||||
const std::pair<Weight, Weight> &p = fit.Value();
|
||||
StateId dest = FindState(Element(e.state, p.second.Quantize(delta_)));
|
||||
PushArc(s, Arc(extra_ilabel_, extra_olabel_, p.first, dest));
|
||||
}
|
||||
} else { // Unit weight. This corresponds to a "real" state.
|
||||
CHECK(e.state != kNoStateId);
|
||||
for (ArcIterator< Fst<A> > ait(*fst_, e.state);
|
||||
!ait.Done();
|
||||
ait.Next()) {
|
||||
const A &arc = ait.Value();
|
||||
FactorIterator fit(arc.weight);
|
||||
if (fit.Done()) { // cannot be factored->just link directly to dest.
|
||||
StateId dest = FindState(Element(arc.nextstate, Weight::One()));
|
||||
PushArc(s, Arc(arc.ilabel, arc.olabel, arc.weight, dest));
|
||||
} else {
|
||||
const std::pair<Weight, Weight> &p = fit.Value();
|
||||
StateId dest = FindState(Element(arc.nextstate, p.second.Quantize(delta_)));
|
||||
PushArc(s, Arc(arc.ilabel, arc.olabel, p.first, dest));
|
||||
}
|
||||
}
|
||||
// See if we have to add arcs for final-states [only if final-weight is factorable].
|
||||
Weight final_w = fst_->Final(e.state);
|
||||
if (final_w != Weight::Zero()) {
|
||||
FactorIterator fit(final_w);
|
||||
if (!fit.Done()) {
|
||||
const std::pair<Weight, Weight> &p = fit.Value();
|
||||
StateId dest = FindState(Element(kNoStateId, p.second.Quantize(delta_)));
|
||||
PushArc(s, Arc(extra_ilabel_, extra_olabel_, p.first, dest));
|
||||
}
|
||||
}
|
||||
}
|
||||
this->SetArcs(s);
|
||||
}
|
||||
|
||||
private:
|
||||
// Equality function for Elements, assume weights have been quantized.
|
||||
class ElementEqual {
|
||||
public:
|
||||
bool operator()(const Element &x, const Element &y) const {
|
||||
return x.state == y.state && x.weight == y.weight;
|
||||
}
|
||||
};
|
||||
|
||||
// Hash function for Elements to Fst states.
|
||||
class ElementKey {
|
||||
public:
|
||||
size_t operator()(const Element &x) const {
|
||||
return static_cast<size_t>(x.state * kPrime + x.weight.Hash());
|
||||
}
|
||||
private:
|
||||
static const int kPrime = 7853;
|
||||
};
|
||||
|
||||
typedef unordered_map<Element, StateId, ElementKey, ElementEqual> ElementMap;
|
||||
|
||||
std::unique_ptr<const Fst<A>> fst_;
|
||||
float delta_;
|
||||
uint32 mode_; // factoring arc and/or final weights
|
||||
Label extra_ilabel_; // ilabel of arc created when factoring final w's
|
||||
Label extra_olabel_; // olabel of arc created when factoring final w's
|
||||
std::vector<Element> elements_; // mapping Fst state to Elements
|
||||
ElementMap element_map_; // mapping Elements to Fst state
|
||||
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/// TrivialFactorWeightFst takes as template parameter a FactorIterator as
|
||||
/// defined above. The result of weight factoring is a transducer
|
||||
/// equivalent to the input whose path weights have been factored
|
||||
/// according to the FactorIterator. States and transitions will be
|
||||
/// added as necessary.
|
||||
/// This algorithm differs from the one implemented in FactorWeightFst
|
||||
/// in that it does not attempt to push the extra weight forward to the
|
||||
/// next state: it uses a sequence of "extra" intermediate state, and
|
||||
/// outputs the remaining weight right away. This ensures that it will
|
||||
/// always succeed, even for Gallic representations of FSTs that have cycles
|
||||
/// with more output than input symbols.
|
||||
|
||||
/// Note that the code below was modified from factor-weight.h by just
|
||||
/// search-and-replacing "FactorWeight" by "TrivialFactorWeight".
|
||||
|
||||
|
||||
template <class A, class F>
|
||||
class TrivialFactorWeightFst :
|
||||
public ImplToFst<internal::TrivialFactorWeightFstImpl<A, F>> {
|
||||
public:
|
||||
friend class ArcIterator< TrivialFactorWeightFst<A, F> >;
|
||||
friend class StateIterator< TrivialFactorWeightFst<A, F> >;
|
||||
|
||||
typedef A Arc;
|
||||
typedef typename A::Weight Weight;
|
||||
typedef typename A::StateId StateId;
|
||||
typedef DefaultCacheStore<Arc> Store;
|
||||
typedef typename Store::State State;
|
||||
typedef internal::TrivialFactorWeightFstImpl<A, F> Impl;
|
||||
|
||||
explicit TrivialFactorWeightFst(const Fst<A> &fst)
|
||||
: ImplToFst<Impl>(std::make_shared<Impl>(fst, TrivialFactorWeightOptions<A>())) {}
|
||||
|
||||
TrivialFactorWeightFst(const Fst<A> &fst, const TrivialFactorWeightOptions<A> &opts)
|
||||
: ImplToFst<Impl>(std::make_shared<Impl>(fst, opts)) {}
|
||||
|
||||
// See Fst<>::Copy() for doc.
|
||||
TrivialFactorWeightFst(const TrivialFactorWeightFst<A, F> &fst, bool copy)
|
||||
: ImplToFst<Impl>(fst, copy) {}
|
||||
|
||||
// Get a copy of this TrivialFactorWeightFst. See Fst<>::Copy() for further doc.
|
||||
TrivialFactorWeightFst<A, F> *Copy(bool copy = false) const override {
|
||||
return new TrivialFactorWeightFst<A, F>(*this, copy);
|
||||
}
|
||||
|
||||
inline void InitStateIterator(StateIteratorData<A> *data) const override;
|
||||
|
||||
void InitArcIterator(StateId s, ArcIteratorData<A> *data) const override {
|
||||
GetMutableImpl()->InitArcIterator(s, data);
|
||||
}
|
||||
|
||||
private:
|
||||
using ImplToFst<Impl>::GetImpl;
|
||||
using ImplToFst<Impl>::GetMutableImpl;
|
||||
|
||||
TrivialFactorWeightFst &operator=(const TrivialFactorWeightFst &fst) = delete;
|
||||
};
|
||||
|
||||
|
||||
// Specialization for TrivialFactorWeightFst.
|
||||
template<class A, class F>
|
||||
class StateIterator< TrivialFactorWeightFst<A, F> >
|
||||
: public CacheStateIterator< TrivialFactorWeightFst<A, F> > {
|
||||
public:
|
||||
explicit StateIterator(const TrivialFactorWeightFst<A, F> &fst)
|
||||
: CacheStateIterator< TrivialFactorWeightFst<A, F> >(fst, fst.GetMutableImpl()) {}
|
||||
};
|
||||
|
||||
|
||||
// Specialization for TrivialFactorWeightFst.
|
||||
template <class A, class F>
|
||||
class ArcIterator< TrivialFactorWeightFst<A, F> >
|
||||
: public CacheArcIterator< TrivialFactorWeightFst<A, F> > {
|
||||
public:
|
||||
typedef typename A::StateId StateId;
|
||||
|
||||
ArcIterator(const TrivialFactorWeightFst<A, F> &fst, StateId s)
|
||||
: CacheArcIterator< TrivialFactorWeightFst<A, F>>(fst.GetMutableImpl(), s) {
|
||||
if (!fst.GetImpl()->HasArcs(s)) fst.GetMutableImpl()->Expand(s);
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class F>
|
||||
inline void TrivialFactorWeightFst<A, F>::InitStateIterator(
|
||||
StateIteratorData<A> *data) const {
|
||||
data->base = new StateIterator< TrivialFactorWeightFst<A, F> >(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace fst
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user