開發(fā)工具:
Visual Studio v2010
.NET Framework 4 Client Profile
版本歷史:
V1.1 2011年06月09日
- 修正UMDHMM在Baum-Welch算法中存在的模型參數(shù)調(diào)整錯(cuò)誤。
?
V1.0 2011年06月08日
- 將C語言實(shí)現(xiàn)的隱馬爾科夫模型算法(UMDHMM)改為C#語言實(shí)現(xiàn)。
功能描述:
- 前向算法(forward algorithm):給定HMM求一個(gè)觀察序列的概率(評估)
- 后向算法(backward algorithm):給定HMM求一個(gè)觀察序列的概率(評估)
- 前向-后向算法(forward-backward algorithm):根據(jù)觀察序列生成隱馬爾科夫模型(學(xué)習(xí))
- 維特比算法(Viterbi algorithm):搜索最有可能生成一個(gè)觀察序列的隱藏狀態(tài)序列(解碼)
下載地址:
隱馬爾科夫模型.zip
源代碼:
HMM.cs(類構(gòu)造函數(shù))
[c-sharp] view plaincopyprint?
??????????????????????????using?System;????namespace?Splash??{??????public?partial?class?HMM??????{????????????????????????????????????????public?readonly?Int32?N;??????????????????????????????????????????public?readonly?Int32?M;???????????????????????????????????????????public?Double[,]??A;??????????????????????????????????????????public?Double[,]??B;??????????????????????????????????????????public?Double[]???PI;?????????????????????????????????????????? ????????????????????public?HMM(Int32?StatesNum,?Int32?ObservationSymbolsNum)??????????{??????????????N?=?StatesNum;?????????????? ??????????????M?=?ObservationSymbolsNum;??????????????????A?=?new?Double[N,?N];?????????????????B?=?new?Double[N,?M];?????????????????PI?=?new?Double[N];???????????????}??????????????}??}??
/* ----------------------------------------------------------
文件名稱:HMM.cs作者:秦建輝MSN:splashcn@msn.com
QQ:36748897版本歷史:V1.1 2011年06月09日修正UMDHMM在Baum-Welch算法中存在的模型參數(shù)調(diào)整錯(cuò)誤。V1.0 2011年06月08日將C語言實(shí)現(xiàn)的隱馬爾科夫模型算法(UMDHMM)改為C#語言實(shí)現(xiàn)。功能描述:1.前向算法(forward algorithm):給定HMM求一個(gè)觀察序列的概率(評估)2.后向算法(backward algorithm):給定HMM求一個(gè)觀察序列的概率(評估)3.前向-后向算法(forward-backward algorithm):根據(jù)觀察序列生成隱馬爾科夫模型(學(xué)習(xí))4.維特比算法(Viterbi algorithm):搜索最有可能生成一個(gè)觀察序列的隱藏狀態(tài)序列(解碼)參考資料:C代碼:http://www.kanungo.com/software/umdhmm-v1.02.zip學(xué)習(xí)資料:http://www.52nlp.cn/category/hidden-markov-model------------------------------------------------------------ */
using System;namespace Splash
{public partial class HMM{/// <summary>/// 隱藏狀態(tài)數(shù)目 N/// </summary>public readonly Int32 N;/// <summary>/// 觀察符號數(shù)目 M/// </summary>public readonly Int32 M; /// <summary>/// 狀態(tài)轉(zhuǎn)移矩陣 A/// </summary>public Double[,] A;/// <summary>/// 混淆矩陣(confusion matrix)B/// </summary>public Double[,] B;/// <summary>/// 初始概率向量 PI/// </summary>public Double[] PI;/// <summary>/// 構(gòu)造函數(shù)/// </summary>/// <param name="StatesNum">隱藏狀態(tài)數(shù)目</param>/// <param name="ObservationSymbolsNum">觀察符號數(shù)目</param>public HMM(Int32 StatesNum, Int32 ObservationSymbolsNum){N = StatesNum; // 隱藏狀態(tài)數(shù)目M = ObservationSymbolsNum; // 觀察符號數(shù)目A = new Double[N, N]; // 狀態(tài)轉(zhuǎn)移矩陣B = new Double[N, M]; // 混淆矩陣 PI = new Double[N]; // 初始概率向量} }
}
Viterbi.cs(維特比算法)
[c-sharp] view plaincopyprint?
using?System;????namespace?Splash??{??????partial?class?HMM??????{??????????????????????????????????????????????????????????????????????????????????????????public?Int32[]?Viterbi(Int32[]?OB,?out?Double?Probability)??????????{??????????????Double[,]?DELTA;??????????????Int32[,]?PSI;????????????????return?Viterbi(OB,?out?DELTA,?out?PSI,?out?Probability);??????????}??????????????????????????????????????????????????????????????????????????????????????????????????????public?Int32[]?Viterbi(Int32[]?OB,?out?Double[,]?DELTA,?out?Int32[,]?PSI,?out?Double?Probability)??????????{??????????????????????????DELTA?=?new?Double[OB.Length,?N];?????????????????PSI?=?new?Int32[OB.Length,?N];????????????????????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????{??????????????????DELTA[0,?j]?=?PI[j]?*?B[j,?OB[0]];??????????????}??????????????????????????????for?(Int32?t?=?1;?t?<?OB.Length;?t++)??????????????{??????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????Double?MaxValue?=?DELTA[t?-?1,?0]?*?A[0,?j];??????????????????????Int32?MaxValueIndex?=?0;??????????????????????for?(Int32?i?=?1;?i?<?N;?i++)??????????????????????{??????????????????????????Double?Value?=?DELTA[t?-?1,?i]?*?A[i,?j];??????????????????????????if?(Value?>?MaxValue)??????????????????????????{??????????????????????????????MaxValue?=?Value;??????????????????????????????MaxValueIndex?=?i;??????????????????????????}??????????????????????}????????????????????????DELTA[t,?j]?=?MaxValue?*?B[j,?OB[t]];??????????????????????PSI[t,?j]?=?MaxValueIndex;???????????????????}??????????????}??????????????????????????????Int32[]?Q?=?new?Int32[OB.Length];?????????????????Probability?=?DELTA[OB.Length?-?1,?0];??????????????Q[OB.Length?-?1]?=?0;??????????????for?(Int32?i?=?1;?i?<?N;?i++)??????????????{??????????????????if?(DELTA[OB.Length?-?1,?i]?>?Probability)??????????????????{??????????????????????Probability?=?DELTA[OB.Length?-?1,?i];??????????????????????Q[OB.Length?-?1]?=?i;??????????????????}??????????????}??????????????????????????????for?(Int32?t?=?OB.Length?-?2;?t?>=?0;?t--)??????????????{??????????????????Q[t]?=?PSI[t?+?1,?Q[t?+?1]];??????????????}????????????????return?Q;??????????}??????????????????????????????????????????????????????????????????????????????????public?Int32[]?ViterbiLog(Int32[]?OB,?out?Double?Probability)??????????{??????????????Double[,]?DELTA;??????????????Int32[,]?PSI;??????????????????return?ViterbiLog(OB,?out?DELTA,?out?PSI,?out?Probability);??????????}??????????????????????????????????????????????????????????????????????????????????????????????????????public?Int32[]?ViterbiLog(Int32[]?OB,?out?Double[,]?DELTA,?out?Int32[,]?PSI,?out?Double?Probability)??????????{??????????????????????????DELTA?=?new?Double[OB.Length,?N];?????????????????PSI?=?new?Int32[OB.Length,?N];????????????????????????????????????Double[,]?LogA?=?new?Double[N,?N];??????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????{??????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????LogA[i,?j]?=?Math.Log(A[i,?j]);??????????????????}??????????????}????????????????Double[,]?LogBIOT?=?new?Double[N,?OB.Length];??????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????{??????????????????for?(Int32?t?=?0;?t?<?OB.Length;?t++)??????????????????{??????????????????????LogBIOT[i,?t]?=?Math.Log(B[i,?OB[t]]);??????????????????}??????????????}????????????????Double[]?LogPI?=?new?Double[N];??????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????{??????????????????LogPI[i]?=?Math.Log(PI[i]);??????????????}??????????????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????{??????????????????DELTA[0,?j]?=?LogPI[j]?+?LogBIOT[j,?0];??????????????}??????????????????????????????for?(Int32?t?=?1;?t?<?OB.Length;?t++)??????????????{??????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????Double?MaxValue?=?DELTA[t?-?1,?0]?+?LogA[0,?j];??????????????????????Int32?MaxValueIndex?=?0;??????????????????????for?(Int32?i?=?1;?i?<?N;?i++)??????????????????????{??????????????????????????Double?Value?=?DELTA[t?-?1,?i]?+?LogA[i,?j];??????????????????????????if?(Value?>?MaxValue)??????????????????????????{??????????????????????????????MaxValue?=?Value;??????????????????????????????MaxValueIndex?=?i;??????????????????????????}??????????????????????}????????????????????????DELTA[t,?j]?=?MaxValue?+?LogBIOT[j,?t];??????????????????????PSI[t,?j]?=?MaxValueIndex;???????????????????}??????????????}??????????????????????????????Int32[]?Q?=?new?Int32[OB.Length];?????????????????Probability?=?DELTA[OB.Length?-?1,?0];??????????????Q[OB.Length?-?1]?=?0;??????????????for?(Int32?i?=?1;?i?<?N;?i++)??????????????{??????????????????if?(DELTA[OB.Length?-?1,?i]?>?Probability)??????????????????{??????????????????????Probability?=?DELTA[OB.Length?-?1,?i];??????????????????????Q[OB.Length?-?1]?=?i;??????????????????}??????????????}??????????????????????????????Probability?=?Math.Exp(Probability);??????????????for?(Int32?t?=?OB.Length?-?2;?t?>=?0;?t--)??????????????{??????????????????Q[t]?=?PSI[t?+?1,?Q[t?+?1]];??????????????}????????????????return?Q;??????????}??????}??}??
using System;namespace Splash
{partial class HMM{/// <summary>/// 維特比算法:通過給定的觀察序列,推算出可能性最大的隱藏狀態(tài)序列/// Viterbi Algorithm: Finding most probable sequence of hidden states/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="Probability">可能性最大的隱藏狀態(tài)序列的概率</param>/// <returns>可能性最大的隱藏狀態(tài)序列</returns>/// <remarks>使用雙精度運(yùn)算,不輸出中間結(jié)果</remarks>public Int32[] Viterbi(Int32[] OB, out Double Probability){Double[,] DELTA;Int32[,] PSI;return Viterbi(OB, out DELTA, out PSI, out Probability);}/// <summary>/// 維特比算法:通過給定的觀察序列,推算出可能性最大的隱藏狀態(tài)序列/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="DELTA">輸出中間結(jié)果:局部最大概率</param>/// <param name="PSI">輸出中間結(jié)果:反向指針指示最可能路徑</param>/// <param name="Probability">可能性最大的隱藏狀態(tài)序列的概率</param>/// <returns>可能性最大的隱藏狀態(tài)序列</returns> /// <remarks>使用雙精度運(yùn)算,且輸出中間結(jié)果</remarks>public Int32[] Viterbi(Int32[] OB, out Double[,] DELTA, out Int32[,] PSI, out Double Probability){ DELTA = new Double[OB.Length, N]; // 局部概率PSI = new Int32[OB.Length, N]; // 反向指針// 1. 初始化for (Int32 j = 0; j < N; j++){DELTA[0, j] = PI[j] * B[j, OB[0]];}// 2. 遞歸for (Int32 t = 1; t < OB.Length; t++){for (Int32 j = 0; j < N; j++){Double MaxValue = DELTA[t - 1, 0] * A[0, j];Int32 MaxValueIndex = 0;for (Int32 i = 1; i < N; i++){Double Value = DELTA[t - 1, i] * A[i, j];if (Value > MaxValue){MaxValue = Value;MaxValueIndex = i;}}DELTA[t, j] = MaxValue * B[j, OB[t]];PSI[t, j] = MaxValueIndex; // 記錄下最有可能到達(dá)此狀態(tài)的上一個(gè)狀態(tài)}}// 3. 終止Int32[] Q = new Int32[OB.Length]; // 定義最佳路徑Probability = DELTA[OB.Length - 1, 0];Q[OB.Length - 1] = 0;for (Int32 i = 1; i < N; i++){if (DELTA[OB.Length - 1, i] > Probability){Probability = DELTA[OB.Length - 1, i];Q[OB.Length - 1] = i;}}// 4. 路徑回溯for (Int32 t = OB.Length - 2; t >= 0; t--){Q[t] = PSI[t + 1, Q[t + 1]];}return Q;}/// <summary>/// 維特比算法:通過給定的觀察序列,推算出可能性最大的隱藏狀態(tài)序列/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="Probability">可能性最大的隱藏狀態(tài)序列的概率</param>/// <returns>可能性最大的隱藏狀態(tài)序列</returns>/// <remarks>使用對數(shù)運(yùn)算,不輸出中間結(jié)果</remarks>public Int32[] ViterbiLog(Int32[] OB, out Double Probability){Double[,] DELTA;Int32[,] PSI; return ViterbiLog(OB, out DELTA, out PSI, out Probability);}/// <summary>/// 維特比算法:通過給定的觀察序列,推算出可能性最大的隱藏狀態(tài)序列/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="DELTA">輸出中間結(jié)果:局部最大概率。結(jié)果為自然對數(shù)值</param>/// <param name="PSI">輸出中間結(jié)果:反向指針指示最可能路徑</param>/// <param name="Probability">可能性最大的隱藏狀態(tài)序列的概率</param>/// <returns>可能性最大的隱藏狀態(tài)序列</returns> /// <remarks>使用對數(shù)運(yùn)算,且輸出中間結(jié)果</remarks>public Int32[] ViterbiLog(Int32[] OB, out Double[,] DELTA, out Int32[,] PSI, out Double Probability){ DELTA = new Double[OB.Length, N]; // 局部概率PSI = new Int32[OB.Length, N]; // 反向指針// 0. 預(yù)處理Double[,] LogA = new Double[N, N];for (Int32 i = 0; i < N; i++){for (Int32 j = 0; j < N; j++){LogA[i, j] = Math.Log(A[i, j]);}}Double[,] LogBIOT = new Double[N, OB.Length];for (Int32 i = 0; i < N; i++){for (Int32 t = 0; t < OB.Length; t++){LogBIOT[i, t] = Math.Log(B[i, OB[t]]);}}Double[] LogPI = new Double[N];for (Int32 i = 0; i < N; i++){LogPI[i] = Math.Log(PI[i]);}// 1. 初始化for (Int32 j = 0; j < N; j++){DELTA[0, j] = LogPI[j] + LogBIOT[j, 0];}// 2. 遞歸for (Int32 t = 1; t < OB.Length; t++){for (Int32 j = 0; j < N; j++){Double MaxValue = DELTA[t - 1, 0] + LogA[0, j];Int32 MaxValueIndex = 0;for (Int32 i = 1; i < N; i++){Double Value = DELTA[t - 1, i] + LogA[i, j];if (Value > MaxValue){MaxValue = Value;MaxValueIndex = i;}}DELTA[t, j] = MaxValue + LogBIOT[j, t];PSI[t, j] = MaxValueIndex; // 記錄下最有可能到達(dá)此狀態(tài)的上一個(gè)狀態(tài)}}// 3. 終止Int32[] Q = new Int32[OB.Length]; // 定義最佳路徑Probability = DELTA[OB.Length - 1, 0];Q[OB.Length - 1] = 0;for (Int32 i = 1; i < N; i++){if (DELTA[OB.Length - 1, i] > Probability){Probability = DELTA[OB.Length - 1, i];Q[OB.Length - 1] = i;}}// 4. 路徑回溯Probability = Math.Exp(Probability);for (Int32 t = OB.Length - 2; t >= 0; t--){Q[t] = PSI[t + 1, Q[t + 1]];}return Q;}}
}
Forward.cs(前向算法)
[c-sharp] view plaincopyprint?
using?System;????namespace?Splash??{??????partial?class?HMM??????{????????????????????????????????????????????????????????????????????????????????public?Double?Forward(Int32[]?OB)??????????{??????????????Double[,]?ALPHA;????????????????????return?Forward(OB,?out?ALPHA);??????????}??????????????????????????????????????????????????????????????????????????????????public?Double?Forward(Int32[]?OB,?out?Double[,]?ALPHA)??????????{??????????????????????????ALPHA?=?new?Double[OB.Length,?N];?????????????????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????{??????????????????ALPHA[0,?j]?=?PI[j]?*?B[j,?OB[0]];??????????????}??????????????????????????????for?(Int32?t?=?1;?t?<?OB.Length;?t++)??????????????{??????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????Double?Sum?=?0;??????????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????????{??????????????????????????Sum?+=?ALPHA[t?-?1,?i]?*?A[i,?j];??????????????????????}????????????????????????ALPHA[t,?j]?=?Sum?*?B[j,?OB[t]];??????????????????}??????????????}???????????????? ??????????????Double?Probability?=?0;??????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????{??????????????????Probability?+=?ALPHA[OB.Length?-?1,?i];??????????????}????????????????return?Probability;??????????}?????????????????????????????????????????????????????????????? ????????????????????private?Double?ForwardWithScale(Int32[]?OB,?ref?Double[,]?ALPHA,?ref?Double[]?SCALE)??????????{??????????????if(ALPHA?==?null)?ALPHA?=?new?Double[OB.Length,?N];??????????????if(SCALE?==?null)?SCALE?=?new?Double[OB.Length];??????????????????????????????SCALE[0]?=?0;??????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????{??????????????????ALPHA[0,?j]?=?PI[j]?*?B[j,?OB[0]];??????????????????SCALE[0]?+=?ALPHA[0,?j];??????????????}????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????{??????????????????ALPHA[0,?j]?/=?SCALE[0];??????????????}??????????????????????????????for?(Int32?t?=?1;?t?<?OB.Length;?t++)??????????????{??????????????????SCALE[t]?=?0;??????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????Double?Sum?=?0;??????????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????????{??????????????????????????Sum?+=?ALPHA[t?-?1,?i]?*?A[i,?j];??????????????????????}????????????????????????ALPHA[t,?j]?=?Sum?*?B[j,?OB[t]];??????????????????????SCALE[t]?+=?ALPHA[t,?j];??????????????????}????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????ALPHA[t,?j]?/=?SCALE[t];??????????????????}??????????????}??????????????????????????????????????????Double?Probability?=?0;??????????????for?(Int32?t?=?0;?t?<?OB.Length;?t++)??????????????{??????????????????Probability?+=?Math.Log(SCALE[t]);??????????????}????????????????return?Probability;???????????????}??????}??}??
using System;namespace Splash
{partial class HMM{/// <summary>/// 前向算法:計(jì)算觀察序列的概率/// Forward Algorithm: Finding the probability of an observed sequence/// </summary>/// <param name="OB">已知的觀察序列</param>/// <returns>觀察序列的概率</returns>/// <remarks>使用雙精度運(yùn)算,不輸出中間結(jié)果</remarks>public Double Forward(Int32[] OB){Double[,] ALPHA; // 只聲明,不定義return Forward(OB, out ALPHA);}/// <summary>/// 前向算法:計(jì)算觀察序列的概率/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="ALPHA">輸出中間結(jié)果:局部概率</param>/// <returns>觀察序列的概率</returns>/// <remarks>使用雙精度運(yùn)算,輸出中間結(jié)果</remarks>public Double Forward(Int32[] OB, out Double[,] ALPHA){ ALPHA = new Double[OB.Length, N]; // 局部概率// 1. 初始化:計(jì)算初始時(shí)刻所有狀態(tài)的局部概率for (Int32 j = 0; j < N; j++){ALPHA[0, j] = PI[j] * B[j, OB[0]];}// 2. 歸納:遞歸計(jì)算每個(gè)時(shí)間點(diǎn)的局部概率for (Int32 t = 1; t < OB.Length; t++){for (Int32 j = 0; j < N; j++){Double Sum = 0;for (Int32 i = 0; i < N; i++){Sum += ALPHA[t - 1, i] * A[i, j];}ALPHA[t, j] = Sum * B[j, OB[t]];}}// 3. 終止:觀察序列的概率等于最終時(shí)刻所有局部概率之和Double Probability = 0;for (Int32 i = 0; i < N; i++){Probability += ALPHA[OB.Length - 1, i];}return Probability;}/// <summary>/// 帶比例因子修正的前向算法:計(jì)算觀察序列的概率/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="ALPHA">中間結(jié)果:局部概率</param>/// <param name="SCALE">中間結(jié)果:比例因子</param>/// <returns>觀察序列的概率(自然對數(shù)值)</returns>private Double ForwardWithScale(Int32[] OB, ref Double[,] ALPHA, ref Double[] SCALE){if(ALPHA == null) ALPHA = new Double[OB.Length, N];if(SCALE == null) SCALE = new Double[OB.Length];// 1. 初始化SCALE[0] = 0;for (Int32 j = 0; j < N; j++){ALPHA[0, j] = PI[j] * B[j, OB[0]];SCALE[0] += ALPHA[0, j];}for (Int32 j = 0; j < N; j++){ALPHA[0, j] /= SCALE[0];}// 2. 歸納for (Int32 t = 1; t < OB.Length; t++){SCALE[t] = 0;for (Int32 j = 0; j < N; j++){Double Sum = 0;for (Int32 i = 0; i < N; i++){Sum += ALPHA[t - 1, i] * A[i, j];}ALPHA[t, j] = Sum * B[j, OB[t]];SCALE[t] += ALPHA[t, j];}for (Int32 j = 0; j < N; j++){ALPHA[t, j] /= SCALE[t];}} // 3. 終止Double Probability = 0;for (Int32 t = 0; t < OB.Length; t++){Probability += Math.Log(SCALE[t]);}return Probability; // 自然對數(shù)值}}
}
Backward.cs(后向算法)
[c-sharp] view plaincopyprint?
using?System;????namespace?Splash??{??????partial?class?HMM??????{?????????????????????????????????????????????????? ??????????public?Double?Backward(Int32[]?OB)??????????{??????????????Double[,]?BETA;?????????????????????return?Backward(OB,?out?BETA);??????????}????????????????????????????????????????????????????????????????????????public?Double?Backward(Int32[]?OB,?out?Double[,]?BETA)??????????{??????????????????????????BETA?=?new?Double[OB.Length,?N];??????????????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????{??????????????????BETA[OB.Length?-?1,?j]?=?1.0;??????????????}??????????????????????????????for?(Int32?t?=?OB.Length?-?2;?t?>=?0;?t--)??????????????{??????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????Double?Sum?=?0;??????????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????????{??????????????????????????Sum?+=?A[j,?i]?*?B[i,?OB[t?+?1]]?*?BETA[t?+?1,?i];??????????????????????}????????????????????????BETA[t,?j]?=?Sum;??????????????????}??????????????}??????????????????????????????Double?Probability?=?0;??????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????{??????????????????Probability?+=?BETA[0,?i];??????????????}????????????????return?Probability;??????????}???????????????????????????????????????????????????? ????????????????????private?void?BackwardWithScale(Int32[]?OB,?Double[]?SCALE,?ref?Double[,]?BETA)??????????{??????????????if(BETA?==?null)?BETA?=?new?Double[OB.Length,?N];??????????????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????{??????????????????BETA[OB.Length?-?1,?j]?=?1.0?/?SCALE[OB.Length?-?1];??????????????}??????????????????????????????for?(Int32?t?=?OB.Length?-?2;?t?>=?0;?t--)??????????????{??????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????{??????????????????????Double?Sum?=?0;??????????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????????{??????????????????????????Sum?+=?A[j,?i]?*?B[i,?OB[t?+?1]]?*?BETA[t?+?1,?i];??????????????????????}????????????????????????BETA[t,?j]?=?Sum?/?SCALE[t];??????????????????}??????????????}??????????}??????}??}??
using System;namespace Splash
{partial class HMM{/// <summary>/// 后向算法:計(jì)算觀察序列的概率/// </summary>/// <param name="OB">已知的觀察序列</param>/// <returns>觀察序列的概率</returns>public Double Backward(Int32[] OB){Double[,] BETA; // 只聲明,不定義return Backward(OB, out BETA);}/// <summary>/// 后向算法:計(jì)算觀察序列的概率/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="BETA">中間結(jié)果</param>/// <returns>觀察序列的概率</returns>public Double Backward(Int32[] OB, out Double[,] BETA){ BETA = new Double[OB.Length, N];// 初始化for (Int32 j = 0; j < N; j++){BETA[OB.Length - 1, j] = 1.0;}// 歸納for (Int32 t = OB.Length - 2; t >= 0; t--){for (Int32 j = 0; j < N; j++){Double Sum = 0;for (Int32 i = 0; i < N; i++){Sum += A[j, i] * B[i, OB[t + 1]] * BETA[t + 1, i];}BETA[t, j] = Sum;}}// 終止Double Probability = 0;for (Int32 i = 0; i < N; i++){Probability += BETA[0, i];}return Probability;}/// <summary>/// 帶比例因子修正的后向算法/// </summary>/// <param name="OB">已知的觀察序列</param>/// <param name="SCALE">用于修正的比例因子</param>/// <param name="BETA">中間結(jié)果:局部概率</param>private void BackwardWithScale(Int32[] OB, Double[] SCALE, ref Double[,] BETA){if(BETA == null) BETA = new Double[OB.Length, N];// 初始化for (Int32 j = 0; j < N; j++){BETA[OB.Length - 1, j] = 1.0 / SCALE[OB.Length - 1];}// 歸納for (Int32 t = OB.Length - 2; t >= 0; t--){for (Int32 j = 0; j < N; j++){Double Sum = 0;for (Int32 i = 0; i < N; i++){Sum += A[j, i] * B[i, OB[t + 1]] * BETA[t + 1, i];}BETA[t, j] = Sum / SCALE[t];}}}}
}
BaumWelch.cs(前向-后向算法)
[c-sharp] view plaincopyprint?
using?System;????namespace?Splash??{??????partial?class?HMM??????{???????????????????????????????????????????????????????????? ???????????????????????????????????????? ?????????? ????????????????????public?Int32?BaumWelch(Int32[]?OB,?out?Double?LogProbInit,?out?Double?LogProbFinal,???????????????Double?ExitError?=?0.001,?Double?MSP?=?0.001,?Double?MOP?=?0.001)??????????{??????????????Double[,]?ALPHA?=?null;??????????????Double[,]?BETA?=?null;??????????????????????????Double[]?SCALE?=?null;??????????????Double[,]?GAMMA?=?null;??????????????Double[,?,]?XI?=?null;????????????????Double?LogProbForward?=?LogProbInit?=?ForwardWithScale(OB,?ref?ALPHA,?ref?SCALE);???????????????BackwardWithScale(OB,?SCALE,?ref?BETA);???????????????ComputeGamma(ALPHA,?BETA,?ref?GAMMA);?????????????????ComputeXI(OB,?ALPHA,?BETA,?ref?XI);?????????????????????????????????Int32?Iterations;??????????????Double?LogProbPrev?=?LogProbForward;??????????????for(Iterations?=?1;?;?Iterations++)??????????????{?????????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????{??? ??????????????????????PI[i]?=?MSP?+?(1?-?MSP?*?N)?*?GAMMA[0,?i];??????????????????}????????????????????for(Int32?i?=?0;?i?<?N;?i++)??????????????????{?????????????????????????Double?DenominatorA?=?0;??????????????????????for(Int32?t?=?0;?t?<?OB.Length?-?1;?t++)??????????????????????????DenominatorA?+=?GAMMA[t,?i];????????????????????????????????????????????for(Int32?j?=?0;?j?<?N;?j++)??????????????????????{??????????????????????????Double?NumeratorA?=?0;??????????????????????????for(Int32?t?=?0;?t?<?OB.Length?-?1;?t++)??????????????????????????????NumeratorA?+=?XI[t,i,j];???????????????????????????? ??????????????????????????A[i,?j]?=?MSP?+?(1?-?MSP?*?N)?*?NumeratorA?/?DenominatorA;??????????????????????}??????????????????????????????????????????????Double?DenominatorB?=?DenominatorA?+?GAMMA[OB.Length?-?1,?i];??????????????????????for(Int32?k?=?0;?k?<?M;?k++)??????????????????????{??????????????????????????Double?NumeratorB?=?0;??????????????????????????for(Int32?t?=?0;?t?<?OB.Length;?t++)??????????????????????????{??????????????????????????????if(OB[t]?==?k)?NumeratorB?+=?GAMMA[t,i];??????????????????????????}???????????????????????????? ??????????????????????????B[i,?k]?=?MOP?+?(1?-?MOP?*?M)?*?NumeratorB?/?DenominatorB;??????????????????????}?????????????????????????????????????}???????????????????????????????????????LogProbForward?=?ForwardWithScale(OB,?ref?ALPHA,?ref?SCALE);??????????????????if?(LogProbForward?-?LogProbPrev?<=?ExitError)?break;????????????????????BackwardWithScale(OB,?SCALE,?ref?BETA);??????????????????ComputeGamma(ALPHA,?BETA,?ref?GAMMA);??????????????????ComputeXI(OB,?ALPHA,?BETA,?ref?XI);??????????????????LogProbPrev?=?LogProbForward;??????????????}? ????????????????LogProbFinal?=?LogProbForward;????????????????????????????????return?Iterations;??????????}?????????????????????????????????????????? ??????????????????????????????private?void?ComputeGamma(Double[,]?ALPHA,?Double[,]?BETA,?ref?Double[,]?GAMMA)??????????{??????????????Int32?T?=?ALPHA.GetLength(0);??????????????if?(GAMMA?==?null)?GAMMA?=?new?Double[T,?N];????????????????for?(Int32?t?=?0;?t?<?T;?t++)??????????????{??????????????????Double?Denominator?=?0;??????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????{??????????????????????GAMMA[t,?i]?=?ALPHA[t,?i]?*?BETA[t,?i];??????????????????????Denominator?+=?GAMMA[t,?i];??????????????????}????????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????{??????????????????????GAMMA[t,?i]?/=?Denominator;???????????????????}??????????????}??????????}?????????????????????????????????????????? ?????????? ??????????????????????????????private?void?ComputeXI(Int32[]?OB,?Double[,]?ALPHA,?Double[,]?BETA,?ref?Double[,,]?XI)??????????{??????????????Int32?T?=?OB.Length;??????????????if?(XI?==?null)?XI?=?new?Double[T,?N,?N];????????????????for?(Int32?t?=?0;?t?<?T?-?1;?t++)??????????????{??????????????????Double?Sum?=?0;??????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????{??????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????????{??????????????????????????XI[t,?i,?j]?=?ALPHA[t,?i]?*?A[i,?j]?*?B[j,?OB[t?+?1]]?*?BETA[t?+?1,?j];??????????????????????????Sum?+=?XI[t,?i,?j];??????????????????????}??????????????????}??????????????????????????????????????for?(Int32?i?=?0;?i?<?N;?i++)??????????????????????for?(Int32?j?=?0;?j?<?N;?j++)??????????????????????????XI[t,?i,?j]?/=?Sum;???????????????}??????????}??????}??}?? 轉(zhuǎn)載:http://blog.csdn.net/jhqin/article/details/6534916
總結(jié)
以上是生活随笔為你收集整理的隐马尔科夫模型C#语言算法实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。