~ubuntu-branches/ubuntu/raring/sphinxtrain/raring-proposed

« back to all changes in this revision

Viewing changes to python/cmusphinx/s3model.py

  • Committer: Package Import Robot
  • Author(s): Samuel Thibault
  • Date: 2013-01-02 04:10:21 UTC
  • Revision ID: package-import@ubuntu.com-20130102041021-ynsizmz33fx02hea
Tags: upstream-1.0.8
ImportĀ upstreamĀ versionĀ 1.0.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2006 Carnegie Mellon University
 
2
#
 
3
# You may copy and modify this freely under the same terms as
 
4
# Sphinx-III
 
5
 
 
6
"""Sphinx-III acoustic models.
 
7
 
 
8
This module provides a class which wraps a set of acoustic models, as
 
9
used by SphinxTrain, Sphinx-III, and PocketSphinx.  It provides
 
10
functions for computing Gaussian mixture densities for acoustic
 
11
feature vectors.
 
12
"""
 
13
 
 
14
__author__ = "David Huggins-Daines <dhuggins@cs.cmu.edu>"
 
15
__version__ = "$Revision: 10963 $"
 
16
 
 
17
import s3gau
 
18
import s3mixw
 
19
import s3tmat
 
20
import s3mdef
 
21
import s3file
 
22
import sys
 
23
import os
 
24
import numpy
 
25
 
 
26
WORSTSCORE = -100000
 
27
 
 
28
class S3Model(object):
 
29
    def __init__(self, path=None, topn=4):
 
30
        self.topn = topn
 
31
        self.mwfloor = 1e-5
 
32
        self.varfloor = 1e-5
 
33
        if path != None:
 
34
            self.read(path)
 
35
 
 
36
    def read(self, path):
 
37
        self.mdef = s3mdef.open(os.path.join(path, "mdef"))
 
38
        self.mean = s3gau.open(os.path.join(path, "means"))
 
39
        self.var = s3gau.open(os.path.join(path, "variances"))
 
40
        self.mixw = s3mixw.open(os.path.join(path, "mixture_weights"))
 
41
        self.tmat = s3tmat.open(os.path.join(path, "transition_matrices"))
 
42
        # Normalize transition matrices and mixture weights
 
43
        for t in range(0, len(self.tmat)):
 
44
            self.tmat[t] = (self.tmat[t].T / self.tmat[t].sum(1)).T
 
45
        for t in range(0, len(self.mixw)):
 
46
            self.mixw[t] = (self.mixw[t].T / self.mixw[t].sum(1)).T.clip(self.mwfloor, 1.0)
 
47
        # Floor variances and precompute normalizing and inverse variance terms
 
48
        self.norm = numpy.empty((len(self.var),
 
49
                                 len(self.var[0]),
 
50
                                 len(self.var[0][0])),'d')
 
51
        for m,mgau in enumerate(self.var):
 
52
            for f,feat in enumerate(mgau):
 
53
                fvar = feat.clip(self.varfloor, numpy.inf)
 
54
                # log of 1/sqrt((2*pi)^N * det(var))
 
55
                det = numpy.log(fvar).sum(1)
 
56
                lrd = -0.5 * (det + numpy.log(2 * numpy.pi) * feat.shape[1])
 
57
                self.norm[m,f] = lrd
 
58
                # "Invert" variances
 
59
                feat[:] = (1 / (fvar * 2))
 
60
        # Construct senone to codebook mapping
 
61
        if os.access(os.path.join(path, "senmgau"), os.F_OK):
 
62
            self.senmgau = s3file.S3File(os.path.join(path, "senmgau")).read1d()
 
63
        elif len(self.mean) == 1:
 
64
            self.senmgau = numpy.ones(len(self.mixw))
 
65
        else:
 
66
            self.senmgau = numpy.arange(0, len(self.mixw))
 
67
        self.senscr = numpy.ones(len(self.mixw)) * WORSTSCORE
 
68
 
 
69
    def cb_compute(self, mgau, feat, obs):
 
70
        "Compute codebook #mgau feature #feat for obs"
 
71
        mean = self.mean[mgau][feat]
 
72
        ivar = self.var[mgau][feat]
 
73
        norm = self.norm[mgau][feat]
 
74
        diff = obs - mean
 
75
        dist = (diff * ivar * diff).sum(1)
 
76
        return norm - dist
 
77
        
 
78
    def senone_compute(self, senones, *features):
 
79
        """Compute senone scores for given list of senones and a
 
80
        frame of acoustic features"""
 
81
        cbs = {}
 
82
        self.senscr[:] = WORSTSCORE
 
83
        for s in senones:
 
84
            m = self.senmgau[s]
 
85
            if not m in cbs:
 
86
                cbs[m] = [self.cb_compute(m, f, features[f])
 
87
                          for f in range(0,len(self.mean[m]))]
 
88
            score = 0
 
89
            for f, vec in enumerate(features):
 
90
                # Compute densities and scale by mixture weights
 
91
                d = cbs[m][f] + numpy.log(self.mixw[s,f])
 
92
                # Take top-N densities
 
93
                d = d.take(d.argsort()[-self.topn:])
 
94
                # Multiply into output score
 
95
                score += numpy.log(numpy.exp(d).sum())
 
96
            self.senscr[s] = score
 
97
        return numpy.exp(self.senscr - self.senscr.max())