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