语音特征参数分析平台(七) HMM模型

五、HMM模型:

HMM是在马尔可夫模型的基础上发展起来的。由于实际问题比Markov链模型所描述的更为复杂,观察到的事件并不是与状态一一对应的,而是通过一组概率分布相联系的,这样的模型成为隐马尔可夫模型(HMM)。它是一个双重的随机过程,其中之一是Markov链,这是基本随机过程,它描述状态的转移概率。另一个随机过程描述状态和观察值之间的统计对应关系。这样站在观察者的角度,只能看到观察值,不像Markov链模型中的观察值状态一一对应,因此不能直接的看到状态,而是通过一个随机过程去感知状态的存在及其特性,因而成为“隐”马尔可夫模型。

具体的HMM的定义可以参见我的论文和https://files.cnblogs.com/chwkai/Hidden%20Markov%20Models.rar,里面涉及了大量的公式,blog比较麻烦。

同样的对HMM模型设计了CHMM类,实现了HMM模型的经典算法

1、CHMM类功能:
1)模型的创建和保存
2)模型的训练
3)DTW语音识别
4)Viterbi识别算法
5)VQ识别算法
6)前后向算法:Forward Backwoard
7)Viterbi算法
8)DTW算法
9)Baum-welch算法

2、CHMM类设计:

  1 //////////////////////////////////////////////////////////////////////////
  2 // 实现基于VQ的HMM模型
  3 // 
  4 // 创建人:        陈文凯
  5 // 创建日期:    2005-06-05
  6 // 修改人:
  7 // 修改日期:
  8 
  9 // 默认状态数
 10 #define CHMM_STATUS_NUMS 6
 11 
 12 // 识别字长度
 13 #define CHMM_WORD_LEN 10
 14 
 15 class CHMM
 16 {
 17 public:
 18     CHMM();
 19     ~CHMM(void);
 20 
 21 public:
 22     // 导入HMM模型信息
 23     BOOL LoadModel(CString strFileName);
 24     // 导出HMM模型信息
 25     BOOL SaveModel(CString strFileName);
 26     // 释放模型占用资源
 27     void Dispose();
 28 
 29     // 获取对应的词
 30     inline CString GetWord() const
 31     {
 32         return this->m_strWord;
 33     }
 34 
 35     // 实现对HMM模型的迭代训练
 36     void Train(
 37         const double* pDataIn,        // 输入采样序列
 38         unsigned int nInLen            // 输入采样序列长度
 39         );
 40 
 41     // 实现对HMM模型得初始化
 42     void PrepareTrain(
 43         CString strWord,                // 模型对应词
 44         const double* pDataIn,            // 第一个输入采样序列
 45         unsigned int nInLen,            // 输入采样序列长度
 46         unsigned int nFrameSize,        // 分帧宽度
 47         unsigned int nStatusNums = 6,    // HMM状态数
 48         unsigned int nCodeNums = 4        // 输入码本长度
 49         );
 50 
 51     // 基于DTW的Vertibi实现对HMM模型的识别
 52     static CString RecogonizeByDTW(
 53         const double* pCodeBook,    // 输入码本
 54         unsigned int nCodeNums,        // 输入码本长度
 55         CString* strModelList,        // 模型文件路径
 56         unsigned int nModelCount    // 模型数量
 57         );
 58 
 59     // 基于Vertibi算法实现对HMM模型的识别
 60     static CString RecogonizeByViterbi(
 61         const double* pCodeBook,    // 输入码本
 62         unsigned int nCodeNums,        // 输入码本长度
 63         CString* strModelList,        // 模型文件路径
 64         unsigned int nModelCount    // 模型数量
 65         );
 66 
 67     // 基于VQ实现对HMM模型的识别
 68     static CString RecogonizeByVQ(
 69         const double* pCodeBook,    // 输入码本
 70         unsigned int nCodeNums,        // 输入码本长度
 71         CString* strModelList,        // 模型文件路径
 72         unsigned int nModelCount    // 模型数量
 73         );
 74 
 75 private:
 76     // 实现前后向算法,并输出最大概率
 77     double ForwardBackward(
 78         const unsigned int* pCodeBook,    // 输入观察码本序列对应的HMM码本的下标
 79         unsigned int nCodeNums,            // 输入观察序列长度
 80         const double* pPi,                // HMM的pi矢量
 81         const double* pA,                // HMM的A矩阵
 82         const double* pB,                // HMM的B矩阵
 83         unsigned int nStatusNums,        // HMM状态数
 84         double* pa,                        // 前后向算法中的a
 85         double* pb                        // 前后向算法中的b
 86         );
 87 
 88     // 实现Viterbi算法
 89     double Viterbi(
 90         const unsigned int* pCodeBook,    // 输入观察码本序列对应的HMM码本的下标
 91         unsigned int nCodeNums,            // 输入观察序列长度
 92         const double* pPi,                // HMM的pi矢量
 93         const double* pA,                // HMM的A矩阵
 94         const double* pB,                // HMM的B矩阵
 95         unsigned int nStatusNums        // HMM状态数
 96         );
 97 
 98     // 实现基于DTW的Viterbi算法
 99     double DTW(
100         const unsigned int* pCodeBook,    // 输入观察码本序列对应的HMM码本的下标
101         unsigned int nCodeNums,            // 输入观察序列长度
102         double* pA,                        // HMM的A矩阵
103         double* pB,                        // HMM的B矩阵
104         unsigned int nStatusNums        // HMM状态数
105         );
106 
107     // 实现Baum-Welch算法
108     void BaumWelch(
109         const unsigned int* pCodeBook,    // 输入观察码本序列对应的HMM码本的下标
110         unsigned int nCodeNums,            // 输入观察序列长度
111         double* pPi,                    // HMM的pi矢量
112         double* pA,                        // HMM的A矩阵
113         double* pB,                        // HMM的B矩阵
114         unsigned int nStatusNums,        // HMM状态数
115         double* pa,                        // 前后向算法计算所得的pa
116         double* pb,                        // 前后向算法计算所得pb
117         double fRate                    // 前后向算法计算所得最大概率
118         );
119 
120 public:
121     double* m_pPi;                    // 初始状态分布序列,t=1时间时q1 = Si的概率pi
122     double* m_pA;                    // 状态转移概率矩阵,由q(i-1)为s(k)转移到q(i)为s(h)的概率
123     double* m_pB;                    // 观察矢量处于某状态的概率
124     double* m_pCodeBook;            // 码本
125     
126     unsigned int m_nStatusNums;        // HMM状态数量
127     unsigned int m_nCodeNums;        // 输入码本长度
128     CString m_strWord;                // 模型对应的词
129     unsigned int m_nFrameSize;        // 求倒谱时所进行的短时快速FFT的短时点数
130 };


3、数字HMM模型的创建和训练过程:
1)输入LPC码本
2)是否初次训练?是,转3);否则转4)
3)调用CHMM::PrepareTrainning函数,初始化模型参数,转5)
4)调用CHMM::LoadModel函数,载入相应的HMM模板
5)调用CHMM::Train函数,进行模型训练:Train函数中调用了BF,Baum-welch和Viterbi算法
6)调用CHMM::SaveModel保存训练模板

posted @ 2005-08-01 22:05  海南K.K  阅读(3211)  评论(0)    收藏  举报