First Environment
Creating Architecture Descriptions
Now we have to make a couple of decisions about how the recognizer should look
like. We have to decide the following things:
- what topologies and transition probablities to use for HMMs of phonemes
- want to start with simple semicontinuous system or with something better
- how many Gaussians do we want in our mixtures
Since this should be a tiny system to make training easily reproducible and
fast, we decide the following:
- the phoneme topology for non-silence phonemes will be:
i.e. two states with transitions to themselves and to the next state,
the silence phone will only use one state, all the transitions have
equal probability (0.5)
- we will start with a continuous densities system, i.e. one codebook for
each of the 2 * 16 + 1 states
- every codebook will have eight Gaussians, this is a number small enough to
be trained awfully fast, and large enough to allow at least a tiny little
bit of recognition accuracy
So we create the following files manually in an editor:
phones:
A E F H I K L N O P R S T U V Y X
trans:
any { {0 0.5} {1 0.5} }
topoSet:
SIL { ROOT-b ROOT-e } { any any }
NONSIL { ROOT-m } { any }
topoTree:
ROOT 0=X NONSIL SIL - -
If you look at the topology defined above and look at the Janus documentation
you will easily understand the meanings of these files (in the phones file
we use the character X for the silence phoneme).
Let Janus Create the Rest
Creating a first recognizer environment means to create some description files.
Although it is possible to not actually create files, but instead reproduce
their information on the fly, while Janus is running, this can become rather
unconvenient. You can use a rather simple script for creating the missing
three files:
- codebookSet: A file that contains the description for 33
codebooks, two for each of the 16 phonemes plus one for the silence phone.
- distribSet: A file that contains the description for 33
mixture-weight distributions; initially there is one distribution for
each of the codebooks.
- distribTree: A simple decision tree with question about the central
phone only, and onoe leaf node for each of the 33 distributions
The following script will create these files. It is establishing the basic
objects that are needed and then fills the initially empty codebook set, and
distribution set, and distribution tree. Eventually all three objects are
saved into a file:
[FeatureSet fs] setDesc ../prepare/featdesc
CodebookSet cbs fs
DistribSet dss cbs
[Phones phones] read ../prepare/phones
PhonesSet phonesSet
Tags tags
Tree dst phones phonesSet tags dss
set modelList {
{A b} {E b} {F b} {H b} {I b} {K b} {L b} {N b} {O b} {P b} {R b}
{S b} {T b} {U b} {V b} {Y b} {A e} {E e} {F e} {H e} {I e} {K e}
{L e} {N e} {O e} {P e} {R e} {S e} {T e} {U e} {V e} {Y e} {X m}
}
foreach model $modelList { eval addModel $model MSC 8 8 DIAGONAL cbs dss dst }
cbs write cbs-desc
dss write dss-dest
dst write tree-desc
The heart of the above script is the call of the "addModel" procedure. It is
documented in more detail in the scripts-thread.
proc addModel { phone subTree feature refN dimN type cbs dss tree } {
set dsname $phone-$subTree
set question 0=$phone
set cbname $phone-$subTree
set root ROOT-$subTree
# Create new codebook $cbname in codebook set $cbs and
# create new distribution $dsname in distribution set $dss
# --------------------------------------------------------
if {[$cbs index $cbname] < 0} { $cbs add $cbname $feature $refN $dimN $type }
if {[$dss index $dsname] < 0} { $dss add $dsname $cbname }
# compose name of hook node (question node) and the attached leaf node
# --------------------------------------------------------------------
set qnode hook-$dsname
set lnode $dsname
# if the requested root in the tree does not yet exist, create it,
# then add the new node (hook and leaf) by traversing all no-successors
# ---------------------------------------------------------------------
if {[$tree index $root] < 0} {
$tree add $root {} $qnode $qnode $qnode "-"
$tree add $qnode $question - $lnode - -
$tree add $lnode {} - - - $dsname
} else {
$tree add $qnode $question - $lnode - -
$tree add $lnode {} - - - $dsname
# Find last NO node starting at root
set lidx [$tree index $root]
set idx $lidx
while { [set idx [$tree.item($lidx) configure -no]] > -1} { set lidx $idx }
$tree.item($lidx) configure -no [$tree index $qnode]
}
}