mirror of
https://github.com/cmusphinx/sphinxtrain.git
synced 2026-06-16 13:14:30 +00:00
165 lines
5.7 KiB
Python
165 lines
5.7 KiB
Python
# Copyright (c) 2006 Carnegie Mellon University
|
|
#
|
|
# You may copy and modify this freely under the same terms as
|
|
# Sphinx-III
|
|
"""Read/write Sphinx-III Gaussian parameter count files.
|
|
|
|
This module reads and writes the expected Gaussian mixture occupancy
|
|
count files created by SphinxTrain's implementation of the
|
|
Forward-Backward algorithm for training (semi-)continuous HMMs.
|
|
"""
|
|
|
|
__author__ = "David Huggins-Daines <dhdaines@gmail.com>"
|
|
__version__ = "$Revision$"
|
|
|
|
from struct import unpack
|
|
from numpy import reshape, frombuffer
|
|
from .s3file import S3File
|
|
import os
|
|
|
|
|
|
def open(filename, mode="rb", attr={"version": 1.0}):
|
|
if mode in ("r", "rb"):
|
|
return S3GauCntFile(filename)
|
|
else:
|
|
raise Exception("mode must be 'r' or 'rb'")
|
|
|
|
|
|
def accumdirs(accumdirs):
|
|
"Read and accumulate counts from several directories"
|
|
gauden = None
|
|
for d in accumdirs:
|
|
try:
|
|
subgau = S3GauCntFile(os.path.join(d, "gauden_counts"), "rb")
|
|
except OSError:
|
|
subgau = None
|
|
continue
|
|
if gauden is None:
|
|
gauden = subgau
|
|
else:
|
|
for m, mgau in enumerate(gauden.mean):
|
|
for f, feat in enumerate(mgau):
|
|
gauden.mean[m][f] += subgau.mean[m][f]
|
|
gauden.var[m][f] += subgau.var[m][f]
|
|
gauden.dnom[m][f] += subgau.dnom[m][f]
|
|
return gauden
|
|
|
|
|
|
def accumdirs_full(accumdirs):
|
|
"Read and accumulate full-covariance counts from several directories"
|
|
gauden = None
|
|
for d in accumdirs:
|
|
try:
|
|
subgau = S3FullGauCntFile(os.path.join(d, "gauden_counts"), "rb")
|
|
except OSError:
|
|
subgau = None
|
|
continue
|
|
if gauden is None:
|
|
gauden = subgau
|
|
else:
|
|
for m, mgau in enumerate(gauden.mean):
|
|
for f, feat in enumerate(mgau):
|
|
gauden.mean[m][f] += subgau.mean[m][f]
|
|
gauden.var[m][f] += subgau.var[m][f]
|
|
gauden.dnom[m][f] += subgau.dnom[m][f]
|
|
return gauden
|
|
|
|
|
|
def open_full(filename, mode="rb", attr={"version": 1.0}):
|
|
if mode in ("r", "rb"):
|
|
return S3FullGauCntFile(filename, mode)
|
|
else:
|
|
raise Exception("mode must be 'r', 'rb'")
|
|
|
|
|
|
class S3GauCntFile(S3File):
|
|
"Read Sphinx-III format Gaussian count files"
|
|
|
|
def __init__(self, file, mode="rb"):
|
|
S3File.__init__(self, file, mode)
|
|
self._load()
|
|
|
|
def readgauheader(self):
|
|
if self.fileattr["version"] != "1.0":
|
|
raise Exception("Version mismatch: must be 1.0 but is " +
|
|
self.fileattr["version"])
|
|
self.fh.seek(self.data_start, 0)
|
|
self.has_mean = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
self.has_var = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
self.pass2var = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
self.n_mgau = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
self.density = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
self.n_feat = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
self.veclen = unpack(self.swap + "I" * self.n_feat,
|
|
self.fh.read(4 * self.n_feat))
|
|
self.blk = sum(self.veclen)
|
|
|
|
def _load(self):
|
|
self.readgauheader()
|
|
if self.has_mean:
|
|
self.mean = self._loadgau()
|
|
if self.has_var:
|
|
self.var = self._loadgau()
|
|
self.dnom = self.read3d()
|
|
|
|
def _loadgau(self):
|
|
self._nfloats = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
if self._nfloats != self.n_mgau * self.density * self.blk:
|
|
raise Exception(
|
|
("Number of data points %d doesn't match " +
|
|
"total %d = %d*%d*%d") %
|
|
(self._nfloats, self.n_mgau * self.density * self.blk,
|
|
self.n_mgau, self.density, self.blk))
|
|
spam = self.fh.read(self._nfloats * 4)
|
|
data = frombuffer(spam, 'f').copy()
|
|
if self.otherend:
|
|
data = data.byteswap()
|
|
params = []
|
|
r = 0
|
|
for i in range(0, self.n_mgau):
|
|
mgau = []
|
|
params.append(mgau)
|
|
for j in range(0, self.n_feat):
|
|
rnext = r + self.density * self.veclen[j]
|
|
gmm = reshape(data[r:rnext], (self.density, self.veclen[j]))
|
|
mgau.append(gmm)
|
|
r = rnext
|
|
return params
|
|
|
|
|
|
class S3FullGauCntFile(S3GauCntFile):
|
|
"Read Sphinx-III format Gaussian full covariance matrix files"
|
|
|
|
def _load(self):
|
|
self.readgauheader()
|
|
if self.has_mean:
|
|
self.mean = self._loadgau()
|
|
if self.has_var:
|
|
self.var = self._loadfullgau()
|
|
self.dnom = self.read3d()
|
|
|
|
def _loadfullgau(self):
|
|
self._nfloats = unpack(self.swap + "I", self.fh.read(4))[0]
|
|
if self._nfloats != self.n_mgau * self.density * self.blk * self.blk:
|
|
raise Exception(
|
|
("Number of data points %d doesn't match " +
|
|
"total %d = %d*%d*%d*%d") %
|
|
(self._nfloats, self.n_mgau * self.density * self.blk *
|
|
self.blk, self.n_mgau, self.density, self.blk, self.blk))
|
|
spam = self.fh.read(self._nfloats * 4)
|
|
data = frombuffer(spam, 'f').copy()
|
|
if self.otherend:
|
|
data = data.byteswap()
|
|
params = []
|
|
r = 0
|
|
for i in range(0, self.n_mgau):
|
|
mgau = []
|
|
params.append(mgau)
|
|
for j in range(0, self.n_feat):
|
|
rnext = r + self.density * self.veclen[j] * self.veclen[j]
|
|
gmm = reshape(data[r:rnext],
|
|
(self.density, self.veclen[j], self.veclen[j]))
|
|
mgau.append(gmm)
|
|
r = rnext
|
|
return params
|