维特比算法(viterbi)python实现

维特比算法(viterbi)python实现

import numpy as np


state_transfer = np.array([[0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5]])  # 状态转移矩阵
observe_prob = np.array([[0.5, 0.5], [0.4, 0.6], [0.7, 0.3]])  # 观测概率矩阵
initial = np.array([0.2, 0.4, 0.4])  # 初始状态概率向量
observes = ['红', '白']  # 所有可能的观测集合
states = [0, 1, 2]  # 所有可能的状态集合
observe_seq = ['红', '白', '红']  # 观测序列


def argmax(path_value, state_transfer, states, state, m):  # 在t时刻状态为i的所有单个路径(i1,i2,...,it)中概率最大的路径第t-1个结点
    max_index = -1
    max_value = -1
    for statej in states:
        if path_value[m-1][statej] * state_transfer[statej][state] > max_value:
            max_value = path_value[m-1][statej] * state_transfer[statej][state]
            max_index = statej

    return max_index


def argmax2(path_value_len):
    max_index = -1
    max_value = -1
    for i in range(len(path_value_len)):
        if path_value_len[i] > max_value:
            max_value = path_value_len[i]
            max_index = i

    return max_index


def viterbi(state_transfer, states, observe_prob, initial, observe_seq):
    path_value = np.zeros(shape=(3, 3))  # 存储在t时刻状态为i的所有单个路径(i1,i2,...it)中概率最大值(t=0,1,2, i=0,1,2)
    path_node = np.zeros(shape=(3, 3), dtype=int) # 存储在t时刻状态为i的所有单个路径(i1,i2,...,it)中概率最大的路径第t-1个结点

    for m in range(len(observe_seq)):
        if m == 0:  #初始化
            for state in states:
                path_value[m][state] = initial[state] * observe_prob[state][observes.index(observe_seq[m])] #在t时刻状态为i的所有单个路径(i1,i2,...it)中概率最大值(t=0,1,2, i=0,1,2)

            path_node[m] = [-1, -1, -1]

        else:
            for state in states:  # 递推
                path_value[m][state] = max([path_value[m-1][statej] * state_transfer[statej][state] for statej in states]) \
                                       * observe_prob[state][observes.index(observe_seq[m])] # 在t时刻状态为i的所有单个路径(i1,i2,...it)中概率最大值(t=0,1,2, i=0,1,2)

                path_node[m][state] = argmax(path_value, state_transfer, states, state, m)  # 在t时刻状态为i的所有单个路径(i1,i2,...,it)中概率最大的路径第t-1个结点

    max_path_value = max(path_value[len(observe_seq)-1])
    path = []

    i_t = argmax2(path_value[len(observe_seq)-1]) #最优路径第t时刻状态
    path.append(i_t)

    for k in range(len(observe_seq)-1, -1, -1):  # 最优路径回溯
        i_t = path_node[k][i_t]
        path.append(i_t)

    print(list(reversed(path))[1:]) # 输出最优路径
    print(max_path_value)


if __name__ == '__main__':
    viterbi(state_transfer, states, observe_prob, initial, observe_seq)

你可能感兴趣的:(维特比算法(viterbi)python实现)