⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhmm_gl.cpp

📁 语音识别配套的VQ及DHMM模型训练程序(C语言)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			}	// end of: for(k=1; k<T[m]; k++)
			
			// 最后一帧状态为吸收态,即只有最后一个状态概率不为0,其余状态概率均为0
			if(End_state_mode & ENDSTATE_ABSORB)						// End_state_mode是在RECOG.CPP中根据用户输入确定的
			{
				for(i=0; i<n-1; i++) Alpha[m][ T[m]-1 ][i] = 0;
				Belta[m][ T[m]-1 ][n-1] = Ct[m][ T[m]-1 ];
				for(i=0; i<n-1; i++) Belta[m][ T[m]-1 ][i] = 0;
			}
			else
			{
				for(i=0; i<n; i++) Belta[m][ T[m]-1 ][i] = Ct[m][ T[m]-1 ];
			}
			
			// 计算Belta
			for(k=T[m]-2; k>=0; k--)
				for(i=0; i<n; i++)
				{
					w = 0;
					for(j=0; j<n; j++)
						w = w + A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
					Belta[m][k][i] = w * Ct[m][k];
				}
		}
	}
	
	// Re-estimate A[i][j], i = 0 to n-1, j = 0 to n-1.
	
	/*  if((mode == REESTIMATE_A) || (mode == REESTIMATE_ALL))
	{
	for(i=0; i<n; i++)
	for(j=0; j<n; j++)
	New_A[i][j] = 0;
	
	  for(m=0; m<Sample_num; m++)
	  {
	  w = 0;
	  for(i=0; i<n; i++)
	  w += Alpha[m][T[m]-1][i];
	  
		for(k=0; k<T[m]-1; k++)
		{
		
		  for(i=0; i<n; i++)
		  for(j=0; j<n; j++)
		  {
		  w1 = Alpha[m][k][i] * A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
		  w1 /= w;
		  New_A[i][j] += w1;
		  }
		  }
		  }
		  
			for(i=0; i<n; i++)
			{
			for(j=0; j<n; j++)
			if((j < i) || (j > (i+1)))
			New_A[i][j] = 0;
			
			  w = 0;
			  for(j=0; j<n; j++) w += New_A[i][j];
			  for(j=0; j<n; j++) New_A[i][j] /= w;
			  
				for(j=0; j<n; j++)
				if((j < i) || (j > (i+1)) && (New_A[i][j] < Epsilon_A))
				New_A[i][j] = Epsilon_A;
				
				  w = 0;
				  for(j=0; j<n; j++) w += New_A[i][j];
				  for(j=0; j<n; j++) New_A[i][j] /= w;
				  }
				  
					for(i=0; i<n; i++)
					for(j=0; j<n; j++)
					A[i][j] = New_A[i][j];
   }*/
   
   // Re-estimate B[i][j], i = 0 to n-1, j = 0 to m-1.
   
   if((mode == REESTIMATE_B) || (mode == REESTIMATE_ALL))
   {
		   // clear new B matrix
			for(i=0; i<n; i++)
				for(j=0; j<Output_num; j++)
					New_B[i][j] = 0;
				   
			for(m=1; m<Sample_num; m++)
			{
				w = 0;
				for(i=0; i<n; i++)
					if (T[m] > 0)    // add by wd @ 030331z
						w += Alpha[m][T[m]-1][i];							// w: 观察序列概率,即P(O)
				   
				// reestimate matrix B
				for(k=0; k<T[m]; k++)
					for(i=0; i<n; i++)
					{
						New_B[i][Out[m][k]] += Alpha[m][k][i] * Belta[m][k][i] /
							Ct[m][k] / w;
					}
			}
			   
			for(i=0; i<n; i++)
			{
				w = 0;
				for(j=0; j<Output_num; j++) w += New_B[i][j];
				for(j=0; j<Output_num; j++)
				{
					New_B[i][j] /= w;		// 归一化
				}

				for(j=0; j<Output_num; j++)
					if(New_B[i][j] < Epsilon_B)						// Epsilon_B=1.0e-6
						New_B[i][j] = Epsilon_B;
					   
					w = 0;
					for(j=0; j<Output_num; j++) w += New_B[i][j];
					for(j=0; j<Output_num; j++) New_B[i][j] /= w;		// 归一化

			}
			   
			for(i=0; i<n; i++)									// 更新B矩阵
				for(j=0; j<Output_num; j++)
					B[i][j] = New_B[i][j];

   }
   
   Residue = 0;
   for(m=0; m<Sample_num; m++)
	   if(T[m] > 0)		// add by wd @ 030331
			Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);
   	   /*if (T[m] > 0)
	   {
		   Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);
	   }
	   else
		   Residue += -10;			*/
   
   for(i=0; i<n; i++) delete New_A[i];
   delete New_A;
   
   for(i=0; i<n; i++) delete New_B[i];
   delete New_B;
   
   for(i=0; i<Sample_num; i++) delete Ct[i];
   delete Ct;
   
   return Residue;
}

static double DHMM_Priority(double *Pi, double **A, double **B, int *Out, int T, int n, int mode)

// input:
// 			Pi				初始概率
//			A				A矩阵
//			B				B矩阵
//			Out				训练集中第m个说话人的观察序列
//			T				训练集中第m个说话人的观察序列帧数
//			n				状态数
//			mode

// return value:
//			logP(o1,o2,...,oT|Pi,A,B)

//caller(r_dhmm.cpp):	Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);

{
	int   i, j, k;
	double  w, p;
	double  *Alpha1;
	double  *Alpha2;
	
	if((Alpha1 = new double [n]) == NULL) { DEBUG_PRINTF("Not enough memory for !\n"); ASSERT(0); }
	if((Alpha2 = new double [n]) == NULL) { DEBUG_PRINTF("Not enough memory for !\n"); ASSERT(0); }
	
	p = 0;
	w = 0;
	for(i=0; i<n; i++)
	{
		Alpha1[i] = Pi[i] * B[i][ Out[0] ];
		w += Alpha1[i];
	}
	for(i=0; i<n; i++) Alpha1[i] /= w;
	p += log(w);
	
	for(k=1; k<T; k++)
	{
		for(i=0; i<n; i++)
		{
			w = 0;
			for(j=0; j<n; j++)
				w = w + Alpha1[j] * A[j][i];
			w = w * B[i][ Out[k] ];
			Alpha2[i] = w;
		}
		
		if(k < T-1)
		{
			w = 0;
			for(i=0; i<n; i++) w += Alpha2[i];
			for(i=0; i<n; i++) Alpha1[i] = Alpha2[i] / w;
			p += log(w);
		}
	}
	
	if(mode & ENDSTATE_ABSORB)
	{
		p += log(Alpha2[n-1]);
	}
	else
	{
		w = 0;
		for(i=0; i<n; i++) w += Alpha2[i];
		p += log(w);
	}
	
	delete Alpha1;
	delete Alpha2;
	
	return p;
}

static double DHMM_Calculate(double ***Alpha, double ***Belta, double *Pi, double **A,
							 double **B, int Out[140][150], int Sample_num, int Output_num, int *T,
							 int n, int mode, int End_state_mode, WORD_SAMPLE * DMAD_pu_Word_Sample)
// 功能:训练某一词条的模型

// input:
//			Pi				初始时刻各状态的概率
//			Alpha			前向概率
//			Belta			后向概率
//			A				初始A矩阵
//			B				初始B矩阵
//			Out				用于训练的各句子的观察序列(输出序列)
//			Sample_num		训练集人数
//			Output_num		VQ码本大小(码字数,即观察值的个数)
//			T				用于训练的各句子的帧数
//			n				状态数
//			mode			训练模式(REESTIMATE_A, REESTIMATE_B, REESTIMATE_ALL)
//			End_state_mode	结尾帧状态模式(ENDSTATE_ABSORB = 0x200)

// output:
//			A
//			B

// caller(r_dhmm.cpp):	u = DHMM_Calculate(Alpha, Belta, Pi, A, B, Output, Train_num, Output_num,
//					      Frame_num, Status_num, REESTIMATE_ALL, mode);
							 
{
	int    i, j, k, m;
	double w;
	double **New_A;
	double **New_B;
	double **Ct;					// to prevent underflow of Alpha and Belta, Ct is the scaling coefficient
	double Residue;
	
	if((New_A = new double *[n]) == NULL)
	{
		DEBUG_PRINTF("Not enough memory for New_A !\n");
		ASSERT(0);
	}
	for(i=0; i<n; i++)
	{
		if((New_A[i] = new double [n]) == NULL)
		{
			DEBUG_PRINTF("Not enough memory for New_A[%d] !\n", i);
			ASSERT(0);
		}
	}
	
	if((New_B = new double *[n]) == NULL)
	{
		DEBUG_PRINTF("Not enough memory for New_B !\n");
		ASSERT(0);
	}
	for(i=0; i<n; i++)
	{
		if((New_B[i] = new double [Output_num]) == NULL)
		{
			DEBUG_PRINTF("Not enough memory for New_B[%d] !\n", i);
			ASSERT(0);
		}
	}

	if((Ct = new double *[Sample_num]) == NULL)
	{
		DEBUG_PRINTF("Not enough memory for Ct !\n");
		ASSERT(0);
	}
	for(i=0; i<Sample_num; i++)
		if((Ct[i] = new double [T[i]]) == NULL)
		{
			DEBUG_PRINTF("Not enough memory for Ct[%d] !\n", i);
			ASSERT(0);
		}
		
	// Calculate Alpha & Belta.
	
	for(m=0; m<Sample_num; m++)
	{
		w = 0;
		for(i=0; i<n; i++)
		{
			Alpha[m][0][i] = Pi[i] * B[i][ DMAD_pu_Word_Sample[m].pn_VQed_Feature_Sequence[i] ];
			w = w + Alpha[m][0][i];
		}
		Ct[m][0] = 1.0 / w;							// scaling coefficient
		for(i=0; i<n; i++)
			Alpha[m][0][i] = Alpha[m][0][i] * Ct[m][0];	// scaling
		
		// 计算Alpha
		for(k=1; k<T[m]; k++)							// 第m个训练utterance的各帧
		{
			Ct[m][k] = 0;
			for(i=0; i<n; i++)
			{
				w = 0;
				for(j=0; j<n; j++)
					w = w + Alpha[m][k-1][j] * A[j][i];
				w = w * B[i][ Out[m][k] ];
				Alpha[m][k][i] = w;
				Ct[m][k] = Ct[m][k] + w;
			}
			Ct[m][k] = 1.0 / Ct[m][k];
			for(i=0; i<n; i++)
				Alpha[m][k][i] = Alpha[m][k][i] * Ct[m][k];
		}	// end of: for(k=1; k<T[m]; k++)
		
		// 最后一帧状态为吸收态,即只有最后一个状态概率不为0,其余状态概率均为0
		if(End_state_mode & ENDSTATE_ABSORB)						// End_state_mode是在RECOG.CPP中根据用户输入确定的
		{
			for(i=0; i<n-1; i++) Alpha[m][ T[m]-1 ][i] = 0;
			Belta[m][ T[m]-1 ][n-1] = Ct[m][ T[m]-1 ];
			for(i=0; i<n-1; i++) Belta[m][ T[m]-1 ][i] = 0;
		}
		else
		{
			for(i=0; i<n; i++) Belta[m][ T[m]-1 ][i] = Ct[m][ T[m]-1 ];
		}
		
		// 计算Belta
		for(k=T[m]-2; k>=0; k--)
			for(i=0; i<n; i++)
			{
				w = 0;
				for(j=0; j<n; j++)
					w = w + A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
				Belta[m][k][i] = w * Ct[m][k];
			}
	}
	
	// Re-estimate A[i][j], i = 0 to n-1, j = 0 to n-1.
	
	/*  if((mode == REESTIMATE_A) || (mode == REESTIMATE_ALL))
	{
	for(i=0; i<n; i++)
	for(j=0; j<n; j++)
	New_A[i][j] = 0;
	
	  for(m=0; m<Sample_num; m++)
	  {
	  w = 0;
	  for(i=0; i<n; i++)
	  w += Alpha[m][T[m]-1][i];
	  
		for(k=0; k<T[m]-1; k++)
		{
		
		  for(i=0; i<n; i++)
		  for(j=0; j<n; j++)
		  {
		  w1 = Alpha[m][k][i] * A[i][j] * B[j][ Out[m][k+1] ] * Belta[m][k+1][j];
		  w1 /= w;
		  New_A[i][j] += w1;
		  }
		  }
		  }
		  
			for(i=0; i<n; i++)
			{
			for(j=0; j<n; j++)
			if((j < i) || (j > (i+1)))
			New_A[i][j] = 0;
			
			  w = 0;
			  for(j=0; j<n; j++) w += New_A[i][j];
			  for(j=0; j<n; j++) New_A[i][j] /= w;
			  
				for(j=0; j<n; j++)
				if((j < i) || (j > (i+1)) && (New_A[i][j] < Epsilon_A))
				New_A[i][j] = Epsilon_A;
				
				  w = 0;
				  for(j=0; j<n; j++) w += New_A[i][j];
				  for(j=0; j<n; j++) New_A[i][j] /= w;
				  }
				  
					for(i=0; i<n; i++)
					for(j=0; j<n; j++)
					A[i][j] = New_A[i][j];
   }*/
   
   // Re-estimate B[i][j], i = 0 to n-1, j = 0 to m-1.
   
   if((mode == REESTIMATE_B) || (mode == REESTIMATE_ALL))
   {
	   // clear new B matrix
	   for(i=0; i<n; i++)
		   for(j=0; j<Output_num; j++)
			   New_B[i][j] = 0;
		   
		   for(m=1; m<Sample_num; m++)
		   {
			   w = 0;
			   for(i=0; i<n; i++)
				   w += Alpha[m][T[m]-1][i];							// w: 观察序列概率,即P(O)
			   
			   // reestimate matrix B
			   for(k=0; k<T[m]; k++)
				   for(i=0; i<n; i++)
				   {
					   New_B[i][Out[m][k]] += Alpha[m][k][i] * Belta[m][k][i] /
						   Ct[m][k] / w;
				   }
		   }
		   
		   for(i=0; i<n; i++)
		   {
			   w = 0;
			   for(j=0; j<Output_num; j++) w += New_B[i][j];
			   for(j=0; j<Output_num; j++)
			   {
				   New_B[i][j] /= w;		// 归一化
			   }

			   for(j=0; j<Output_num; j++)
				   if(New_B[i][j] < Epsilon_B)						// Epsilon_B=1.0e-6
					   New_B[i][j] = Epsilon_B;
				   
				   w = 0;
				   for(j=0; j<Output_num; j++) w += New_B[i][j];
				   for(j=0; j<Output_num; j++) New_B[i][j] /= w;		// 归一化

		   }
		   
		   for(i=0; i<n; i++)									// 更新B矩阵
			   for(j=0; j<Output_num; j++)
				   B[i][j] = New_B[i][j];
   }
   
   Residue = 0;
   for(m=1; m<Sample_num; m++)
	   Residue += DHMM_Priority(Pi, A, B, Out[m], T[m], n, End_state_mode);
   
   for(i=0; i<n; i++) delete New_A[i];
   delete New_A;
   
   for(i=0; i<n; i++) delete New_B[i];
   delete New_B;
   
   for(i=0; i<Sample_num; i++) delete Ct[i];
   delete Ct;
   
   return Residue;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -