DHMM_GL.cpp
上传用户:avbj512
上传日期:2013-09-18
资源大小:6239k
文件大小:25k
源码类别:

DSP编程

开发平台:

Visual C++

  1. // DHMM_GL.cpp:
  2. // Implementation of the DHMM_GL Module.
  3. // That is the transform of previous DHMM Code by GuLiang.
  4. //
  5. // Created 2001/08, By DongMing, MDSR.
  6. //
  7. //////////////////////////////////////////////////////////////////////
  8. #include "stdafx.h"
  9. #include "DHMM_GL.h"
  10. #include <math.h>
  11. #define REESTIMATE_ALL (0x0001)
  12. #define ENDSTATE_ABSORB (0x0002)
  13. #define REESTIMATE_B (0x0004)
  14. //////////////////////////////////////////////////////////////////////
  15. // Private Function Head
  16. void DHMM_VQ(int *DMNU_Sound_attrib, int DMNU_Speaker_num, char *DMNU_Featurefile_name, char *DMNU_Codefile_name,
  17.  int Codeword_num, double K_means_precision, int DMNU_mode,
  18.  int DMAD_n_Code_Word_Num, int DMAD_n_Code_Word_Dim,
  19.  DYNA_2DIM_DOUBLE_ARRAY DMAD_d2dda_Code_Book, DYNA_2DIM_DOUBLE_ARRAY DMAD_d2dda_Code_Word);
  20. void DHMM_train(int *DMNU_Sound_attrib, int Speaker_num, int Train_num, char *DMNU_Featurefile_name,
  21. char *DMNU_Codefile_name, char *DMNU_Patternfile_name, int Status_num, int mode,
  22. WORD_SAMPLE * DMAD_pu_Word_Sample,
  23. DHMM_MODEL * DMAD_pu_DHMM_Model);
  24. double DHMM_Calculate(double ***Alpha, double ***Belta, double *Pi, double **A,
  25.   double **B, int **Out, int Sample_num, int Output_num, int *T,
  26.   int n, int mode, int End_state_mode);
  27. double DHMM_Priority(double *Pi, double **A, double **B, int *Out, int T, int n, int mode);
  28. //////////////////////////////////////////////////////////////////////
  29. // API functions
  30. int DHMM_VQ_Train_Code_Book_GL(DYNA_2DIM_DOUBLE_ARRAY d2dda_Code_Word, int n_Code_Word_Num, int n_Code_Word_Dim,
  31.    DYNA_2DIM_DOUBLE_ARRAY d2dda_Initial_Code_Book, DYNA_2DIM_DOUBLE_ARRAY d2dda_Code_Book, int n_Code_Book_Size)
  32. {
  33. PRO_LOG("tVQ = GL, K-mean precision = %15.4E.n", KMEAN_PRECISION);
  34. DHMM_VQ(NULL, 0, NULL, NULL,
  35. n_Code_Book_Size, KMEAN_PRECISION, 0,
  36. n_Code_Word_Num, n_Code_Word_Dim,
  37. d2dda_Code_Book, d2dda_Code_Word);
  38. return 0;
  39. }
  40. int DHMM_Model_Train_DHMM_Model_GL(WORD_SAMPLE * pu_Word_Sample, int n_Word_Sample_Num,
  41.    DHMM_MODEL * pu_DHMM_Model)
  42. {
  43. PRO_LOG("tModel = GL, max loop = %4d, precision = %15.4E.n", MAX_CALC_NUM, EPSILON_CALC);
  44. DHMM_train(NULL, n_Word_Sample_Num, n_Word_Sample_Num, NULL,
  45. NULL, NULL, pu_DHMM_Model->n_State_Num, ~ENDSTATE_ABSORB,
  46. pu_Word_Sample, pu_DHMM_Model);
  47. return 0;
  48. }
  49. int DHMM_Recog_Forward_Backward_GL(DHMM_MODEL * pu_DHMM_Model,
  50.    WORD_SAMPLE * pu_Word_Sample,
  51.    double * pd_Max_Likelihood)
  52. {
  53. (*pd_Max_Likelihood) = DHMM_Priority(pu_DHMM_Model->pdPi, pu_DHMM_Model->d2dda_A, pu_DHMM_Model->d2dda_B,
  54. pu_Word_Sample->pn_VQed_Feature_Sequence, pu_Word_Sample->n_Feature_Sequence_Len,
  55. pu_DHMM_Model->n_State_Num, ~ENDSTATE_ABSORB);
  56. return 0;
  57. }
  58. //////////////////////////////////////////////////////////////////////
  59. // Original Code
  60. //////////////////////////////////////////////////////////////////////
  61. // DMNU = DongMing doesn't use this when transforming.
  62. // DMAD = DongMing addes this when transforming.
  63. // binary split VQ code-book training (clustering) algorithm
  64. static void DHMM_VQ(int *DMNU_Sound_attrib, int DMNU_Speaker_num, char *DMNU_Featurefile_name, char *DMNU_Codefile_name,
  65. int Codeword_num, double K_means_precision, int DMNU_mode,
  66. int DMAD_n_Code_Word_Num, int DMAD_n_Code_Word_Dim,
  67. DYNA_2DIM_DOUBLE_ARRAY DMAD_d2dda_Code_Book, DYNA_2DIM_DOUBLE_ARRAY DMAD_d2dda_Code_Word)
  68. {
  69. int    i, j, p, m;
  70. int    Dimension; // Dimension: 特征维数
  71. int    Nearer;
  72. int    *Counter; // 记录各码字聚类到的训练向量个数
  73. int    Total_num; // 训练向量集的总帧数
  74. double **Codeword; // VQ码本
  75. double **Sum;
  76. double **s; // 训练向量集
  77. double Min_Dist;
  78. double Dist; // 某一训练向量和某一码字间的距离
  79. double New_D; // 所有训练向量的量化失真之和?
  80. double Old_D;
  81. // Initial Memory Block
  82. Dimension = DMAD_n_Code_Word_Dim;
  83. Total_num = DMAD_n_Code_Word_Num;
  84. Codeword = DMAD_d2dda_Code_Book;
  85. if((Sum = new double *[Codeword_num]) == NULL)
  86. {
  87. DEBUG_PRINTF("Not enough memory for Sum !n");
  88. ASSERT(0);
  89. }
  90. for(i=0; i<Codeword_num; i++)
  91. {
  92. if((Sum[i] = new double [Dimension]) == NULL)
  93. {
  94. DEBUG_PRINTF("Not enough memory for Sum[%d] !n", i);
  95. ASSERT(0);
  96. }
  97. }
  98. if((Counter  = new int [Codeword_num]) == NULL)
  99. {
  100. DEBUG_PRINTF("Not enough memory for Counter !n");
  101. ASSERT(0);
  102. }
  103. s = DMAD_d2dda_Code_Word;
  104. // k-means Clusteration
  105. for(p=0; p<Dimension; p++) Codeword[0][p] = 0; // 第一个码字清零
  106. for(i=0; i<Total_num; i++)
  107. for(p=0; p<Dimension; p++)
  108. Codeword[0][p] += s[i][p];
  109. for(p=0; p<Dimension; p++) Codeword[0][p] /= Total_num; // 第一个码字置为所有训练向量的平均值
  110. for(m=2; m<=Codeword_num; m*=2) // m: 分裂后码本大小
  111. {
  112. DEBUG_PRINTF("tM = %d.n", m);
  113. for(i=m/2-1; i>=0; i--)
  114. for(j=0; j<Dimension; j++) // initialize Codeword[0],Codeword[1],...,Codeword[m-1] by splitting current code words
  115. {
  116. Codeword[i*2+1][j] = Codeword[i][j] * 0.9; // splitting parameter epsilon set to 0.1
  117. Codeword[i*2][j]   = Codeword[i][j] * 1.1;
  118. }
  119. Old_D = 1.0e20;
  120. New_D = 1.0e15;
  121. while(((Old_D - New_D) / New_D) > K_means_precision)
  122. {
  123. for(j=0; j<m; j++)
  124. {
  125. for(p=0; p<Dimension; p++) Sum[j][p] = 0;
  126. Counter[j] = 0;
  127. }
  128. Old_D = New_D;
  129. New_D = 0;
  130. for(i=0; i<Total_num; i++)
  131. {
  132. Dist = 0;
  133. for(p=0; p<Dimension; p++)
  134. Dist += (Codeword[0][p] - s[i][p]) * (Codeword[0][p] - s[i][p]);
  135. Min_Dist = Dist; // 计算该训练向量与第一个码字间的距离
  136. Nearer = 0;
  137. for(j=1; j<m; j++) // 计算该训练向量与第2到第m个码字间的距离,并求最小值
  138. {
  139. Dist = 0;
  140. for(p=0; p<Dimension; p++)
  141. Dist += (Codeword[j][p] - s[i][p]) * (Codeword[j][p] - s[i][p]);
  142. if(Dist < Min_Dist)
  143. {
  144. Min_Dist = Dist;
  145. Nearer = j; // 记录距离最近的码字标号
  146. }
  147. }
  148. for(p=0; p<Dimension; p++) Sum[Nearer][p] += s[i][p]; // 累加聚类到标号为Nearer的码字的所有训练向量
  149. Counter[Nearer] ++; // 记录聚类到标号为Nearer的码字的训练向量的个数
  150. New_D += Min_Dist;
  151. }
  152. for(j=0; j<m; j++)
  153. {
  154. if(Counter[j] > 0)
  155. for(p=0; p<Dimension; p++)
  156. Codeword[j][p] = Sum[j][p] / Counter[j]; // 用聚类到标号为j的码字的所有训练的平均值更新该码字
  157. }
  158. }
  159. }
  160. for(i=0; i<Codeword_num; i++)
  161. {
  162. delete Sum[i];
  163. }
  164. delete Sum;
  165. delete Counter;
  166. }
  167. static void DHMM_train(int *DMNU_Sound_attrib, int Speaker_num, int Train_num, char *DMNU_Featurefile_name,
  168.    char *DMNU_Codefile_name, char *DMNU_Patternfile_name, int Status_num, int mode,
  169.    WORD_SAMPLE * DMAD_pu_Word_Sample,
  170.    DHMM_MODEL * DMAD_pu_DHMM_Model)
  171. // Speaker_num 说话人个数
  172. // Train_num 训练集人数(Train_num=Speaker_num-Test_num)
  173. // Status_num 状态数
  174. // mode 训练模式
  175. {
  176. int     i, j, k, /* n, */ m;
  177. int     Output_num; // VQ码本大小(码字个数)
  178. int     **Output; // for each word item model being trained, the output sequence (observation sequence) of each utterance of this model. (每个元素保存该帧的码字标号)
  179. // 1st dimension: index of the training utterance; 
  180. // 2nd dimension: index of frame
  181. int     *Frame_num; // 各训练句子的帧数
  182. double  *Pi; // 初始概率
  183. double  **A; // A矩阵:Status_num*Status_num
  184. double  **B; // B矩阵:Status_num*Output_num
  185. double  ***Alpha; // Train_num*帧数*状态数的double矩阵
  186. double  ***Belta; // Train_num*帧数*状态数的double矩阵
  187. double  w, u;
  188. // Generate (A, B, Pi)
  189. Output_num = DMAD_pu_DHMM_Model->n_Code_Book_Size;
  190. Pi = DMAD_pu_DHMM_Model->pdPi; // The above block transform to this line. #DongMing#
  191. // allocate memory for A matrix
  192. A = DMAD_pu_DHMM_Model->d2dda_A; // The above block transform to this line. #DongMing#
  193. // allocate memory for B matrix
  194. B = DMAD_pu_DHMM_Model->d2dda_B; // The above block transform to this line. #DongMing#
  195. //事实上,此处为Alpha和Belta分配了过多的内存,没有必要为所有用于训练的说话人分配Alpha和Belta
  196. if((Alpha = new double **[Train_num]) == NULL)
  197. {
  198. DEBUG_PRINTF("Not enough memory for Alpha !n");
  199. ASSERT(0);
  200. }
  201. if((Belta = new double **[Train_num]) == NULL)
  202. {
  203. DEBUG_PRINTF("Not enough memory for Belta !n");
  204. ASSERT(0);
  205. }
  206. if((Output = new int *[Train_num]) == NULL)
  207. {
  208. DEBUG_PRINTF("Not enough memory for Output !n");
  209. ASSERT(0);
  210. }
  211. if((Frame_num = new int [Train_num]) == NULL)
  212. {
  213. DEBUG_PRINTF("Not enough memory for Frame_num !n");
  214. ASSERT(0);
  215. }
  216. for(i=1; i<Status_num; i++) Pi[i] = 0; // 初始状态概率:第一个状态为1,其余为0
  217. Pi[0] = 1;
  218. // 初始化A矩阵、B矩阵
  219. for(i=0; i<Status_num; i++)
  220. {
  221. for(j=0; j<Status_num; j++) A[i][j] = 0;
  222. if(i < Status_num-1)
  223. {
  224. A[i][i]   = 0.5;
  225. A[i][i+1] = 0.5;
  226. }
  227. else
  228. {
  229. A[i][i]   = 1.0;
  230. }
  231. w = 0;
  232. for(j=0; j<Status_num; j++) w = w + A[i][j];
  233. for(j=0; j<Status_num; j++) A[i][j] = A[i][j] / w; // 归一化A矩阵的每一行
  234. w = 0;
  235. for(j=0; j<Output_num; j++) // 随机初始化B矩阵
  236. {
  237. B[i][j] = 1.0 / Output_num * (0.9 + ((rand()%1000) / 5000.0)); // RAND_MAX is defined as 0x7fff in "stdlib.h"
  238. // B[i][j] = 1.0 / Output_num;
  239. w = w + B[i][j];
  240. }
  241. for(j=0; j<Output_num; j++) B[i][j] = B[i][j] / w; // 归一化B矩阵的每一行
  242. }
  243. k = 0; // k: training utterance counter for each word item model being trained
  244. // 装入该词条的训练数据
  245. for(m=0; m<Speaker_num; m++)
  246. {
  247. Frame_num[k] = DMAD_pu_Word_Sample[k].n_Feature_Sequence_Len;
  248. // ????????????? is it necessary to save alpha and beta for each training utterance ??????????????
  249. if((Alpha[k] = new double *[Frame_num[k]]) == NULL)
  250. {
  251. DEBUG_PRINTF("Not enough memory for Alpha[%d] !n", k);
  252. ASSERT(0);
  253. }
  254. for(i=0; i<Frame_num[k]; i++)
  255. if((Alpha[k][i] = new double [Status_num]) == NULL)
  256. {
  257. DEBUG_PRINTF("Not enough memory for Alpha[%d][%d] !n", k, i);
  258. ASSERT(0);
  259. }
  260. if((Belta[k] = new double *[Frame_num[k]]) == NULL)
  261. {
  262. DEBUG_PRINTF("Not enough memory for Belta[%d] !n", k);
  263. ASSERT(0);
  264. }
  265. for(i=0; i<Frame_num[k]; i++)
  266. if((Belta[k][i] = new double [Status_num]) == NULL)
  267. {
  268. DEBUG_PRINTF("Not enough memory for Belta[%d][%d] !n", k, i);
  269. ASSERT(0);
  270. }
  271. if((Output[k] = new int [Frame_num[k]]) == NULL)
  272. {
  273. DEBUG_PRINTF("Not enough memory for Frame_num[%d] !n", k);
  274. ASSERT(0);
  275. }
  276. for(i=0; i<Frame_num[k]; i++)
  277. Output[k][i] = DMAD_pu_Word_Sample[k].pn_VQed_Feature_Sequence[i];
  278. k ++;
  279. }
  280. w = 1;
  281. m = 0;
  282. while(m < MAX_CALC_NUM)
  283. {
  284. // Alpha和Belta作为事先分配好内存的变量,并未在调用DHMM_Calculate后使用,因此应该在DHMM_Calculate函数内部分配内存,
  285. // 而入口参数只传递大小信息(如训练句子数、帧数、状态数等等),甚至可以不必为Alpha和Belta分配如此多的内存。
  286. u = DHMM_Calculate(Alpha, Belta, Pi, A, B, Output, Train_num, Output_num,
  287. Frame_num, Status_num, REESTIMATE_ALL, mode);
  288. //u = DHMM_Calculate(Alpha, Belta, Pi, A, B, Output, Train_num, Output_num,
  289. //Frame_num, Status_num, REESTIMATE_ALL, mode, DMAD_pu_Word_Sample);
  290. // for (i = 0; i < Status_num; i++) for (j = 0; j < Output_num; j++) PRO_LOG("%dt%dt:%15.4E.n", i, j, B[i][j]);
  291. m ++;
  292. if((u > w) && (fabs((u-w)/w) < EPSILON_CALC)) break;
  293. else w = u;
  294. }
  295. // for (i = 0; i < Status_num; i++) for (j = 0; j < Output_num; j++) TRACE("%dt%dt:%15.4E.n", i, j, B[i][j]);
  296. PRO_LOG("tLoop = %4d.n", m);
  297. // 释放内存
  298. for(k=0; k<Train_num; k++)
  299. {
  300. for(i=0; i<Frame_num[k]; i++)
  301. delete Alpha[k][i];
  302. delete Alpha[k];
  303. for(i=0; i<Frame_num[k]; i++)
  304. delete Belta[k][i];
  305. delete Belta[k];
  306. //delete Output[k];
  307. }
  308. delete Alpha;
  309. delete Belta;
  310. //delete Output;
  311. delete Frame_num;
  312. }
  313. static double DHMM_Calculate(double ***Alpha, double ***Belta, double *Pi, double **A,
  314.  double **B, int **Out, int Sample_num, int Output_num, int *T,
  315.  int n, int mode, int End_state_mode)
  316. // 功能:训练某一词条的模型
  317. // input:
  318. // Pi 初始时刻各状态的概率
  319. // Alpha 前向概率
  320. // Belta 后向概率
  321. // A 初始A矩阵
  322. // B 初始B矩阵
  323. // Out 用于训练的各句子的观察序列(输出序列)
  324. // Sample_num 训练集人数
  325. // Output_num VQ码本大小(码字数,即观察值的个数)
  326. // T 用于训练的各句子的帧数
  327. // n 状态数
  328. // mode 训练模式(REESTIMATE_A, REESTIMATE_B, REESTIMATE_ALL)
  329. // End_state_mode 结尾帧状态模式(ENDSTATE_ABSORB = 0x200)
  330. // output:
  331. // A
  332. // B
  333. // caller(r_dhmm.cpp): u = DHMM_Calculate(Alpha, Belta, Pi, A, B, Output, Train_num, Output_num,
  334. //       Frame_num, Status_num, REESTIMATE_ALL, mode);
  335.  
  336. {
  337. int    i, j, k, m;
  338. double w;
  339. double **New_A;
  340. double **New_B;
  341. double **Ct; // to prevent underflow of Alpha and Belta, Ct is the scaling coefficient
  342. double Residue;
  343. if((New_A = new double *[n]) == NULL)
  344. {
  345. DEBUG_PRINTF("Not enough memory for New_A !n");
  346. ASSERT(0);
  347. }
  348. for(i=0; i<n; i++)
  349. {
  350. if((New_A[i] = new double [n]) == NULL)
  351. {
  352. DEBUG_PRINTF("Not enough memory for New_A[%d] !n", i);
  353. ASSERT(0);
  354. }
  355. }
  356. if((New_B = new double *[n]) == NULL)
  357. {
  358. DEBUG_PRINTF("Not enough memory for New_B !n");
  359. ASSERT(0);
  360. }
  361. for(i=0; i<n; i++)
  362. {
  363. if((New_B[i] = new double [Output_num]) == NULL)
  364. {
  365. DEBUG_PRINTF("Not enough memory for New_B[%d] !n", i);
  366. ASSERT(0);
  367. }
  368. }
  369. if((Ct = new double *[Sample_num]) == NULL)
  370. {
  371. DEBUG_PRINTF("Not enough memory for Ct !n");
  372. ASSERT(0);
  373. }
  374. for(i=0; i<Sample_num; i++)
  375. if((Ct[i] = new double [T[i]]) == NULL)
  376. {
  377. DEBUG_PRINTF("Not enough memory for Ct[%d] !n", i);
  378. ASSERT(0);
  379. }
  380. // Calculate Alpha & Belta.
  381. for(m=0; m<Sample_num; m++)
  382. {
  383. if (T[m] > 0)
  384. {
  385. w = 0;
  386. for(i=0; i<n; i++)
  387. {
  388. Alpha[m][0][i] = Pi[i] * B[i][ Out[m][0] ];
  389. w = w + Alpha[m][0][i];
  390. }
  391. Ct[m][0] = 1.0 / w; // scaling coefficient
  392. for(i=0; i<n; i++)
  393. Alpha[m][0][i] = Alpha[m][0][i] * Ct[m][0]; // scaling
  394. // 计算Alpha
  395. for(k=1; k<T[m]; k++) // 第m个训练utterance的各帧
  396. {
  397. Ct[m][k] = 0;
  398. for(i=0; i<n; i++)
  399. {
  400. w = 0;
  401. for(j=0; j<n; j++)
  402. w = w + Alpha[m][k-1][j] * A[j][i];
  403. w = w * B[i][ Out[m][k] ];
  404. Alpha[m][k][i] = w;
  405. Ct[m][k] = Ct[m][k] + w;
  406. }
  407. Ct[m][k] = 1.0 / Ct[m][k];
  408. for(i=0; i<n; i++)
  409. Alpha[m][k][i] = Alpha[m][k][i] * Ct[m][k];
  410. } // end of: for(k=1; k<T[m]; k++)
  411. // 最后一帧状态为吸收态,即只有最后一个状态概率不为0,其余状态概率均为0
  412. if(End_state_mode & ENDSTATE_ABSORB) // End_state_mode是在RECOG.CPP中根据用户输入确定的
  413. {
  414. for(i=0; i<n-1; i++) Alpha[m][ T[m]-1 ][i] = 0;
  415. Belta[m][ T[m]-1 ][n-1] = Ct[m][ T[m]-1 ];
  416. for(i=0; i<n-1; i++) Belta[m][ T[m]-1 ][i] = 0;
  417. }
  418. else
  419. {
  420. for(i=0; i<n; i++) Belta[m][ T[m]-1 ][i] = Ct[m][ T[m]-1 ];
  421. }
  422. // 计算Belta
  423. for(k=T[m]-2; k>=0; k--)
  424. for(i=0; i<n; i++)
  425. {
  426. w = 0;
  427. for(j=0; j<n; j++)
  428. w = w + A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
  429. Belta[m][k][i] = w * Ct[m][k];
  430. }
  431. }
  432. }
  433. // Re-estimate A[i][j], i = 0 to n-1, j = 0 to n-1.
  434. /*  if((mode == REESTIMATE_A) || (mode == REESTIMATE_ALL))
  435. {
  436. for(i=0; i<n; i++)
  437. for(j=0; j<n; j++)
  438. New_A[i][j] = 0;
  439.   for(m=0; m<Sample_num; m++)
  440.   {
  441.   w = 0;
  442.   for(i=0; i<n; i++)
  443.   w += Alpha[m][T[m]-1][i];
  444.   
  445. for(k=0; k<T[m]-1; k++)
  446. {
  447.   for(i=0; i<n; i++)
  448.   for(j=0; j<n; j++)
  449.   {
  450.   w1 = Alpha[m][k][i] * A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
  451.   w1 /= w;
  452.   New_A[i][j] += w1;
  453.   }
  454.   }
  455.   }
  456.   
  457. for(i=0; i<n; i++)
  458. {
  459. for(j=0; j<n; j++)
  460. if((j < i) || (j > (i+1)))
  461. New_A[i][j] = 0;
  462.   w = 0;
  463.   for(j=0; j<n; j++) w += New_A[i][j];
  464.   for(j=0; j<n; j++) New_A[i][j] /= w;
  465.   
  466. for(j=0; j<n; j++)
  467. if((j < i) || (j > (i+1)) && (New_A[i][j] < Epsilon_A))
  468. New_A[i][j] = Epsilon_A;
  469.   w = 0;
  470.   for(j=0; j<n; j++) w += New_A[i][j];
  471.   for(j=0; j<n; j++) New_A[i][j] /= w;
  472.   }
  473.   
  474. for(i=0; i<n; i++)
  475. for(j=0; j<n; j++)
  476. A[i][j] = New_A[i][j];
  477.    }*/
  478.    
  479.    // Re-estimate B[i][j], i = 0 to n-1, j = 0 to m-1.
  480.    
  481.    if((mode == REESTIMATE_B) || (mode == REESTIMATE_ALL))
  482.    {
  483.    // clear new B matrix
  484. for(i=0; i<n; i++)
  485. for(j=0; j<Output_num; j++)
  486. New_B[i][j] = 0;
  487.    
  488. for(m=1; m<Sample_num; m++)
  489. {
  490. w = 0;
  491. for(i=0; i<n; i++)
  492. if (T[m] > 0)    // add by wd @ 030331z
  493. w += Alpha[m][T[m]-1][i]; // w: 观察序列概率,即P(O)
  494.    
  495. // reestimate matrix B
  496. for(k=0; k<T[m]; k++)
  497. for(i=0; i<n; i++)
  498. {
  499. New_B[i][Out[m][k]] += Alpha[m][k][i] * Belta[m][k][i] /
  500. Ct[m][k] / w;
  501. }
  502. }
  503.    
  504. for(i=0; i<n; i++)
  505. {
  506. w = 0;
  507. for(j=0; j<Output_num; j++) w += New_B[i][j];
  508. for(j=0; j<Output_num; j++)
  509. {
  510. New_B[i][j] /= w; // 归一化
  511. }
  512. for(j=0; j<Output_num; j++)
  513. if(New_B[i][j] < Epsilon_B) // Epsilon_B=1.0e-6
  514. New_B[i][j] = Epsilon_B;
  515.    
  516. w = 0;
  517. for(j=0; j<Output_num; j++) w += New_B[i][j];
  518. for(j=0; j<Output_num; j++) New_B[i][j] /= w; // 归一化
  519. }
  520.    
  521. for(i=0; i<n; i++) // 更新B矩阵
  522. for(j=0; j<Output_num; j++)
  523. B[i][j] = New_B[i][j];
  524.    }
  525.    
  526.    Residue = 0;
  527.    for(m=0; m<Sample_num; m++)
  528.    if(T[m] > 0) // add by wd @ 030331
  529. Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);
  530.        /*if (T[m] > 0)
  531.    {
  532.    Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);
  533.    }
  534.    else
  535.    Residue += -10; */
  536.    
  537.    for(i=0; i<n; i++) delete New_A[i];
  538.    delete New_A;
  539.    
  540.    for(i=0; i<n; i++) delete New_B[i];
  541.    delete New_B;
  542.    
  543.    for(i=0; i<Sample_num; i++) delete Ct[i];
  544.    delete Ct;
  545.    
  546.    return Residue;
  547. }
  548. static double DHMM_Priority(double *Pi, double **A, double **B, int *Out, int T, int n, int mode)
  549. // input:
  550. //  Pi 初始概率
  551. // A A矩阵
  552. // B B矩阵
  553. // Out 训练集中第m个说话人的观察序列
  554. // T 训练集中第m个说话人的观察序列帧数
  555. // n 状态数
  556. // mode
  557. // return value:
  558. // logP(o1,o2,...,oT|Pi,A,B)
  559. //caller(r_dhmm.cpp): Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);
  560. {
  561. int   i, j, k;
  562. double  w, p;
  563. double  *Alpha1;
  564. double  *Alpha2;
  565. if((Alpha1 = new double [n]) == NULL) { DEBUG_PRINTF("Not enough memory for !n"); ASSERT(0); }
  566. if((Alpha2 = new double [n]) == NULL) { DEBUG_PRINTF("Not enough memory for !n"); ASSERT(0); }
  567. p = 0;
  568. w = 0;
  569. for(i=0; i<n; i++)
  570. {
  571. Alpha1[i] = Pi[i] * B[i][ Out[0] ];
  572. w += Alpha1[i];
  573. }
  574. for(i=0; i<n; i++) Alpha1[i] /= w;
  575. p += log(w);
  576. for(k=1; k<T; k++)
  577. {
  578. for(i=0; i<n; i++)
  579. {
  580. w = 0;
  581. for(j=0; j<n; j++)
  582. w = w + Alpha1[j] * A[j][i];
  583. w = w * B[i][ Out[k] ];
  584. Alpha2[i] = w;
  585. }
  586. if(k < T-1)
  587. {
  588. w = 0;
  589. for(i=0; i<n; i++) w += Alpha2[i];
  590. for(i=0; i<n; i++) Alpha1[i] = Alpha2[i] / w;
  591. p += log(w);
  592. }
  593. }
  594. if(mode & ENDSTATE_ABSORB)
  595. {
  596. p += log(Alpha2[n-1]);
  597. }
  598. else
  599. {
  600. w = 0;
  601. for(i=0; i<n; i++) w += Alpha2[i];
  602. p += log(w);
  603. }
  604. delete Alpha1;
  605. delete Alpha2;
  606. return p;
  607. }
  608. static double DHMM_Calculate(double ***Alpha, double ***Belta, double *Pi, double **A,
  609.  double **B, int Out[140][150], int Sample_num, int Output_num, int *T,
  610.  int n, int mode, int End_state_mode, WORD_SAMPLE * DMAD_pu_Word_Sample)
  611. // 功能:训练某一词条的模型
  612. // input:
  613. // Pi 初始时刻各状态的概率
  614. // Alpha 前向概率
  615. // Belta 后向概率
  616. // A 初始A矩阵
  617. // B 初始B矩阵
  618. // Out 用于训练的各句子的观察序列(输出序列)
  619. // Sample_num 训练集人数
  620. // Output_num VQ码本大小(码字数,即观察值的个数)
  621. // T 用于训练的各句子的帧数
  622. // n 状态数
  623. // mode 训练模式(REESTIMATE_A, REESTIMATE_B, REESTIMATE_ALL)
  624. // End_state_mode 结尾帧状态模式(ENDSTATE_ABSORB = 0x200)
  625. // output:
  626. // A
  627. // B
  628. // caller(r_dhmm.cpp): u = DHMM_Calculate(Alpha, Belta, Pi, A, B, Output, Train_num, Output_num,
  629. //       Frame_num, Status_num, REESTIMATE_ALL, mode);
  630.  
  631. {
  632. int    i, j, k, m;
  633. double w;
  634. double **New_A;
  635. double **New_B;
  636. double **Ct; // to prevent underflow of Alpha and Belta, Ct is the scaling coefficient
  637. double Residue;
  638. if((New_A = new double *[n]) == NULL)
  639. {
  640. DEBUG_PRINTF("Not enough memory for New_A !n");
  641. ASSERT(0);
  642. }
  643. for(i=0; i<n; i++)
  644. {
  645. if((New_A[i] = new double [n]) == NULL)
  646. {
  647. DEBUG_PRINTF("Not enough memory for New_A[%d] !n", i);
  648. ASSERT(0);
  649. }
  650. }
  651. if((New_B = new double *[n]) == NULL)
  652. {
  653. DEBUG_PRINTF("Not enough memory for New_B !n");
  654. ASSERT(0);
  655. }
  656. for(i=0; i<n; i++)
  657. {
  658. if((New_B[i] = new double [Output_num]) == NULL)
  659. {
  660. DEBUG_PRINTF("Not enough memory for New_B[%d] !n", i);
  661. ASSERT(0);
  662. }
  663. }
  664. if((Ct = new double *[Sample_num]) == NULL)
  665. {
  666. DEBUG_PRINTF("Not enough memory for Ct !n");
  667. ASSERT(0);
  668. }
  669. for(i=0; i<Sample_num; i++)
  670. if((Ct[i] = new double [T[i]]) == NULL)
  671. {
  672. DEBUG_PRINTF("Not enough memory for Ct[%d] !n", i);
  673. ASSERT(0);
  674. }
  675. // Calculate Alpha & Belta.
  676. for(m=0; m<Sample_num; m++)
  677. {
  678. w = 0;
  679. for(i=0; i<n; i++)
  680. {
  681. Alpha[m][0][i] = Pi[i] * B[i][ DMAD_pu_Word_Sample[m].pn_VQed_Feature_Sequence[i] ];
  682. w = w + Alpha[m][0][i];
  683. }
  684. Ct[m][0] = 1.0 / w; // scaling coefficient
  685. for(i=0; i<n; i++)
  686. Alpha[m][0][i] = Alpha[m][0][i] * Ct[m][0]; // scaling
  687. // 计算Alpha
  688. for(k=1; k<T[m]; k++) // 第m个训练utterance的各帧
  689. {
  690. Ct[m][k] = 0;
  691. for(i=0; i<n; i++)
  692. {
  693. w = 0;
  694. for(j=0; j<n; j++)
  695. w = w + Alpha[m][k-1][j] * A[j][i];
  696. w = w * B[i][ Out[m][k] ];
  697. Alpha[m][k][i] = w;
  698. Ct[m][k] = Ct[m][k] + w;
  699. }
  700. Ct[m][k] = 1.0 / Ct[m][k];
  701. for(i=0; i<n; i++)
  702. Alpha[m][k][i] = Alpha[m][k][i] * Ct[m][k];
  703. } // end of: for(k=1; k<T[m]; k++)
  704. // 最后一帧状态为吸收态,即只有最后一个状态概率不为0,其余状态概率均为0
  705. if(End_state_mode & ENDSTATE_ABSORB) // End_state_mode是在RECOG.CPP中根据用户输入确定的
  706. {
  707. for(i=0; i<n-1; i++) Alpha[m][ T[m]-1 ][i] = 0;
  708. Belta[m][ T[m]-1 ][n-1] = Ct[m][ T[m]-1 ];
  709. for(i=0; i<n-1; i++) Belta[m][ T[m]-1 ][i] = 0;
  710. }
  711. else
  712. {
  713. for(i=0; i<n; i++) Belta[m][ T[m]-1 ][i] = Ct[m][ T[m]-1 ];
  714. }
  715. // 计算Belta
  716. for(k=T[m]-2; k>=0; k--)
  717. for(i=0; i<n; i++)
  718. {
  719. w = 0;
  720. for(j=0; j<n; j++)
  721. w = w + A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
  722. Belta[m][k][i] = w * Ct[m][k];
  723. }
  724. }
  725. // Re-estimate A[i][j], i = 0 to n-1, j = 0 to n-1.
  726. /*  if((mode == REESTIMATE_A) || (mode == REESTIMATE_ALL))
  727. {
  728. for(i=0; i<n; i++)
  729. for(j=0; j<n; j++)
  730. New_A[i][j] = 0;
  731.   for(m=0; m<Sample_num; m++)
  732.   {
  733.   w = 0;
  734.   for(i=0; i<n; i++)
  735.   w += Alpha[m][T[m]-1][i];
  736.   
  737. for(k=0; k<T[m]-1; k++)
  738. {
  739.   for(i=0; i<n; i++)
  740.   for(j=0; j<n; j++)
  741.   {
  742.   w1 = Alpha[m][k][i] * A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
  743.   w1 /= w;
  744.   New_A[i][j] += w1;
  745.   }
  746.   }
  747.   }
  748.   
  749. for(i=0; i<n; i++)
  750. {
  751. for(j=0; j<n; j++)
  752. if((j < i) || (j > (i+1)))
  753. New_A[i][j] = 0;
  754.   w = 0;
  755.   for(j=0; j<n; j++) w += New_A[i][j];
  756.   for(j=0; j<n; j++) New_A[i][j] /= w;
  757.   
  758. for(j=0; j<n; j++)
  759. if((j < i) || (j > (i+1)) && (New_A[i][j] < Epsilon_A))
  760. New_A[i][j] = Epsilon_A;
  761.   w = 0;
  762.   for(j=0; j<n; j++) w += New_A[i][j];
  763.   for(j=0; j<n; j++) New_A[i][j] /= w;
  764.   }
  765.   
  766. for(i=0; i<n; i++)
  767. for(j=0; j<n; j++)
  768. A[i][j] = New_A[i][j];
  769.    }*/
  770.    
  771.    // Re-estimate B[i][j], i = 0 to n-1, j = 0 to m-1.
  772.    
  773.    if((mode == REESTIMATE_B) || (mode == REESTIMATE_ALL))
  774.    {
  775.    // clear new B matrix
  776.    for(i=0; i<n; i++)
  777.    for(j=0; j<Output_num; j++)
  778.    New_B[i][j] = 0;
  779.    
  780.    for(m=1; m<Sample_num; m++)
  781.    {
  782.    w = 0;
  783.    for(i=0; i<n; i++)
  784.    w += Alpha[m][T[m]-1][i]; // w: 观察序列概率,即P(O)
  785.    
  786.    // reestimate matrix B
  787.    for(k=0; k<T[m]; k++)
  788.    for(i=0; i<n; i++)
  789.    {
  790.    New_B[i][Out[m][k]] += Alpha[m][k][i] * Belta[m][k][i] /
  791.    Ct[m][k] / w;
  792.    }
  793.    }
  794.    
  795.    for(i=0; i<n; i++)
  796.    {
  797.    w = 0;
  798.    for(j=0; j<Output_num; j++) w += New_B[i][j];
  799.    for(j=0; j<Output_num; j++)
  800.    {
  801.    New_B[i][j] /= w; // 归一化
  802.    }
  803.    for(j=0; j<Output_num; j++)
  804.    if(New_B[i][j] < Epsilon_B) // Epsilon_B=1.0e-6
  805.    New_B[i][j] = Epsilon_B;
  806.    
  807.    w = 0;
  808.    for(j=0; j<Output_num; j++) w += New_B[i][j];
  809.    for(j=0; j<Output_num; j++) New_B[i][j] /= w; // 归一化
  810.    }
  811.    
  812.    for(i=0; i<n; i++) // 更新B矩阵
  813.    for(j=0; j<Output_num; j++)
  814.    B[i][j] = New_B[i][j];
  815.    }
  816.    
  817.    Residue = 0;
  818.    for(m=1; m<Sample_num; m++)
  819.    Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);
  820.    
  821.    for(i=0; i<n; i++) delete New_A[i];
  822.    delete New_A;
  823.    
  824.    for(i=0; i<n; i++) delete New_B[i];
  825.    delete New_B;
  826.    
  827.    for(i=0; i<Sample_num; i++) delete Ct[i];
  828.    delete Ct;
  829.    
  830.    return Residue;
  831. }