DHMM_HQ.cpp
资源名称:VQ-DHMM.rar [点击查看]
上传用户:avbj512
上传日期:2013-09-18
资源大小:6239k
文件大小:19k
源码类别:
DSP编程
开发平台:
Visual C++
- // DHMM_HQ.cpp:
- // Implementation of the DHMM_HQ Module.
- // That is the C rewritten
- // of previous Matlab DHMM program by HeQiang.
- //
- // Created 2001/08, By DongMing, MDSR.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "DHMM_HQ.h"
- #include "kwspot.h"
- #include <math.h>
- #include "DHMM_GL.h"
- extern PRO_CONFIG u_Pro_Config;
- #define VQ_TRAIN_CODE_BOOK_LOOP_TIME 40 // 设置VQ中K-mean的最大迭代次数
- // The best loop: 100, better than 80
- #define MODEL_TRAIN_CODE_BOOK_LOOP_TIME 32 // 设置模型训练时的最大迭代次数
- // 20, 40 are better
- //////////////////////////////////////////////////////////////////////
- // Private Function Head
- int DHMM_Model_Calculate_Gamma(WORD_SAMPLE * pu_Word_Sample, DHMM_MODEL * pu_DHMM_Model);
- //////////////////////////////////////////////////////////////////////
- // API functions
- int DHMM_VQ_Train_Code_Book_HQ(DYNA_2DIM_DOUBLE_ARRAY d2dda_Code_Word, int n_Code_Word_Num, int n_Code_Word_Dim,
- DYNA_2DIM_DOUBLE_ARRAY d2dda_Initial_Code_Book, DYNA_2DIM_DOUBLE_ARRAY d2dda_Code_Book, int n_Code_Book_Size)
- {
- int * pn_Initial_Code_Book_Index;
- int * pn_Code_Word_Min_Index; // 存储每个特征的最近类中心
- double * pd_Code_Word_Min_Distance; // 存储每个特征到最近类中心的距离
- int n_Loop_Index, n_Feature_Index, n_Code_Word_Index, n_Dim_Index;
- double dTmp;
- double d_Old_Distance, d_Distance; // 上次与此次的类内平均距离
- int nTmp;
- BOOL boolTmp;
- PRO_LOG("tVQ = HQ, loop = %4d.n", VQ_TRAIN_CODE_BOOK_LOOP_TIME);
- // 若设置初始码本,拷贝之
- if (d2dda_Initial_Code_Book != NULL)
- {
- for (n_Code_Word_Index = 0; n_Code_Word_Index < n_Code_Book_Size; n_Code_Word_Index++)
- {
- memcpy(d2dda_Code_Book[n_Code_Word_Index], d2dda_Initial_Code_Book[n_Code_Word_Index], sizeof(double) * n_Code_Word_Dim);
- }
- }
- // 若没有设置初始码本,则随机生成
- else
- {
- pn_Initial_Code_Book_Index = new int[n_Code_Book_Size];
- ASSERT(pn_Initial_Code_Book_Index);
- for (n_Code_Word_Index = 0; n_Code_Word_Index < n_Code_Book_Size; n_Code_Word_Index++)
- {
- do {
- pn_Initial_Code_Book_Index[n_Code_Word_Index] = int((double(rand()) / (double(RAND_MAX) + 1)) * n_Code_Word_Num);
- boolTmp = FALSE;
- for (nTmp = 0; nTmp < n_Code_Word_Index; nTmp++)
- {
- if (pn_Initial_Code_Book_Index[n_Code_Word_Index] == pn_Initial_Code_Book_Index[nTmp]) boolTmp = TRUE;
- }
- } while (boolTmp);
- }
- for (n_Code_Word_Index = 0; n_Code_Word_Index < n_Code_Book_Size; n_Code_Word_Index++)
- {
- memcpy(d2dda_Code_Book[n_Code_Word_Index], d2dda_Code_Word[pn_Initial_Code_Book_Index[n_Code_Word_Index]], sizeof(double) * n_Code_Word_Dim);
- }
- delete[] pn_Initial_Code_Book_Index;
- }
- pn_Code_Word_Min_Index = new int[n_Code_Word_Num];
- pd_Code_Word_Min_Distance = new double[n_Code_Word_Num];
- ASSERT((pn_Code_Word_Min_Index != NULL) && (pd_Code_Word_Min_Distance != NULL));
- d_Distance = MAX_DOUBLE_VALUE;
- for (n_Loop_Index = 0; n_Loop_Index < VQ_TRAIN_CODE_BOOK_LOOP_TIME; n_Loop_Index++)
- {
- DEBUG_PRINTF("VQ:tLoop = %4d of %d.n", n_Loop_Index, VQ_TRAIN_CODE_BOOK_LOOP_TIME);
- // 计算每个特征的最近类中心及距离
- for (n_Feature_Index = 0; n_Feature_Index < n_Code_Word_Num; n_Feature_Index++)
- {
- pn_Code_Word_Min_Index[n_Feature_Index] = -1;
- pd_Code_Word_Min_Distance[n_Feature_Index] = MAX_DOUBLE_VALUE;
- for (n_Code_Word_Index = 0; n_Code_Word_Index < n_Code_Book_Size; n_Code_Word_Index++)
- {
- dTmp = 0.0F;
- for (n_Dim_Index = 0; n_Dim_Index < n_Code_Word_Dim; n_Dim_Index++)
- {
- dTmp += (d2dda_Code_Word[n_Feature_Index][n_Dim_Index] - d2dda_Code_Book[n_Code_Word_Index][n_Dim_Index])
- * (d2dda_Code_Word[n_Feature_Index][n_Dim_Index] - d2dda_Code_Book[n_Code_Word_Index][n_Dim_Index]);
- }
- if (dTmp < pd_Code_Word_Min_Distance[n_Feature_Index])
- {
- pn_Code_Word_Min_Index[n_Feature_Index] = n_Code_Word_Index;
- pd_Code_Word_Min_Distance[n_Feature_Index] = dTmp;
- }
- }
- }
- // 计算类内平均距离
- d_Old_Distance = d_Distance;
- d_Distance = 0.0F;
- for (n_Feature_Index = 0; n_Feature_Index < n_Code_Word_Num; n_Feature_Index++)
- {
- d_Distance += pd_Code_Word_Min_Distance[n_Feature_Index];
- }
- d_Distance /= n_Code_Word_Num;
- DEBUG_PRINTF("tAverage Distance = %10.4f, Changed %15.4E.n", d_Distance, ((d_Old_Distance - d_Distance) / d_Old_Distance));
- // 按最近距离原则给每类分派样点,并用该类样点的平均值更新类中心
- for (n_Code_Word_Index = 0; n_Code_Word_Index < n_Code_Book_Size; n_Code_Word_Index++)
- {
- nTmp = 0;
- for (n_Dim_Index = 0; n_Dim_Index < n_Code_Word_Dim; n_Dim_Index++)
- {
- d2dda_Code_Book[n_Code_Word_Index][n_Dim_Index] = 0.0F;
- }
- for (n_Feature_Index = 0; n_Feature_Index < n_Code_Word_Num; n_Feature_Index++)
- {
- if (pn_Code_Word_Min_Index[n_Feature_Index] == n_Code_Word_Index)
- {
- nTmp++;
- for (n_Dim_Index = 0; n_Dim_Index < n_Code_Word_Dim; n_Dim_Index++)
- {
- d2dda_Code_Book[n_Code_Word_Index][n_Dim_Index] += d2dda_Code_Word[n_Feature_Index][n_Dim_Index];
- }
- }
- }
- // 该类分到了样点,直接计算
- if (nTmp != 0)
- {
- for (n_Dim_Index = 0; n_Dim_Index < n_Code_Word_Dim; n_Dim_Index++)
- {
- d2dda_Code_Book[n_Code_Word_Index][n_Dim_Index] /= nTmp;
- }
- }
- // 该类没有分到样点,则丢弃原类中心,随机选中一个样点作为该类中心
- else
- {
- do {
- nTmp = int((double(rand()) / (double(RAND_MAX) + 1)) * n_Code_Word_Num);
- boolTmp = FALSE;
- if (pd_Code_Word_Min_Distance[nTmp] < EPSILON_DOUBLE_VALUE) boolTmp = TRUE;
- } while (boolTmp);
- memcpy(d2dda_Code_Book[n_Code_Word_Index], d2dda_Code_Word[nTmp], sizeof(double) * n_Code_Word_Dim);
- }
- }
- }
- PRO_LOG("VQ:tLoop = %4d, Average Distance = %10.4f, Changed %15.4E.n", n_Loop_Index, d_Distance, ((d_Old_Distance - d_Distance) / d_Old_Distance));
- delete[] pn_Code_Word_Min_Index;
- delete[] pd_Code_Word_Min_Distance;
- return 0;
- }
- int DHMM_Model_Train_DHMM_Model_HQ(WORD_SAMPLE * pu_Word_Sample, int n_Word_Sample_Num,
- DHMM_MODEL * pu_DHMM_Model)
- {
- DYNA_2DIM_DOUBLE_ARRAY d2dda_Nom; // 状态数 * 输出个数
- double * pd_Denom; // 状态数
- int n_Loop_Index, n_State_Index, n_Code_Word_Index, n_Word_Sample_Index, n_Frame_Index;
- int nTmp;
- double d_Old_Total_Likelihood, d_Total_Likelihood; // 上次与此次迭代的模型对所有词条匹配分数的加和
- double dTmp;
- PRO_LOG("tModel = HQ, loop = %4d.n", MODEL_TRAIN_CODE_BOOK_LOOP_TIME);
- // 初始化Pi,初始状态为状态0
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- pu_DHMM_Model->pdPi[n_State_Index] = 0.0F;
- }
- pu_DHMM_Model->pdPi[0] = 1.0F;
- // 初始化A,只能停留或跳向下一个状态,并且等概0.5,最后一个状态只能停留
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- pu_DHMM_Model->d2dda_A[n_State_Index][nTmp] = 0.0F;
- }
- }
- for (n_State_Index = 0; n_State_Index < (pu_DHMM_Model->n_State_Num - 1); n_State_Index++)
- {
- pu_DHMM_Model->d2dda_A[n_State_Index][n_State_Index] = 0.5F;
- pu_DHMM_Model->d2dda_A[n_State_Index][n_State_Index + 1] = 0.5F;
- }
- pu_DHMM_Model->d2dda_A[pu_DHMM_Model->n_State_Num - 1][pu_DHMM_Model->n_State_Num - 1] = 1.0F;
- // 初始化B,均匀初始化,每个状态输出各个输出码字的概率均等,为码字总数的倒数
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- for (n_Code_Word_Index = 0; n_Code_Word_Index < pu_DHMM_Model->n_Code_Book_Size; n_Code_Word_Index++)
- {
- pu_DHMM_Model->d2dda_B[n_State_Index][n_Code_Word_Index] = 1.0F / pu_DHMM_Model->n_Code_Book_Size;
- }
- }
- d2dda_Nom = d2dda_New(pu_DHMM_Model->n_State_Num, pu_DHMM_Model->n_Code_Book_Size);
- pd_Denom = new double[pu_DHMM_Model->n_State_Num];
- ASSERT((d2dda_Nom != NULL) && (pd_Denom != NULL));
- for (n_Word_Sample_Index = 0; n_Word_Sample_Index < n_Word_Sample_Num; n_Word_Sample_Index++)
- {
- pu_Word_Sample[n_Word_Sample_Index].d2dda_Gamma = d2dda_New(pu_Word_Sample[n_Word_Sample_Index].n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- ASSERT(pu_Word_Sample[n_Word_Sample_Index].d2dda_Gamma != NULL);
- }
- d_Total_Likelihood = -MAX_DOUBLE_VALUE;
- for (n_Loop_Index = 0; n_Loop_Index < MODEL_TRAIN_CODE_BOOK_LOOP_TIME; n_Loop_Index++)
- {
- // 计算每个词条的Gamma系数,二维数组,帧数 * 状态数
- for (n_Word_Sample_Index = 0; n_Word_Sample_Index < n_Word_Sample_Num; n_Word_Sample_Index++)
- {
- DHMM_Model_Calculate_Gamma(&pu_Word_Sample[n_Word_Sample_Index], pu_DHMM_Model);
- }
- // 准备重估B
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- pd_Denom[n_State_Index] = 0.0F;
- for (n_Code_Word_Index = 0; n_Code_Word_Index < pu_DHMM_Model->n_Code_Book_Size; n_Code_Word_Index++)
- {
- d2dda_Nom[n_State_Index][n_Code_Word_Index] = 0.0F;
- }
- }
- // 计算重估B时每项的分子,和每行的分母
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- for (n_Word_Sample_Index = 0; n_Word_Sample_Index < n_Word_Sample_Num; n_Word_Sample_Index++)
- {
- for (n_Frame_Index = 0; n_Frame_Index < pu_Word_Sample[n_Word_Sample_Index].n_Feature_Sequence_Len; n_Frame_Index++)
- {
- d2dda_Nom[n_State_Index][pu_Word_Sample[n_Word_Sample_Index].pn_VQed_Feature_Sequence[n_Frame_Index]]
- += pu_Word_Sample[n_Word_Sample_Index].d2dda_Gamma[n_Frame_Index][n_State_Index];
- pd_Denom[n_State_Index] += pu_Word_Sample[n_Word_Sample_Index].d2dda_Gamma[n_Frame_Index][n_State_Index];
- }
- }
- }
- // 重新计算B
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- for (n_Code_Word_Index = 0; n_Code_Word_Index < pu_DHMM_Model->n_Code_Book_Size; n_Code_Word_Index++)
- {
- pu_DHMM_Model->d2dda_B[n_State_Index][n_Code_Word_Index] =
- d2dda_Nom[n_State_Index][n_Code_Word_Index] / pd_Denom[n_State_Index];
- }
- }
- // 计算当前模型对于全体训练词条的匹配分数和
- d_Old_Total_Likelihood = d_Total_Likelihood;
- d_Total_Likelihood = 0.0F;
- for (n_Word_Sample_Index = 0; n_Word_Sample_Index < n_Word_Sample_Num; n_Word_Sample_Index++)
- {
- DHMM_Recog_Forward_Backward_GL(pu_DHMM_Model, &pu_Word_Sample[n_Word_Sample_Index], &dTmp);
- d_Total_Likelihood += dTmp;
- }
- // 如果迭代收敛,跳出
- // if (fabs((d_Old_Total_Likelihood - d_Total_Likelihood) / d_Old_Total_Likelihood) < 1.0E-6) break;
- // DEBUG_PRINTF("tTotal likelihood = %10.4f, changed %15.4E.n", d_Total_Likelihood, ((d_Old_Total_Likelihood - d_Total_Likelihood) / d_Old_Total_Likelihood));
- }
- PRO_LOG("tLoop = %4d, Total likelihood = %10.4f, changed %15.4E.n", n_Loop_Index, d_Total_Likelihood, ((d_Old_Total_Likelihood - d_Total_Likelihood) / d_Old_Total_Likelihood));
- for (n_Word_Sample_Index = 0; n_Word_Sample_Index < n_Word_Sample_Num; n_Word_Sample_Index++)
- {
- d2dda_Free(pu_Word_Sample[n_Word_Sample_Index].d2dda_Gamma, pu_Word_Sample[n_Word_Sample_Index].n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- pu_Word_Sample[n_Word_Sample_Index].d2dda_Gamma = NULL;
- }
- d2dda_Free(d2dda_Nom, pu_DHMM_Model->n_State_Num, pu_DHMM_Model->n_Code_Book_Size);
- delete[] pd_Denom;
- return 0;
- }
- int DHMM_Recog_Viterbi_HQ(DHMM_MODEL * pu_DHMM_Model,
- WORD_SAMPLE * pu_Word_Sample,
- double * pd_Max_Likelihood, int * pn_Status_Sequence)
- {
- DYNA_2DIM_DOUBLE_ARRAY d2dda_B;
- DYNA_2DIM_INT_ARRAY d2dna_LogB;
- int n_Code_Word_Index, n_State_Index;
- d2dda_B = d2dda_New(pu_DHMM_Model->n_State_Num, pu_DHMM_Model->n_Code_Book_Size);
- d2dna_LogB = d2dna_New(pu_DHMM_Model->n_State_Num, pu_DHMM_Model->n_Code_Book_Size);
- ASSERT((d2dda_B != NULL) && (d2dna_LogB != NULL));
- // 对于B矩阵进行定点化处理,下截底并取对数
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- memcpy(d2dda_B[n_State_Index], pu_DHMM_Model->d2dda_B[n_State_Index], sizeof(double) * pu_DHMM_Model->n_Code_Book_Size);
- }
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- for (n_Code_Word_Index = 0; n_Code_Word_Index < pu_DHMM_Model->n_Code_Book_Size; n_Code_Word_Index++)
- {
- if (d2dda_B[n_State_Index][n_Code_Word_Index] < EPSILON_DOUBLE_VALUE)
- d2dda_B[n_State_Index][n_Code_Word_Index] = EPSILON_DOUBLE_VALUE;
- d2dna_LogB[n_State_Index][n_Code_Word_Index]
- = (short)(log10(d2dda_B[n_State_Index][n_Code_Word_Index]) * (65536L / LOG_SCALE) + 32768L);
- ASSERT((d2dna_LogB[n_State_Index][n_Code_Word_Index] >= short(MIN_SHORT_VALUE)) && (d2dna_LogB[n_State_Index][n_Code_Word_Index] <= MAX_SHORT_VALUE));
- }
- }
- // 调用定点的Viterbi算法计算匹配分数
- *pd_Max_Likelihood = DHMM_Recog_Viterbi_HQ_FIX(d2dna_LogB, pu_DHMM_Model->n_State_Num,
- pu_Word_Sample->pn_VQed_Feature_Sequence, pu_Word_Sample->n_Feature_Sequence_Len);
- d2dda_Free(d2dda_B, pu_DHMM_Model->n_State_Num, pu_DHMM_Model->n_Code_Book_Size);
- d2dna_Free(d2dna_LogB, pu_DHMM_Model->n_State_Num, pu_DHMM_Model->n_Code_Book_Size);
- return 0;
- }
- // 定点viterbi算法,已经对于Pi和A作了简化假设
- long DHMM_Recog_Viterbi_HQ_FIX(DYNA_2DIM_INT_ARRAY d2dna_LogB, int n_State_Num,
- int * pn_VQed_Feature_Sequence, int n_Feature_Sequence_Len)
- {
- long * pl_Alpha;
- int n_State_Index, n_Frame_Index;
- long lTmp1, lTmp2;
- int i=0;
- int first = 1;
- long sl_1 = 0;
- long sl_2 = 0;
- int second = 1;
- pl_Alpha = new long[n_State_Num];
- ASSERT(pl_Alpha != NULL);
- for (n_State_Index = 0; n_State_Index < n_State_Num; n_State_Index++) pl_Alpha[n_State_Index] = long(MIN_LONG_VALUE) / 2;
- pl_Alpha[0] = 0;
- pl_Alpha[1] = 0;
- // lTmp1: Delta[t-1][i-1], lTmp2: Delta[t-1][i]
- for (n_Frame_Index = 1; n_Frame_Index < n_Feature_Sequence_Len; n_Frame_Index++)
- {
- lTmp1 = MIN_LONG_VALUE;
- for (n_State_Index = 0; n_State_Index < n_State_Num; n_State_Index++)
- {
- lTmp2 = pl_Alpha[n_State_Index];
- if (lTmp1 > lTmp2)
- pl_Alpha[n_State_Index] = lTmp1;
- pl_Alpha[n_State_Index] += d2dna_LogB[n_State_Index][pn_VQed_Feature_Sequence[n_Frame_Index]];
- lTmp1 = lTmp2;
- }
- }
- lTmp1 = MIN_LONG_VALUE;
- for (n_State_Index = 0; n_State_Index < n_State_Num; n_State_Index++)
- {
- if (lTmp1 < pl_Alpha[n_State_Index])
- lTmp1 = pl_Alpha[n_State_Index];
- }
- delete[] pl_Alpha;
- return lTmp1;
- }
- int DHMM_Recog_Forward_Backward_HQ(DHMM_MODEL * pu_DHMM_Model,
- WORD_SAMPLE * pu_Word_Sample,
- double * pd_Max_Likelihood)
- {
- DYNA_2DIM_DOUBLE_ARRAY d2dda_Alpha;
- int n_Frame_Index, n_State_Index;
- int nTmp;
- double dTmp;
- d2dda_Alpha = d2dda_New(pu_Word_Sample->n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- ASSERT(d2dda_Alpha != NULL);
- for (n_Frame_Index = 0; n_Frame_Index < pu_Word_Sample->n_Feature_Sequence_Len; n_Frame_Index++)
- {
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- d2dda_Alpha[n_Frame_Index][n_State_Index] = 0.0F;
- }
- }
- d2dda_Alpha[0][0] = pu_DHMM_Model->d2dda_B[0][pu_Word_Sample->pn_VQed_Feature_Sequence[0]];
- for (n_Frame_Index = 1; n_Frame_Index < pu_Word_Sample->n_Feature_Sequence_Len; n_Frame_Index++)
- {
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- dTmp = 0.0F;
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- dTmp += d2dda_Alpha[n_Frame_Index - 1][nTmp] * pu_DHMM_Model->d2dda_A[nTmp][n_State_Index];
- }
- d2dda_Alpha[n_Frame_Index][n_State_Index] = dTmp * pu_DHMM_Model->d2dda_B[n_State_Index][pu_Word_Sample->pn_VQed_Feature_Sequence[n_Frame_Index]];
- }
- }
- dTmp = 0.0F;
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- dTmp += d2dda_Alpha[pu_Word_Sample->n_Feature_Sequence_Len - 1][n_State_Index];
- }
- (*pd_Max_Likelihood) = log(dTmp);
- d2dda_Free(d2dda_Alpha, pu_Word_Sample->n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- return 0;
- }
- static int DHMM_Model_Calculate_Gamma(WORD_SAMPLE * pu_Word_Sample, DHMM_MODEL * pu_DHMM_Model)
- {
- DYNA_2DIM_DOUBLE_ARRAY d2dda_Alpha;
- DYNA_2DIM_DOUBLE_ARRAY d2dda_Beta;
- double * pd_C;
- int n_Frame_Index, n_State_Index;
- int nTmp;
- double dTmp;
- d2dda_Alpha = d2dda_New(pu_Word_Sample->n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- ASSERT(d2dda_Alpha !=NULL);
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- d2dda_Alpha[0][nTmp] = 0.0F;
- }
- d2dda_Alpha[0][0] = pu_DHMM_Model->d2dda_B[0][pu_Word_Sample->pn_VQed_Feature_Sequence[0]];
- pd_C = new double[pu_Word_Sample->n_Feature_Sequence_Len];
- pd_C[0] = 0.0F;
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- pd_C[0] += d2dda_Alpha[0][nTmp];
- }
- pd_C[0] = 1.0F / pd_C[0];
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- d2dda_Alpha[0][nTmp] *= pd_C[0];
- }
- for (n_Frame_Index = 1; n_Frame_Index < pu_Word_Sample->n_Feature_Sequence_Len; n_Frame_Index++)
- {
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- dTmp = 0.0F;
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- dTmp += d2dda_Alpha[n_Frame_Index - 1][nTmp] * pu_DHMM_Model->d2dda_A[nTmp][n_State_Index];
- }
- d2dda_Alpha[n_Frame_Index][n_State_Index] = dTmp * pu_DHMM_Model->d2dda_B[n_State_Index][pu_Word_Sample->pn_VQed_Feature_Sequence[n_Frame_Index]];
- }
- pd_C[n_Frame_Index] = 0.0F;
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- pd_C[n_Frame_Index] += d2dda_Alpha[n_Frame_Index][nTmp];
- }
- pd_C[n_Frame_Index] = 1.0F / pd_C[n_Frame_Index];
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- d2dda_Alpha[n_Frame_Index][nTmp] *= pd_C[n_Frame_Index];
- }
- }
- d2dda_Beta = d2dda_New(pu_Word_Sample->n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- ASSERT(d2dda_Beta != NULL);
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- d2dda_Beta[pu_Word_Sample->n_Feature_Sequence_Len - 1][nTmp] = pd_C[pu_Word_Sample->n_Feature_Sequence_Len - 1];
- }
- for (n_Frame_Index = pu_Word_Sample->n_Feature_Sequence_Len - 2; n_Frame_Index >= 0; n_Frame_Index--)
- {
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- d2dda_Beta[n_Frame_Index][n_State_Index] = 0.0F;
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- d2dda_Beta[n_Frame_Index][n_State_Index] +=
- d2dda_Beta[n_Frame_Index + 1][nTmp] * pu_DHMM_Model->d2dda_B[nTmp][pu_Word_Sample->pn_VQed_Feature_Sequence[n_Frame_Index + 1]] * pu_DHMM_Model->d2dda_A[n_State_Index][nTmp];
- }
- }
- for (nTmp = 0; nTmp < pu_DHMM_Model->n_State_Num; nTmp++)
- {
- d2dda_Beta[n_Frame_Index][nTmp] *= pd_C[n_Frame_Index];
- }
- }
- for (n_Frame_Index = 0; n_Frame_Index < pu_Word_Sample->n_Feature_Sequence_Len; n_Frame_Index++)
- {
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- pu_Word_Sample->d2dda_Gamma[n_Frame_Index][n_State_Index]
- = d2dda_Alpha[n_Frame_Index][n_State_Index] * d2dda_Beta[n_Frame_Index][n_State_Index];
- }
- dTmp = 0.0F;
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- dTmp += pu_Word_Sample->d2dda_Gamma[n_Frame_Index][n_State_Index];
- }
- for (n_State_Index = 0; n_State_Index < pu_DHMM_Model->n_State_Num; n_State_Index++)
- {
- pu_Word_Sample->d2dda_Gamma[n_Frame_Index][n_State_Index] /= dTmp;
- }
- }
- d2dda_Free(d2dda_Beta, pu_Word_Sample->n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- delete[] pd_C;
- d2dda_Free(d2dda_Alpha, pu_Word_Sample->n_Feature_Sequence_Len, pu_DHMM_Model->n_State_Num);
- return 0;
- }