1. 程式人生 > >HMM前向演算法,維位元演算法,後向演算法,前向後向演算法程式碼

HMM前向演算法,維位元演算法,後向演算法,前向後向演算法程式碼

typedef struct
{
int N; /* 隱藏狀態數目;Q={1,2,…,N} */
int M; /* 觀察符號數目; V={1,2,…,M}*/
double **A; /* 狀態轉移矩陣A[1..N][1..N]. a[i][j] 是從t時刻狀態i到t+1時刻狀態j的轉移概率 */
double **B; /* 混淆矩陣B[1..N][1..M]. b[j][k]在狀態j時觀察到符合k的概率。*/
double *pi; /* 初始向量pi[1..N],pi[i] 是初始狀態概率分佈 */
} HMM;

前向演算法程式示例如下:
/*
 函式引數說明:
 *phmm:已知的HMM模型;T:觀察符號序列長度;
 *O:觀察序列;**alpha:區域性概率;*pprob:最終的觀察概率
*/
void Forward(HMM *phmm, int T, int *O, double **alpha, double *pprob)
{
  int i, j;   /* 狀態索引 */
  int t;    /* 時間索引 */
  double sum; /*求區域性概率時的中間值 */
  /* 1. 初始化:計算t=1時刻所有狀態的區域性概率: */
  for (i = 1; i <= phmm->N; i++)
    alpha[1][i] = phmm->pi[i]* phmm->B[i][O[1]];
  
  /* 2. 歸納:遞迴計算每個時間點,t=2,… ,T時的區域性概率 */
  for (t = 1; t < T; t++)
  {
    for (j = 1; j <= phmm->N; j++)
    {
      sum = 0.0;
      for (i = 1; i <= phmm->N; i++)
        sum += alpha[t][i]* (phmm->A[i][j]);
      alpha[t+1][j] = sum*(phmm->B[j][O[t+1]]);
    }
  }
  /* 3. 終止:觀察序列的概率等於T時刻所有區域性概率之和*/
  *pprob = 0.0;
  for (i = 1; i <= phmm->N; i++)
    *pprob += alpha[T][i];
}



維位元演算法:
void Viterbi(HMM *phmm, int T, int *O, double **delta, int **psi,int *q, double *pprob)
{
  int i, j; /* state indices */
  int t; /* time index */
  int maxvalind;
  double maxval, val;
  /* 1. Initialization */
  for (i = 1; i <= phmm->N; i++)
  {
    delta[1][i] = phmm->pi[i] * (phmm->B[i][O[1]]);
    psi[1][i] = 0;
  }
  /* 2. Recursion */
  for (t = 2; t <= T; t++)
  {
    for (j = 1; j <= phmm->N; j++)
    {
      maxval = 0.0;
      maxvalind = 1;
      for (i = 1; i <= phmm->N; i++)
      {
        val = delta[t-1][i]*(phmm->A[i][j]);
        if (val > maxval)
        {
          maxval = val;
          maxvalind = i;
        }
      }
      delta[t][j] = maxval*(phmm->B[j][O[t]]);
      psi[t][j] = maxvalind;
    }
  }
  /* 3. Termination */
  *pprob = 0.0;
  q[T] = 1;
  for (i = 1; i <= phmm->N; i++)
  {
    if (delta[T][i] > *pprob)
    {
      *pprob = delta[T][i];
      q[T] = i;
    }
  }
  /* 4. Path (state sequence) backtracking */
  for (t = T – 1; t >= 1; t–)
    q[t] = psi[t+1][q[t+1]];
}


後向演算法:
void Backward(HMM *phmm, int T, int *O, double **beta, double *pprob)
{
  int i, j; /* state indices */
  int t; /* time index */
  double sum;
  /* 1. Initialization */
  for (i = 1; i <= phmm->N; i++)
    beta[T][i] = 1.0;
  /* 2. Induction */
  for (t = T - 1; t >= 1; t--)
  {
    for (i = 1; i <= phmm->N; i++)
    {
      sum = 0.0;
      for (j = 1; j <= phmm->N; j++)
        sum += phmm->A[i][j] *
              (phmm->B[j][O[t+1]])*beta[t+1][j];
      beta[t][i] = sum;
    }
  }
  /* 3. Termination */
  *pprob = 0.0;
  for (i = 1; i <= phmm->N; i++)
    *pprob += beta[1][i];
}


前向後向演算法:
void BaumWelch(HMM *phmm, int T, int *O, double **alpha, double **beta, double **gamma, int *pniter, double *plogprobinit, double *plogprobfinal)
{
  int i, j, k;
  int t, l = 0;
  double logprobf, logprobb, threshold;
  double numeratorA, denominatorA;
  double numeratorB, denominatorB;
  double ***xi, *scale;
  double delta, deltaprev, logprobprev;
  deltaprev = 10e-70;
  xi = AllocXi(T, phmm->N);
  scale = dvector(1, T);
  ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);
  *plogprobinit = logprobf; /* log P(O |intial model) */
  BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
  ComputeGamma(phmm, T, alpha, beta, gamma);
  ComputeXi(phmm, T, O, alpha, beta, xi);
  logprobprev = logprobf;
  do
  {
    /* reestimate frequency of state i in time t=1 */
    for (i = 1; i <= phmm->N; i++)
      phmm->pi[i] = .001 + .999*gamma[1][i];
    /* reestimate transition matrix and symbol prob in
        each state */
    for (i = 1; i <= phmm->N; i++)
    {
      denominatorA = 0.0;
      for (t = 1; t <= T - 1; t++)
        denominatorA += gamma[t][i];
      for (j = 1; j <= phmm->N; j++)
      {
        numeratorA = 0.0;
        for (t = 1; t <= T - 1; t++)
          numeratorA += xi[t][i][j];
        phmm->A[i][j] = .001 +
                 .999*numeratorA/denominatorA;
      }
      denominatorB = denominatorA + gamma[T][i];
      for (k = 1; k <= phmm->M; k++)
      {
        numeratorB = 0.0;
        for (t = 1; t <= T; t++)
        {
          if (O[t] == k)
            numeratorB += gamma[t][i];
        }
        phmm->B[i][k] = .001 +
                 .999*numeratorB/denominatorB;
      }
    }
    ForwardWithScale(phmm, T, O, alpha, scale, &logprobf);
    BackwardWithScale(phmm, T, O, beta, scale, &logprobb);
    ComputeGamma(phmm, T, alpha, beta, gamma);
    ComputeXi(phmm, T, O, alpha, beta, xi);
    /* compute difference between log probability of
      two iterations */
    delta = logprobf - logprobprev;
    logprobprev = logprobf;
    l++;
  }
  while (delta > DELTA); /* if log probability does not
              change much, exit */
  *pniter = l;
  *plogprobfinal = logprobf; /* log P(O|estimated model) */
  FreeXi(xi, T, phmm->N);
  free_dvector(scale, 1, T);
}

相關推薦

HMM演算法位元演算法演算法演算法程式碼

typedef struct { int N; /* 隱藏狀態數目;Q={1,2,…,N} */ int M; /* 觀察符號數目; V={1,2,…,M}*/ double **A; /* 狀態轉移矩陣A[1..N][1..N]. a[i][j] 是從t時刻狀態i到t+1

隱馬爾科夫模型(演算法、鮑姆-韋爾奇演算法特比演算法)

 概率圖模型是一類用圖來表達變數相關關係的概率模型。它以圖為表示工具,最常見的是用一個結點表示一個或一組隨機變數,結點之間的變表是變數間的概率相關關係。根據邊的性質不同,可以將概率圖模型分為兩類:一類是使用有向無環圖表示變數間的依賴關係,稱為有向圖模型或貝葉斯網;另一類是使用無向圖表示變數間的相關關係,稱為無

設計一個演算法,將一陣列A(下標從1開始)中的元素迴圈右移k位要求只用一個元素大小的附加儲存空間。給出演算法的時間複雜度。

程式碼 #include<stdio.h> #include<stdlib.h> #define n 10 int main() { int a[n] = { 0,1,2,3,4,5,6,7,8,9 }; int k, t=0,i,j,m; printf(

千萬級高效簡便判斷是否為素數若為合數左右搜尋最近的素數。(非米勒羅賓素數測試演算法

現在ZRain要讓n個孩子變成天使,每個孩子都有一個RP值,當RP值為一個質數時孩子就能變成天使。但是改變孩子的RP值是有代價的,比如rp從x改到y需要付出|x-y|的代價。ZRain真的太喜歡這些孩子了,他希望這些孩子都變成可愛的天使,但又希望付出最小的代價。   &nbs

程式設計基礎57 隨機選擇演算法找出陣列第n/2大並返回一半減去一半的值複雜度o(n)

#include<cstdio> #include<cstdlib> #include<ctime> #include<algorithm> using namespace std; const int max_n = 1000

機試演算法講解: 第6題 給n個整數按從大到小的順序輸出m大的整數

/* 問題:給n個整數,按從大到小的順序,輸出前m大的整數 0<m,n<1000000,每個整數[-500000,500000] 輸入: 5 3 3 -35 92 213 -644 輸出: 213 92 3 思路: 先按從小到大用快排排好序,然後輸出排好序的陣

演算法:給定一個整數陣列和一個目標值找出陣列中和為目標值的兩個數、判斷一個整數是否是迴文數

<!-- 給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。 示例: 給定 nums = [2, 7, 11, 15], target = 9 因為 nums[0] + nums[1] = 2 + 7 = 9

吳恩達機器學習 - PCA演算法 吳恩達機器學習 - PCA演算法

原 吳恩達機器學習 - PCA演算法降維 2018年06月25日 13:08:17 離殤灬孤狼 閱讀數:152 更多

演算法--20181111--陣列分成長度相等兩個陣列使兩部分和最接近

給定一個數組,長度為偶數,將陣列分成長度相等兩部分,使兩部分和最接近 先介紹01揹包,然後解決長度可以不相等的情況,最後解決該問題 問題0: 01揹包問題---k件商品,每件都有重量wi以及價格vi,給定一個袋子容量為W,求袋子中存放商品價值最大的取貨方案 令f(k,w)為袋裡可用

演算法題004 -- [給定一個整數的陣列nums返回相加為target的兩個數字的索引值] by java

題目 給定一個整數的陣列nums,返回相加為target的兩個數字的索引值。 假設每次輸入都只有一個答案,並且不會使用同一個元素兩次。 舉例: Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums

資料結構與演算法之美 課程筆記一 如何抓住重點系統高效地學習資料結構與演算法

什麼是資料結構?什麼是演算法? 從廣義上講,資料結構就是指一組資料的儲存結構。演算法就是操作資料的一種方法。 從狹義上講,是指某些著名的資料結構和演算法,比如佇列、棧、堆、二分查詢、動態規劃等。 那資料結構和演算法有什麼關係呢? 資料結構和演算法是相輔相成的。資料結構是為演算法服務的

資料結構--C語言--已知線性表中的元素以值遞增有序排列並以單鏈表作儲存結構。試寫一高效演算法刪除表中所有值大於mink且小於maxk的元素

#include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #define LEN sizeof(struct LNode) struct LNode{ int data;//資料域 struct

[Al]演算法:有n級階梯每次走1步或2步最多有多少種走法

@Filename : floor.c * @Author : Mr.Zhong * @Date : 2018-11-02 * @Description: n級階梯,每次走一步或2步,最多有多少種走法 * @Analysis :

布隆過濾器(Bloom Filter)(給兩個檔案分別有100億個字串我們只要1g的記憶體如何找到兩個檔案的交集?分別給出精確演算法和近似演算法?)

  給兩個檔案,分別有100億個字串,我們只要1g的記憶體,如何找到兩個檔案的交集?分別給出精確演算法和近似演算法? 精確演算法:   我們可以建立1000個檔案,運用雜湊函式先將檔案1的字串儲存在對應的檔案中,之後再檔案2中取元素,通過雜湊函式計算出雜湊地址

影象演算法(一):最近鄰插值雙線性插值三次插值

最近在複習影象演算法,對於一些簡單的影象演算法進行一個程式碼實現,由於找工作比較忙,具體原理後期補上,先上程式碼。今天先給出最近鄰插值,雙線性插值,三次插值。 1.最近鄰插值 原始圖中影響點數為1 (1)程式碼 # include<iostream>

HDU 1853 & HDU 3488【有環最小權值覆蓋問題 】帶權二分圖匹配 KM演算法

In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000) one-way roads connecting them. You are lucky

《程式設計珠璣》程式碼之路7:這個演算法全世界程式設計師16年才寫對你肯定想不到竟然是這個

這篇部落格要講的演算法,是個有故事的演算法,大家一定會喜歡的: 有這麼一個演算法: 1:業界巨佬經典鉅著《程式設計珠璣》的作者,在課堂上給出了思想,不限時間讓程式設計師們實現,所有的程式設計師在提交的時候都覺得自己寫的是對的,然而結果是即使是高階程式設計師,90%以上的人都寫錯了。 2:

演算法導論第三課(fibonacci,二分查詢歸併排序)

3.1 乘方實現 A:實現方法 乘方實現有兩種方法,一個是使用O(N)的時間複雜度還有種方法可以使用遞迴的方式,遞迴的公式如下 通過兩種方式的實現,可以進行比較兩種方法的時間複雜度 B:時間複雜度 第二種方法的遞迴表示式如下 通過主定理可以算出第二種的時間複雜

資料結構--C語言--圖的深度優先遍歷廣度優先遍歷拓撲排序用prime演算法實現最小生成樹用迪傑斯特拉演算法實現關鍵路徑和關鍵活動的求解最短路徑

實驗七  圖的深度優先遍歷(選做,驗證性實驗,4學時) 實驗目的 熟悉圖的陣列表示法和鄰接表儲存結構,掌握構造有向圖、無向圖的演算法 ,在掌握以上知識的基礎上,熟悉圖的深度優先遍歷演算法,並實現。 實驗內容 (1)圖的陣列表示法定義及

分治法:關於選擇演算法找最大找最小同時找最大和最小找第二大

找最大或者最小,蠻力演算法為最優的演算法,需要比較n-1次 # 這個已經是最優的演算法了,比較n-1次 def findMax(arr): max_pivot = arr[0] for i in range(1,len(arr)): if arr