PocketSphinx  5prealpha
tmat.c
1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3  * Copyright (c) 1999-2004 Carnegie Mellon University. All rights
4  * reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * This work was supported in part by funding from the Defense Advanced
19  * Research Projects Agency and the National Science Foundation of the
20  * United States of America, and the CMU Sphinx Speech Consortium.
21  *
22  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
23  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
26  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * ====================================================================
35  *
36  */
37 
38 /* System headers. */
39 #include <string.h>
40 
41 /* SphinxBase headers. */
42 #include <sphinxbase/logmath.h>
43 #include <sphinxbase/err.h>
44 #include <sphinxbase/ckd_alloc.h>
45 #include <sphinxbase/bio.h>
46 
47 /* Local headers. */
48 #include "tmat.h"
49 #include "hmm.h"
50 #include "vector.h"
51 
52 #define TMAT_PARAM_VERSION "1.0"
53 
54 
59 static int32 tmat_chk_uppertri(tmat_t *tmat, logmath_t *lmath);
60 
61 
68 static int32 tmat_chk_1skip(tmat_t *tmat, logmath_t *lmath);
69 
70 
71 void
72 tmat_dump(tmat_t * tmat, FILE * fp)
73 {
74  int32 i, src, dst;
75 
76  for (i = 0; i < tmat->n_tmat; i++) {
77  fprintf(fp, "TMAT %d = %d x %d\n", i, tmat->n_state,
78  tmat->n_state + 1);
79  for (src = 0; src < tmat->n_state; src++) {
80  for (dst = 0; dst <= tmat->n_state; dst++)
81  fprintf(fp, " %12d", tmat->tp[i][src][dst]);
82  fprintf(fp, "\n");
83  }
84  fprintf(fp, "\n");
85  }
86  fflush(fp);
87 }
88 
89 
90 /*
91  * Check model tprob matrices that they conform to upper-triangular assumption;
92  * i.e. no "backward" transitions allowed.
93  */
94 int32
95 tmat_chk_uppertri(tmat_t * tmat, logmath_t *lmath)
96 {
97  int32 i, src, dst;
98 
99  /* Check that each tmat is upper-triangular */
100  for (i = 0; i < tmat->n_tmat; i++) {
101  for (dst = 0; dst < tmat->n_state; dst++)
102  for (src = dst + 1; src < tmat->n_state; src++)
103  if (tmat->tp[i][src][dst] < 255) {
104  E_ERROR("tmat[%d][%d][%d] = %d\n",
105  i, src, dst, tmat->tp[i][src][dst]);
106  return -1;
107  }
108  }
109 
110  return 0;
111 }
112 
113 
114 int32
115 tmat_chk_1skip(tmat_t * tmat, logmath_t *lmath)
116 {
117  int32 i, src, dst;
118 
119  for (i = 0; i < tmat->n_tmat; i++) {
120  for (src = 0; src < tmat->n_state; src++)
121  for (dst = src + 3; dst <= tmat->n_state; dst++)
122  if (tmat->tp[i][src][dst] < 255) {
123  E_ERROR("tmat[%d][%d][%d] = %d\n",
124  i, src, dst, tmat->tp[i][src][dst]);
125  return -1;
126  }
127  }
128 
129  return 0;
130 }
131 
132 
133 tmat_t *
134 tmat_init(char const *file_name, logmath_t *lmath, float64 tpfloor, int32 breport)
135 {
136  char tmp;
137  int32 n_src, n_dst, n_tmat;
138  FILE *fp;
139  int32 byteswap, chksum_present;
140  uint32 chksum;
141  float32 **tp;
142  int32 i, j, k, tp_per_tmat;
143  char **argname, **argval;
144  tmat_t *t;
145 
146 
147  if (breport) {
148  E_INFO("Reading HMM transition probability matrices: %s\n",
149  file_name);
150  }
151 
152  t = (tmat_t *) ckd_calloc(1, sizeof(tmat_t));
153 
154  if ((fp = fopen(file_name, "rb")) == NULL)
155  E_FATAL_SYSTEM("Failed to open transition file '%s' for reading", file_name);
156 
157  /* Read header, including argument-value info and 32-bit byteorder magic */
158  if (bio_readhdr(fp, &argname, &argval, &byteswap) < 0)
159  E_FATAL("Failed to read header from file '%s'\n", file_name);
160 
161  /* Parse argument-value list */
162  chksum_present = 0;
163  for (i = 0; argname[i]; i++) {
164  if (strcmp(argname[i], "version") == 0) {
165  if (strcmp(argval[i], TMAT_PARAM_VERSION) != 0)
166  E_WARN("Version mismatch(%s): %s, expecting %s\n",
167  file_name, argval[i], TMAT_PARAM_VERSION);
168  }
169  else if (strcmp(argname[i], "chksum0") == 0) {
170  chksum_present = 1; /* Ignore the associated value */
171  }
172  }
173  bio_hdrarg_free(argname, argval);
174  argname = argval = NULL;
175 
176  chksum = 0;
177 
178  /* Read #tmat, #from-states, #to-states, arraysize */
179  if ((bio_fread(&n_tmat, sizeof(int32), 1, fp, byteswap, &chksum)
180  != 1)
181  || (bio_fread(&n_src, sizeof(int32), 1, fp, byteswap, &chksum) !=
182  1)
183  || (bio_fread(&n_dst, sizeof(int32), 1, fp, byteswap, &chksum) !=
184  1)
185  || (bio_fread(&i, sizeof(int32), 1, fp, byteswap, &chksum) != 1)) {
186  E_FATAL("Failed to read header from '%s'\n", file_name);
187  }
188  if (n_tmat >= MAX_INT16)
189  E_FATAL("%s: Number of transition matrices (%d) exceeds limit (%d)\n", file_name,
190  n_tmat, MAX_INT16);
191  t->n_tmat = n_tmat;
192 
193  if (n_dst != n_src + 1)
194  E_FATAL("%s: Unsupported transition matrix. Number of source states (%d) != number of target states (%d)-1\n", file_name,
195  n_src, n_dst);
196  t->n_state = n_src;
197 
198  if (i != t->n_tmat * n_src * n_dst) {
199  E_FATAL
200  ("%s: Invalid transitions. Number of coefficients (%d) doesn't match expected array dimension: %d x %d x %d\n",
201  file_name, i, t->n_tmat, n_src, n_dst);
202  }
203 
204  /* Allocate memory for tmat data */
205  t->tp = ckd_calloc_3d(t->n_tmat, n_src, n_dst, sizeof(***t->tp));
206 
207  /* Temporary structure to read in the float data */
208  tp = ckd_calloc_2d(n_src, n_dst, sizeof(**tp));
209 
210  /* Read transition matrices, normalize and floor them, and convert to log domain */
211  tp_per_tmat = n_src * n_dst;
212  for (i = 0; i < t->n_tmat; i++) {
213  if (bio_fread(tp[0], sizeof(float32), tp_per_tmat, fp,
214  byteswap, &chksum) != tp_per_tmat) {
215  E_FATAL("Failed to read transition matrix %d from '%s'\n", i, file_name);
216  }
217 
218  /* Normalize and floor */
219  for (j = 0; j < n_src; j++) {
220  if (vector_sum_norm(tp[j], n_dst) == 0.0)
221  E_WARN("Normalization failed for transition matrix %d from state %d\n",
222  i, j);
223  vector_nz_floor(tp[j], n_dst, tpfloor);
224  vector_sum_norm(tp[j], n_dst);
225 
226  /* Convert to logs3. */
227  for (k = 0; k < n_dst; k++) {
228  int ltp;
229 #if 0 /* No, don't do this! It will subtly break 3-state HMMs. */
230  /* For these ones, we floor them even if they are
231  * zero, otherwise HMM evaluation goes nuts. */
232  if (k >= j && k-j < 3 && tp[j][k] == 0.0f)
233  tp[j][k] = tpfloor;
234 #endif
235  /* Log and quantize them. */
236  ltp = -logmath_log(lmath, tp[j][k]) >> SENSCR_SHIFT;
237  if (ltp > 255) ltp = 255;
238  t->tp[i][j][k] = (uint8)ltp;
239  }
240  }
241  }
242 
243  ckd_free_2d(tp);
244 
245  if (chksum_present)
246  bio_verify_chksum(fp, byteswap, chksum);
247 
248  if (fread(&tmp, 1, 1, fp) == 1)
249  E_ERROR("Non-empty file beyond end of data\n");
250 
251  fclose(fp);
252 
253  if (tmat_chk_uppertri(t, lmath) < 0)
254  E_FATAL("Tmat not upper triangular\n");
255  if (tmat_chk_1skip(t, lmath) < 0)
256  E_FATAL("Topology not Left-to-Right or Bakis\n");
257 
258  return t;
259 }
260 
261 void
263 {
264  E_INFO_NOFN("Initialization of tmat_t, report:\n");
265  E_INFO_NOFN("Read %d transition matrices of size %dx%d\n",
266  t->n_tmat, t->n_state, t->n_state + 1);
267  E_INFO_NOFN("\n");
268 
269 }
270 
271 /*
272  * RAH, Free memory allocated in tmat_init ()
273  */
274 void
276 {
277  if (t) {
278  if (t->tp)
279  ckd_free_3d(t->tp);
280  ckd_free(t);
281  }
282 }
uint8 *** tp
The transition matrices; kept in the same scale as acoustic scores; tp[tmatid][from-state][to-state]...
Definition: tmat.h:56
int16 n_tmat
Number matrices.
Definition: tmat.h:58
void tmat_free(tmat_t *t)
RAH, add code to remove memory allocated by tmat_init.
Definition: tmat.c:275
Implementation of HMM base structure.
tmat_t * tmat_init(char const *tmatfile, logmath_t *lmath, float64 tpfloor, int32 breport)
Initialize transition matrix.
Definition: tmat.c:134
int16 n_state
Number source states in matrix (only the emitting states); Number destination states = n_state+1...
Definition: tmat.h:59
void tmat_dump(tmat_t *tmat, FILE *fp)
Dumping the transition matrix for debugging.
Definition: tmat.c:72
#define SENSCR_SHIFT
Shift count for senone scores.
Definition: hmm.h:73
Transition matrix data structure.
Transition matrix data structure.
Definition: tmat.h:55
void tmat_report(tmat_t *t)
Report the detail of the transition matrix structure.
Definition: tmat.c:262