日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

维特比算法的java实现_原创:维特比算法

發(fā)布時(shí)間:2023/12/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 维特比算法的java实现_原创:维特比算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

看了宗成慶博士的《統(tǒng)計(jì)自然語言處理(中文信息處理)》的第六章,對維特比算法有著非常精辟的講解。把其中的講解上傳上來,個(gè)人感覺比較正統(tǒng)。

今天用Java實(shí)現(xiàn)了這個(gè)算法,也可以轉(zhuǎn)換為C代碼:

package com.nlp.hmm.algorithm.viterbi;

/**

* 維特比算法

*

* @author XueQiang Tong

* @date 2017/04/25

*/

public class Viterbi {

/**

* @param obs

* 觀察輸出序列

* @param state

* 狀態(tài)序列(隱式)

* @param start_p

* 初始概率

* @param trans_p

* 狀態(tài)轉(zhuǎn)換概率

* @param emit_p

* 發(fā)射概率

* @return 返回最優(yōu)狀態(tài)路徑(這個(gè)路徑具有最好的解釋能力)

*/

public static int[] compute(int obs[], int state[], double[] start_p, double[][] trans_p, double[][] emit_p) {

double v[][] = new double[obs.length][state.length];// viterbi值矩陣

int path[][] = new int[state.length][obs.length];// 存儲路徑

// 1.初始化時(shí)間序列為0的節(jié)點(diǎn)( t=0)

for (int s : state) {

v[obs[0]][s] = start_p[s] * emit_p[s][obs[0]];

path[s][obs[0]] = s;

}

// 2.開始遞歸計(jì)算viterbi矩陣(從t=1開始)

for (int t = 1; t < obs.length; ++t) {

int newpath[][] = new int[state.length][obs.length];// 每次迭代時(shí),定義一個(gè)新的存儲path,因?yàn)槊總€(gè)時(shí)間序列的path都依賴于

// 上個(gè)序列的path

// 對該時(shí)間序列上的每個(gè)state節(jié)點(diǎn)進(jìn)行迭代,每個(gè)節(jié)點(diǎn)都與上個(gè)序列的所有state交互

for (int s : state) {

double maxValue = -1.0;

int label = -1;

for (int s0 : state) {// 尋找出備選路徑

double viterbiValue = v[t - 1][s0] * trans_p[s0][s] * emit_p[s][obs[t]];

if (viterbiValue > maxValue) {

maxValue = viterbiValue;

label = s0;

// 記錄最大概率

v[t][s] = maxValue;

// 記錄路徑

System.arraycopy(path[label], 0, newpath[s], 0, t);

newpath[s][t] = s;

}

}

}

path = newpath;

}

// 找出最后一個(gè)時(shí)間序列上的viterbi值最大的state,從而找出最優(yōu)路徑

double maxValue = -1.0;

int label = -1;

for (int s : state) {

if (v[obs.length - 1][s] > maxValue) {

maxValue = v[obs.length - 1][s];

label = s;

}

}

return path[label];

}

}

測試文件:

1 packagecom.nlp.hmm.algorithm.viterbi;2

3

4 public classViterbiTest {5

6 public static voidmain(String[] args) {7 int[] obs = {0,1,2};//0--walk,1--shop,2--clean

8 int[] states = {0,1};//0--rainy,1--sunny

9 double[] start_p = {0.6,0.4};//0.6--rainy,0.4--sunny

10 double[][] trans_p = new double[states.length][states.length];//0--rainy,1--sunny

11 trans_p[0][0] = 0.7;12 trans_p[0][1] = 0.3;13 trans_p[1][0] = 0.4;14 trans_p[1][1] = 0.6;15 double[][] emit_p = new double[states.length][obs.length];//dimension1:rainy 0,sunny 1;dimension2:walk 0 shop 1 clean 2

16 emit_p[0][0] = 0.1;17 emit_p[0][1] = 0.4;18 emit_p[0][2] = 0.5;19 emit_p[1][0] = 0.6;20 emit_p[1][1] = 0.3;21 emit_p[1][2] = 0.1;22 int []path =Viterbi.compute(obs, states, start_p, trans_p, emit_p);23 for (intpa:path){24 System.out.print(pa+" ");25 }26 }27

28 }

輸出結(jié)果為1,0,0,就是sunny,rainy,rainy。對比了一下,結(jié)果沒問題,邏輯也沒問題。維特比算法和前向搜索算法有著共同點(diǎn),兩者解決的hmm問題不一樣。

下面是本人的python實(shí)現(xiàn)代碼:

import numpy as np

def viterbi(obs,state,start_prob,transition_prob,emit_prob):

vit = np.array(np.zeros(shape = [len(obs),len(state)],dtype = np.float64))

path = np.array(np.zeros(shape = [len(state),len(obs)],dtype = np.int32))

#初始化

for i in range(len(state)):

vit[0,i] = start_prob[i] * emit_prob[i][0]

path[i][0] = state[i]

for t in range(1,len(obs)):

newPath = np.zeros_like(path)

v = np.dot(np.reshape(vit[t-1],[len(state),1]),np.reshape(emit_prob[:,t],[1,len(state)])) * transition_prob

vi = np.max(v,axis = 0)

vit[t,:] = vi[:]

pa = np.argmax(v,axis = 0)

for i in range(len(pa)):

label = pa[i]

newPath[i,:] = path[label,:]

newPath[i][t] = state[i]

path = newPath

return path[np.argmax(vit[len(obs)-1,:]),:]

總結(jié)

以上是生活随笔為你收集整理的维特比算法的java实现_原创:维特比算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。